@layer junds.tokens, junds.base, junds.components;
/* AUTO-GENERATED by tokens/build/generate.mjs — DO NOT EDIT */
@layer junds.tokens {
  :root {
    --jd-color-background: #f5f4f8;
    --jd-color-foreground: #1a1726;
    --jd-color-card: #ffffff;
    --jd-color-card-hover: #f9f8fc;
    --jd-color-border: #e2dfe8;
    --jd-color-border-light: #efedf4;
    --jd-color-primary: #5b4cc7;
    --jd-color-primary-hover: #4a3db0;
    --jd-color-primary-light: #eceafc;
    --jd-color-primary-glow: rgba(91, 76, 199, 0.18);
    --jd-color-accent: #7c5ce7;
    --jd-color-accent-light: #efebff;
    --jd-color-danger: #c93636;
    --jd-color-danger-hover: #b92f2f;
    --jd-color-danger-light: #fff1f1;
    --jd-color-muted: #6b6880;
    --jd-color-muted-light: #9895a8;
    --jd-color-success: #2f8f57;
    --jd-color-success-light: #eaf6ee;
    --jd-color-warning: #b7791f;
    --jd-color-warning-light: #fff7e6;
    --jd-color-info: #3b82f6;
    --jd-color-info-light: #eff6ff;
    --jd-color-neutral-25: #faf9fc;
    --jd-color-neutral-50: #f5f4f8;
    --jd-color-neutral-100: #eeecf3;
    --jd-color-neutral-200: #e2dfe8;
    --jd-color-neutral-300: #d0ccdb;
    --jd-color-neutral-400: #a9a5b9;
    --jd-color-neutral-500: #837f96;
    --jd-color-neutral-600: #6b6880;
    --jd-color-neutral-700: #524f64;
    --jd-color-neutral-800: #363348;
    --jd-color-neutral-900: #1a1726;
    --jd-color-control-surface: #ffffff;
    --jd-color-control-surface-hover: #faf9fc;
    --jd-color-control-surface-muted: #f5f4f8;
    --jd-color-control-track: var(--jd-color-neutral-200);
    --jd-color-control-track-strong: var(--jd-color-neutral-300);
    --jd-color-control-knob: #ffffff;
    --jd-color-ring-primary: rgba(91, 76, 199, 0.55);
    --jd-color-ring-danger: rgba(201, 54, 54, 0.5);
    --jd-color-highlight: rgba(255, 255, 255, 0.16);
    --jd-color-shade: rgba(26, 23, 38, 0.10);
    --jd-color-overlay-scrim: rgba(26, 23, 38, 0.45);
    --jd-color-sidebar-bg: #1a1726;
    --jd-color-sidebar-hover: #272338;
    --jd-color-sidebar-text: #a09cb0;
    --jd-color-sidebar-active: #9580fa;
    --jd-color-surface: #161329;
    --jd-color-surface-raised: #1c1932;
    --jd-color-surface-overlay: #22203a;
    --jd-color-on-surface: #e4e2ee;
    --jd-color-on-surface-muted: #a09cb5;
    --jd-color-primary-ink: #5b4cc7;
    --jd-color-hue-gray: #6b6880;
    --jd-color-hue-blue: #2563eb;
    --jd-color-hue-green: #157f47;
    --jd-color-hue-amber: #a97317;
    --jd-color-hue-orange: #c2410c;
    --jd-color-hue-red: #c93636;
    --jd-color-hue-rose: #be123c;
    --jd-color-hue-purple: #7c3aed;
    --jd-color-hue-violet: #6d28d9;
    --jd-color-hue-teal: #0f766e;
    --jd-color-hue-cyan: #0e7490;
    --jd-color-hue-pink: #be185d;
    --jd-color-status-todo-bg: #f3f4f6;
    --jd-color-status-todo-text: #6b7280;
    --jd-color-status-progress-bg: #dbeafe;
    --jd-color-status-progress-text: #2563eb;
    --jd-color-status-review-bg: #fef3c7;
    --jd-color-status-review-text: #d97706;
    --jd-color-status-done-bg: #d1fae5;
    --jd-color-status-done-text: #059669;
    --jd-color-status-hold-bg: #fee2e2;
    --jd-color-status-hold-text: #dc2626;
    --jd-color-priority-p0-bg: #fef2f2;
    --jd-color-priority-p0-text: #dc2626;
    --jd-color-priority-p0-border: #fca5a5;
    --jd-color-priority-p1-bg: #fff7ed;
    --jd-color-priority-p1-text: #ea580c;
    --jd-color-priority-p1-border: #fdba74;
    --jd-color-priority-p2-bg: #fefce8;
    --jd-color-priority-p2-text: #ca8a04;
    --jd-color-priority-p2-border: #fde047;
    --jd-color-priority-p3-bg: #eff6ff;
    --jd-color-priority-p3-text: #2563eb;
    --jd-color-priority-p3-border: #93c5fd;
    --jd-space-0: 0;
    --jd-space-1: 0.25rem;
    --jd-space-2: 0.5rem;
    --jd-space-3: 0.75rem;
    --jd-space-4: 1rem;
    --jd-space-5: 1.25rem;
    --jd-space-6: 1.5rem;
    --jd-space-8: 2rem;
    --jd-space-10: 2.5rem;
    --jd-space-12: 3rem;
    --jd-space-16: 4rem;
    --jd-space-20: 5rem;
    --jd-space-24: 6rem;
    --jd-space-px: 1px;
    --jd-space-0-5: 0.125rem;
    --jd-space-1-5: 0.375rem;
    --jd-space-2-5: 0.625rem;
    --jd-space-3-5: 0.875rem;
    --jd-radius-none: 0;
    --jd-radius-sm: 0.25rem;
    --jd-radius-md: 0.375rem;
    --jd-radius-lg: 0.5rem;
    --jd-radius-xl: 0.75rem;
    --jd-radius-2xl: 1rem;
    --jd-radius-full: 9999px;
    --jd-font-sans: "Pretendard Variable", Pretendard, "Inter", "Noto Sans KR", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    --jd-font-serif: "Noto Serif KR", "Nanum Myeongjo", Georgia, "Times New Roman", serif;
    --jd-font-display: "Playfair Display", Georgia, "Times New Roman", serif;
    --jd-font-hand: "Caveat", "Bradley Hand", "Segoe Script", cursive;
    --jd-font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, "Liberation Mono", monospace;
    --jd-text-2xs: 0.6875rem;
    --jd-text-xs: 0.75rem;
    --jd-text-sm: 0.8125rem;
    --jd-text-md: 0.875rem;
    --jd-text-lg: 1rem;
    --jd-text-xl: 1.125rem;
    --jd-text-2xl: 1.25rem;
    --jd-text-3xl: 1.5rem;
    --jd-text-4xl: 1.875rem;
    --jd-text-5xl: 2.25rem;
    --jd-weight-normal: 400;
    --jd-weight-medium: 500;
    --jd-weight-semibold: 600;
    --jd-weight-bold: 700;
    --jd-leading-none: 1;
    --jd-leading-tight: 1.25;
    --jd-leading-snug: 1.375;
    --jd-leading-normal: 1.5;
    --jd-leading-relaxed: 1.625;
    --jd-leading-loose: 2;
    --jd-tracking-tighter: -0.05em;
    --jd-tracking-tight: -0.025em;
    --jd-tracking-normal: 0em;
    --jd-tracking-wide: 0.025em;
    --jd-tracking-wider: 0.08em;
    --jd-duration-instant: 0ms;
    --jd-duration-press: 90ms;
    --jd-duration-fast: 100ms;
    --jd-duration-snap: 140ms;
    --jd-duration-normal: 200ms;
    --jd-duration-slow: 300ms;
    --jd-duration-slower: 500ms;
    --jd-duration-emphasis: 420ms;
    --jd-easing-default: cubic-bezier(0.16, 1, 0.3, 1);
    --jd-easing-linear: linear;
    --jd-easing-ease-in: cubic-bezier(0.4, 0, 1, 1);
    --jd-easing-ease-out: cubic-bezier(0, 0, 0.2, 1);
    --jd-easing-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
    --jd-easing-spring: cubic-bezier(0.16, 1, 0.3, 1);
    --jd-easing-emphasized: cubic-bezier(0.2, 0, 0, 1);
    --jd-easing-overshoot: cubic-bezier(0.34, 1.4, 0.64, 1);
    --jd-shadow-none: none;
    --jd-shadow-xs: 0 1px 1px -0.5px rgba(26,23,38,0.08), 0 1px 3px -1px rgba(26,23,38,0.06);
    --jd-shadow-sm: 0 1px 2px -1px rgba(26,23,38,0.10), 0 2px 6px -2px rgba(26,23,38,0.08);
    --jd-shadow-md: 0 2px 4px -2px rgba(26,23,38,0.10), 0 6px 14px -4px rgba(26,23,38,0.10);
    --jd-shadow-lg: 0 4px 8px -4px rgba(26,23,38,0.10), 0 14px 28px -8px rgba(26,23,38,0.12);
    --jd-shadow-xl: 0 8px 14px -8px rgba(26,23,38,0.10), 0 24px 48px -12px rgba(26,23,38,0.16);
    --jd-shadow-2xl: 0 12px 20px -12px rgba(26,23,38,0.12), 0 40px 72px -16px rgba(26,23,38,0.22);
    --jd-shadow-knob: 0 1px 1px rgba(26,23,38,0.16), 0 2px 5px -1px rgba(26,23,38,0.14);
    --jd-shadow-focus-ring: 0 0 0 3px var(--jd-color-primary-glow);
    --jd-shadow-focus-ring-danger: 0 0 0 3px rgba(220,63,63,0.15);
    --jd-z-hide: -1;
    --jd-z-base: 0;
    --jd-z-dropdown: 10;
    --jd-z-sticky: 20;
    --jd-z-header: 30;
    --jd-z-overlay: 40;
    --jd-z-modal: 50;
    --jd-z-popover: 60;
    --jd-z-toast: 70;
    --jd-z-tooltip: 80;
    --jd-z-max: 9999;
    --jd-opacity-0: 0;
    --jd-opacity-5: 0.05;
    --jd-opacity-10: 0.1;
    --jd-opacity-15: 0.15;
    --jd-opacity-20: 0.2;
    --jd-opacity-25: 0.25;
    --jd-opacity-30: 0.3;
    --jd-opacity-40: 0.4;
    --jd-opacity-50: 0.5;
    --jd-opacity-60: 0.6;
    --jd-opacity-70: 0.7;
    --jd-opacity-75: 0.75;
    --jd-opacity-80: 0.8;
    --jd-opacity-90: 0.9;
    --jd-opacity-95: 0.95;
    --jd-opacity-100: 1;
    --jd-border-none: 0px;
    --jd-border-thin: 1px;
    --jd-border-medium: 2px;
    --jd-border-thick: 3px;
    --jd-border-heavy: 4px;
    --jd-breakpoint-sm: 640px;
    --jd-breakpoint-md: 768px;
    --jd-breakpoint-lg: 1024px;
    --jd-breakpoint-xl: 1280px;
    --jd-breakpoint-2xl: 1536px;
    --jd-container-xs: 512px;
    --jd-container-sm: 640px;
    --jd-container-md: 768px;
    --jd-container-lg: 1024px;
    --jd-container-xl: 1280px;
    --jd-container-2xl: 1536px;
    --jd-gradient-primary: linear-gradient(135deg, var(--jd-color-primary) 0%, var(--jd-color-primary-hover) 100%);
    --jd-gradient-primary-soft: linear-gradient(135deg, var(--jd-color-primary-light) 0%, var(--jd-color-primary-glow) 100%);
    --jd-gradient-success: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
    --jd-gradient-warning: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
    --jd-gradient-danger: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%);
    --jd-gradient-info: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
    --jd-gradient-surface-top: linear-gradient(180deg, var(--jd-color-surface) 0%, transparent 100%);
    --jd-gradient-surface-bottom: linear-gradient(0deg, var(--jd-color-surface) 0%, transparent 100%);
    --jd-gradient-sunset: linear-gradient(135deg, #ff7e5f 0%, #feb47b 100%);
    --jd-gradient-ocean: linear-gradient(135deg, #2193b0 0%, #6dd5ed 100%);
    --jd-gradient-aurora: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
    --jd-gradient-midnight: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
    --jd-gradient-cyber: linear-gradient(135deg, #ff00cc 0%, #333399 100%);
    --jd-gradient-forest: linear-gradient(135deg, #134e5e 0%, #71b280 100%);
    --jd-gradient-flame: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);
    --jd-gradient-candy: linear-gradient(135deg, #ee9ca7 0%, #ffdde1 100%);
    --jd-gradient-shimmer: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.4) 50%, transparent 100%);
  }
  /* 전환기: 구 셀렉터 병기 — react 어댑터가 v2 앱(data-theme) 위에서도 동작.
     v3 GA에서 [data-theme="dark"]를 제거한다. (02-tokens §4.1) */
  [data-jd-theme="dark"],
  [data-theme="dark"] {
    --jd-color-background: #0c0a14;
    --jd-color-foreground: #e4e2ee;
    --jd-color-card: #161329;
    --jd-color-card-hover: #1c1932;
    --jd-color-border: #2a2744;
    --jd-color-border-light: #22203a;
    --jd-color-primary-light: rgba(91, 76, 199, 0.15);
    --jd-color-accent-light: rgba(124, 92, 231, 0.12);
    --jd-color-danger: #dc3f3f;
    --jd-color-danger-light: rgba(220, 63, 63, 0.15);
    --jd-color-muted: #a09cb5;
    --jd-color-muted-light: #706d88;
    --jd-color-success-light: rgba(47, 143, 87, 0.15);
    --jd-color-warning-light: rgba(183, 121, 31, 0.15);
    --jd-color-info-light: rgba(59, 130, 246, 0.15);
    --jd-color-neutral-25: #100e1c;
    --jd-color-neutral-50: #161329;
    --jd-color-neutral-100: #1c1932;
    --jd-color-neutral-200: #2a2744;
    --jd-color-neutral-300: #3a3656;
    --jd-color-neutral-400: #575271;
    --jd-color-neutral-500: #7b768f;
    --jd-color-neutral-600: #a09cb5;
    --jd-color-neutral-700: #bdb9cd;
    --jd-color-neutral-800: #d5d2e0;
    --jd-color-neutral-900: #e4e2ee;
    --jd-color-control-surface: #1c1932;
    --jd-color-control-surface-hover: #221f3a;
    --jd-color-control-surface-muted: #181530;
    --jd-color-control-track: var(--jd-color-neutral-200);
    --jd-color-control-track-strong: var(--jd-color-neutral-300);
    --jd-color-control-knob: #f2f0f8;
    --jd-color-ring-primary: rgba(149, 128, 250, 0.65);
    --jd-color-ring-danger: rgba(220, 63, 63, 0.6);
    --jd-color-highlight: rgba(255, 255, 255, 0.07);
    --jd-color-shade: rgba(0, 0, 0, 0.38);
    --jd-color-overlay-scrim: rgba(6, 5, 12, 0.66);
    --jd-color-surface: #161329;
    --jd-color-surface-raised: #1c1932;
    --jd-color-surface-overlay: #22203a;
    --jd-color-on-surface: #e4e2ee;
    --jd-color-on-surface-muted: #a09cb5;
    --jd-color-primary-ink: #9580fa;
    --jd-color-status-todo-bg: rgba(160, 156, 181, 0.14);
    --jd-color-status-todo-text: #a09cb5;
    --jd-color-status-progress-bg: rgba(59, 130, 246, 0.16);
    --jd-color-status-progress-text: #7fb0ff;
    --jd-color-status-review-bg: rgba(183, 121, 31, 0.18);
    --jd-color-status-review-text: #e0a94e;
    --jd-color-status-done-bg: rgba(47, 143, 87, 0.16);
    --jd-color-status-done-text: #5fc98c;
    --jd-color-status-hold-bg: rgba(220, 63, 63, 0.16);
    --jd-color-status-hold-text: #ff8b8b;
    --jd-color-priority-p0-bg: rgba(220, 63, 63, 0.14);
    --jd-color-priority-p0-text: #ff8b8b;
    --jd-color-priority-p0-border: rgba(220, 63, 63, 0.42);
    --jd-color-priority-p1-bg: rgba(234, 88, 12, 0.14);
    --jd-color-priority-p1-text: #ffa668;
    --jd-color-priority-p1-border: rgba(234, 88, 12, 0.42);
    --jd-color-priority-p2-bg: rgba(202, 138, 4, 0.14);
    --jd-color-priority-p2-text: #e8c65a;
    --jd-color-priority-p2-border: rgba(202, 138, 4, 0.45);
    --jd-color-priority-p3-bg: rgba(59, 130, 246, 0.14);
    --jd-color-priority-p3-text: #7fb0ff;
    --jd-color-priority-p3-border: rgba(59, 130, 246, 0.42);
    --jd-shadow-xs: 0 0 0 1px rgba(255,255,255,0.045), 0 1px 2px -1px rgba(0,0,0,0.55);
    --jd-shadow-sm: 0 0 0 1px rgba(255,255,255,0.05), 0 2px 6px -2px rgba(0,0,0,0.65);
    --jd-shadow-md: 0 0 0 1px rgba(255,255,255,0.055), 0 6px 14px -4px rgba(0,0,0,0.7);
    --jd-shadow-lg: 0 0 0 1px rgba(255,255,255,0.06), 0 14px 28px -8px rgba(0,0,0,0.75);
    --jd-shadow-xl: 0 0 0 1px rgba(255,255,255,0.065), 0 24px 48px -12px rgba(0,0,0,0.8);
    --jd-shadow-2xl: 0 0 0 1px rgba(255,255,255,0.07), 0 40px 72px -16px rgba(0,0,0,0.85);
    --jd-shadow-knob: 0 1px 1px rgba(0,0,0,0.5), 0 2px 6px -1px rgba(0,0,0,0.6);
    --jd-gradient-primary-soft: linear-gradient(135deg, var(--jd-color-primary-light) 0%, var(--jd-color-primary-glow) 100%);
    --jd-gradient-surface-top: linear-gradient(180deg, var(--jd-color-surface) 0%, transparent 100%);
    --jd-gradient-surface-bottom: linear-gradient(0deg, var(--jd-color-surface) 0%, transparent 100%);
    color-scheme: dark;
  }
}

/* @junds/web base — 레이어 서열 선언은 라이브러리가 가장 먼저 채택하는 시트가 담당 (03-web-arch §4.2).
   @layer 선언은 멱등이라 이중 로드 무해. 레이어 밖 소비자 CSS가 항상 이긴다. */
@layer junds.tokens, junds.base, junds.components;

@layer junds.base {
  /* 포커스 링 단일 레시피 (DEC-039). 컴포넌트는 `outline: var(--jd-focus-ring)` +
     `outline-offset: var(--jd-focus-ring-offset)` 두 줄만 쓴다 — 두께·색·간격을 한
     곳에서 바꿀 수 있고, 168개 CSS가 각자 color-mix로 링을 조제하던 편차가 사라진다.
     box-shadow가 아니라 outline인 이유: outline은 border-radius를 따라가므로
     (에버그린 전제, DEC-004) 둥근 컨트롤에서 링이 각지지 않고, 레이아웃·클리핑에
     영향을 주지 않아 overflow:hidden 조상 안에서도 잘리지 않는다. */
  :root {
    --jd-focus-ring: var(--jd-border-medium) solid var(--jd-color-ring-primary);
    --jd-focus-ring-danger: var(--jd-border-medium) solid var(--jd-color-ring-danger);
    --jd-focus-ring-offset: 2px;
  }

  /* 톤 레시피 (DEC-044) — 색 하나에서 틴트 배경·테두리·글자를 파생하는 단일 공식.
     컴포넌트는 변종마다 `--jd-tone: <앵커색>` 한 줄만 두고, 기본 규칙에 세 줄을 쓴다:

       --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
       background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
       color:      color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));

     모드가 갖는 것은 **색이 아니라 혼합비**라 다크 분기가 컴포넌트마다 필요 없다 —
     v2 이식본이 Tailwind 50/700 리터럴 쌍을 굳혀 두어 다크에서 형광 슬래브 + 검은
     글자로 뒤집히던 결함(실측 92건)의 구조적 해소.

     ① face(승강) — 앵커는 라이트에서 옅은 틴트 위 글자가 AA를 넘도록 600~700단에
        두었다. 그 어두운 앵커를 다크에서 그대로 쓰면 틴트가 검은 진흙이 된다(실측).
        그래서 다크에서만 앵커를 흰 쪽으로 들어 올린 뒤 나머지 공식에 넣는다.
        라이트는 lift 100% = 앵커 그대로라 분기 없이 한 공식으로 흐른다.
        승강은 **면(배경·테두리) 전용**이다 — 글자는 1단 공식이라 face 변수를 걸
        자리가 없는 일회성 규칙(hint·detail-panel 등)과 값이 같아진다.
     ② 배경을 흰색이 아니라 transparent 와 섞는 이유: 카드·모달·시트 등 어떤 표면
        위에 얹혀도 그 표면의 명도를 물려받아야 같은 색으로 읽힌다.
     ③ 글자는 라이트에서 잉크 쪽으로, 다크에서 흰 쪽으로 민다(--jd-tone-ink-toward).

     소비자 확장: 임의 요소에 `--jd-tone`을 지정하면 그 하위 톤 컴포넌트가 전부 그
     색을 따른다(브랜드 색 주입 경로). 톤의 세기만 바꾸려면 --jd-tone-*-mix. */
  :root {
    --jd-tone: var(--jd-color-hue-gray);
    --jd-tone-lift: 100%;
    --jd-tone-bg-mix: 12%;
    --jd-tone-bg-strong-mix: 22%;
    --jd-tone-border-mix: 30%;
    --jd-tone-ink-mix: 82%;
    --jd-tone-ink-toward: #17141f;
  }
  [data-jd-theme="dark"],
  [data-theme="dark"] {
    --jd-tone-lift: 58%;
    --jd-tone-bg-mix: 26%;
    --jd-tone-bg-strong-mix: 40%;
    --jd-tone-border-mix: 46%;
    --jd-tone-ink-mix: 58%;
    --jd-tone-ink-toward: #ffffff;
  }

  /* FOUC 방지(§3.2): 업그레이드 전 기본 박스 — 태그별 display만 선지정.
     오버레이류는 업그레이드 전 display:none으로 내용 번쩍임 차단. */
  jd-button:not(:defined) {
    display: inline-flex;
  }
  jd-text-field:not(:defined) {
    display: flex;
    flex-direction: column;
  }
  jd-modal:not(:defined) {
    display: none;
  }

  /* B1 core — 컨테이너·타이포는 골격 이동이 없거나 얕아 display 선지정으로 충분 */
  jd-box:not(:defined),
  jd-heading:not(:defined),
  jd-text:not(:defined),
  jd-divider:not(:defined),
  jd-page:not(:defined),
  jd-page-header:not(:defined),
  jd-section:not(:defined) {
    display: block;
  }
  jd-flex:not(:defined),
  jd-center:not(:defined),
  jd-hstack:not(:defined),
  jd-group:not(:defined) {
    display: flex;
  }
  jd-vstack:not(:defined),
  jd-page-body:not(:defined) {
    display: flex;
    flex-direction: column;
  }
  jd-grid-layout:not(:defined) {
    display: grid;
  }

  /* B2 layout */
  jd-container:not(:defined),
  jd-spacer:not(:defined),
  jd-aspect-ratio-box:not(:defined) {
    display: block;
  }
  jd-wrap:not(:defined),
  jd-app-shell:not(:defined) {
    display: flex;
  }
  jd-stack:not(:defined) {
    display: flex;
    flex-direction: column;
  }
  jd-grid:not(:defined),
  jd-simple-grid:not(:defined) {
    display: grid;
  }
  jd-show:not(:defined),
  jd-hide:not(:defined) {
    display: contents;
  }
  jd-overlay:not(:defined) {
    position: absolute;
    inset: 0;
  }

  /* B3 primitives 폼 코어 */
  jd-icon-button:not(:defined),
  jd-label:not(:defined),
  jd-checkbox:not(:defined),
  jd-toggle:not(:defined),
  jd-switch:not(:defined) {
    display: inline-flex;
  }
  jd-textarea:not(:defined),
  jd-slider:not(:defined),
  jd-range-slider:not(:defined) {
    display: block;
  }
  jd-radio-group:not(:defined) {
    display: flex;
    flex-direction: column;
  }

  /* B4 primitives 표시 */
  jd-badge:not(:defined),
  jd-tag:not(:defined),
  jd-avatar:not(:defined),
  jd-spinner:not(:defined),
  jd-kbd:not(:defined),
  jd-key-cap:not(:defined),
  jd-status-dot:not(:defined),
  jd-battery-indicator:not(:defined),
  jd-severity-badge:not(:defined) {
    display: inline-flex;
  }

  /* composites 선택 입력 1 — 팝업은 JS가 만들므로 업그레이드 전에는 새어 나올 것이
     없다. 호스트 display만 선지정해 골격 도착 시 자리 이동(레이아웃 시프트)을 막는다.
     select는 v2 w-fit 기본이라 inline-flex, 나머지 입력형은 폭 100% flex다. */
  jd-select:not(:defined),
  jd-segmented-control:not(:defined) {
    display: inline-flex;
  }
  jd-multi-select:not(:defined),
  jd-combobox:not(:defined),
  jd-auto-complete:not(:defined) {
    display: flex;
    flex-direction: column;
  }
  jd-tag-input:not(:defined) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }
  jd-transfer:not(:defined) {
    display: flex;
    align-items: center;
  }

  /* composites 날짜·시간 1 — 픽커 필드는 트리거 하나만 보이므로 inline-flex,
     격자 픽커는 카드라 inline-block. 업그레이드 전 패널이 새어 나오지 않게
     내부 골격이 아직 없다는 점에 기대지 않고 호스트 display만 선지정한다. */
  jd-date-range-picker:not(:defined),
  jd-time-picker:not(:defined),
  jd-countdown:not(:defined) {
    display: inline-flex;
  }
  jd-month-picker:not(:defined),
  jd-year-picker:not(:defined) {
    display: inline-block;
  }
  jd-date-input:not(:defined),
  jd-date-range-filter:not(:defined) {
    display: flex;
    flex-direction: column;
  }

  /* composites 오버레이·플로팅 2 — 화면에 떠 있는 것들은 업그레이드 전에 **문서 흐름
     안에 잠깐 나타났다가 튀어 오르는** 것이 가장 큰 번쩍임이다. 최종 좌표는 JS가
     쓰는 --jd-affix-* 에 달려 있으므로 여기서는 흐름에서 빼는 것까지만 선지정한다. */
  jd-affix:not(:defined) {
    display: block;
    position: fixed;
    bottom: 20px;
    right: 20px;
  }
  jd-sticky:not(:defined) {
    display: block;
    position: sticky;
    top: 0;
  }
  jd-floating-action-button:not(:defined) {
    display: flex;
    flex-direction: column-reverse;
    position: fixed;
    bottom: 1.5rem;
    right: 1.5rem;
  }
  jd-dock:not(:defined) {
    display: inline-flex;
    align-items: flex-end;
  }
  jd-dock-item:not(:defined) {
    display: block;
  }
  /* 덮개는 JS가 만든다 — 업그레이드 전에는 본문만 보이면 되므로 display만 준다 */
  jd-loading-overlay:not(:defined) {
    display: block;
    position: relative;
  }

  /* composites 내비게이션 1 — 항목이 전부 데이터(프로퍼티·JSON 슬롯)라 업그레이드
     전에는 내용이 아예 없다. 번쩍임이 아니라 **골격이 도착하는 순간의 자리 이동**이
     문제이므로 호스트 display(+주축 정렬)만 선지정한다. */
  jd-breadcrumb:not(:defined),
  jd-stepper:not(:defined),
  jd-tree-view:not(:defined),
  jd-tree-nav:not(:defined) {
    display: block;
  }
  jd-tabs:not(:defined) {
    display: flex;
    align-items: flex-end;
  }
  jd-pagination:not(:defined) {
    display: flex;
    align-items: center;
  }
  jd-navigation-menu:not(:defined) {
    display: inline-flex;
  }

  /* composites 상태 표시 2 — 전부 표시 전용이라 번쩍일 내용이 없고, 업그레이드 순간의
     자리 이동만 막으면 된다. 카드형(Stat/Metric/Trust)은 블록, 뱃지·인디케이터는
     인라인이 최종 형태다. */
  jd-stat-card:not(:defined),
  jd-metric-card:not(:defined),
  jd-trust-indicator:not(:defined) {
    display: block;
  }
  jd-stat:not(:defined) {
    display: flex;
    flex-direction: column;
  }
  jd-security-badge:not(:defined),
  jd-thinking-indicator:not(:defined),
  jd-online-status:not(:defined) {
    display: inline-flex;
    align-items: center;
  }
}


  @layer junds.base {
    jd-accordion:not(:defined) {
      display: block;
    }
    jd-accordion:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-accordion {
      display: block;
      box-sizing: border-box;
      overflow: hidden;
      /* 면 없이 선만 있으면 열린 행이 위아래 구분선 + 컨테이너 좌우선에 둘러싸여
       **별도의 상자**로 읽힌다(실측: 테두리 이중). 카드 면과 위에서 받는 빛을 줘서
       컨테이너 전체가 하나의 표면이 되게 한다 — 행은 그 표면의 구획일 뿐이다.
       hover의 card-hover도 배경이 있어야 실제로 보인다(투명 위에서는 페이지
       배경과 구분되지 않았다). */
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-xs);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    /* v2 divide-y — 첫 행 위에는 선이 없다 */
    jd-accordion > jd-disclosure + jd-disclosure {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    jd-accordion .jd-accordion__trigger {
      padding: var(--jd-space-3) var(--jd-space-4);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-accordion .jd-accordion__trigger:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
    }
    /* 행은 폭 전체를 차지하므로 scale로 줄이면 컨테이너에서 떨어져 보인다 —
     눌린 면이 빛을 잃는 신호(inset shade)만 남긴다 (button link variant 선례). */
    jd-accordion .jd-accordion__trigger:active:not(:disabled) {
      background: var(--jd-color-border-light);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 링을 행 **안쪽**에 그린다: 바깥으로 나가면 컨테이너의 overflow:hidden에 좌우가
     잘리고 남은 위아래 선이 '테두리 한 겹'으로 읽힌다. */
    jd-accordion .jd-accordion__trigger:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(var(--jd-focus-ring-offset) * -1);
      box-shadow: none;
    }

    jd-accordion .jd-accordion__icon {
      display: inline-flex;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }
    jd-accordion .jd-accordion__icon[hidden] {
      display: none;
    }
    jd-accordion .jd-accordion__icon > svg {
      width: 1em;
      height: 1em;
    }

    jd-accordion .jd-accordion__title {
      flex: 1 1 auto;
      min-width: 0;
    }

    /* justify-between의 자리 — 아이콘·제목은 왼쪽, 셰브런은 오른쪽 */
    jd-accordion .jd-accordion__chevron {
      display: inline-flex;
      flex-shrink: 0;
      margin-inline-start: auto;
      color: var(--jd-color-muted);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-accordion .jd-accordion__chevron > svg {
      width: 1rem;
      height: 1rem;
    }
    jd-accordion .jd-accordion__trigger[data-state="open"] > .jd-accordion__chevron {
      transform: rotate(180deg);
    }

    jd-accordion .jd-accordion__content {
      padding: 0 var(--jd-space-4) var(--jd-space-3);
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-relaxed);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-accordion .jd-accordion__trigger,
      jd-accordion .jd-accordion__chevron {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-action-bar {
      display: none;
    }
    jd-action-bar[open] {
      position: fixed;
      z-index: var(--jd-z-toast);
      box-sizing: border-box;
      inset-block-end: var(--jd-space-6);
      inset-inline-start: 50%;
      transform: translateX(-50%);
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-3);
      max-width: calc(100vw - 2rem);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: #ffffff;
      background: var(--jd-color-foreground);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-2xl);
      animation: jd-action-bar-in var(--jd-duration-normal) var(--jd-easing-ease-out);
    }

    .jd-action-bar__count {
      font-weight: var(--jd-weight-medium);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-action-bar__divider {
      flex-shrink: 0;
      width: 1px;
      height: 1.25rem;
      background: rgba(255, 255, 255, 0.2);
    }
    .jd-action-bar__divider[hidden] {
      display: none;
    }
    .jd-action-bar__actions {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-action-bar__clear {
      border: 0;
      background: none;
      cursor: pointer;
      padding: 0;
      font-family: inherit;
      font-size: var(--jd-text-xs);
      color: rgba(255, 255, 255, 0.7);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-action-bar__clear:hover {
      color: #ffffff;
    }
    .jd-action-bar__clear:focus-visible {
      outline: none;
      color: #ffffff;
      box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5);
      border-radius: var(--jd-radius-sm);
    }
    .jd-action-bar__clear[hidden] {
      display: none;
    }

    @keyframes jd-action-bar-in {
      from {
        opacity: 0;
        transform: translate(-50%, 1rem);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-action-bar[open] {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-action-sheet {
      display: none;
    }
    jd-action-sheet[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: flex-end;
      justify-content: center;
      padding: var(--jd-space-4);
    }

    jd-action-sheet .jd-modal__panel {
      max-width: min(32rem, 100%);
      background: none;
      box-shadow: none;
      gap: var(--jd-space-2);
      overflow: visible;
      animation: jd-action-sheet-in var(--jd-duration-normal) cubic-bezier(0.16, 1, 0.3, 1);
    }
    @keyframes jd-action-sheet-in {
      from {
        transform: translateY(1rem);
        opacity: 0;
      }
    }

    .jd-action-sheet__title {
      margin: 0;
      padding: var(--jd-space-3) var(--jd-space-4);
      text-align: center;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-2xl) var(--jd-radius-2xl) 0 0;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-action-sheet__title[hidden] {
      display: none;
    }
    /* 제목이 없으면 목록이 위 모서리를 둥글게 받는다 */
    .jd-action-sheet__title[hidden] + .jd-action-sheet__list {
      border-start-start-radius: var(--jd-radius-2xl);
      border-start-end-radius: var(--jd-radius-2xl);
    }

    .jd-action-sheet__list {
      display: flex;
      flex-direction: column;
      overflow: hidden;
      background: var(--jd-color-card);
      border-end-start-radius: var(--jd-radius-2xl);
      border-end-end-radius: var(--jd-radius-2xl);
    }

    .jd-action-sheet__item,
    .jd-action-sheet__cancel {
      width: 100%;
      padding: var(--jd-space-3-5) var(--jd-space-4);
      border: 0;
      background: var(--jd-color-card);
      cursor: pointer;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      text-align: center;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-action-sheet__item {
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-action-sheet__item:last-child {
      border-block-end: 0;
    }
    .jd-action-sheet__item[data-danger] {
      color: var(--jd-color-danger);
    }
    .jd-action-sheet__item:hover:not(:disabled),
    .jd-action-sheet__cancel:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-action-sheet__item:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-action-sheet__item:focus-visible,
    .jd-action-sheet__cancel:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-action-sheet__cancel {
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-semibold);
      border-radius: var(--jd-radius-2xl);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-action-sheet .jd-modal__panel {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-address-input {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    jd-address-input[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-address-input__row {
      display: flex;
      gap: var(--jd-space-2);
    }

    .jd-address-input__field {
      box-sizing: border-box;
      margin: 0;
      width: 100%;
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-address-input__field::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-address-input__field:disabled {
      cursor: not-allowed;
    }
    .jd-address-input__field:read-only {
      cursor: default;
    }

    .jd-address-input__zonecode {
      width: 7rem;
      flex: 0 0 auto;
      font-variant-numeric: tabular-nums;
    }

    /* 유일하게 편집 가능한 칸 — 카드 배경 + 포커스 글로우 */
    .jd-address-input__detail {
      background: var(--jd-color-card);
    }
    .jd-address-input__detail:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-address-input__search {
      flex: 0 0 auto;
      margin: 0;
      border: 0;
      height: 2.25rem;
      padding-inline: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: #fff;
      background: var(--jd-color-primary);
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-address-input__search:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    .jd-address-input__search:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-address-input__search:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-address-input__field,
      .jd-address-input__search {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-affix {
      /* block이면 자식 둘이 서로 달라붙어 한 덩어리로 읽힌다 — 떠 있는 상자는 서로
       떨어져 있어야 각각으로 보인다. 자식이 하나면 세로 스택은 block과 같다. */
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      /* 고정 상자는 shrink-to-fit이라 내용이 넓으면 화면 밖으로 자란다 — 컨테이닝
       블록(뷰포트 또는 contain 조상) 폭을 넘지 않게 상한을 둔다(§6). */
      max-width: 100%;
      min-width: 0;
      position: fixed;
      z-index: var(--jd-affix-z, var(--jd-z-overlay));
      top: var(--jd-affix-top, auto);
      bottom: var(--jd-affix-bottom, 20px);
      left: var(--jd-affix-left, auto);
      right: var(--jd-affix-right, 20px);
    }
  }

  @layer junds.components {
    jd-alert {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--_jd-alert-color) 20%, transparent);
      border-inline-start: var(--jd-border-thick) solid var(--_jd-alert-color);
      border-radius: var(--jd-radius-lg);
      background: color-mix(in srgb, var(--_jd-alert-color) 5%, transparent);
      --_jd-alert-color: var(--jd-color-primary); /* variant 기본 info */
    }
    jd-alert[hidden] {
      display: none;
    }
    jd-alert[variant="success"] {
      --_jd-alert-color: var(--jd-color-success);
    }
    jd-alert[variant="warning"] {
      --_jd-alert-color: var(--jd-color-warning);
    }
    jd-alert[variant="danger"] {
      --_jd-alert-color: var(--jd-color-danger);
    }

    .jd-alert__icon {
      display: flex;
      flex-shrink: 0;
      margin-block-start: var(--jd-space-px);
      color: var(--_jd-alert-color);
    }
    .jd-alert__body {
      flex: 1;
      min-width: 0;
    }
    .jd-alert__title {
      margin: 0 0 var(--jd-space-1);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      /* 제목도 텍스트라 원색 대신 혼합값(AA) */
      color: color-mix(in srgb, var(--_jd-alert-color) 65%, var(--jd-color-foreground));
    }
    .jd-alert__title[hidden] {
      display: none;
    }
    .jd-alert__content {
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
    }

    .jd-alert__close {
      display: flex;
      flex-shrink: 0;
      padding: var(--jd-space-1);
      border: 0;
      background: none;
      cursor: pointer;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-alert__close:hover {
      color: var(--jd-color-foreground);
    }
    .jd-alert__close[hidden] {
      display: none;
    }
    .jd-alert__close:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-alert__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-alert-button {
      display: inline-flex;
    }
    button.jd-alert-button {
      position: relative;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      height: 2.25rem;
      padding: 0 var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-bold);
      font-size: 12px;
      line-height: 1;
      white-space: nowrap;
      cursor: pointer;
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-default),
        color var(--jd-duration-fast) var(--jd-easing-default),
        border-color var(--jd-duration-fast) var(--jd-easing-default);
    }
    button.jd-alert-button[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 12%, transparent);
      color: var(--jd-color-primary-ink);
      border-color: var(--jd-color-primary);
    }
    button.jd-alert-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    button.jd-alert-button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-alert-button__bell {
      font-size: 13px;
      line-height: 1;
    }

    /* Badge size=sm variant=danger 동형 — 틴트 red pill */
    .jd-alert-button__count {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      background: color-mix(in srgb, var(--jd-color-danger) 10%, transparent);
      color: color-mix(
        in srgb,
        var(--jd-color-danger) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
      box-shadow: 0 0 0 1px inset color-mix(in srgb, var(--jd-color-danger) 15%, transparent);
    }
    .jd-alert-button__count[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-alert-dialog {
      display: none;
    }
    jd-alert-dialog[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-4);
    }

    jd-alert-dialog .jd-modal__panel {
      max-width: min(26rem, calc(100vw - 2rem));
      padding: var(--jd-space-6);
      gap: var(--jd-space-2);
    }

    .jd-alert-dialog__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-alert-dialog__title[hidden] {
      display: none;
    }
    .jd-alert-dialog__desc {
      margin: 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-alert-dialog__desc[hidden] {
      display: none;
    }

    .jd-alert-dialog__actions {
      display: flex;
      justify-content: flex-end;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-4);
    }

    .jd-alert-dialog__cancel,
    .jd-alert-dialog__confirm {
      padding: var(--jd-space-2) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-alert-dialog__cancel {
      color: var(--jd-color-foreground);
      background: transparent;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-alert-dialog__cancel:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-alert-dialog__cancel[hidden] {
      display: none;
    }
    .jd-alert-dialog__confirm {
      color: #ffffff;
      background: var(--jd-color-primary);
      border: 0;
    }
    .jd-alert-dialog__confirm:hover {
      background: var(--jd-color-primary-hover);
    }
    jd-alert-dialog[danger] .jd-alert-dialog__confirm {
      background: var(--jd-color-danger);
    }
    jd-alert-dialog[danger] .jd-alert-dialog__confirm:hover {
      background: var(--jd-color-danger-hover);
    }
    .jd-alert-dialog__cancel:focus-visible,
    .jd-alert-dialog__confirm:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-alert-dialog__cancel,
      .jd-alert-dialog__confirm {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-alert-header-button {
      display: inline-flex;
      flex-shrink: 0;
    }
    a.jd-alert-header-button {
      position: relative;
      display: grid;
      place-items: center;
      box-sizing: border-box;
      width: 2.25rem;
      height: 2.25rem;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-xs);
      text-decoration: none;
      flex-shrink: 0;
      -webkit-tap-highlight-color: transparent;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    a.jd-alert-header-button:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    a.jd-alert-header-button:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    a.jd-alert-header-button:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-alert-header-button__icon {
      display: block;
    }

    .jd-alert-header-button__badge {
      position: absolute;
      top: 0.125rem;
      right: 0.125rem;
      /* content-box면 링 2px이 밖으로 더해져 36px 버튼 밖으로 나간다 */
      box-sizing: border-box;
      min-width: 1.125rem;
      height: 1.125rem;
      padding-inline: var(--jd-space-1);
      display: grid;
      place-items: center;
      border-radius: var(--jd-radius-full);
      background: var(--jd-finance-up, var(--jd-color-success));
      color: #fff;
      border: var(--jd-border-medium) solid var(--jd-color-card);
      /* v2의 9.5px는 읽기 하한(11px) 아래다 — 배지를 키워 글자를 지킨다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-none);
      font-variant-numeric: tabular-nums;
    }
    .jd-alert-header-button__badge[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      a.jd-alert-header-button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-alert-manager {
      display: none;
    }
  }

  @layer junds.components {
    .jd-alert-sheet__body {
      padding: var(--jd-space-1) var(--jd-space-4) var(--jd-space-5);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-alert-sheet__field-label {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
    }
    .jd-alert-sheet__name {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-xl);
      font-weight: 800;
      line-height: var(--jd-leading-tight);
    }
    .jd-alert-sheet__price {
      margin-top: var(--jd-space-1);
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-2);
      font-size: 12.5px;
    }
    .jd-alert-sheet__price-label {
      color: var(--jd-color-muted);
    }
    .jd-alert-sheet__price-value {
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }

    .jd-alert-sheet__group {
      margin-top: var(--jd-space-4);
    }
    .jd-alert-sheet__group-label {
      display: block;
      margin: 0 0 var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }

    /* ── SegmentedPill ── */
    .jd-alert-sheet__segmented {
      display: flex;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      border-radius: var(--jd-radius-full);
    }
    .jd-alert-sheet__seg {
      flex: 1 1 0;
      height: 2.25rem;
      border-radius: var(--jd-radius-full);
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      background: transparent;
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-default),
        color var(--jd-duration-fast) var(--jd-easing-default),
        box-shadow var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-alert-sheet__seg[data-selected] {
      background: var(--jd-color-card);
      color: var(--jd-color-primary-ink);
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-alert-sheet__seg:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 목표가 입력 ── */
    .jd-alert-sheet__input {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      height: 3rem;
      padding: 0 var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-default),
        box-shadow var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-alert-sheet__input:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-alert-sheet__won {
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
    }
    .jd-alert-sheet__field {
      flex: 1 1 auto;
      min-width: 0;
      border: 0;
      background: transparent;
      outline: none;
      font-family: inherit;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-alert-sheet__delta {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    .jd-alert-sheet__quick {
      margin-top: var(--jd-space-2);
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
    }
    .jd-alert-sheet__quick-pill {
      padding: 3px var(--jd-space-2-5);
      border-radius: var(--jd-radius-full);
      font-family: inherit;
      font-size: 11px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      cursor: pointer;
    }
    .jd-alert-sheet__quick-pill:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
    }
    .jd-alert-sheet__quick-pill:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 액션 ── */
    .jd-alert-sheet__actions {
      margin-top: var(--jd-space-5);
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: var(--jd-space-2);
    }
    .jd-alert-sheet__cancel,
    .jd-alert-sheet__submit {
      height: 3rem;
      border-radius: var(--jd-radius-lg);
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-default),
        opacity var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-alert-sheet__cancel {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      color: var(--jd-color-foreground);
      border: 0;
    }
    .jd-alert-sheet__cancel:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
    }
    .jd-alert-sheet__submit {
      background: var(--jd-color-primary);
      color: #fff;
      border: 0;
    }
    .jd-alert-sheet__submit:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    .jd-alert-sheet__submit:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-alert-sheet__cancel:focus-visible,
    .jd-alert-sheet__submit:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
  }

  @layer junds.components {
    jd-animated-counter {
      display: inline;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }

    /* 시각 표시부 — aria-hidden. 숫자 덩어리는 줄바꿈으로 쪼개지지 않는다 */
    .jd-animated-counter__value {
      white-space: nowrap;
    }

    .jd-animated-counter__char {
      display: inline-block;
      transition: transform var(--jd-duration-slow) var(--jd-easing-ease-out);
    }

    /*
   * 낭독 전용 텍스트. display:none·hidden은 접근성 트리에서도 지우므로 쓰지 않는다
   * (jd-visually-hidden과 같은 clip 관용구). user-select:none이라 화면 복사에는
   * 눈에 보이는 숫자만 담기고 이 사본은 딸려오지 않는다.
   */
    .jd-animated-counter__text {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
      -webkit-user-select: none;
      user-select: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-animated-counter__char {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-annotation-note {
      display: block;
      --_jd-an-hue: var(--jd-color-hue-amber); /* yellow 기본 */
    }
    jd-annotation-note[color="green"] {
      --_jd-an-hue: var(--jd-color-hue-green);
    }
    jd-annotation-note[color="blue"] {
      --_jd-an-hue: var(--jd-color-hue-blue);
    }
    jd-annotation-note[color="pink"] {
      --_jd-an-hue: var(--jd-color-hue-pink);
    }
    jd-annotation-note[color="orange"] {
      --_jd-an-hue: var(--jd-color-hue-orange);
    }

    .jd-annotation-note {
      box-sizing: border-box; /* DEC-014-9 — padding + border를 자기 폭 안에 */
      --_jd-an-face: color-mix(in srgb, var(--_jd-an-hue) var(--jd-tone-lift), #ffffff);
      padding: var(--jd-space-3);
      border-inline-start: var(--jd-border-heavy) solid var(--_jd-an-face);
      /* 나머지 세 변은 실선 없이 끝나 틴트 슬래브로 읽혔다 — 같은 색에서 뽑은 실낱
       테두리가 면의 경계를 만든다(§2 채움만 있는 면은 색종이로 읽힌다). */
      border-block: var(--jd-border-thin) solid
        color-mix(in srgb, var(--_jd-an-face) var(--jd-tone-border-mix), transparent);
      border-inline-end: var(--jd-border-thin) solid
        color-mix(in srgb, var(--_jd-an-face) var(--jd-tone-border-mix), transparent);
      border-start-end-radius: var(--jd-radius-md);
      border-end-end-radius: var(--jd-radius-md);
      background: color-mix(in srgb, var(--_jd-an-face) var(--jd-tone-bg-mix), transparent);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
    }

    /* 따옴표는 본문 텍스트가 아니라 표기다 — 글리프는 v2와 같은 " */
    .jd-annotation-note__quote {
      margin: 0;
      quotes: '"' '"';
      line-height: var(--jd-leading-relaxed);
    }
    .jd-annotation-note__quote::before {
      content: open-quote;
    }
    .jd-annotation-note__quote::after {
      content: close-quote;
    }

    .jd-annotation-note__note {
      margin: var(--jd-space-2) 0 0;
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }

    .jd-annotation-note__footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-block-start: var(--jd-space-2);
      font-size: var(--jd-text-2xs); /* v2 text-[11px] = 2xs 하한 */
      color: var(--jd-color-muted);
    }
    .jd-annotation-note__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-annotation-note__note[hidden],
    .jd-annotation-note__footer[hidden],
    .jd-annotation-note__page[hidden],
    .jd-annotation-note__date[hidden] {
      display: none;
    }

    .jd-annotation-note__delete {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      border: 0;
      background: transparent;
      color: inherit;
      cursor: pointer;
      opacity: var(--jd-opacity-50);
      border-radius: var(--jd-radius-sm);
      transition: opacity var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-annotation-note__delete:hover {
      opacity: var(--jd-opacity-100);
      color: var(--jd-color-danger);
      background: color-mix(in srgb, var(--jd-color-danger) 10%, transparent);
    }
    .jd-annotation-note__delete:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-danger) 16%, transparent);
    }
    .jd-annotation-note__delete:focus-visible {
      opacity: var(--jd-opacity-100);
      outline: var(--jd-focus-ring-danger);
      outline-offset: var(--jd-focus-ring-offset);
    }

    jd-annotation-note[clickable] > .jd-annotation-note {
      cursor: pointer;
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-annotation-note[clickable] > .jd-annotation-note:hover {
      box-shadow: var(--jd-shadow-sm);
      border-color: color-mix(in srgb, var(--_jd-an-face) 52%, transparent);
      border-inline-start-color: var(--_jd-an-face);
    }
    /* 눌린 카드는 떠 있지 않다 — 그림자를 거두고 안으로 눌린다 */
    jd-annotation-note[clickable] > .jd-annotation-note:active {
      scale: 0.99;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-annotation-note[clickable] > .jd-annotation-note:focus-visible {
      /* 카드가 overflow 안에 들어가도 링이 잘리지 않게 outline 대신 box-shadow */
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring); /* StatCard와 같은 카드 포커스 링 */
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-annotation-note__delete,
      jd-annotation-note[clickable] > .jd-annotation-note {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-announcement-bar {
      display: flex;
      align-items: center;
      justify-content: center;
      /* 아이콘은 본문에 속하므로 12px로 붙여 두고, 본문과 CTA 사이만 벌린다
       (아래 __cta margin) — 균일 gap을 키우면 아이콘까지 문장에서 떨어져 나간다. */
      gap: var(--jd-space-3);
      box-sizing: border-box;
      /* 세로 여백은 **한 줄 기준이 아니라 접힌 두 줄 기준**이다. 좁은 폭에서
       본문이 접히면 위아래가 압착돼 띠가 글자에 끼인 것처럼 보였다(§9 —
       폭이 좁다고 글자를 줄이지 말고 줄 수를 늘린다). */
      padding: var(--jd-space-3) var(--jd-space-5);
      min-height: 2.75rem;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
      color: #ffffff;
      background: color-mix(in srgb, var(--_jd-ann-color) 80%, var(--jd-color-foreground));
      --_jd-ann-color: var(--jd-color-primary); /* variant 기본 primary */
    }
    jd-announcement-bar[hidden] {
      display: none;
    }

    /* 반전 톤 — 배경/전경을 통째로 맞바꾼다(색 혼합 대상이 없다) */
    jd-announcement-bar[variant="neutral"] {
      color: var(--jd-color-background);
      background: var(--jd-color-foreground);
    }
    jd-announcement-bar[variant="success"] {
      --_jd-ann-color: var(--jd-color-success);
    }
    jd-announcement-bar[variant="warning"] {
      --_jd-ann-color: var(--jd-color-warning);
    }
    jd-announcement-bar[variant="danger"] {
      --_jd-ann-color: var(--jd-color-danger);
    }

    /* v2 JSDoc이 약속했던 sticky를 opt-in으로 실제 제공 */
    jd-announcement-bar[sticky] {
      position: sticky;
      top: 0;
      z-index: var(--jd-z-sticky);
    }

    /* 본문이 길어도 아이콘·CTA·닫기를 밀어내지 않게 — flex item 기본 min-width:auto 해제.
     두 줄로 접힐 때는 한 줄에 한 단어만 남는 사다리꼴이 되지 않게 폭을 고르게 나눈다. */
    jd-announcement-bar > .jd-banner__content {
      min-width: 0;
      text-wrap: balance;
    }

    .jd-announcement-bar__icon {
      display: flex;
      flex-shrink: 0;
    }
    .jd-announcement-bar__icon[hidden] {
      display: none;
    }

    /* 밑줄 친 맨 텍스트는 본문과 같은 줄에 붙으면 문장의 일부로 읽힌다(§7). 눌리는
     면(알약)을 줘서 본문에서 떼어 내고, 라벨은 절대 접히지 않는다(§5). */
    .jd-announcement-bar__cta {
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      margin-inline-start: var(--jd-space-2);
      padding: var(--jd-space-1) var(--jd-space-3);
      border: 0;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, currentColor 16%, transparent);
      font: inherit;
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      color: inherit;
      cursor: pointer;
      text-decoration: none;
      /* opacity가 아니라 실색 전환 — 투명도는 글자까지 함께 흐려 배경에 녹는다(§1) */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-announcement-bar__cta:hover {
      background: color-mix(in srgb, currentColor 28%, transparent);
    }
    .jd-announcement-bar__cta:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-announcement-bar__cta[hidden] {
      display: none;
    }
    .jd-announcement-bar__cta:focus-visible {
      outline: var(--jd-border-medium) solid currentColor;
      outline-offset: 2px;
    }

    /* 상속받은 닫기 버튼은 흰 글자 전제(hover rgb(255 255 255/.2), outline #fff)라
     neutral 톤·다크 테마에서 보이지 않는다 — currentColor 기준으로 되돌린다.
     특이도 (0,2,1) > jd-banner의 (0,2,0)이므로 같은 레이어에서 이긴다. */
    jd-announcement-bar .jd-banner__close:hover {
      background: color-mix(in srgb, currentColor 20%, transparent);
    }
    jd-announcement-bar .jd-banner__close:focus-visible {
      outline-color: currentColor;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-announcement-bar__cta {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-announcer {
      display: contents;
    }
    .jd-announcer__region {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-app-header {
      display: block;
    }
    header.jd-app-header {
      padding: var(--jd-space-3) var(--jd-space-4) var(--jd-space-2);
      background: color-mix(in srgb, var(--jd-color-background) 90%, transparent);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
    }
    jd-app-header:not([static]) header.jd-app-header {
      position: sticky;
      top: 0;
      z-index: var(--jd-z-sticky);
    }

    .jd-app-header__bar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-app-header__brand {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-app-header__meta {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-app-header__meta[hidden] {
      display: none;
    }
    .jd-app-header__actions {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
    }

    .jd-app-header__search {
      margin-top: var(--jd-space-3);
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-app-header__search[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-app-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      line-height: 0;
      vertical-align: middle;
      color: inherit;
    }
    /* 좁은 행(칩·배지 안)에서 플렉스 자식으로 눌려 찌그러지지 않게 — SVG는 width/height
     속성이 말하는 크기 그대로 있어야 한다 */
    jd-app-icon > svg.jd-app-icon {
      display: block;
      flex: none;
    }
    /* 이름이 비었거나 레지스트리에 없으면 svg 내용이 통째로 비어(update의 innerHTML="")
     자리만 차지한 투명 구멍이 남는다 — 빠진 글리프는 보이지 않는 실패다. 점선 자리로
     드러내 이름 오타가 화면에서 잡히게 한다. */
    jd-app-icon > svg.jd-app-icon:empty {
      box-sizing: border-box;
      border: var(--jd-border-thin) dashed color-mix(in srgb, currentColor 35%, transparent);
      border-radius: var(--jd-radius-sm);
    }
  }

  @layer junds.components {
    jd-app-shell {
      display: flex;
      height: 100vh;
      overflow: hidden;
      background: var(--jd-color-background);
    }

    .jd-app-shell__sidebar {
      flex-shrink: 0;
      box-sizing: border-box; /* DEC-014-9 */
      overflow: auto;
      width: var(--_jd-shell-rail, 260px);
      background: var(--jd-color-card);
      border-right: 1px solid var(--jd-color-border);
      transition: width 300ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    /* 모바일: 레일 → 고정 드로어 (닫힘 = 미표시, v2 조건부 렌더 동형) */
    jd-app-shell[data-mobile] .jd-app-shell__sidebar {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      bottom: 0;
      z-index: 1400;
      width: var(--_jd-shell-drawer, 260px);
      box-shadow: 0 20px 25px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04);
      transition: none;
    }
    jd-app-shell[data-mobile][mobile-open] .jd-app-shell__sidebar {
      display: block;
    }

    .jd-app-shell__backdrop {
      display: none;
    }
    jd-app-shell[data-mobile][mobile-open] .jd-app-shell__backdrop {
      display: block;
      position: fixed;
      inset: 0;
      z-index: 1300;
      background: #000000;
      opacity: 0.3;
    }

    .jd-app-shell__main {
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      min-width: 0;
    }

    .jd-app-shell__header {
      flex-shrink: 0;
      position: relative;
      background: var(--jd-color-card);
      border-bottom: 1px solid var(--jd-color-border);
    }
    jd-app-shell[sticky-header] .jd-app-shell__header {
      position: sticky;
      top: 0;
      z-index: 1100;
    }

    .jd-app-shell__menu {
      display: none;
      position: absolute;
      left: var(--jd-space-3);
      top: 50%;
      translate: 0 -50%;
      z-index: 10;
      padding: var(--jd-space-2);
      border: 0;
      background: transparent;
      color: var(--jd-color-muted);
      cursor: pointer;
    }
    .jd-app-shell__menu:hover {
      color: var(--jd-color-foreground);
    }
    .jd-app-shell__menu:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    jd-app-shell[data-mobile] .jd-app-shell__menu {
      display: block;
    }

    .jd-app-shell__content {
      flex-grow: 1;
      overflow: auto;
    }
    /* tabindex=0 스크롤러(DEC-027) — 키보드 포커스 안쪽 링 */
    .jd-app-shell__content:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: -2px;
    }

    .jd-app-shell__footer {
      flex-shrink: 0;
      background: var(--jd-color-card);
      border-top: 1px solid var(--jd-color-border);
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-area-chart {
      --jd-chart-fill-opacity: 0.25;
      /* 계열색은 hue 팔레트에서만(§8) — 공용 기본값은 success/warning/danger를 계열색
       으로 써서 "2번 시리즈"와 "성공"이 같은 색이 된다. 계열은 범주일 뿐 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 480px 뷰박스가 카드보다 넓으면 오른쪽 끝 x축 라벨("6월")이 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 비율을
     대신 말하므로 폭만 줄여도 그림이 찌그러지지 않는다. min-width는 플렉스 자식의
     min-width:auto(=내용 폭 480) 바닥을 풀되, 범례 옆에서 한 줄로 뭉개지지 않게
     컨테이너가 더 좁을 때만 양보하도록 잡는다. */
    jd-area-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 15rem);
    }
    jd-area-chart:not(:defined) {
      display: inline-block;
    }
  }

  @layer junds.components {
    /* v2 기본값: ratio=16/9, position relative + overflow hidden */
    jd-aspect-ratio-box {
      display: block;
      position: relative;
      overflow: hidden;
      aspect-ratio: 16 / 9;
    }
  }

  @layer junds.components {
    jd-audio-player {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-3) var(--jd-space-4);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      --_jd-audio-fill: var(--jd-color-primary);
      --_jd-audio-track: var(--jd-color-control-track); /* v2 bg-gray-200 (G2 gray 어휘) */
    }

    /* 오디오 요소 자체는 보이지 않는다 — 컨트롤을 우리가 그린다 */
    jd-audio-player > .jd-audio-player__media {
      display: none;
    }

    .jd-audio-player__controls {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
    }

    .jd-audio-player__toggle {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.25rem;
      height: 2.25rem;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
      color: #fff;
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 채움만 있는 원은 색종이로 읽힌다 — 위에서 받는 빛을 얹는다. jd-video-player는
     같은 클래스를 투명 버튼으로 갈아 끼우므로(video-player.css) 면 처리는 물려주지
     않는다 — :where()로 특이도 0을 유지한 채 호스트만 좁힌다. */
    :where(jd-audio-player) .jd-audio-player__toggle {
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-audio-player__toggle:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-audio-player__toggle:active {
      scale: 0.94;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-audio-player__toggle:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 아이콘 교체는 DOM이 아니라 [data-playing] 훅 — JS가 노드를 붙였다 뗐다 하지 않는다 */
    .jd-audio-player__icon {
      display: block;
    }
    .jd-audio-player__icon--pause {
      display: none;
    }
    jd-audio-player[data-playing] .jd-audio-player__icon--play {
      display: none;
    }
    jd-audio-player[data-playing] .jd-audio-player__icon--pause {
      display: block;
    }

    .jd-audio-player__body {
      flex: 1;
      min-width: 0;
    }

    .jd-audio-player__title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-audio-player__title[hidden] {
      display: none;
    }

    .jd-audio-player__transport {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    /* 10px는 토큰 하한(11px) 아래였다 — 좁다고 글자를 줄이지 않는다(§9) */
    .jd-audio-player__time {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    /* 시크바 — 네이티브 range 재도색(jd-slider와 같은 크로스 브라우저 레시피) */
    .jd-audio-player__seek {
      appearance: none;
      -webkit-appearance: none;
      flex: 1;
      min-width: 0;
      margin: 0;
      padding: 0;
      height: 1rem; /* 썸 히트 영역 — 트랙은 6px */
      background: transparent;
      cursor: pointer;
    }
    .jd-audio-player__seek:disabled {
      cursor: default;
      opacity: var(--jd-opacity-60);
    }

    /* 홈이 파인 트랙 — 평평한 회색 실선 한 줄은 진행 막대가 아니라 구분선으로 읽힌다 */
    .jd-audio-player__seek::-webkit-slider-runnable-track {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: linear-gradient(
        to right,
        var(--_jd-audio-fill) var(--_jd-audio-pct, 0%),
        var(--_jd-audio-track) var(--_jd-audio-pct, 0%)
      );
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-audio-player__seek::-moz-range-track {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--_jd-audio-track);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-audio-player__seek::-moz-range-progress {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--_jd-audio-fill);
    }

    /* 손잡이는 **항상 보인다**. v2엔 막대만 있었지만, 잡을 것이 없는 막대는 조작
     가능해 보이지 않는다(§7) — 쉼 상태에선 작게, 호버·포커스에서 커진다. */
    .jd-audio-player__seek::-webkit-slider-thumb {
      appearance: none;
      -webkit-appearance: none;
      width: 0.75rem;
      height: 0.75rem;
      margin-top: -3px; /* (12-6)/2 */
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      border: var(--jd-border-medium) solid var(--_jd-audio-fill);
      box-sizing: border-box;
      box-shadow: var(--jd-shadow-knob);
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-audio-player__seek::-moz-range-thumb {
      width: 0.75rem;
      height: 0.75rem;
      box-sizing: border-box;
      border: var(--jd-border-medium) solid var(--_jd-audio-fill);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      box-shadow: var(--jd-shadow-knob);
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-audio-player__seek:hover::-webkit-slider-thumb,
    .jd-audio-player__seek:focus-visible::-webkit-slider-thumb {
      scale: 1.2;
      box-shadow: var(--jd-shadow-knob),
        0 0 0 4px color-mix(in srgb, var(--_jd-audio-fill) 20%, transparent);
    }
    .jd-audio-player__seek:hover::-moz-range-thumb,
    .jd-audio-player__seek:focus-visible::-moz-range-thumb {
      scale: 1.2;
      box-shadow: var(--jd-shadow-knob),
        0 0 0 4px color-mix(in srgb, var(--_jd-audio-fill) 20%, transparent);
    }
    .jd-audio-player__seek:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--_jd-audio-fill) 40%, transparent);
      outline-offset: 2px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-audio-player__toggle {
        transition: none;
      }
      .jd-audio-player__seek::-webkit-slider-thumb {
        transition: none;
      }
      .jd-audio-player__seek::-moz-range-thumb {
        transition: none;
      }
      .jd-audio-player__seek:hover::-webkit-slider-thumb,
      .jd-audio-player__seek:focus-visible::-webkit-slider-thumb {
        scale: 1;
      }
      .jd-audio-player__seek:hover::-moz-range-thumb,
      .jd-audio-player__seek:focus-visible::-moz-range-thumb {
        scale: 1;
      }
    }
  }

  @layer junds.components {
    jd-auth-layout {
      display: grid;
      grid-template-columns: 1fr;
      min-height: 100dvh;
    }

    /* 브랜드 패널 — 기본 숨김. split/branded만 노출 */
    .jd-auth-layout__brand {
      display: none;
    }
    .jd-auth-layout__brand-inner {
      max-width: 28rem;
    }
    .jd-auth-layout__brand-title {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-3xl);
      font-weight: var(--jd-weight-bold);
      margin-block-end: var(--jd-space-3);
    }
    .jd-auth-layout__brand-text {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      /* 브랜드 패널 배경은 항상 primary(#5b4cc7) — v2 text-white/80 승계. #fff on primary = 6.4:1 */
      color: color-mix(in srgb, #fff 80%, transparent);
    }

    .jd-auth-layout__main {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-10) var(--jd-space-4);
      background: var(--jd-color-background);
    }

    .jd-auth-layout__wrap {
      width: 100%;
      max-width: 28rem;
      margin-inline: auto;
    }

    .jd-auth-layout__logo {
      display: flex;
      justify-content: center;
      margin-block-end: var(--jd-space-6);
    }
    .jd-auth-layout__logo[hidden] {
      display: none;
    }

    /* 로그인 카드는 "앱의 본문"이다 — 모드를 따라가야 한다. surface 3단은 라이트에서도
     어두운 크롬이라(DEC-044) 그 위에 foreground 잉크를 얹으면 라이트 모드에서
     검은 글자가 검은 면에 얹혀 폼이 통째로 사라진다. 그래서 배경을 card로 내린다.
     상단 인셋 하이라이트는 '위에서 빛을 받는 면' — 채움만 있는 카드는 색종이로 읽힌다. */
    .jd-auth-layout__card {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-sm), inset 0 1px 0 var(--jd-color-highlight);
      padding: var(--jd-space-6);
    }
    @media (min-width: 40rem) {
      .jd-auth-layout__card {
        padding: var(--jd-space-8);
      }
    }

    .jd-auth-layout__header {
      margin-block-end: var(--jd-space-6);
      text-align: center;
    }
    .jd-auth-layout__header[hidden] {
      display: none;
    }
    .jd-auth-layout__title {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-auth-layout__title[hidden] {
      display: none;
    }
    @media (min-width: 40rem) {
      .jd-auth-layout__title {
        font-size: var(--jd-text-2xl);
      }
    }
    .jd-auth-layout__subtitle {
      margin: var(--jd-space-1) 0 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-auth-layout__subtitle[hidden] {
      display: none;
    }

    .jd-auth-layout__footer {
      margin-block-start: var(--jd-space-6);
      padding-block-start: var(--jd-space-4);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-auth-layout__page-footer {
      margin-block-start: var(--jd-space-6);
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    /* branded — 카드 뒤로 primary 그라디언트 (v2 from-primary to-primary-hover) */
    jd-auth-layout[variant="branded"] .jd-auth-layout__main {
      background: linear-gradient(135deg, var(--jd-color-primary), var(--jd-color-primary-hover));
    }

    /* split — 데스크톱(lg=64rem)에서만 좌측 브랜드 패널 노출 */
    jd-auth-layout[variant="split"] .jd-auth-layout__brand {
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-10);
      /* v2 branded 브랜드 패널 text-white 승계 — #fff on primary(#5b4cc7) = 6.4:1 */
      background: var(--jd-color-primary);
      color: #fff;
    }
    @media (min-width: 64rem) {
      jd-auth-layout[variant="split"] {
        grid-template-columns: 1fr 1fr;
      }
      jd-auth-layout[variant="split"] .jd-auth-layout__brand {
        display: flex;
      }
    }
  }

  @layer junds.components {
    jd-auto-complete {
      position: relative;
      display: flex;
      flex-direction: column;
      width: 100%;
    }
    jd-auto-complete[error] > .jd-combobox__control {
      border-color: var(--jd-color-danger);
    }
    jd-auto-complete[error] > .jd-combobox__control:focus-within {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-auto-complete[disabled] > .jd-combobox__control {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    /* v2 AutoComplete는 활성 행 배경만 있고 hover는 primary/10이었다 */
    jd-auto-complete .jd-combobox__option:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
    }
  }

  @layer junds.components {
    jd-auto-hide-header {
      display: block;
      box-sizing: border-box;
      width: 100%;
      position: sticky;
      inset-block-start: 0;
      z-index: var(--jd-z-header);
      transition: transform var(--jd-duration-slow) var(--jd-easing-ease-in-out);
      /* will-change를 상시로 둔다. transform이 걸린 요소는 position:fixed 자손의
       컨테이닝 블록이 되는데(레포 선례: .container transform → 하단 고정물 밀림),
       [collapsed]일 때만 transform이 생기면 헤더 안의 fixed 드롭다운이 **접힘 여부에
       따라 다른 기준으로 배치된다**. 상시 승격으로 그 분기를 없앤다. */
      will-change: transform;
    }
    jd-auto-hide-header[collapsed] {
      transform: translateY(-100%);
    }

    .jd-auto-hide-header__bar {
      display: block;
      box-sizing: border-box;
      width: 100%;
      height: var(--jd-auto-hide-header-height, 64px);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-auto-hide-header {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-auto-play-demo {
      --jd-auto-play-demo-exit: none; /* fade · crossfade = 불투명도만 */
      position: relative;
      display: grid;
      width: 100%;
      box-sizing: border-box; /* DEC-014-9 — width:100% + padding 병용 대비 */
    }
    jd-auto-play-demo[transition="slide-up"] {
      --jd-auto-play-demo-exit: translateY(0.75rem);
    }
    jd-auto-play-demo[transition="slide-left"] {
      --jd-auto-play-demo-exit: translateX(1rem);
    }
    jd-auto-play-demo[transition="scale"] {
      --jd-auto-play-demo-exit: scale(0.9);
    }

    .jd-auto-play-demo__frame {
      grid-area: 1 / 1; /* 전부 같은 칸 — 상자는 가장 큰 프레임에 맞는다 */
      min-width: 0;
      visibility: hidden;
      pointer-events: none;
      opacity: var(--jd-opacity-0);
      transform: var(--jd-auto-play-demo-exit);
      transition-property: opacity, transform;
      transition-duration: var(--jd-auto-play-demo-duration, 400ms);
      transition-timing-function: var(--jd-easing-spring);
    }

    /* 나가는 프레임은 전이가 끝날 때까지만 보인다 — 그동안 클릭을 먹지 않는다 */
    .jd-auto-play-demo__frame[data-leaving] {
      visibility: visible;
    }

    /* 활성 프레임만 보이고, 만질 수 있다 (포커스가 들어오면 순환이 멈춘다) */
    .jd-auto-play-demo__frame[data-active] {
      visibility: visible;
      pointer-events: auto;
      opacity: var(--jd-opacity-100);
      transform: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-auto-play-demo__frame {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-avatar {
      position: relative;
      display: inline-flex;
      flex-shrink: 0;
      font-family: var(--jd-font-sans);
      /* size 기본 md — 36px */
      --_jd-avatar-size: 2.25rem;
      --_jd-avatar-font: var(--jd-text-md);
      --_jd-avatar-dot: 10px;
      --_jd-avatar-ring: 1.5px;
    }
    jd-avatar[size="xs"] {
      --_jd-avatar-size: 1.5rem;
      /* 2xs(11px)가 하한이다 — 이니셜을 10px로 줄이면 24px 원 안에서 읽히지 않는다 */
      --_jd-avatar-font: var(--jd-text-2xs);
      --_jd-avatar-dot: 6px;
      --_jd-avatar-ring: 1px;
    }
    jd-avatar[size="sm"] {
      --_jd-avatar-size: 2rem;
      --_jd-avatar-font: var(--jd-text-xs);
      --_jd-avatar-dot: 8px;
      --_jd-avatar-ring: 1.5px;
    }
    jd-avatar[size="lg"] {
      --_jd-avatar-size: 2.75rem;
      --_jd-avatar-font: var(--jd-text-lg);
      --_jd-avatar-dot: 12px;
      --_jd-avatar-ring: 2px;
    }
    jd-avatar[size="xl"] {
      --_jd-avatar-size: 3.5rem;
      --_jd-avatar-font: var(--jd-text-xl);
      --_jd-avatar-dot: 14px;
      --_jd-avatar-ring: 2px;
    }

    .jd-avatar__img {
      width: var(--_jd-avatar-size);
      height: var(--_jd-avatar-size);
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      display: block;
      /* 밝은 사진이 흰 카드에 녹지 않게 잉크에서 뽑은 한 겹 — 링이 아니라 경계다 */
      box-shadow: 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-color-foreground) 10%, transparent);
    }
    .jd-avatar__fallback {
      position: relative; /* 실루엣 조각의 기준면 */
      width: var(--_jd-avatar-size);
      height: var(--_jd-avatar-size);
      border-radius: var(--jd-radius-full);
      overflow: hidden; /* 어깨가 원 밖으로 나가지 않는다 */
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: var(--_jd-avatar-font);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      user-select: none;
      /* DEC-044 톤 레시피 — 팔레트 8종은 앵커만 바꾼다(base.css --jd-tone-*).
       채워진 원이라 배경은 한 단 진한 혼합비를 쓴다. */
      --jd-tone: var(--jd-color-hue-gray); /* 무이름 기본 */
      --jd-tone-ink-mix: 68%; /* xs 크기 이니셜까지 AA 대비를 유지 */
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background-color: color-mix(
        in srgb,
        var(--jd-tone-face) var(--jd-tone-bg-strong-mix),
        transparent
      );
      /* 채움만 있는 원은 색종이로 읽힌다(§2) — 위에서 받는 빛 한 겹과 앵커에서 뽑은
       테두리로 면을 세운다. 링은 흰색이 아니라 모드를 따라가는 --jd-color-highlight다. */
      background-image: linear-gradient(180deg, var(--jd-color-highlight), transparent 60%);
      box-shadow: inset 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-tone) 18%, transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }

    /* 이름이 없으면 element.ts가 "?"를 넣는다. 물음표는 "아직 모르는 사람"이 아니라
     "무언가 잘못됐다"로 읽힌다 — 글자를 지우고 은은한 그라데이션 위 사람 실루엣으로
     바꾼다. 실루엣은 DOM이 아니라 두 조각(머리·어깨)이라 접근성 트리에 남지 않는다.
     팔레트 속성이 없다 = 이름이 없다 (element.ts가 이름이 있을 때만 붙인다). */
    .jd-avatar__fallback:not([data-palette]) {
      font-size: 0;
      background-image: linear-gradient(180deg, var(--jd-color-highlight), transparent 60%),
        linear-gradient(
          150deg,
          color-mix(in srgb, var(--jd-color-neutral-400) 34%, transparent),
          color-mix(in srgb, var(--jd-color-neutral-500) 18%, transparent)
        );
    }
    .jd-avatar__fallback:not([data-palette])::before,
    .jd-avatar__fallback:not([data-palette])::after {
      content: "";
      position: absolute;
      background: currentColor;
      opacity: var(--jd-opacity-50);
    }
    .jd-avatar__fallback:not([data-palette])::before {
      /* 머리 */
      inset-block-start: 21%;
      inset-inline-start: 34%;
      width: 32%;
      aspect-ratio: 1;
      border-radius: var(--jd-radius-full);
    }
    .jd-avatar__fallback:not([data-palette])::after {
      /* 어깨 — 아래는 원이 잘라낸다 */
      inset-block-start: 61%;
      inset-inline-start: 21%;
      width: 58%;
      height: 34%;
      border-radius: var(--jd-radius-full) var(--jd-radius-full) 0 0;
    }
    .jd-avatar__fallback[data-palette="0"] {
      --jd-tone: var(--jd-color-hue-violet);
    }
    .jd-avatar__fallback[data-palette="1"] {
      --jd-tone: var(--jd-color-hue-blue);
    }
    .jd-avatar__fallback[data-palette="2"] {
      --jd-tone: var(--jd-color-hue-green);
    }
    .jd-avatar__fallback[data-palette="3"] {
      --jd-tone: var(--jd-color-hue-amber);
    }
    .jd-avatar__fallback[data-palette="4"] {
      --jd-tone: var(--jd-color-hue-rose);
    }
    .jd-avatar__fallback[data-palette="5"] {
      --jd-tone: var(--jd-color-hue-cyan);
    }
    .jd-avatar__fallback[data-palette="6"] {
      --jd-tone: var(--jd-color-hue-purple);
    }
    .jd-avatar__fallback[data-palette="7"] {
      --jd-tone: var(--jd-color-hue-teal);
    }

    .jd-avatar__status {
      position: absolute;
      bottom: 0;
      right: 0;
      width: var(--_jd-avatar-dot);
      height: var(--_jd-avatar-dot);
      border-radius: var(--jd-radius-full);
      /* 링은 아바타에서 점을 떼어 내는 장치라 '흰색'이 아니라 '그 자리의 면'이다 */
      border: var(--_jd-avatar-ring) solid var(--jd-color-card);
      background: var(--jd-color-neutral-400);
    }
    jd-avatar[status="online"] .jd-avatar__status {
      background: var(--jd-color-success);
    }
    jd-avatar[status="away"] .jd-avatar__status {
      background: var(--jd-color-warning);
    }
    jd-avatar[status="busy"] .jd-avatar__status {
      background: var(--jd-color-danger);
    }
  }

  @layer junds.components {
    jd-avatar-stack {
      display: inline-flex;
      align-items: center;
      font-family: var(--jd-font-sans);
      /* size 기본 sm — v2 AvatarStack 기본값 */
      --_jd-stack-size: 2rem;
      --_jd-stack-font: var(--jd-text-2xs);
      --_jd-stack-ring: 2px;
      /* 겹침은 고정 px이 아니라 **지름의 비율**이다. v2의 -space-x-2(8px 고정)는
       xs(24px)에서 지름의 33%를 덮어 두 글자 이니셜의 첫 글자가 링 밑으로 들어갔다.
       링 두께까지 합쳐도 30%를 넘지 않도록 20%로 잡는다. */
      --_jd-stack-overlap: calc(var(--_jd-stack-size) * 0.2);
    }
    jd-avatar-stack[size="xs"] {
      --_jd-stack-size: 1.5rem;
      /* 2xs(11px)가 하한 — "+9"가 읽혀야 한다 */
      --_jd-stack-font: var(--jd-text-2xs);
      --_jd-stack-ring: 1.5px;
    }
    jd-avatar-stack[size="md"] {
      --_jd-stack-size: 2.25rem;
      --_jd-stack-font: var(--jd-text-xs);
    }
    jd-avatar-stack[size="lg"] {
      --_jd-stack-size: 2.75rem;
      --_jd-stack-font: var(--jd-text-md);
      --_jd-stack-ring: 2.5px;
    }
    jd-avatar-stack[size="xl"] {
      --_jd-stack-size: 3.5rem;
      --_jd-stack-font: var(--jd-text-lg);
      --_jd-stack-ring: 3px;
    }

    .jd-avatar-stack__item {
      position: relative;
      display: inline-flex;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      /* ring-2 ring-white — 링은 배경을 잘라내는 표면색이라 토큰.
       그 바깥에 잉크에서 뽑은 머리카락 선을 한 겹 더 둔다: 카드색 링만으로는
       카드 위에 얹혔을 때 앞뒤 아바타의 경계가 사라져 겹친 부분이 한 덩어리로 읽힌다. */
      box-shadow: 0 0 0 var(--_jd-stack-ring) var(--jd-color-card),
        0 0 0 calc(var(--_jd-stack-ring) + var(--jd-border-thin))
          color-mix(in srgb, var(--jd-color-foreground) 10%, transparent);
    }
    /* -space-x-2 — 첫 항목을 뺀 나머지가 앞으로 파고든다. 뒤 항목이 위로 겹친다 */
    .jd-avatar-stack__item + .jd-avatar-stack__item {
      margin-inline-start: calc(var(--_jd-stack-overlap) * -1);
    }

    .jd-avatar-stack__more {
      display: flex;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      width: var(--_jd-stack-size);
      height: var(--_jd-stack-size);
      border-radius: var(--jd-radius-full);
      font-size: var(--_jd-stack-font);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      user-select: none;
      /* 아바타 팔레트와 같은 계약 — DEC-044 톤 레시피 */
      --jd-tone: var(--jd-color-hue-gray);
      /* 11px "+N"이 옆의 이니셜 칩과 같은 무게로 읽히도록 잉크 비율을 아바타와 맞춘다 */
      --jd-tone-ink-mix: 68%;
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background-color: color-mix(
        in srgb,
        var(--jd-tone-face) var(--jd-tone-bg-strong-mix),
        transparent
      );
      /* jd-avatar 이니셜 칩과 같은 면 처리(§2) — 한 줄에 서므로 빛도 같아야 한다 */
      background-image: linear-gradient(180deg, var(--jd-color-highlight), transparent 60%);
      box-shadow: inset 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-tone) 18%, transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }

    /* 이름·"외 N명"은 읽히기만 한다 (jd-trust-indicator __sr 관용구) */
    .jd-avatar-stack__name {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-back-top {
      position: fixed;
      inset-block-end: var(--jd-space-6);
      inset-inline-end: var(--jd-space-6);
      z-index: var(--jd-z-sticky);
    }
    jd-back-top:not([visible]) {
      display: none;
    }

    .jd-back-top__button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 2.5rem;
      height: 2.5rem;
      padding: 0;
      background: var(--jd-color-card);
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      box-shadow: var(--jd-shadow-lg);
      cursor: pointer;
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-back-top__button:hover {
      color: var(--jd-color-primary-ink);
      box-shadow: var(--jd-shadow-xl);
      border-color: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-back-top__button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-lg);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-back-top__button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-backtest-runner {
      /* 등락색은 직접 칠하지 않는다(§8). 앱이 한국 관례(적상승·청하락)로 뒤집을 때
       거치는 정본 훅은 --jd-finance-* 다 — --bm-* 는 v2 앱이 쓰던 이름이라 앞에
       남겨 두되, 그것이 없으면 반드시 정본 훅을 경유해 기본값에 닿는다. 이 사슬을
       건너뛰고 --jd-color-danger를 상승에 박으면 앱의 override가 이 컴포넌트만
       비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--bm-up, var(--jd-finance-up, var(--jd-color-success)));
      --jd-fin-down: var(--bm-down, var(--jd-finance-down, var(--jd-color-danger)));
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: flex;
      flex-direction: column;
      gap: var(--jd-space-5);
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-backtest-runner * {
      box-sizing: border-box;
    }

    jd-backtest-runner .jd-backtest-runner__card {
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
      box-shadow: var(--jd-shadow-sm);
    }
    jd-backtest-runner .jd-backtest-runner__settings {
      padding: var(--jd-space-5);
    }

    /* 설정 헤더 */
    jd-backtest-runner .jd-backtest-runner__settings-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-end: var(--jd-space-3);
    }
    jd-backtest-runner .jd-backtest-runner__spark-icon {
      color: var(--jd-fin-accent);
    }
    jd-backtest-runner .jd-backtest-runner__settings-title {
      font-size: var(--jd-text-sm);
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
    }

    /* 그리드 */
    jd-backtest-runner .jd-backtest-runner__grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--jd-space-3);
    }
    @media (min-width: 768px) {
      jd-backtest-runner .jd-backtest-runner__grid {
        grid-template-columns: repeat(3, 1fr);
      }
    }
    jd-backtest-runner .jd-backtest-runner__field {
      min-width: 0;
    }
    jd-backtest-runner .jd-backtest-runner__symbol-field {
      position: relative;
    }
    jd-backtest-runner .jd-backtest-runner__label {
      display: block;
      margin-block-end: var(--jd-space-1-5);
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__control {
      width: 100%;
      min-width: 0; /* 긴 거장 이름이 1/3 칸을 밀어내지 않게(§5) */
      height: 40px;
      padding: 0 var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      font: inherit;
      font-size: var(--jd-text-sm);
      font-weight: 700;
      text-overflow: ellipsis;
      color: var(--jd-fin-text);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* select는 목록이 비어 있어도 눌리는 것이다 — 커서와 호버로 그렇게 보이게 한다(§7).
     네이티브 화살표는 그대로 둔다: appearance를 끄면 우리가 화살표를 다시 그려야 하고
     그 순간 OS별 접근성 동작(키보드 열기·타이핑 점프)까지 우리 책임이 된다. */
    jd-backtest-runner select.jd-backtest-runner__control {
      cursor: pointer;
    }
    jd-backtest-runner .jd-backtest-runner__control:hover:not(:disabled) {
      border-color: color-mix(in srgb, var(--jd-fin-accent) 40%, var(--jd-fin-border));
    }
    /* outline: none + box-shadow 조합은 링이 border-radius를 따라가지 않는다.
     라이브러리 단일 레시피(base.css --jd-focus-ring)를 그대로 쓴다. */
    jd-backtest-runner .jd-backtest-runner__control:focus-visible {
      border-color: var(--jd-fin-accent);
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* 서제스트 */
    jd-backtest-runner .jd-backtest-runner__suggest {
      position: absolute;
      z-index: var(--jd-z-dropdown);
      inset-inline: 0;
      inset-block-start: calc(100% + var(--jd-space-1));
      list-style: none;
      margin: 0;
      padding: 0;
      max-height: 240px;
      overflow-y: auto;
      overflow-x: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
    }
    jd-backtest-runner .jd-backtest-runner__suggest-item {
      display: block;
      width: 100%;
      text-align: start;
      cursor: pointer;
      padding: var(--jd-space-2) var(--jd-space-3);
      font: inherit;
      font-size: var(--jd-text-sm);
      font-weight: 700;
      color: var(--jd-fin-text);
      background: none;
      border: 0;
    }
    jd-backtest-runner .jd-backtest-runner__suggest-item:hover {
      background: var(--jd-fin-soft);
    }
    jd-backtest-runner .jd-backtest-runner__suggest-item:active {
      background: color-mix(in srgb, var(--jd-fin-accent) 14%, transparent);
    }
    jd-backtest-runner .jd-backtest-runner__suggest-item:focus-visible {
      background: var(--jd-fin-soft);
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    jd-backtest-runner .jd-backtest-runner__suggest-sector {
      margin-inline-start: var(--jd-space-2);
      font-size: var(--jd-text-2xs);
      font-weight: 400;
      color: var(--jd-fin-muted);
    }

    /* 기간 버튼 — 4칩이 1/3 칸에 들어가지 못하면 v2는 **오른쪽에서 그냥 잘렸다**.
     칩 행은 부모 폭 안에서 끝나거나 스스로 굴러야 한다(§6).
     오른쪽 끝의 페이드가 "더 있다"를 알리는데, 페이드가 마지막 칩을 갉지 않도록
     같은 폭의 뒷여백을 둔다 — 칩은 그 앞에서 멈추고, 끝까지 굴리면 페이드 밑에
     여백만 남아 아무것도 흐려지지 않는다. */
    jd-backtest-runner .jd-backtest-runner__ranges {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      padding-inline-end: var(--jd-space-4);
      -webkit-mask-image: linear-gradient(
        90deg,
        #000 0 calc(100% - var(--jd-space-4)),
        transparent 100%
      );
      mask-image: linear-gradient(90deg, #000 0 calc(100% - var(--jd-space-4)), transparent 100%);
    }
    jd-backtest-runner .jd-backtest-runner__range {
      /* 남는 폭은 나눠 갖되(1) 좁아도 글자 밑으로는 줄지 않는다(0) — 줄어들면
       "60일"이 한 글자씩 세로로 선다(§5) */
      flex: 1 0 auto;
      height: 40px;
      padding-inline: var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      font: inherit;
      font-size: var(--jd-text-sm);
      font-weight: 800;
      white-space: nowrap;
      cursor: pointer;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-text);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-backtest-runner .jd-backtest-runner__range:hover:not([data-active="true"]) {
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
      border-color: color-mix(in srgb, var(--jd-fin-accent) 40%, transparent);
    }
    /* 눌린 면은 빛을 잃는다(§1) */
    jd-backtest-runner .jd-backtest-runner__range:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-backtest-runner .jd-backtest-runner__range[data-active="true"] {
      background: var(--jd-fin-accent);
      color: #fff;
      border-color: var(--jd-fin-accent);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    jd-backtest-runner .jd-backtest-runner__range:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 결과 헤더 */
    jd-backtest-runner .jd-backtest-runner__results-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3-5) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-backtest-runner .jd-backtest-runner__results-title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-md);
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
    }
    jd-backtest-runner .jd-backtest-runner__head-emoji {
      font-size: 16px;
      line-height: var(--jd-leading-none);
    }
    jd-backtest-runner .jd-backtest-runner__results-note {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
      white-space: nowrap;
    }

    /* 스탯 그리드 */
    jd-backtest-runner .jd-backtest-runner__stat-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: var(--jd-border-thin);
      background: var(--jd-fin-border);
    }
    @media (min-width: 768px) {
      jd-backtest-runner .jd-backtest-runner__stat-grid {
        grid-template-columns: repeat(4, 1fr);
      }
    }
    jd-backtest-runner .jd-backtest-runner__stat {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-fin-card);
    }
    jd-backtest-runner .jd-backtest-runner__stat-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__stat-value {
      font-size: var(--jd-text-lg);
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-backtest-runner .jd-backtest-runner__stat-value[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-backtest-runner .jd-backtest-runner__stat-value[data-tone="down"] {
      color: var(--jd-fin-down);
    }

    /* 자산곡선 */
    jd-backtest-runner .jd-backtest-runner__chart {
      padding: var(--jd-space-4);
    }
    jd-backtest-runner .jd-backtest-runner__equity {
      display: block;
      width: 100%;
      height: auto;
    }
    jd-backtest-runner .jd-backtest-runner__baseline {
      stroke: var(--jd-fin-border);
    }
    jd-backtest-runner .jd-backtest-runner__axis {
      fill: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__line-eq {
      stroke: var(--jd-fin-accent);
    }
    jd-backtest-runner .jd-backtest-runner__line-bh {
      stroke: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__legend-box {
      fill: var(--jd-fin-card);
      stroke: var(--jd-fin-border);
    }
    jd-backtest-runner .jd-backtest-runner__legend-eq {
      fill: var(--jd-fin-text);
    }
    jd-backtest-runner .jd-backtest-runner__legend-bh {
      fill: var(--jd-fin-muted);
    }

    /* 의견 분포 */
    jd-backtest-runner .jd-backtest-runner__histogram {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      flex-wrap: wrap;
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-backtest-runner .jd-backtest-runner__histogram-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__verdict {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      font-variant-numeric: tabular-nums;
    }
    jd-backtest-runner .jd-backtest-runner__verdict-name {
      color: var(--jd-fin-muted);
    }
    jd-backtest-runner .jd-backtest-runner__verdict-count[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-backtest-runner .jd-backtest-runner__verdict-count[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-backtest-runner .jd-backtest-runner__verdict-count[data-tone="flat"] {
      color: var(--jd-fin-text);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-backtest-runner .jd-backtest-runner__control,
      jd-backtest-runner .jd-backtest-runner__range {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-badge {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-semibold);
      letter-spacing: var(--jd-tracking-wide);
      white-space: nowrap;
      /* size 기본 md */
      padding: var(--jd-space-1) var(--jd-space-2-5);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
      /* variant 기본 default — gray. DEC-044 톤 레시피: 변종은 앵커 한 줄만 바꾸고
       배경·글자·인셋 링은 여기 세 줄이 공식으로 파생한다(base.css --jd-tone-*).
       variant 7종 × 모드 2 = 14가지를 손으로 적던 것이 한 벌로 줄었다. */
      --jd-tone: var(--jd-color-hue-gray);
      /* 11~14px 배지 글자는 일반 본문보다 엄격한 대비가 필요하다. 앵커색을 그대로
       많이 쓰지 않고 잉크 쪽 비율을 늘려 success/warning/info도 AA를 넘긴다. */
      --jd-tone-ink-mix: 68%;
      /* 기본 12%는 gray 앵커에서 배경과 구분되지 않아 배지가 "평평한 회색 알약"으로
       읽혔다(실측). 의미색 -light 짝과 같은 무게가 되도록 한 단 올린다. */
      --jd-tone-bg-mix: 18%;
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
      /* 채움 + 인셋 링만으로는 면이 서지 않는다(§2) — 위에서 받는 빛 한 겹과
       바닥 그림자를 더해 종잇조각이 아니라 얹힌 칩으로 읽히게 한다. */
      box-shadow: 0 0 0 var(--jd-border-thin) inset
          color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-border-mix), transparent),
        inset 0 1px 0 var(--jd-color-highlight), var(--jd-shadow-xs);
    }
    jd-badge[size="sm"] {
      padding: var(--jd-space-0-5) var(--jd-space-2);
      /* 2xs(11px)가 하한이다 — 10px 배지는 §9 미달이었다 */
      font-size: var(--jd-text-2xs);
      border-radius: var(--jd-radius-md);
    }
    jd-badge[size="lg"] {
      padding: var(--jd-space-1) var(--jd-space-3);
      font-size: var(--jd-text-md);
    }

    jd-badge[variant="primary"] {
      --jd-tone: var(--jd-color-primary);
    }
    jd-badge[variant="success"] {
      --jd-tone: var(--jd-color-success);
    }
    jd-badge[variant="warning"] {
      --jd-tone: var(--jd-color-warning);
    }
    jd-badge[variant="danger"] {
      --jd-tone: var(--jd-color-danger);
    }
    jd-badge[variant="info"] {
      --jd-tone: var(--jd-color-info);
    }
    jd-badge[variant="outline"] {
      background: transparent;
      color: var(--jd-color-foreground);
      box-shadow: none;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }

    /* dot — DOM 없이 ::before. 틴트가 아니라 앵커 원색이라 변종 분기가 필요 없다 */
    jd-badge[dot]::before {
      content: "";
      flex-shrink: 0;
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-tone);
    }
    jd-badge[dot][variant="outline"]::before {
      background: var(--jd-color-foreground);
    }

    /* 카운트 모드 — 원형 danger (v2 동형). 원은 18px에서 20px로 키웠다:
     글자 하한이 11px(§9)이라 18px 원 안에서는 "99+"가 테두리에 닿았다. */
    jd-badge[data-count-mode] {
      justify-content: center;
      padding: 0 var(--jd-space-1-5);
      min-width: 1.25rem;
      height: 1.25rem;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-danger);
      color: #fff;
      /* 알림 배지는 늘 다른 것 위에 얹힌다 — 면과 빛을 유지해야 떠 있는 것으로 읽힌다 */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      font-variant-numeric: tabular-nums;
      font-size: var(--jd-text-2xs);
      letter-spacing: var(--jd-tracking-normal);
    }
  }

  @layer junds.components {
    jd-banner {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      padding: var(--jd-space-2-5) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      /* 흰 글자를 받으려면 배경이 충분히 어두워야 한다. semantic 원색 그대로면
       info 3.9:1 · warning 3.6:1 · success 4.0:1로 AA 미달(axe 실측, v2 승계 결함) —
       foreground를 20% 섞어 색상은 유지하고 명도만 내린다(DEC-030-7의 배경판). */
      color: #ffffff;
      background: color-mix(in srgb, var(--_jd-banner-color) 80%, var(--jd-color-foreground));
      --_jd-banner-color: var(--jd-color-info); /* variant 기본 info */
    }
    jd-banner[hidden] {
      display: none;
    }
    jd-banner[variant="success"] {
      --_jd-banner-color: var(--jd-color-success);
    }
    jd-banner[variant="warning"] {
      --_jd-banner-color: var(--jd-color-warning);
    }
    jd-banner[variant="danger"] {
      --_jd-banner-color: var(--jd-color-danger);
    }

    .jd-banner__content {
      text-align: center;
    }

    .jd-banner__close {
      display: flex;
      flex-shrink: 0;
      padding: var(--jd-space-1);
      margin-inline-start: var(--jd-space-2);
      border: 0;
      background: none;
      color: inherit;
      cursor: pointer;
      border-radius: var(--jd-radius-sm);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-banner__close:hover {
      background: rgb(255 255 255 / 0.2);
    }
    .jd-banner__close[hidden] {
      display: none;
    }
    .jd-banner__close:focus-visible {
      outline: var(--jd-border-medium) solid #ffffff;
      outline-offset: 1px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-banner__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-bar-chart {
      /* 계열색은 hue 팔레트에서만(§8). 공용 기본값은 success/warning/danger를 계열색으로
       써서 "3번 시리즈"와 "경고"가 한 화면에서 같은 색이 된다 — 계열은 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 480px 뷰박스가 카드보다 넓으면 오른쪽 끝 축 라벨이 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 비율을
     대신 말하므로 폭만 줄여도 그림이 찌그러지지 않는다. min-width는 플렉스 자식의
     min-width:auto(=내용 폭 480) 바닥을 풀되, 범례 옆에서 뭉개지지 않게 컨테이너가
     더 좁을 때만 양보하도록 잡는다. */
    jd-bar-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 15rem);
    }

    /* 채움만 있는 면은 색종이로 읽힌다(§2) — 위에서 빛을 받는 세로 그라데이션.
     페인트 서버(element.ts의 시리즈별 defs)는 url()만 넘기고 색은 여기서 정한다.
     지원하지 않는 환경이면 폴백으로 기존 단색이 그대로 남는다. */
    jd-bar-chart .jd-chart__bar {
      fill: var(--jd-bar-fill, var(--jd-series-color));
      /* rx는 SVG2에서 CSS 기하 속성이다 — 표시 속성 rx="2"를 이겨 값을 토큰으로
       말한다. CSS rx를 모르는 브라우저에선 그 속성이 그대로 폴백이 된다. */
      rx: var(--jd-radius-sm);
    }
    .jd-chart__bar-stop-top {
      stop-color: color-mix(in srgb, var(--jd-series-color) 84%, #fff);
    }
    .jd-chart__bar-stop-bottom {
      stop-color: var(--jd-series-color);
    }

    jd-bar-chart:not(:defined) {
      display: inline-block;
    }
  }

  @layer junds.components {
    jd-battery-indicator {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-battery-indicator:hover {
      transform: scale(1.05);
    }

    /* --jd-color-muted가 이미 모드별 값을 갖는다 — 다크 분기가 있으면 토큰이 바뀌어도
     이 컴포넌트만 옛 회색에 묶인다. */
    .jd-battery__label {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
    }

    .jd-battery__body {
      position: relative;
      overflow: hidden;
      border: 2px solid var(--jd-color-neutral-400);
      border-radius: var(--jd-radius-sm);
      width: 3.5rem;
      height: 1.5rem; /* md 기본 56×24 */
    }
    [data-jd-theme="dark"] .jd-battery__body,
    [data-theme="dark"] .jd-battery__body {
      border-color: var(--jd-color-neutral-500);
    }
    jd-battery-indicator[size="sm"] .jd-battery__body {
      width: 2.5rem;
      height: 1rem;
    }
    jd-battery-indicator[size="lg"] .jd-battery__body {
      width: 5rem;
      height: 2rem;
    }

    /* 채운 면은 위에서 빛을 받는다 — 인셋 하이라이트가 없으면 색종이로 읽힌다(jd-button 규약) */
    .jd-battery__fill {
      position: absolute;
      inset-block: 0;
      left: 0;
      background: var(--jd-color-primary);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      transition: background-color var(--jd-duration-slower) var(--jd-easing-ease-out),
        border-color var(--jd-duration-slower) var(--jd-easing-ease-out),
        color var(--jd-duration-slower) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-slower) var(--jd-easing-ease-out),
        opacity var(--jd-duration-slower) var(--jd-easing-ease-out),
        scale var(--jd-duration-slower) var(--jd-easing-ease-out),
        transform var(--jd-duration-slower) var(--jd-easing-ease-out);
    }
    jd-battery-indicator[data-fill="success"] .jd-battery__fill {
      background: var(--jd-color-success);
    }
    jd-battery-indicator[data-fill="warning"] .jd-battery__fill {
      background: var(--jd-color-warning);
    }
    jd-battery-indicator[data-fill="danger"] .jd-battery__fill {
      background: var(--jd-color-danger);
    }

    .jd-battery__pct {
      display: none;
      position: absolute;
      inset: 0;
      align-items: center;
      justify-content: center;
      /* 11px 아래로는 내려가지 않는다 — lg(80×32) 안에서 2xs가 넉넉히 들어간다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      /* v2 blend-difference → 흰 글자+다크 헤일로 (axe 대비 실측 가능, DEC-027) */
      color: #fff;
      text-shadow: 0 0 2px rgba(17, 24, 39, 0.95), 0 0 1px rgba(17, 24, 39, 0.95),
        0 1px 2px rgba(17, 24, 39, 0.85);
    }
    jd-battery-indicator[size="lg"] .jd-battery__pct {
      display: flex;
    }

    .jd-battery__cap {
      border-start-end-radius: var(--jd-radius-sm);
      border-end-end-radius: var(--jd-radius-sm);
      background: var(--jd-color-neutral-400);
      width: 6px;
      height: 12px; /* md */
    }
    [data-jd-theme="dark"] .jd-battery__cap,
    [data-theme="dark"] .jd-battery__cap {
      background: var(--jd-color-neutral-500);
    }
    jd-battery-indicator[size="sm"] .jd-battery__cap {
      width: 4px;
      height: 8px;
    }
    jd-battery-indicator[size="lg"] .jd-battery__cap {
      width: 8px;
      height: 16px;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-battery-indicator,
      .jd-battery__fill {
        transition: none;
      }
      jd-battery-indicator:hover {
        transform: none;
      }
    }
  }

  @layer junds.base {
    jd-bento-grid:not(:defined) {
      display: grid;
    }
    jd-bento-grid-item:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-bento-grid {
      --jd-bento-gap: var(--jd-space-4);
      /* 계산식에는 실제 간격이 아니라 **상한**을 넣는다 — gap 스타일 프롭은 인라인으로
       들어와 시트가 볼 수 없다. 상한보다 좁은 간격이면 열 수가 그대로 유지되고,
       상한을 크게 잡아도 1fr가 남는 폭을 도로 나눠 가지므로 보이는 폭은 같다. */
      --jd-bento-gap-max: var(--jd-space-6);
      --jd-bento-cols: 4;
      --jd-bento-col-min: 11rem;
      display: grid;
      /* 4열은 넓을 때의 이야기다. 고정 repeat(4)는 좁은 부모 안에서 셀을 60px로 눌러
       제목이 세로로 서거나 잘린다 — 하한을 두고 auto-fit에 맡기면 넓을 때는 그대로
       4열이고 좁아지면 3 → 2 → 1열로 접힌다(§5). 뷰포트가 아니라 부모 폭을 본다. */
      grid-template-columns: repeat(
        auto-fit,
        minmax(
          min(
            100%,
            max(
              var(--jd-bento-col-min),
              (100% - (var(--jd-bento-cols) - 1) * var(--jd-bento-gap-max)) / var(--jd-bento-cols)
            )
          ),
          1fr
        )
      );
      /* 열이 접힌 뒤 col-span이 남은 열 수를 넘으면 암시 열이 생긴다 — 폭 0으로 못 박아
       격자가 부모를 밀고 나가지 못하게 한다(§6) */
      grid-auto-columns: 0;
      /* 180px은 최소이지 정답이 아니다 — 고정 행이면 "이번 달 수익률"의 둘째 줄이
       그대로 잘린다(실측). 내용이 넘치면 행이 자란다. */
      grid-auto-rows: minmax(180px, auto);
      gap: var(--jd-bento-gap);
    }

    jd-bento-grid-item {
      display: block;
      box-sizing: border-box;
      min-width: 0; /* 격자 자식 기본 min-width:auto가 칸을 밀어내지 못하게(§5) */
      padding: var(--jd-space-5);
      overflow: hidden;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
      /* 면만 있는 카드는 색종이로 읽힌다 — 쉬는 상태의 얕은 그림자가 있어야
       hover의 shadow-lg가 '떠오름'으로 읽힌다(§2) */
      box-shadow: var(--jd-shadow-xs);
      word-break: keep-all; /* 셀 안의 CJK 제목이 글자 단위로 쪼개지지 않게 */
      overflow-wrap: break-word;
      transition: box-shadow var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    jd-bento-grid-item:hover,
    jd-bento-grid-item:focus-within {
      box-shadow: var(--jd-shadow-lg);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-bento-grid-item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-blockquote {
      display: block;
    }

    .jd-blockquote {
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-lg);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
      border-inline-start: var(--jd-border-heavy) solid var(--jd-color-border);
      padding-inline-start: var(--jd-space-4);
    }
    /* 이탤릭은 본문에만 — 출처까지 기울면 되돌리는 규칙이 또 필요해진다 */
    .jd-blockquote__body {
      font-style: italic;
    }

    .jd-blockquote__footer {
      margin-block-start: var(--jd-space-2);
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
    }
    .jd-blockquote__footer[hidden] {
      display: none;
    }
    /* <cite>의 UA 기본 이탤릭 해제 (v2 not-italic) */
    .jd-blockquote__cite {
      font-style: normal;
    }

    jd-blockquote[variant="bordered"] > .jd-blockquote {
      border-inline-start-color: var(--jd-color-primary);
    }
    jd-blockquote[variant="filled"] > .jd-blockquote {
      background: var(--jd-color-card-hover);
      border-inline-start-color: var(--jd-color-primary);
      border-radius: var(--jd-radius-md);
      padding: var(--jd-space-4);
    }
    jd-blockquote[variant="callout"] > .jd-blockquote {
      background: var(--jd-color-primary-light);
      border-inline-start: 0;
      border-radius: var(--jd-radius-md);
      padding: var(--jd-space-4);
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
    }
    jd-blockquote[variant="callout"] .jd-blockquote__footer {
      color: color-mix(in srgb, var(--jd-color-primary) 45%, var(--jd-color-foreground));
    }
  }

  @layer junds.components {
    jd-blog-post {
      display: block;
      max-width: 72rem;
      margin-inline: auto;
      padding: var(--jd-space-10) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    @media (min-width: 640px) {
      jd-blog-post {
        padding-inline: var(--jd-space-6);
      }
    }

    .jd-blog-post__header {
      max-width: 48rem;
      margin: 0 auto var(--jd-space-8);
      text-align: center;
    }

    .jd-blog-post__tags {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
      justify-content: center;
      margin: 0 0 var(--jd-space-4);
      padding: 0;
      list-style: none;
    }
    /* 원색 글자를 제 색의 옅은 틴트 위에 그대로 두면 대비가 무너진다 — primary는
     다크에서 들어 올려지지 않는 토큰이라(#5b4cc7 고정) 틴트 위에서 2.4:1이 된다.
     jd-calendar-month 이벤트 칩과 같은 공식으로 글자를 잉크 쪽으로 당긴다. */
    .jd-blog-post__tag {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      white-space: nowrap;
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
    }

    .jd-blog-post__title {
      margin: 0;
      font-size: var(--jd-text-3xl);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
      line-height: var(--jd-leading-tight);
    }
    @media (min-width: 640px) {
      .jd-blog-post__title {
        font-size: var(--jd-text-4xl);
      }
    }
    @media (min-width: 1024px) {
      .jd-blog-post__title {
        font-size: var(--jd-text-5xl);
      }
    }

    .jd-blog-post__excerpt {
      margin: var(--jd-space-4) 0 0;
      font-size: var(--jd-text-lg);
      color: var(--jd-color-muted);
    }

    .jd-blog-post__meta {
      margin-top: var(--jd-space-6);
      display: flex;
      align-items: center;
      justify-content: center;
      flex-wrap: wrap;
      gap: var(--jd-space-3);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-blog-post__author {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-blog-post__avatar {
      width: 1.5rem;
      height: 1.5rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
    }
    .jd-blog-post__author a {
      color: inherit;
      text-decoration: none;
      text-underline-offset: 2px;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-blog-post__author a:hover {
      color: var(--jd-color-foreground);
      text-decoration-line: underline;
    }
    .jd-blog-post__author a:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }
    /* 날짜·읽기시간은 "숫자 + 단위" 한 덩어리다 — 좁은 화면에서 접히면 한 글자씩 선다 */
    .jd-blog-post__date,
    .jd-blog-post__reading {
      white-space: nowrap;
    }

    .jd-blog-post__cover {
      max-width: 64rem;
      margin: 0 auto var(--jd-space-10);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
    }
    .jd-blog-post__cover-img {
      display: block;
      width: 100%;
      height: auto;
      object-fit: cover;
    }

    .jd-blog-post__layout {
      display: grid;
      gap: var(--jd-space-10);
      max-width: 48rem;
      margin-inline: auto;
    }
    .jd-blog-post__sidebar {
      display: none;
    }
    @media (min-width: 1024px) {
      .jd-blog-post__layout[data-has-sidebar] {
        max-width: none;
        grid-template-columns: 1fr 240px;
      }
      .jd-blog-post__layout[data-has-sidebar] .jd-blog-post__sidebar {
        display: block;
      }
      .jd-blog-post__layout[data-has-sidebar] .jd-blog-post__sidebar > * {
        position: sticky;
        top: var(--jd-space-6);
      }
    }

    /* 본문 prose — 스코프된 bare 요소 규칙(라이브러리 산문 타이포) */
    .jd-blog-post__body {
      min-width: 0;
      line-height: var(--jd-leading-relaxed);
    }
    .jd-blog-post__body > :first-child {
      margin-top: 0;
    }
    .jd-blog-post__body h2 {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
      letter-spacing: var(--jd-tracking-tight);
      margin: var(--jd-space-8) 0 var(--jd-space-3);
    }
    .jd-blog-post__body h3 {
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      margin: var(--jd-space-6) 0 var(--jd-space-2);
    }
    .jd-blog-post__body p {
      margin: 0 0 var(--jd-space-4);
    }
    .jd-blog-post__body a {
      color: var(--jd-color-primary-ink);
      text-underline-offset: 2px;
    }
    .jd-blog-post__body img {
      max-width: 100%;
      height: auto;
      border-radius: var(--jd-radius-lg);
    }
    .jd-blog-post__body blockquote {
      margin: var(--jd-space-4) 0;
      padding-left: var(--jd-space-4);
      border-left: var(--jd-border-medium) solid var(--jd-color-border);
      color: var(--jd-color-muted);
    }
    /* 코드 면은 라이트에서도 어둡다(DEC-044) — 잉크를 모드에 맡기면 라이트 모드에서
     검은 글자가 검은 면에 얹혀 코드가 사라진다. 그 면의 짝은 on-surface다.
     잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다 — 가로 스크롤을 코드면 안에 가둔다. */
    .jd-blog-post__body pre {
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      padding: var(--jd-space-4);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-surface-raised);
      color: var(--jd-color-on-surface);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
    }

    .jd-blog-post__footer:empty {
      display: none;
    }
    .jd-blog-post__footer {
      max-width: 48rem;
      margin: var(--jd-space-16) auto 0;
      padding-top: var(--jd-space-8);
      border-top: var(--jd-border-thin) solid var(--jd-color-border);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-blog-post__author a {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-bm-switch {
      display: inline-flex;
      --_accent: var(--jd-fin-accent, var(--jd-color-primary));
      --_accent-2: var(--jd-fin-accent-glow, var(--jd-color-accent));
      --_off: var(--jd-fin-soft-200, var(--jd-color-control-track));
      --_thumb: var(--jd-fin-surface, var(--jd-color-control-knob));
      --_text: var(--jd-fin-text, var(--jd-color-foreground));
    }

    .jd-bm-switch {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
    }
    jd-bm-switch[disabled] > .jd-bm-switch {
      cursor: not-allowed;
      opacity: var(--jd-opacity-50);
    }

    .jd-bm-switch__track {
      position: relative;
      display: inline-flex;
      flex-shrink: 0;
      border: 0;
      margin: 0;
      padding: 0;
      cursor: inherit;
      width: 44px;
      height: 24px; /* md 기본 */
      border-radius: var(--jd-radius-full);
      background: var(--_off);
      /* 파인 홈은 그림자도 토큰에서 — 리터럴 rgba는 다크에서 안 깊어진다 */
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
      transition: background var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-bm-switch[checked] .jd-bm-switch__track {
      background: linear-gradient(135deg, var(--_accent) 0%, var(--_accent-2) 100%);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 호버는 실색 전환(filter: brightness 금지 — 썸까지 밝혀 트랙과 붙는다). 켜짐/꺼짐을
     각각 명시해 두 규칙의 특이도를 같게 맞춘다 — 한쪽만 쓰면 꺼짐 호버가 켜짐을 이긴다. */
    jd-bm-switch:not([checked], [disabled]) .jd-bm-switch:hover .jd-bm-switch__track {
      /* 새 훅을 만들지 않고 --_off를 잉크 쪽으로 민다 — 소비자가 soft-200을 무엇으로
       바꾸든 호버는 그 색의 한 단 짙은 값이 된다 */
      background: color-mix(in srgb, var(--jd-color-foreground) 8%, var(--_off));
    }
    jd-bm-switch[checked]:not([disabled]) .jd-bm-switch:hover .jd-bm-switch__track {
      background: linear-gradient(
        135deg,
        color-mix(in srgb, var(--_accent) 86%, var(--jd-color-foreground)) 0%,
        var(--_accent) 100%
      );
    }
    /* 눌린 면은 빛을 잃는다 */
    jd-bm-switch:not([disabled]) .jd-bm-switch:active .jd-bm-switch__track {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-bm-switch__track:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-bm-switch__thumb {
      position: absolute;
      top: 50%;
      left: 3px;
      width: 18px;
      height: 18px; /* md 기본 */
      border-radius: var(--jd-radius-full);
      background: var(--_thumb);
      /* 노브 그림자는 전용 토큰 — 다크에서 더 깊어져야 흰 노브가 트랙에서 떠 보인다 */
      box-shadow: var(--jd-shadow-knob);
      transform: translateY(-50%) translateX(0);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-bm-switch[checked] .jd-bm-switch__thumb {
      transform: translateY(-50%) translateX(20px);
    }

    /* sm 36×20 / 썸 14 / 이동 16 */
    jd-bm-switch[size="sm"] .jd-bm-switch__track {
      width: 36px;
      height: 20px;
    }
    jd-bm-switch[size="sm"] .jd-bm-switch__thumb {
      width: 14px;
      height: 14px;
    }
    jd-bm-switch[size="sm"][checked] .jd-bm-switch__thumb {
      transform: translateY(-50%) translateX(16px);
    }

    /* lg 56×28 / 썸 22 / 이동 28 */
    jd-bm-switch[size="lg"] .jd-bm-switch__track {
      width: 56px;
      height: 28px;
    }
    jd-bm-switch[size="lg"] .jd-bm-switch__thumb {
      width: 22px;
      height: 22px;
    }
    jd-bm-switch[size="lg"][checked] .jd-bm-switch__thumb {
      transform: translateY(-50%) translateX(28px);
    }

    .jd-bm-switch__text {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--_text);
    }
    .jd-bm-switch__text[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-bm-switch__track,
      .jd-bm-switch__thumb {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-book-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-book-card {
      display: block;
    }

    .jd-book-card__button {
      display: block;
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      border: 0;
      text-align: start;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      cursor: pointer;
      transition: transform var(--jd-duration-slow) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-book-card__button:hover,
    .jd-book-card__button:focus-visible {
      box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2), 0 8px 10px -6px rgba(0, 0, 0, 0.2);
    }
    .jd-book-card__button:focus-visible {
      outline: none;
      box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2), 0 8px 10px -6px rgba(0, 0, 0, 0.2),
        var(--jd-shadow-focus-ring);
    }
    @media (prefers-reduced-motion: no-preference) {
      /* 키보드 사용자도 같은 상승을 받는다(v2는 hover 전용이었다) */
      .jd-book-card__button:hover,
      .jd-book-card__button:focus-visible {
        transform: translateY(-0.25rem);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-book-card__button {
        transition: none;
      }
    }

    .jd-book-card__cover {
      position: relative;
      display: block;
      aspect-ratio: 3 / 4;
      overflow: hidden;
      border-start-start-radius: var(--jd-radius-xl);
      border-start-end-radius: var(--jd-radius-xl);
      isolation: isolate;
    }

    /* 광택 — 호버·포커스에서만 (DOM 0) */
    .jd-book-card__cover::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 2;
      pointer-events: none;
      background: linear-gradient(
        135deg,
        rgba(255, 255, 255, 0.25) 0%,
        transparent 50%,
        transparent 100%
      );
      opacity: 0;
      transition: opacity var(--jd-duration-slower) var(--jd-easing-ease-out);
    }
    .jd-book-card__button:hover .jd-book-card__cover::before,
    .jd-book-card__button:focus-visible .jd-book-card__cover::before {
      opacity: 1;
    }

    /* 그레인 텍스처 — v2 데이터 URI 그대로 (DOM 0) */
    .jd-book-card__cover::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 3;
      pointer-events: none;
      opacity: 0.06;
      mix-blend-mode: overlay;
      background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    }

    .jd-book-card__lock {
      position: absolute;
      inset: 0;
      z-index: 4;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      color: #fff;
      background: rgba(0, 0, 0, 0.5);
      -webkit-backdrop-filter: blur(2px);
      backdrop-filter: blur(2px);
    }
    .jd-book-card__lock[hidden] {
      display: none;
    }
    .jd-book-card__lock-icon {
      font-size: 1.875rem;
      line-height: var(--jd-leading-none);
    }
    .jd-book-card__lock-text {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      opacity: var(--jd-opacity-80);
    }

    .jd-book-card__meta {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-3);
      background: var(--jd-color-card);
    }
    .jd-book-card__title {
      display: block;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .jd-book-card__sub {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      min-width: 0;
    }
    .jd-book-card__kind {
      color: var(--jd-color-muted);
    }
    .jd-book-card__kind[hidden] {
      display: none;
    }
    .jd-book-card__author {
      color: var(--jd-color-muted-light);
    }
    .jd-book-card__author[hidden] {
      display: none;
    }

    .jd-book-card__badge {
      margin-block-start: var(--jd-space-1-5);
    }
    /* 저작 display가 UA의 [hidden]을 이긴다 — jd-badge는 inline-flex다(레포 관용구) */
    .jd-book-card__badge[hidden] {
      display: none;
    }
  }

  @layer junds.base {
    jd-book-cover:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-book-cover {
      position: relative;
      display: block;
      box-sizing: border-box;
      width: 8rem;
      height: 11rem; /* md 기본 — size는 attribute가 고른다 */
      overflow: hidden;
      border-radius: var(--jd-radius-md);
      box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
      font-family: var(--jd-font-sans);
      isolation: isolate;
    }
    jd-book-cover[size="sm"] {
      width: 5rem;
      height: 7rem;
    }
    jd-book-cover[size="lg"] {
      width: 11rem;
      height: 15rem;
    }
    jd-book-cover[size="xl"] {
      width: 14rem;
      height: 20rem;
    }
    /* 부모 상자를 채운다 — 라운딩·그림자는 부모(jd-book-card)가 정한다 */
    jd-book-cover[size="fill"] {
      width: 100%;
      height: 100%;
      border-radius: inherit;
      box-shadow: none;
    }

    .jd-book-cover__img {
      position: absolute;
      inset: 0;
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    /* 이미지가 없거나 실패했으면 폴백만, 있으면 이미지만 그린다 */
    jd-book-cover:not([data-image]) .jd-book-cover__img {
      display: none;
    }
    jd-book-cover[data-image] .jd-book-cover__fallback {
      display: none;
    }

    .jd-book-cover__fallback {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      box-sizing: border-box;
      padding: var(--jd-space-3);
      /* 면이 항상 어두우므로 잉크도 모드를 따라가면 안 된다 — surface의 짝은
       on-surface다 (DEC-044). 캡션은 표지 위 보조 정보라 muted 단계를 쓴다. */
      color: var(--jd-color-on-surface);
      background: var(
        --jd-book-cover-hue,
        linear-gradient(135deg, var(--jd-color-surface-overlay) 0%, var(--jd-color-surface) 100%)
      ); /* 책등은 항상 어둡다 — 모드 무관 (DEC-044) */
    }
    .jd-book-cover__title {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      display: -webkit-box;
      -webkit-line-clamp: 3;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .jd-book-cover__title[hidden] {
      display: none;
    }
    /* v2 text-[10px] → 2xs(11px). 11px 아래로 내려가면 표지 캡션이 읽히지 않는다.
     흐림은 opacity가 아니라 잉크 단계로 낸다 — opacity는 뒤의 그라디언트까지 비친다. */
    .jd-book-cover__author {
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-on-surface-muted);
    }
    .jd-book-cover__author[hidden] {
      display: none;
    }

    /* 하단 광택 — DOM 0 */
    jd-book-cover::after {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
      background: linear-gradient(to top, rgba(0, 0, 0, 0.1) 0%, transparent 100%);
    }

    .jd-book-cover__spine {
      display: none;
    }
    jd-book-cover[effect="spine"] .jd-book-cover__spine {
      display: block;
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      width: 0.375rem;
      background: rgba(0, 0, 0, 0.15);
      border-start-start-radius: var(--jd-radius-md);
      border-end-start-radius: var(--jd-radius-md);
    }

    jd-book-cover[effect="tilt"] {
      transition: transform var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    @media (prefers-reduced-motion: no-preference) {
      jd-book-cover[effect="tilt"]:hover {
        transform: translateY(-0.25rem) rotate(-2deg);
      }
    }
    /* 기울기를 끄는 것만으로는 부족하다 — 전이가 남아 있으면 다른 원인으로 transform이
     바뀔 때 여전히 움직인다 */
    @media (prefers-reduced-motion: reduce) {
      jd-book-cover[effect="tilt"] {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-book-rating {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    .jd-book-rating__summary {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-book-rating__value {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }

    .jd-book-rating__stars {
      display: inline-flex;
      align-items: center;
    }
    .jd-book-rating__star {
      position: relative;
      display: inline-block;
      width: 1rem;
      height: 1rem;
    }
    .jd-book-rating__star-base,
    .jd-book-rating__star-fill {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
    }
    .jd-book-rating__star-base > path {
      fill: var(--jd-color-neutral-300);
    } /* v2 gray-300 — 빈 별 */
    .jd-book-rating__star-fill > path {
      fill: #fbbf24;
    } /* v2 amber-400 — 채움 */

    .jd-book-rating__reviews {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-book-rating__reviews[hidden] {
      display: none;
    }

    /* 점수 분포 */
    .jd-book-rating__dist {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      margin-top: var(--jd-space-1);
    }
    .jd-book-rating__dist[hidden] {
      display: none;
    }
    .jd-book-rating__row {
      display: grid;
      grid-template-columns: 20px 1fr 42px;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: 11px;
      color: var(--jd-color-muted);
    }
    .jd-book-rating__score {
      text-align: right;
      font-variant-numeric: tabular-nums;
    }
    .jd-book-rating__track {
      height: var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-neutral-200);
      overflow: hidden; /* v2 gray-200 */
    }
    .jd-book-rating__bar {
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-hue-amber);
    }
    .jd-book-rating__count {
      text-align: right;
      font-variant-numeric: tabular-nums;
    }

    /* neutral 램프가 다크에서 반전하므로(DEC-039) 빈 별·트랙은 분기 없이 neutral-200
     하나로 두 모드가 맞는다 — 옛 분기는 다크에서 near-white 트랙을 그리고 있었다. */
  }

  @layer junds.components {
    /* 리더 캔버스는 모드와 무관하게 어두운 면이다(DEC-044) — 종이 대신 밤을 깐다.
     그래서 그 위의 잉크·테두리·구분선은 모드를 따라가면 안 된다: foreground를 쓰면
     라이트 모드에서 검은 글자가 검은 면에 얹혀 본문이 통째로 사라진다.
     강조색도 같은 이유로 이 면 위에서 다시 조제한다 — primary(#5b4cc7)는 이 캔버스에서
     2.2:1, 기본 포커스 링은 1.4:1이라 사실상 보이지 않는다. 잉크 쪽으로 들어 올린
     accent 하나를 만들어 진행바·북마크·활성 목차·포커스 링이 함께 쓴다. 링은 색 변수만
     갈아 끼우므로 안쪽 규칙은 DEC-039 두 줄 관용구를 그대로 유지한다. */
    jd-book-reader {
      position: relative;
      display: block;
      min-height: 100vh;
      background: var(--jd-color-surface);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-on-surface);
      --jd-book-reader-accent: color-mix(
        in srgb,
        var(--jd-color-accent) 70%,
        var(--jd-color-on-surface)
      );
      --jd-color-ring-primary: color-mix(
        in srgb,
        var(--jd-book-reader-accent) 65%,
        transparent
      );
    }

    .jd-book-reader__progressbar {
      position: fixed;
      inset-block-start: 0;
      inset-inline: 0;
      height: 2px;
      z-index: var(--jd-z-sticky);
      background: transparent;
    }
    .jd-book-reader__progressbar-fill {
      display: block;
      height: 100%;
      width: 0%;
      background: var(--jd-book-reader-accent);
      transition: width var(--jd-duration-fast) var(--jd-easing-linear);
    }

    .jd-book-reader__header {
      position: sticky;
      inset-block-start: 0;
      z-index: var(--jd-z-header);
      background: color-mix(in srgb, var(--jd-color-surface) 90%, transparent);
      backdrop-filter: blur(8px);
      /* 어두운 면 위의 구분선은 border 토큰이 아니라 잉크에서 뽑는다 */
      border-bottom: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
    }
    .jd-book-reader__topbar {
      max-width: 72rem;
      margin-inline: auto;
      padding: var(--jd-space-2) var(--jd-space-4);
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-book-reader__toc-toggle,
    .jd-book-reader__bookmark,
    .jd-book-reader__close {
      flex-shrink: 0;
      width: 2rem;
      height: 2rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: transparent;
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      color: var(--jd-color-on-surface);
      font-size: var(--jd-text-md);
      transition: background var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-book-reader__toc-toggle:hover,
    .jd-book-reader__bookmark:hover,
    .jd-book-reader__close:hover {
      background: color-mix(in srgb, var(--jd-color-on-surface) 12%, transparent);
    }
    /* 눌린 면은 빛을 잃는다 — 세 버튼 모두 v2에 :active가 아예 없었다 */
    .jd-book-reader__toc-toggle:active,
    .jd-book-reader__bookmark:active,
    .jd-book-reader__close:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-on-surface) 18%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-book-reader__toc-toggle:focus-visible,
    .jd-book-reader__bookmark:focus-visible,
    .jd-book-reader__close:focus-visible,
    .jd-book-reader__toc-link:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    /* v2 병렬: 핸들러가 있을 때만 노출(bookmarkable / closable) */
    .jd-book-reader__bookmark {
      display: none;
    }
    .jd-book-reader__close {
      display: none;
    }
    jd-book-reader[bookmarkable] .jd-book-reader__bookmark {
      display: inline-flex;
    }
    jd-book-reader[closable] .jd-book-reader__close {
      display: inline-flex;
    }
    jd-book-reader[bookmarked] .jd-book-reader__bookmark {
      color: var(--jd-book-reader-accent);
    }

    .jd-book-reader__titles {
      min-width: 0;
      flex: 1;
    }
    .jd-book-reader__title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .jd-book-reader__author {
      margin: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-on-surface-muted);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .jd-book-reader__pageprogress {
      max-width: 72rem;
      margin-inline: auto;
      padding: 0 var(--jd-space-4) var(--jd-space-2);
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-book-reader__pagebar {
      flex: 1;
      height: 4px;
      border-radius: var(--jd-radius-full);
      /* 트랙도 어두운 면 위의 잉크에서 뽑는다 — border-light는 라이트 모드에서
       거의 흰색이라 이 캔버스에서 홀로 튄다 */
      background: color-mix(in srgb, var(--jd-color-on-surface) 16%, transparent);
      overflow: hidden;
    }
    .jd-book-reader__pagebar-fill {
      display: block;
      height: 100%;
      width: 0%;
      background: var(--jd-book-reader-accent);
      transition: width var(--jd-duration-normal) var(--jd-easing-default);
    }
    .jd-book-reader__pagelabel {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-on-surface-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    .jd-book-reader__layout {
      max-width: 72rem;
      margin-inline: auto;
      padding: var(--jd-space-6) var(--jd-space-4);
      display: grid;
      gap: var(--jd-space-6);
    }
    .jd-book-reader__toc {
      display: none;
    }
    @media (min-width: 1024px) {
      jd-book-reader[toc-open] .jd-book-reader__layout {
        grid-template-columns: 260px 1fr;
      }
      jd-book-reader[toc-open] .jd-book-reader__toc {
        display: block;
        position: sticky;
        inset-block-start: 6rem;
        align-self: start;
        max-height: calc(100vh - 7rem);
        overflow-y: auto;
        padding-right: var(--jd-space-2);
      }
    }

    .jd-book-reader__toc-list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-book-reader__toc-list .jd-book-reader__toc-list {
      padding-left: var(--jd-space-3);
    }
    .jd-book-reader__toc-link {
      display: block;
      padding: var(--jd-space-1-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-on-surface-muted);
      text-decoration: none;
      transition: background var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-book-reader__toc-link:hover {
      background: color-mix(in srgb, var(--jd-color-on-surface) 12%, transparent);
      color: var(--jd-color-on-surface);
    }
    .jd-book-reader__toc-link:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-book-reader__toc-link[data-active] {
      background: color-mix(in srgb, var(--jd-book-reader-accent) 16%, transparent);
      color: var(--jd-book-reader-accent);
      font-weight: var(--jd-weight-medium);
    }

    .jd-book-reader__body {
      min-width: 0;
      line-height: var(--jd-leading-relaxed);
    }
    .jd-book-reader__body > :first-child {
      margin-top: 0;
    }
    .jd-book-reader__body h2 {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
      margin: var(--jd-space-8) 0 var(--jd-space-3);
    }
    .jd-book-reader__body h3 {
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      margin: var(--jd-space-6) 0 var(--jd-space-2);
    }
    .jd-book-reader__body p {
      margin: 0 0 var(--jd-space-4);
    }
    .jd-book-reader__body a {
      color: var(--jd-book-reader-accent);
      text-underline-offset: 2px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-book-reader__progressbar-fill,
      .jd-book-reader__pagebar-fill,
      .jd-book-reader__toc-toggle,
      .jd-book-reader__bookmark,
      .jd-book-reader__close,
      .jd-book-reader__toc-link {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-book-shelf {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      padding: var(--jd-space-2); /* minimal 기본 */
    }

    jd-book-shelf[variant="card"] {
      padding: var(--jd-space-5);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-sm);
    }
    jd-book-shelf[variant="wood"] {
      padding: var(--jd-space-4);
      border-radius: var(--jd-radius-2xl);
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--jd-color-warning) 8%, var(--jd-color-card)) 0%,
        color-mix(in srgb, var(--jd-color-warning) 16%, var(--jd-color-card)) 100%
      );
      box-shadow: inset 0 -4px 8px rgba(0, 0, 0, 0.08);
    }

    .jd-book-shelf__header {
      margin-block-end: var(--jd-space-3);
      padding-inline: var(--jd-space-1);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      letter-spacing: var(--jd-tracking-tight);
      color: var(--jd-color-foreground);
    }
    .jd-book-shelf__header[hidden] {
      display: none;
    }

    .jd-book-shelf__grid {
      display: grid;
      gap: var(--jd-space-3);
      grid-template-columns: repeat(2, minmax(0, 1fr)); /* columns=5 기본, ~640 */
    }
    jd-book-shelf[columns="3"] .jd-book-shelf__grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    jd-book-shelf[columns="4"] .jd-book-shelf__grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
    jd-book-shelf[columns="6"] .jd-book-shelf__grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    jd-book-shelf[columns="8"] .jd-book-shelf__grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    @media (min-width: 640px) {
      jd-book-shelf[columns="5"] .jd-book-shelf__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
      jd-book-shelf[columns="6"] .jd-book-shelf__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
      jd-book-shelf[columns="8"] .jd-book-shelf__grid {
        grid-template-columns: repeat(6, minmax(0, 1fr));
      }
    }
    @media (min-width: 1024px) {
      jd-book-shelf[columns="5"] .jd-book-shelf__grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
      }
      jd-book-shelf[columns="6"] .jd-book-shelf__grid {
        grid-template-columns: repeat(6, minmax(0, 1fr));
      }
      jd-book-shelf[columns="8"] .jd-book-shelf__grid {
        grid-template-columns: repeat(8, minmax(0, 1fr));
      }
    }
  }

  @layer junds.components {
    jd-bookmark-button {
      display: inline-flex;
      --_jd-bookmark-size: 18px;
    }

    .jd-bookmark-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-1-5);
      border: 0;
      background: none;
      cursor: pointer;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-bookmark-button:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
    }
    .jd-bookmark-button:active:not(:disabled) {
      transform: scale(0.95);
    }
    .jd-bookmark-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-bookmark-button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-bookmark-button__icon {
      width: var(--_jd-bookmark-size);
      height: var(--_jd-bookmark-size);
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
    }
    jd-bookmark-button[bookmarked] .jd-bookmark-button {
      color: #f59e0b;
    } /* v2 amber-500 */
    jd-bookmark-button[bookmarked] .jd-bookmark-button__icon {
      fill: currentColor;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-bookmark-button {
        transition: none;
      }
      .jd-bookmark-button:active:not(:disabled) {
        transform: none;
      }
    }
  }

  @layer junds.components {
    /* 강조색 기본값은 팔레트 안에 있어야 한다(§8) — v2가 박아 둔 민트(#14b8a6)는
     브랜드 색도 아니고 다크에서 따라오지도 않았다. --jd-fin-accent를 준 앱은 그대로
     그 색을 쓰고, 안 준 앱은 브랜드 primary를 받는다. */
    jd-bottom-nav {
      display: block;
      font-family: var(--jd-font-sans);
      --_accent: var(--jd-fin-accent, var(--jd-color-primary));
      --_accent-strong: var(--jd-fin-accent-strong, var(--jd-color-primary-hover));
      --_accent-soft: var(--jd-fin-accent-soft, var(--jd-color-primary-light));
      --_surface: var(--jd-fin-surface, var(--jd-color-card));
      --_text: var(--jd-fin-text, var(--jd-color-foreground));
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_border: var(--jd-fin-border, var(--jd-color-border));
    }

    /* ── 탭바 ── */
    .jd-bottom-nav__bar {
      display: flex;
      align-items: stretch;
      justify-content: space-between;
      gap: var(--jd-space-1);
      padding: var(--jd-space-2) var(--jd-space-2)
        max(env(safe-area-inset-bottom), var(--jd-space-1-5));
      background: var(--_surface);
      border-block-start: var(--jd-border-thin) solid var(--_border);
    }
    .jd-bottom-nav__tab {
      /* flex-basis 0 + min-width 0 — 기본 min-width:auto면 라벨이 칸을 밀어내 항목마다
       폭이 달라진다. 0에서 출발해 균등하게 나눠 갖는다(§5). */
      flex: 1 1 0;
      min-width: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1) 0;
      appearance: none;
      border: 0;
      background: transparent;
      cursor: pointer;
      text-decoration: none;
      color: inherit;
      font-family: inherit;
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-bottom-nav__tab-icon {
      display: grid;
      place-items: center;
      width: 2.25rem;
      height: 2.25rem;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      color: var(--_muted);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 누를 수 있는 것은 세 상태를 다 갖는다(§1) — v2에는 hover도 active도 없었다.
     선택 표시([data-active])와 특정도가 같으므로 **뒤에 오는 쪽이 이긴다** — 선택된
     탭을 가리켰을 때 옅은 호버색으로 내려앉지 않게 선택 규칙을 뒤에 둔다. */
    .jd-bottom-nav__tab:hover .jd-bottom-nav__tab-icon {
      color: var(--_accent);
      background: color-mix(in srgb, var(--_accent) 10%, transparent);
    }
    .jd-bottom-nav__tab:hover .jd-bottom-nav__tab-label {
      color: var(--_accent);
    }
    .jd-bottom-nav__tab:active {
      scale: 0.97;
    }
    .jd-bottom-nav__tab[data-active] .jd-bottom-nav__tab-icon {
      color: var(--_accent);
      background: var(--_accent-soft);
    }
    /* 내비 라벨은 접히지 않는다 — "포트폴리오"가 두 줄이 되면 항목 높이가 어긋난다.
     11px은 읽기의 바닥이라 더 줄일 수 없으므로(§9) 자간을 좁혀 폭을 번다. */
    .jd-bottom-nav__tab-label {
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      letter-spacing: var(--jd-tracking-tight);
      font-weight: var(--jd-weight-semibold);
      color: var(--_muted);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-bottom-nav__tab[data-active] .jd-bottom-nav__tab-label {
      color: var(--_accent);
    }
    .jd-bottom-nav__tab:focus-visible {
      /* 바 안쪽이라 바깥으로 나가는 링은 잘린다 — offset을 안으로 접는다 */
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
      border-radius: var(--jd-radius-md);
    }

    /* ── 더보기 시트 내용 ── */
    .jd-bottom-nav__sheet-body {
      padding: 0 var(--jd-space-3) var(--jd-space-2);
    }
    .jd-bottom-nav__sheet-section {
      margin-block-end: var(--jd-space-3);
    }
    .jd-bottom-nav__sheet-title {
      padding: 0 var(--jd-space-3);
      margin-block-end: var(--jd-space-1-5);
      /* 10.5px은 읽기의 바닥(11px, §9) 아래였다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-wider);
      color: var(--_muted);
    }
    .jd-bottom-nav__sheet-list {
      margin: 0;
      padding: 0;
      list-style: none;
      border: var(--jd-border-thin) solid var(--_border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
    }
    .jd-bottom-nav__sheet-item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      text-decoration: none;
      color: var(--_text);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-bottom-nav__sheet-list > li + li > .jd-bottom-nav__sheet-item {
      border-block-start: var(--jd-border-thin) solid var(--_border);
    }
    /* 시트 항목도 누를 수 있다 — 세 상태를 다 준다(§1). 선택 표시와 특정도가 같아
     뒤에 오는 쪽이 이기므로 [data-active]를 마지막에 둔다. */
    .jd-bottom-nav__sheet-item:hover {
      background: color-mix(in srgb, var(--_accent) 8%, transparent);
    }
    .jd-bottom-nav__sheet-item:active {
      background: color-mix(in srgb, var(--_accent) 14%, transparent);
    }
    .jd-bottom-nav__sheet-item:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-bottom-nav__sheet-item[data-active] {
      background: var(--_accent-soft);
      color: var(--_accent-strong);
    }
    .jd-bottom-nav__sheet-icon {
      display: grid;
      place-items: center;
      width: var(--jd-space-5);
      flex-shrink: 0;
      color: var(--_muted);
    }
    .jd-bottom-nav__sheet-item[data-active] .jd-bottom-nav__sheet-icon {
      color: var(--_accent-strong);
    }
    .jd-bottom-nav__sheet-label {
      flex: 1;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-bottom-nav__sheet-desc {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-medium);
      color: var(--_muted);
      flex-shrink: 1;
      min-width: 0;
      max-width: 11.25rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-bottom-nav__tab,
      .jd-bottom-nav__tab-icon,
      .jd-bottom-nav__tab-label,
      .jd-bottom-nav__sheet-item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-bottom-sheet {
      display: none;
    }
    jd-bottom-sheet[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: flex-end;
      justify-content: center;
      padding: 0;
    }

    jd-bottom-sheet .jd-modal__panel {
      width: 100%;
      max-width: 100%;
      border-radius: var(--jd-radius-2xl) var(--jd-radius-2xl) 0 0;
      /* height 기본 auto — v2 max-h 80vh */
      max-height: 80vh;
      animation: jd-sheet-in var(--jd-duration-normal) var(--jd-easing-spring);
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 시트 안에 포커스 가능한 것이 없으면 포커스트랩이 패널에 tabindex="-1"을 심고
     패널 자체를 포커스한다(behaviors/focus-trap) — 그때 UA 기본 아웃라인이 패널
     테두리를 따라 그려져 팔레트를 벗어난다. 패널은 감금 기점일 뿐 조작 대상이
     아니므로 표시를 지운다. 시트에 담기는 조작 요소(jd-button 등)는 각자 자기
     :focus-visible을 갖고 있어 §1의 "대체 없이 지우기"에 해당하지 않는다. */
    jd-bottom-sheet > .jd-modal__panel:focus,
    jd-bottom-sheet > .jd-modal__panel:focus-visible {
      outline: none;
    }
    jd-bottom-sheet[height="half"] .jd-modal__panel {
      height: 50vh;
      max-height: 50vh;
    }
    jd-bottom-sheet[height="full"] .jd-modal__panel {
      height: 90vh;
      max-height: 90vh;
    }

    @keyframes jd-sheet-in {
      from {
        transform: translateY(100%);
      }
    }

    .jd-bottom-sheet__grabber {
      flex-shrink: 0;
      width: 2.5rem;
      height: 0.25rem;
      margin: var(--jd-space-3) auto var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-bottom-sheet__grabber[hidden] {
      display: none;
    }
    jd-bottom-sheet[draggable] .jd-bottom-sheet__grabber {
      cursor: grab;
      touch-action: none; /* 끌 때 브라우저 스크롤과 다투지 않는다 */
      /* 손잡이만으로는 잡기 어렵다 — 히트 영역을 넓힌다 */
      padding-block: var(--jd-space-2);
      background-clip: content-box;
      height: calc(0.25rem + var(--jd-space-4));
      box-sizing: content-box;
    }
    /* draggable일 때만 손잡이가 잡히는 것이다 — 잡을 수 있음을 색으로 먼저 말하고,
     잡은 동안 커서를 grabbing으로 바꿔 "지금 끌고 있다"를 남긴다. draggable이
     아닌 시트의 손잡이는 장식이라 응답하지 않는다. */
    jd-bottom-sheet[draggable] .jd-bottom-sheet__grabber:hover {
      background: var(--jd-color-muted-light);
    }
    jd-bottom-sheet[draggable] .jd-bottom-sheet__grabber:active {
      cursor: grabbing;
      background: var(--jd-color-muted);
    }

    .jd-bottom-sheet__title {
      flex-shrink: 0;
      margin: 0;
      padding: var(--jd-space-2) var(--jd-space-5) var(--jd-space-3);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-bottom-sheet__title[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-bottom-sheet .jd-modal__panel {
        animation: none;
        transition: none;
      }
      .jd-bottom-sheet__grabber {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-box {
      display: block;
    }
  }

  @layer junds.base {
    jd-brand-switcher:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-brand-switcher {
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-brand-switcher[variant="chips"] {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
    }
    jd-brand-switcher[variant="list"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
    }
    jd-brand-switcher[variant="select"] {
      display: inline-block;
    }

    /* 네이티브 radio는 시각적으로 숨기되 포커스 가능(화살표 순회 유지) */
    .jd-brand-switcher__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      border: 0;
      overflow: hidden;
      clip: rect(0 0 0 0);
      clip-path: inset(50%);
      white-space: nowrap;
    }

    .jd-brand-switcher__item {
      position: relative;
      cursor: pointer;
    }
    .jd-brand-switcher__item:has(.jd-brand-switcher__input:focus-visible) {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-brand-switcher__text {
      min-width: 0;
    }
    .jd-brand-switcher__label {
      color: var(--jd-color-foreground);
    }

    /* ── select ── */
    .jd-brand-switcher__select {
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-md);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      cursor: pointer;
    }
    .jd-brand-switcher__select:focus-visible {
      outline: none;
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }

    /* ── chips ── */
    jd-brand-switcher[variant="chips"] .jd-brand-switcher__item {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      background: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-brand-switcher[variant="chips"] .jd-brand-switcher__item:hover {
      background: color-mix(in srgb, var(--jd-color-foreground) 10%, transparent);
    }
    jd-brand-switcher[variant="chips"]
      .jd-brand-switcher__item:has(.jd-brand-switcher__input:checked) {
      background: var(--jd-color-primary);
    }
    jd-brand-switcher[variant="chips"]
      .jd-brand-switcher__item:has(.jd-brand-switcher__input:checked)
      .jd-brand-switcher__label {
      color: #fff;
    }
    jd-brand-switcher[variant="chips"] .jd-brand-switcher__swatch {
      flex-shrink: 0;
      width: 0.75rem;
      height: 0.75rem;
      border-radius: var(--jd-radius-full);
      background: var(--jd-bs-primary, var(--jd-color-primary));
      box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
    }
    jd-brand-switcher[variant="chips"] .jd-brand-switcher__tagline {
      display: none;
    }

    /* ── list ── */
    jd-brand-switcher[variant="list"] .jd-brand-switcher__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      width: 100%;
      padding: var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      text-align: left;
      transition: border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-brand-switcher[variant="list"] .jd-brand-switcher__item:hover {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    jd-brand-switcher[variant="list"]
      .jd-brand-switcher__item:has(.jd-brand-switcher__input:checked) {
      border-color: var(--jd-color-primary);
      background: color-mix(in srgb, var(--jd-color-primary) 5%, transparent);
    }
    jd-brand-switcher[variant="list"]
      .jd-brand-switcher__item:has(.jd-brand-switcher__input:checked)::after {
      content: "✓";
      margin-inline-start: auto;
      color: var(--jd-color-primary-ink);
      font-size: var(--jd-text-md);
    }
    jd-brand-switcher[variant="list"] .jd-brand-switcher__swatch {
      flex-shrink: 0;
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-md);
      background: linear-gradient(
        135deg,
        var(--jd-bs-primary, var(--jd-color-primary)),
        var(--jd-bs-accent, var(--jd-color-accent))
      );
    }
    jd-brand-switcher[variant="list"] .jd-brand-switcher__text {
      flex: 1;
      display: flex;
      flex-direction: column;
    }
    jd-brand-switcher[variant="list"] .jd-brand-switcher__label {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
    }
    jd-brand-switcher[variant="list"] .jd-brand-switcher__tagline {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* disabled */
    jd-brand-switcher[disabled] .jd-brand-switcher__item,
    jd-brand-switcher[disabled] .jd-brand-switcher__select {
      opacity: 0.6;
      cursor: not-allowed;
    }
  }

  @layer junds.components {
    jd-breadcrumb {
      display: block;
      font-size: var(--jd-text-md);
    }

    .jd-breadcrumb__list {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-breadcrumb__item {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      min-width: 0;
    }

    .jd-breadcrumb__separator {
      display: inline-flex;
      flex-shrink: 0;
      align-items: center;
      color: var(--jd-color-muted-light);
    }
    .jd-breadcrumb__separator > svg {
      width: 14px;
      height: 14px;
    }

    .jd-breadcrumb__content {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      min-width: 0;
      color: var(--jd-color-muted);
      text-decoration: none;
      transition: color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    a.jd-breadcrumb__content:hover {
      color: var(--jd-color-foreground);
    }
    a.jd-breadcrumb__content:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }
    .jd-breadcrumb__content[aria-current="page"] {
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-medium);
    }

    .jd-breadcrumb__icon {
      display: inline-flex;
      flex-shrink: 0;
    }
    .jd-breadcrumb__icon[hidden] {
      display: none;
    }
    .jd-breadcrumb__icon > svg {
      width: 1em;
      height: 1em;
    }

    .jd-breadcrumb__label {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-breadcrumb__content {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-button {
      display: inline-flex;
    }
    jd-button[full-width] {
      display: flex;
    }
    jd-button[full-width] > .jd-button,
    .jd-button[data-jd-full-width="true"] {
      width: 100%;
    }

    /* 기본값(variant=primary·size=md)은 base에 — 디폴트는 attribute로 반영되지
     않으므로(§1.3 reflect는 set 시점) 호스트 속성 셀렉터는 비기본값만 담당한다.
     §4.3 정본 스케치와 동형. */
    .jd-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      margin: 0;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      user-select: none;
      white-space: nowrap;
      /* all 금지 — height·padding·font-size까지 대상이 되어 size 전환이 흐르고,
       레이아웃 속성 트랜지션은 매 프레임 리플로우를 만든다 (DEC-039) */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
      /* size 기본 md — v2: 36px */
      height: 2.25rem;
      padding-inline: var(--jd-space-4);
      gap: var(--jd-space-2);
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-xl);
      /* variant 기본 primary. 상단 인셋 하이라이트가 '위에서 빛을 받는 면'을 만든다 —
       채움만 있는 버튼은 색종이처럼 읽힌다. */
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 호버는 filter: brightness가 아니라 실색 전환 — brightness는 텍스트·스피너까지
     함께 밝혀 흰 글자가 배경에 녹고, GPU 레이어를 새로 만든다. */
    .jd-button:hover {
      background: var(--jd-color-primary-hover);
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-button:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-button:disabled,
    .jd-button[data-jd-disabled="true"] {
      opacity: var(--jd-opacity-40);
      pointer-events: none;
      box-shadow: none;
    }
    .jd-button:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* loading ≠ disabled (DEC-039). element.ts가 로딩 중 네이티브 disabled를 켜므로
     (§1.6-1 폼 위임) 위의 :disabled 흐림이 그대로 걸려 '비활성'과 구분되지 않았다.
     로딩은 **작동 중**이라는 신호다 — 색을 유지하고 커서만 진행형으로 바꾼다. */
    jd-button[loading] > .jd-button:disabled,
    .jd-button[data-jd-loading="true"] {
      opacity: 1;
      cursor: progress;
      /* :disabled의 pointer-events:none을 되돌려야 progress 커서가 실제로 보인다.
       클릭은 네이티브 disabled가 이미 막고 있으므로 안전하다. */
      pointer-events: auto;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }

    /* size — v2: xs 28px / sm 32px / lg 44px (md는 base) */
    jd-button[size="xs"] > .jd-button,
    .jd-button[data-jd-size="xs"] {
      height: 1.75rem;
      padding-inline: var(--jd-space-2-5);
      gap: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
    }
    jd-button[size="sm"] > .jd-button,
    .jd-button[data-jd-size="sm"] {
      height: 2rem;
      padding-inline: var(--jd-space-3-5);
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
    }
    jd-button[size="lg"] > .jd-button,
    .jd-button[data-jd-size="lg"] {
      height: 2.75rem;
      padding-inline: var(--jd-space-6);
      gap: var(--jd-space-2-5);
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-xl);
    }

    /* 비기본 variant — primary의 배경·그림자·필터를 각자 재정의한다 */
    /* secondary */
    jd-button[variant="secondary"] > .jd-button,
    .jd-button[data-jd-variant="secondary"] {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: var(--jd-shadow-xs);
    }
    jd-button[variant="secondary"] > .jd-button:hover,
    .jd-button[data-jd-variant="secondary"]:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    jd-button[variant="secondary"] > .jd-button:active,
    .jd-button[data-jd-variant="secondary"]:active {
      background: var(--jd-color-border-light);
      box-shadow: none;
      scale: 0.97;
    }

    /* danger */
    jd-button[variant="danger"] > .jd-button,
    .jd-button[data-jd-variant="danger"] {
      background: var(--jd-color-danger);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    jd-button[variant="danger"] > .jd-button:hover,
    .jd-button[data-jd-variant="danger"]:hover {
      /* 글로우는 danger 토큰 파생 — DEC-027 라이트 보정(#c93636)에 자동 추종 */
      background: var(--jd-color-danger-hover);
      box-shadow: 0 4px 12px color-mix(in srgb, var(--jd-color-danger) 25%, transparent),
        var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    jd-button[variant="danger"] > .jd-button:active,
    .jd-button[data-jd-variant="danger"]:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-button[variant="danger"] > .jd-button:focus-visible,
    .jd-button[data-jd-variant="danger"]:focus-visible {
      outline: var(--jd-focus-ring-danger);
    }

    /* ghost — 투명 배경, 호버 시만 배경 */
    jd-button[variant="ghost"] > .jd-button,
    .jd-button[data-jd-variant="ghost"] {
      background: transparent;
      color: var(--jd-color-foreground);
      box-shadow: none;
    }
    jd-button[variant="ghost"] > .jd-button:hover,
    .jd-button[data-jd-variant="ghost"]:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    jd-button[variant="ghost"] > .jd-button:active,
    .jd-button[data-jd-variant="ghost"]:active {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      scale: 0.97;
    }

    /* outline */
    jd-button[variant="outline"] > .jd-button,
    .jd-button[data-jd-variant="outline"] {
      background: transparent;
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: none;
    }
    jd-button[variant="outline"] > .jd-button:hover,
    .jd-button[data-jd-variant="outline"]:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    jd-button[variant="outline"] > .jd-button:active,
    .jd-button[data-jd-variant="outline"]:active {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      scale: 0.97;
    }

    /* link — 패딩/높이 없음 */
    jd-button[variant="link"] > .jd-button,
    .jd-button[data-jd-variant="link"] {
      background: transparent;
      box-shadow: none;
      height: auto;
      padding: 0;
      color: var(--jd-color-primary-ink);
      text-underline-offset: 2px;
      text-decoration-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    jd-button[variant="link"] > .jd-button:hover,
    .jd-button[data-jd-variant="link"]:hover {
      text-decoration-line: underline;
      text-decoration-color: var(--jd-color-primary-ink);
    }
    jd-button[variant="link"] > .jd-button:active,
    .jd-button[data-jd-variant="link"]:active {
      scale: none;
    }

    /* spinner — v2: xs 12px / sm 14px / md·lg 16px */
    .jd-button__spinner {
      flex-shrink: 0;
      width: 16px;
      height: 16px;
      animation: jd-spin 1s linear infinite;
    }
    jd-button[size="xs"] .jd-button__spinner,
    .jd-button[data-jd-size="xs"] .jd-button__spinner {
      width: 12px;
      height: 12px;
    }
    jd-button[size="sm"] .jd-button__spinner,
    .jd-button[data-jd-size="sm"] .jd-button__spinner {
      width: 14px;
      height: 14px;
    }
    @keyframes jd-spin {
      to {
        transform: rotate(360deg);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-button {
        transition: none;
      }
      .jd-button__spinner {
        animation-duration: 1.6s;
      }
    }
  }

  @layer junds.components {
    jd-button-group {
      display: inline-flex;
      align-items: center;
    }

    jd-button-group[full-width] {
      display: flex;
      width: 100%;
    }
    jd-button-group[full-width] > * {
      flex: 1 1 0;
      min-width: 0;
    }
    jd-button-group[full-width] > * > :is(.jd-button, .jd-icon-button) {
      width: 100%;
    }

    /* v2 separated: 간격만 두고 모서리는 각자 유지 */
    jd-button-group[separated] {
      gap: var(--jd-space-1);
    }

    /* ── 붙임 모드(기본) ── */
    jd-button-group:not([separated]) > *,
    jd-button-group:not([separated]) > * > :is(.jd-button, .jd-icon-button) {
      border-radius: 0;
    }
    jd-button-group:not([separated]) > :first-child,
    jd-button-group:not([separated]) > :first-child > :is(.jd-button, .jd-icon-button) {
      border-start-start-radius: var(--jd-radius-lg);
      border-end-start-radius: var(--jd-radius-lg);
    }
    jd-button-group:not([separated]) > :last-child,
    jd-button-group:not([separated]) > :last-child > :is(.jd-button, .jd-icon-button) {
      border-start-end-radius: var(--jd-radius-lg);
      border-end-end-radius: var(--jd-radius-lg);
    }
    /* v2 border-r-0 — 인접 테두리를 한 겹으로 */
    jd-button-group:not([separated]) > :not(:last-child),
    jd-button-group:not([separated]) > :not(:last-child) > :is(.jd-button, .jd-icon-button) {
      border-inline-end-width: 0;
    }
    /* 초점 링이 옆 버튼에 잘리지 않게 위로 올린다 */
    jd-button-group:not([separated]) > *:focus-within {
      position: relative;
      z-index: 1;
    }
  }

  @layer junds.base {
    jd-calendar:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-calendar {
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-cal {
      box-sizing: border-box; /* width:100% + padding + border — 안 그러면 호스트를 넘쳐 가로 스크롤 */
      width: 100%;
      border-radius: var(--jd-radius-2xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-sm);
      padding: var(--jd-space-4);
    }

    /* ── 헤더 ── */
    .jd-cal__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: var(--jd-space-3);
      padding: 0 var(--jd-space-1);
    }
    .jd-cal__header-left {
      position: relative;
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-cal__month-btn {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      border: 0;
      background: transparent;
      padding: var(--jd-space-0-5) var(--jd-space-1);
      border-radius: var(--jd-radius-lg);
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__month-btn:hover {
      color: var(--jd-color-primary-ink);
    }
    .jd-cal__month-btn:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-cal__caret {
      width: 0.75rem;
      height: 0.75rem;
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-cal__month-btn[aria-expanded="true"] .jd-cal__caret {
      transform: rotate(180deg);
    }

    .jd-cal__today {
      border: 0;
      background: transparent;
      padding: var(--jd-space-1) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__today:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      color: var(--jd-color-foreground);
    }
    .jd-cal__today:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-cal__header-right {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-cal__view-toggle {
      display: flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      border-radius: var(--jd-radius-lg);
      padding: var(--jd-space-0-5);
      margin-right: var(--jd-space-2);
    }
    .jd-cal__view-tab {
      border: 0;
      background: transparent;
      padding: var(--jd-space-1) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__view-tab[data-active] {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-medium);
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-cal__view-tab:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-cal__arrow {
      width: 2rem;
      height: 2rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: transparent;
      border-radius: var(--jd-radius-md);
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__arrow > svg {
      width: 0.875rem;
      height: 0.875rem;
    }
    .jd-cal__arrow:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    .jd-cal__arrow:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 월 선택 팝오버 ── */
    .jd-cal__picker {
      position: absolute;
      top: 100%;
      left: 0;
      margin-top: var(--jd-space-1);
      z-index: var(--jd-z-dropdown);
      width: 16.25rem;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-lg);
      padding: var(--jd-space-3);
    }
    .jd-cal__picker[hidden] {
      display: none;
    }
    .jd-cal__picker-yearrow {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: var(--jd-space-3);
    }
    .jd-cal__picker-arrow {
      width: 1.75rem;
      height: 1.75rem;
    }
    .jd-cal__picker-year {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-cal__picker-grid {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: var(--jd-space-1);
    }
    .jd-cal__picker-month {
      border: 0;
      background: transparent;
      padding: var(--jd-space-1-5) 0;
      border-radius: var(--jd-radius-lg);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__picker-month:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    .jd-cal__picker-month[data-current] {
      background: var(--jd-color-primary);
      color: #fff;
    }
    .jd-cal__picker-month:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 요일 헤더 ── */
    .jd-cal__weekdays {
      display: grid;
      grid-template-columns: repeat(7, minmax(0, 1fr));
      margin-bottom: var(--jd-space-1);
      border-bottom: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 50%, transparent);
      padding-bottom: var(--jd-space-1);
    }
    .jd-cal__weekday {
      text-align: center;
      padding: var(--jd-space-1-5) 0;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }
    .jd-cal__weekday[data-sun] {
      color: var(--jd-color-danger);
    }
    .jd-cal__weekday[data-sat] {
      color: var(--jd-color-info);
    }

    /* ── 그리드 ── */
    .jd-cal__grid {
      display: grid;
      grid-template-columns: repeat(7, minmax(0, 1fr));
      gap: var(--jd-space-px);
    }
    .jd-cal__cell {
      position: relative;
      min-height: 5rem;
      padding: var(--jd-space-1-5);
      border-radius: var(--jd-radius-lg);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cal__cell:hover {
      box-shadow: var(--jd-shadow-md);
      background: var(--jd-color-card);
    }
    .jd-cal__cell[data-empty] {
      cursor: default;
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
      box-shadow: none;
    }
    .jd-cal__cell[data-in-range] {
      background: var(--jd-color-primary-light);
    }
    .jd-cal__cell[data-disabled] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
      box-shadow: none;
    }
    .jd-cal__cell[data-focus] {
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    .jd-cal__cell:focus-visible {
      outline: none;
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }

    .jd-cal__num {
      align-self: flex-start;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.5rem;
      height: 1.5rem;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-cal__cell[data-sun] > .jd-cal__num {
      color: var(--jd-color-danger);
    }
    .jd-cal__cell[data-sat] > .jd-cal__num {
      color: var(--jd-color-info);
    }
    .jd-cal__cell[data-today] > .jd-cal__num {
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-bold);
    }
    .jd-cal__cell[data-selected] > .jd-cal__num {
      background: var(--jd-color-primary);
      color: #fff;
      font-weight: var(--jd-weight-semibold);
    }

    .jd-cal__cell-events {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      overflow: hidden;
    }
    .jd-cal__chip {
      border-radius: var(--jd-radius-sm);
      padding: 0.0625rem var(--jd-space-1);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }
    .jd-cal__chip-meta {
      opacity: var(--jd-opacity-70);
      margin-right: var(--jd-space-0-5);
    }

    .jd-cal__dots {
      display: flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      flex-wrap: wrap;
    }
    .jd-cal__dot {
      width: 0.375rem;
      height: 0.375rem;
      border-radius: var(--jd-radius-full);
      flex-shrink: 0;
    }
    .jd-cal__dots-more {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted-light);
    }
  }

  @layer junds.base {
    jd-calendar-month:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-calendar-month {
      display: block;
      font-family: var(--jd-font-sans);
    }

    /* 달력 격자는 "앱의 본문"이다 — 라이트에서도 어두워야 할 이유가 없으므로 surface가
     아니라 card다(DEC-044). v2 bg-surface 를 이름만 보고 옮겨 오면서 라이트 모드에서
     검은 판 위에 검은 글자가 얹혀 달력이 통째로 검은 상자로 렌더됐다.
     인셋 하이라이트는 '위에서 빛을 받는 면' — 채움만 있는 패널은 색종이로 읽힌다. */
    .jd-cm {
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      padding: var(--jd-space-4);
    }

    .jd-cm__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: var(--jd-space-3);
    }
    .jd-cm__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
      /* "2026년 7월"이 두 줄로 접히면 헤더 높이가 달마다 흔들린다 */
      white-space: nowrap;
    }
    .jd-cm__nav {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-cm__arrow,
    .jd-cm__today {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      height: 2rem;
      border: 0;
      background: transparent;
      color: var(--jd-color-foreground);
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: background var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-cm__arrow {
      width: 2rem;
    }
    .jd-cm__arrow > svg {
      width: 0.875rem;
      height: 0.875rem;
    }
    .jd-cm__today {
      padding: 0 var(--jd-space-3);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
    }
    .jd-cm__arrow:hover,
    .jd-cm__today:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    /* 눌린 면은 빛을 잃는다 — v2에도 v3 이식본에도 :active가 없어 세 버튼 모두
     클릭 순간 아무 반응이 없었다 */
    .jd-cm__arrow:active,
    .jd-cm__today:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-cm__arrow:focus-visible,
    .jd-cm__today:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-cm__weekdays,
    .jd-cm__grid {
      display: grid;
      grid-template-columns: repeat(7, minmax(0, 1fr));
      gap: var(--jd-space-1);
    }
    .jd-cm__weekday {
      padding: var(--jd-space-1) 0;
      text-align: center;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-cm__grid {
      margin-top: var(--jd-space-1);
      border-radius: var(--jd-radius-md);
    }
    .jd-cm__grid:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-cm__cell {
      min-height: 4rem;
      border-radius: var(--jd-radius-md);
      border: var(--jd-border-thin) solid transparent;
      padding: var(--jd-space-1);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      cursor: pointer;
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-cm__cell:hover {
      border-color: var(--jd-color-border);
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
    }
    .jd-cm__cell[data-outside] {
      opacity: var(--jd-opacity-40);
    }
    .jd-cm__cell[data-selected] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      border-color: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-cm__cell[data-focus] {
      border-color: color-mix(in srgb, var(--jd-color-primary) 50%, transparent);
    }
    /* :active는 선택·포커스 규칙 **뒤에** 둔다 — 앞에 두면 같은 특이도라 이미 선택된
     칸을 눌렀을 때 아무 반응이 없다. 셀은 scale로 누르지 않는다: 이웃과 선을 맞대고
     있어 한 칸만 줄면 격자가 흔들린다. 대신 면이 빛을 잃게 한다. */
    .jd-cm__cell:active {
      background: color-mix(in srgb, var(--jd-color-muted) 14%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }

    .jd-cm__num {
      align-self: flex-start;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.5rem;
      height: 1.5rem;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-cm__cell[data-today] > .jd-cm__num {
      background: var(--jd-color-primary);
      color: #fff;
      font-weight: var(--jd-weight-bold);
    }

    .jd-cm__events {
      list-style: none;
      margin: 0;
      padding: 0;
      flex: 1;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      overflow: hidden;
    }
    /* 색 변종은 **앵커색 한 줄**만 바꾼다 — 배경·글자·호버를 변종마다 다시 적으면
     상태를 하나 늘릴 때 6곳을 고쳐야 하고 실제로 호버가 primary에만 붙어 있었다.
     원색을 옅은 틴트 위에 그대로 두면 라이트 모드 대비가 무너지므로 글자는
     foreground 쪽으로 당긴다(테마 적응). */
    .jd-cm__event {
      --jd-cm-event-tone: var(--jd-color-primary);
      display: block;
      width: 100%;
      text-align: left;
      border: 0;
      border-radius: var(--jd-radius-sm);
      padding: 0.0625rem var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
      cursor: pointer;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      background: color-mix(in srgb, var(--jd-cm-event-tone) 15%, transparent);
      color: color-mix(in srgb, var(--jd-cm-event-tone) 65%, var(--jd-color-foreground));
      transition: background var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-cm__event[data-color="success"] {
      --jd-cm-event-tone: var(--jd-color-success);
    }
    .jd-cm__event[data-color="warning"] {
      --jd-cm-event-tone: var(--jd-color-warning);
    }
    .jd-cm__event[data-color="danger"] {
      --jd-cm-event-tone: var(--jd-color-danger);
    }
    .jd-cm__event[data-color="info"] {
      --jd-cm-event-tone: var(--jd-color-info);
    }
    .jd-cm__event[data-color="accent"] {
      --jd-cm-event-tone: var(--jd-color-accent);
    }
    .jd-cm__event:hover {
      background: color-mix(in srgb, var(--jd-cm-event-tone) 26%, transparent);
    }
    .jd-cm__event:active {
      scale: 0.97;
    }
    /* 링을 **안쪽**에 그린다 — 이벤트 목록(.jd-cm__events)이 overflow:hidden이라
     바깥으로 그린 outline도 box-shadow도 그대로 잘려 나간다 */
    .jd-cm__event:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(var(--jd-focus-ring-offset) * -1);
    }

    .jd-cm__more {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      padding-left: var(--jd-space-1-5);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cm__arrow,
      .jd-cm__today,
      .jd-cm__cell,
      .jd-cm__event {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-callout {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      border-inline-start: var(--jd-border-thick) solid var(--_jd-callout-color);
      border-radius: var(--jd-radius-md);
      background: color-mix(in srgb, var(--_jd-callout-color) 5%, transparent);
      --_jd-callout-color: var(--jd-color-muted); /* variant 기본 note */
    }
    jd-callout[variant="tip"] {
      --_jd-callout-color: var(--jd-color-success);
    }
    jd-callout[variant="info"] {
      --_jd-callout-color: var(--jd-color-info);
    }
    jd-callout[variant="warning"] {
      --_jd-callout-color: var(--jd-color-warning);
    }
    jd-callout[variant="danger"] {
      --_jd-callout-color: var(--jd-color-danger);
    }

    .jd-callout__head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: color-mix(in srgb, var(--_jd-callout-color) 65%, var(--jd-color-foreground));
    }
    summary.jd-callout__head {
      cursor: pointer;
      list-style: none;
    }
    summary.jd-callout__head::-webkit-details-marker {
      display: none;
    }
    /* 네이티브 마커 대신 방향 표시 — details[open]이 상태를 준다 */
    summary.jd-callout__head::after {
      content: "\\25BE";
      margin-inline-start: auto;
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    details[open] > summary.jd-callout__head::after {
      transform: rotate(180deg);
    }
    summary.jd-callout__head:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-callout__icon {
      flex-shrink: 0;
    }
    .jd-callout__title[hidden] {
      display: none;
    }

    .jd-callout__body {
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-callout__head + .jd-callout__body,
    details .jd-callout__body {
      margin-block-start: var(--jd-space-2);
    }

    @media (prefers-reduced-motion: reduce) {
      summary.jd-callout__head::after {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }


    jd-candle-chart {
      display: inline-block;
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --_up: var(--jd-fin-up);
      --_down: var(--jd-fin-down);
      --_grid: var(--jd-fin-grid, color-mix(in srgb, var(--jd-color-border) 70%, transparent));
      --_axis: var(--jd-fin-muted, var(--jd-color-muted));
      /* 마커·현재가 배지는 등락이 아니라 강조다 — 민트 리터럴은 팔레트 밖이었다(§8) */
      --_accent: var(--jd-fin-accent, var(--jd-color-primary));
      /* 이동평균 선색은 element의 MA_COLOR가 --jd-fin-cat-*로 참조한다. 그 변수를 아무도
       정의하지 않아 v2 승계 리터럴(#22c55e·#f59e0b·#ef4444·#a855f7·#ec4899)이 그대로
       발화했다 — 형광 다섯 줄이 캔들 위에서 서로 싸운다(§8). 기본값을 여기서 hue 램프로
       정의하면 리터럴은 더 이상 발화하지 않고, 소비자는 이 변수만 바꿔 갈아끼운다
       (jd-quarter-bar-chart의 --jd-qbar-* 선례). */
      --jd-fin-cat-1: var(--jd-color-hue-amber);
      --jd-fin-cat-2: var(--jd-color-hue-teal);
      --jd-fin-cat-4: var(--jd-color-hue-rose);
      --jd-fin-cat-6: var(--jd-color-hue-violet);
      --jd-fin-cat-7: var(--jd-color-hue-blue);
      /* DEFAULT_MA 밖의 기간은 element가 var(--jd-fin-muted, #94a3b8)로 떨어진다 —
       그 슬레이트 리터럴도 발화하지 않게 여기서 muted를 잡아 준다 */
      --jd-fin-muted: var(--jd-color-muted);
    }

    /* viewBox가 비율을 말하므로 height:auto면 좁은 카드 안에서도 잘리지 않고 줄어든다(§6) */
    .jd-candle-chart__svg {
      display: block;
      max-width: 100%;
      height: auto;
      cursor: crosshair;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
    }

    /* 격자·축 */
    .jd-candle-chart__gridline {
      stroke: var(--_grid);
      stroke-dasharray: 2 4;
      shape-rendering: crispEdges;
    }
    .jd-candle-chart__axis-label {
      font-size: 10px;
      fill: var(--_axis);
    }

    /* 캔들 */
    .jd-candle-chart__candle[data-dir="up"] {
      --_c: var(--_up);
    }
    .jd-candle-chart__candle[data-dir="down"] {
      --_c: var(--_down);
    }
    .jd-candle-chart__wick {
      stroke: var(--_c);
      stroke-width: 1;
    }
    .jd-candle-chart__body {
      fill: var(--_c);
      stroke: none;
    }
    .jd-candle-chart__candle[data-last] .jd-candle-chart__body {
      stroke: var(--_c);
      stroke-width: 1.2;
    }

    /* 라인/에어리어 표현 */
    .jd-candle-chart__price-line {
      fill: none;
      stroke: var(--_up);
      stroke-width: 1.6;
      stroke-linejoin: round;
      stroke-linecap: round;
    }
    .jd-candle-chart__area {
      stroke: none;
      opacity: 0.4;
    }
    .jd-candle-chart__area-stop0 {
      stop-color: var(--_up);
      stop-opacity: 0.45;
    }
    .jd-candle-chart__area-stop1 {
      stop-color: var(--_up);
      stop-opacity: 0;
    }

    /* 이동평균 — 색은 인라인 --_ma */
    .jd-candle-chart__ma {
      fill: none;
      stroke: var(--_ma, var(--jd-fin-muted, var(--jd-color-neutral-400)));
      stroke-width: 1.4;
      stroke-linejoin: round;
      stroke-linecap: round;
      opacity: 0.85;
    }

    /* 오버레이 지표 */
    /* 지표 오버레이(BB·VWAP)는 등락이 아니라 계열이다 — 형광 초록/주황 리터럴 대신
     팔레트 안에서 뽑아 캔들과 색이 싸우지 않게 한다(§8) */
    .jd-candle-chart__bb {
      fill: none;
      stroke: var(--jd-fin-success, var(--jd-color-hue-teal));
      stroke-width: 1;
    }
    .jd-candle-chart__bb--band {
      stroke-dasharray: 2 3;
      opacity: 0.7;
    }
    .jd-candle-chart__bb--mid {
      opacity: 0.5;
    }
    .jd-candle-chart__vwap {
      fill: none;
      stroke: var(--jd-fin-warning, var(--jd-color-hue-amber));
      stroke-width: 1.2;
      stroke-dasharray: 4 3;
      opacity: 0.8;
    }
    .jd-candle-chart__compare {
      fill: none;
      stroke: var(--_line, var(--jd-fin-muted, var(--jd-color-neutral-400)));
      stroke-width: 1.4;
      stroke-dasharray: 5 3;
      opacity: 0.85;
    }
    .jd-candle-chart__separator {
      stroke: var(--_axis);
      stroke-width: 1;
    }

    /* 거래량 */
    .jd-candle-chart__vol[data-dir="up"] {
      fill: color-mix(in srgb, var(--_up) 55%, transparent);
    }
    .jd-candle-chart__vol[data-dir="down"] {
      fill: color-mix(in srgb, var(--_down) 55%, transparent);
    }

    /* 마커 */
    .jd-candle-chart__marker {
      --_mk: var(--_accent);
    }
    .jd-candle-chart__marker-line {
      stroke: var(--_mk);
      stroke-width: 1.5;
    }
    .jd-candle-chart__marker[data-live] .jd-candle-chart__marker-line {
      stroke-dasharray: 5 4;
      opacity: 0.85;
    }
    .jd-candle-chart__marker-pulse {
      fill: var(--_mk);
      opacity: 0.25;
    }
    .jd-candle-chart__marker-dot {
      fill: var(--_mk);
    }
    .jd-candle-chart__marker-badge,
    .jd-candle-chart__marker-price-bg {
      fill: var(--_mk);
    }
    .jd-candle-chart__marker-label,
    .jd-candle-chart__marker-price {
      fill: #fff;
      font-size: 10.5px;
      font-weight: 700;
    }
    .jd-candle-chart__marker-label {
      text-anchor: middle;
    }
    .jd-candle-chart__marker-price {
      text-anchor: end;
    }

    /* 이벤트 */
    .jd-candle-chart__event {
      --_ev: var(--_axis);
    }
    .jd-candle-chart__event-line {
      stroke: var(--_ev);
      stroke-dasharray: 3 3;
      opacity: 0.55;
    }
    .jd-candle-chart__event-dot {
      fill: var(--_ev);
    }
    .jd-candle-chart__event-label {
      fill: #fff;
      font-size: 9px;
      font-weight: 800;
      text-anchor: middle;
    }

    /* 현재가 */
    .jd-candle-chart__current[data-dir="up"] {
      --_c: var(--_up);
    }
    .jd-candle-chart__current[data-dir="down"] {
      --_c: var(--_down);
    }
    .jd-candle-chart__current-line {
      stroke: var(--_c);
      stroke-width: 1;
      stroke-dasharray: 2 3;
      opacity: 0.6;
    }
    .jd-candle-chart__current-bg {
      fill: var(--_c);
    }
    .jd-candle-chart__current-text {
      fill: #fff;
      font-size: 10.5px;
      font-weight: 700;
      text-anchor: end;
    }

    /* x라벨 */
    .jd-candle-chart__xlabel {
      font-size: 10px;
      font-weight: 500;
      fill: var(--_axis);
    }
    .jd-candle-chart__xlabel[data-bold] {
      font-weight: 700;
    }

    /* 크로스헤어 + 툴팁 */
    .jd-candle-chart__crosshair-line {
      stroke: var(--_axis);
      stroke-dasharray: 3 3;
    }
    /* 툴팁 면은 라이트에서도 어두운 surface다 — 그 위의 잉크는 모드를 따라가면 안 된다.
     neutral-200/400은 다크에서 뒤집혀 어두운 면에 어두운 글자를 얹었다(§4, DEC-044).
     등락 틴트도 리터럴 대신 훅에서 파생해 앱의 관례 전환을 그대로 따른다. */
    .jd-candle-chart__tooltip {
      --_tt-up: color-mix(in srgb, var(--_up) 55%, #fff);
      --_tt-down: color-mix(in srgb, var(--_down) 55%, #fff);
    }
    .jd-candle-chart__tooltip-bg {
      fill: var(--jd-fin-tooltip-bg, var(--jd-color-surface-overlay));
      stroke: var(
        --jd-fin-tooltip-border,
        color-mix(in srgb, var(--jd-color-on-surface) 22%, transparent)
      );
      stroke-width: 1;
    }
    .jd-candle-chart__tooltip-idx {
      fill: var(--jd-fin-tooltip-muted, var(--jd-color-on-surface-muted));
      font-size: 10.5px;
      font-weight: 700;
    }
    /* 원색 등락색은 어두운 툴팁 면 위에서 대비가 3:1을 못 넘긴다 — 같은 색의 밝은 틴트로
     올린다(아래 tooltip-row와 같은 값). */
    .jd-candle-chart__tooltip[data-dir="up"] .jd-candle-chart__tooltip-pct {
      fill: var(--_tt-up);
    }
    .jd-candle-chart__tooltip[data-dir="down"] .jd-candle-chart__tooltip-pct {
      fill: var(--_tt-down);
    }
    .jd-candle-chart__tooltip-pct {
      font-size: 10.5px;
      font-weight: 800;
      text-anchor: end;
    }
    .jd-candle-chart__tooltip-key {
      fill: var(--jd-fin-tooltip-muted, var(--jd-color-on-surface-muted));
      font-size: 10.5px;
    }
    .jd-candle-chart__tooltip-val {
      fill: var(--jd-fin-tooltip-fg, var(--jd-color-on-surface));
      font-size: 10.5px;
      font-weight: 700;
      text-anchor: end;
    }
    .jd-candle-chart__tooltip-row[data-tone="up"] .jd-candle-chart__tooltip-val {
      fill: var(--_tt-up);
    }
    .jd-candle-chart__tooltip-row[data-tone="down"] .jd-candle-chart__tooltip-val {
      fill: var(--_tt-down);
    }
  }

  @layer junds.base {
    jd-card:not(:defined),
    jd-card-header:not(:defined),
    jd-card-body:not(:defined),
    jd-card-footer:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-card {
      display: block;
      box-sizing: border-box; /* 스타일 프롭 w/maxW + border 병용 (DEC-014-9) */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-card) 95%, transparent);
      -webkit-backdrop-filter: blur(4px);
      backdrop-filter: blur(4px);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 60%, transparent);
      border-radius: var(--jd-radius-2xl);
      /* v2의 rgba 리터럴 그림자는 다크에서 검정 위 검정이라 사라졌다 — 모드별로
       값이 갈리는 토큰으로 옮기고, 위에서 받는 빛 한 겹을 더한다(§2). */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      transition: box-shadow var(--jd-duration-slow) var(--jd-easing-ease-out),
        transform var(--jd-duration-slow) var(--jd-easing-ease-out),
        border-color var(--jd-duration-slow) var(--jd-easing-ease-out);
    }

    jd-card[hoverable] {
      cursor: pointer;
    }
    /* :focus-within — 키보드 사용자도 같은 피드백을 받는다(v2에는 없었다) */
    jd-card[hoverable]:hover,
    jd-card[hoverable]:focus-within {
      box-shadow: var(--jd-shadow-lg), inset 0 1px 0 var(--jd-color-highlight);
      border-color: var(--jd-color-border);
    }
    /* 누른 순간은 빛을 잃는다(§1) — 상승도 함께 거둔다 */
    jd-card[hoverable]:active {
      box-shadow: var(--jd-shadow-xs), inset 0 1px 2px var(--jd-color-shade);
      transform: none;
    }
    jd-card[hoverable]:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-lg), var(--jd-shadow-focus-ring);
    }
    @media (prefers-reduced-motion: no-preference) {
      jd-card[hoverable]:hover,
      jd-card[hoverable]:focus-within {
        transform: translateY(-2px);
      }
    }

    jd-card-header {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-4) var(--jd-space-6);
      border-block-end: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 40%, transparent);
    }
    /* 헤더뿐인 카드(본문·바닥 없음)에서는 구분선이 나눌 것이 없다. 그대로 두면 선이
     카드의 둥근 아래 모서리를 가로질러 제목 둘레에 어중간한 테두리를 만든다 —
     실측된 "헤더가 깨져 보인다"의 정체다. 같은 이유로 바닥만 있는 카드도 막는다. */
    jd-card-header:last-child {
      border-block-end: 0;
    }
    jd-card-footer:first-child {
      border-block-start: 0;
    }
    .jd-card-header__title {
      margin: 0;
      font-size: var(--jd-text-lg); /* v2 text-base = 1rem */
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
    }

    jd-card-body {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-4) var(--jd-space-5);
    }

    jd-card-footer {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-3-5) var(--jd-space-6);
      border-block-start: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 40%, transparent);
      /* v2 bg-gray-50/30 — 배경 토큰 30%로 번역해 다크에서도 "카드보다 한 톤" 유지 */
      background: color-mix(in srgb, var(--jd-color-background) 30%, transparent);
      border-end-start-radius: var(--jd-radius-2xl);
      border-end-end-radius: var(--jd-radius-2xl);
    }
    jd-card-footer:first-child {
      border-start-start-radius: var(--jd-radius-2xl);
      border-start-end-radius: var(--jd-radius-2xl);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-card {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-carousel {
      display: block;
      position: relative;
      font-family: var(--jd-font-sans);
    }

    .jd-carousel__track {
      display: flex;
      overflow-x: auto;
      scroll-snap-type: x mandatory;
      scrollbar-width: none; /* v2 overflow-x-hidden의 의미(스크롤바 없음)를 유지하되 */
      overscroll-behavior-x: contain;
    }
    .jd-carousel__track::-webkit-scrollbar {
      display: none;
    }

    .jd-carousel__slide {
      flex: 0 0 100%;
      max-width: 100%;
      scroll-snap-align: start;
    }

    .jd-carousel__arrow {
      position: absolute;
      inset-block-start: 50%;
      transform: translateY(-50%);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      padding: 0;
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-card) 80%, transparent);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      box-shadow: var(--jd-shadow-sm);
      cursor: pointer;
      opacity: var(--jd-opacity-0);
      transition: opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-carousel__arrow[hidden] {
      display: none;
    }
    .jd-carousel__arrow[data-dir="prev"] {
      inset-inline-start: var(--jd-space-2);
    }
    .jd-carousel__arrow[data-dir="next"] {
      inset-inline-end: var(--jd-space-2);
    }
    .jd-carousel__arrow > svg {
      width: 1rem;
      height: 1rem;
    }
    jd-carousel:hover .jd-carousel__arrow,
    jd-carousel:focus-within .jd-carousel__arrow {
      opacity: var(--jd-opacity-100);
    }
    .jd-carousel__arrow:hover {
      background: var(--jd-color-card);
    }
    .jd-carousel__arrow:focus-visible {
      opacity: var(--jd-opacity-100);
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-carousel__arrow:disabled {
      opacity: var(--jd-opacity-30);
      cursor: not-allowed;
    }
    /* 포인터가 없는 기기에서는 hover가 없다 — 화살표를 상시 노출한다 */
    @media (hover: none) {
      .jd-carousel__arrow {
        opacity: var(--jd-opacity-100);
      }
    }

    .jd-carousel__dots {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      margin-block-start: var(--jd-space-3);
    }
    .jd-carousel__dots[hidden] {
      display: none;
    }
    .jd-carousel__dot {
      width: 0.5rem;
      height: 0.5rem;
      padding: 0;
      background: var(--jd-color-border);
      border: 0;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      transition: width var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-carousel__dot:hover {
      background: var(--jd-color-muted);
    }
    .jd-carousel__dot[data-active] {
      width: 1rem;
      background: var(--jd-color-foreground);
    }
    .jd-carousel__dot:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    @media (prefers-reduced-motion: no-preference) {
      .jd-carousel__track {
        scroll-behavior: smooth;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-carousel__arrow,
      .jd-carousel__dot {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-cart-item:not(:defined) {
      display: flex;
    }
  }
  @layer junds.components {
    jd-cart-item {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto auto auto;
      grid-template-rows: auto auto 1fr;
      align-items: start;
      /* 칸 사이 여백은 column-gap이 아니라 **앞 칸의 뒷여백**이다. gap은 칸이 비어도
       (썸네일 없음·삭제 없음) 그대로 남아 행이 한쪽으로 밀린다 — 마진은 사라진 칸과
       함께 사라진다. */
      column-gap: 0;
      padding-block: var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-cart-item:last-of-type {
      border-block-end: none;
    }
    jd-cart-item[disabled] {
      opacity: var(--jd-opacity-60);
    }

    .jd-cart-item__thumb {
      display: block;
      grid-column: 1;
      grid-row: 1 / -1;
      align-self: center;
      flex-shrink: 0;
      width: 5rem;
      height: 5rem;
      margin-inline-end: var(--jd-space-4);
      border-radius: var(--jd-radius-lg);
      overflow: hidden;
      background: var(--jd-color-background);
      /* 빈 자리도 면이어야 한다 — 이미지가 늦게 뜰 때 구멍으로 보이지 않게(§2) */
      box-shadow: inset 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
    }
    /* display 지정 요소는 [hidden]이 안 먹으므로 명시 가드 */
    .jd-cart-item__thumb[hidden],
    .jd-cart-item__variant[hidden],
    .jd-cart-item__price[hidden] {
      display: none;
    }
    .jd-cart-item__image {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    /* 래퍼를 풀어 자식이 곧 그리드 칸이 된다 — 골격은 v2 그대로 남는다 */
    .jd-cart-item__body,
    .jd-cart-item__aside {
      display: contents;
    }

    .jd-cart-item__title {
      grid-column: 2;
      grid-row: 1;
      margin: 0 var(--jd-space-4) 0 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .jd-cart-item__variant {
      display: block;
      grid-column: 2;
      grid-row: 2;
      margin: var(--jd-space-0-5) var(--jd-space-4) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    /* 단가는 **소계의 보조**다. 같은 크기로 두면 한 행에 금액이 두 번 있는 것으로
     읽힌다 — 한 단 작게, muted로, 숫자는 자릿수가 흔들리지 않게(§5). */
    .jd-cart-item__price {
      display: block;
      grid-column: 2;
      grid-row: 3;
      margin: var(--jd-space-1-5) var(--jd-space-4) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-cart-item__qty {
      grid-column: 3;
      grid-row: 1 / -1;
      align-self: center;
      justify-self: start;
      margin-inline-end: var(--jd-space-4);
    }

    .jd-cart-item__subtotal {
      grid-column: 4;
      grid-row: 1 / -1;
      align-self: center;
      justify-self: end;
      margin-inline-end: var(--jd-space-2);
      /* 이 행에서 결제되는 금액 — 단가보다 한 단 크고 무겁게 */
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    /* 맨 텍스트는 트리거가 아니다(§7) — 눌리는 면을 주고 상태 3종을 붙인다 */
    .jd-cart-item__remove {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      grid-column: 5;
      grid-row: 1 / -1;
      align-self: center;
      padding: var(--jd-space-1-5) var(--jd-space-2-5);
      border: 0;
      border-radius: var(--jd-radius-lg);
      background: transparent;
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-cart-item__remove[hidden] {
      display: none;
    }
    .jd-cart-item__remove:hover:not(:disabled) {
      color: var(--jd-color-danger);
      background: var(--jd-color-danger-light);
    }
    .jd-cart-item__remove:active:not(:disabled) {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-cart-item__remove:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-cart-item__remove:focus-visible {
      outline: var(--jd-focus-ring-danger);
      outline-offset: var(--jd-focus-ring-offset);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cart-item__remove {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-center {
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }

  @layer junds.components {
    jd-chapter-list {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
    }

    .jd-chapter-list__root,
    .jd-chapter-list__sub {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-chapter-list__sub {
      margin-block-start: var(--jd-space-0-5);
    }

    .jd-chapter-list__row {
      width: 100%;
      box-sizing: border-box;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding-block: var(--jd-space-2);
      padding-inline-end: var(--jd-space-3);
      text-align: left;
      cursor: pointer;
      font-family: inherit;
      font-size: inherit;
      color: var(--jd-color-foreground);
      background: transparent;
      border: 0;
      border-radius: var(--jd-radius-md);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-chapter-list__row:hover:not(:disabled) {
      background: var(--jd-color-border-light);
    }
    .jd-chapter-list__row:active:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-chapter-list__row:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    /* 활성 글자는 primary를 foreground와 섞지 않는다 — 다크에서 어두운 앵커가 옅은
     틴트 위에 얹혀 대비가 무너진다. 링크 잉크 토큰이 두 모드를 이미 갈라 둔다. */
    .jd-chapter-list__row[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 12%, transparent);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-chapter-list__row[data-done] {
      color: var(--jd-color-muted);
    }
    .jd-chapter-list__row:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-chapter-list__lead {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-chapter-list__title {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-chapter-list__marker {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.25rem;
      height: 1.25rem;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
      color: var(--jd-color-muted);
    }
    .jd-chapter-list__marker[data-active] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 완독 마커도 톤 레시피를 경유한다 — 혼합비만 모드를 따라가면 분기가 필요 없다 */
    .jd-chapter-list__marker[data-done]:not([data-active]) {
      --jd-tone: var(--jd-color-success);
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(
        in srgb,
        var(--jd-tone-face) var(--jd-tone-bg-strong-mix),
        transparent
      );
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }

    .jd-chapter-list__meta {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-chapter-list__meta[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-chapter-list__row {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-chart-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-chart-card {
      display: block;
      box-sizing: border-box;
      width: 100%;
      --jd-cc-track: color-mix(in srgb, var(--jd-color-muted) 15%, transparent);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      transition: border-color var(--jd-duration-normal) var(--jd-easing-default);
    }
    jd-chart-card[variant="card"] {
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-4);
      box-shadow: var(--jd-shadow-xs);
    }

    /* 헤더 */
    .jd-chart-card__head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__heading {
      min-width: 0;
    }
    .jd-chart-card__title-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-chart-card__title {
      margin: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__badge {
      flex-shrink: 0;
    }
    .jd-chart-card__badge:empty,
    .jd-chart-card__actions:empty {
      display: none;
    }
    .jd-chart-card__desc {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__desc[hidden] {
      display: none;
    }
    .jd-chart-card__actions {
      flex-shrink: 0;
    }

    /* KPI */
    .jd-chart-card__kpi {
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-block-start: var(--jd-space-4);
    }
    .jd-chart-card__kpi[hidden] {
      display: none;
    }
    .jd-chart-card__value {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__value[hidden] {
      display: none;
    }

    .jd-chart-card__trend {
      display: inline-flex;
      flex-shrink: 0;
      align-items: center;
      gap: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      padding: var(--jd-space-1) var(--jd-space-2);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-chart-card__trend[hidden] {
      display: none;
    }
    /* 증감 배지는 등락이다 — success/danger를 직접 칠하면 한국 관례(적상승)로 전환한 앱에서
     이 카드만 옛 색으로 남아 같은 화면의 price-badge와 갈라진다. 훅을 경유한다(§8). */
    .jd-chart-card__trend[data-direction="up"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 14%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 65%,
        var(--jd-color-foreground)
      );
    }
    .jd-chart-card__trend[data-direction="down"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 14%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 65%,
        var(--jd-color-foreground)
      );
    }
    .jd-chart-card__trend[data-direction="neutral"] {
      background: var(--jd-cc-track);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__trend-icon[data-flip] {
      transform: rotate(180deg);
    }
    .jd-chart-card__trend-label {
      font-weight: var(--jd-weight-normal);
      opacity: 0.8;
    }

    /* 차트 영역 */
    .jd-chart-card__chart {
      margin-block-start: var(--jd-space-3);
    }
    .jd-chart-card__kpi:not([hidden]) + .jd-chart-card__chart {
      margin-block-start: var(--jd-space-4);
    }

    /* 푸터 */
    .jd-chart-card__footer {
      margin-block-start: var(--jd-space-4);
      padding-block-start: var(--jd-space-3);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-chart-card__footer:empty {
      display: none;
    }

    /* ── bar (세로) ── */
    .jd-chart-card__bar-wrap {
      position: relative;
    }
    .jd-chart-card__grid {
      pointer-events: none;
      position: absolute;
      inset-inline: 0;
      top: 20px;
      bottom: 20px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }
    .jd-chart-card__gridline {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-chart-card__bars {
      position: relative;
      z-index: 1;
      display: flex;
      height: 100%;
      align-items: flex-end;
      gap: var(--jd-space-2);
      padding-block-start: var(--jd-space-5);
    }
    .jd-chart-card__bar-col {
      display: flex;
      height: 100%;
      min-width: 0;
      flex: 1 1 0;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-chart-card__bar-val {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__bar-track {
      display: flex;
      width: 100%;
      flex: 1 1 0;
      align-items: flex-end;
    }
    /* 막대는 트랙 위에 선 실체다 — 윗면 인셋 하이라이트가 없으면 색종이로 읽힌다 */
    .jd-chart-card__bar {
      width: 100%;
      border-radius: var(--jd-radius-md) var(--jd-radius-md) 0 0;
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      transition: height var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-chart-card__bar-label {
      width: 100%;
      text-align: center;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }

    /* ── horizontal-bar ── */
    .jd-chart-card__hbars {
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__hrow {
      display: grid;
      grid-template-columns: minmax(4rem, 7rem) 1fr auto;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__hlabel {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__htrack {
      height: 0.625rem;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-cc-track);
    }
    .jd-chart-card__hfill {
      height: 100%;
      border-radius: var(--jd-radius-full);
      transition: width var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-chart-card__hval {
      min-width: 2rem;
      text-align: right;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }

    /* ── stacked-bar ── */
    .jd-chart-card__stacked {
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__srows {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__srow {
      display: grid;
      grid-template-columns: minmax(4rem, 6rem) 1fr auto;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-chart-card__slabel {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__strack {
      display: flex;
      height: 0.75rem;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-cc-track);
    }
    .jd-chart-card__sseg {
      height: 100%;
      transition: width var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-chart-card__stotal {
      min-width: 2rem;
      text-align: right;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }

    /* ── line / area / sparkline (SVG) ── */
    .jd-chart-card__svg {
      display: block;
      width: 100%;
      overflow: visible;
    }
    .jd-chart-card__svg-gridline {
      stroke: var(--jd-color-border-light);
      stroke-width: 1;
    }
    .jd-chart-card__area {
      fill-opacity: 0.16;
      stroke: none;
    }
    .jd-chart-card__line {
      fill: none;
      stroke-width: 2.5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .jd-chart-card__dot {
      fill: var(--jd-color-card);
      stroke-width: 2;
    }
    .jd-chart-card__spark-end {
      stroke: none;
    }
    .jd-chart-card__axis {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__axis span {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-chart-card__axis-max {
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__spark-meta {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__spark-val {
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }

    /* ── donut / radial (ring) ── */
    .jd-chart-card__donut,
    .jd-chart-card__radial {
      display: flex;
      align-items: center;
      gap: var(--jd-space-5);
    }
    .jd-chart-card__ring {
      flex-shrink: 0;
    }
    .jd-chart-card__ring-bg {
      stroke: var(--jd-color-border-light);
    }
    .jd-chart-card__arc {
      transform-box: view-box;
      transform-origin: center;
      transform: rotate(-90deg);
      transition: stroke-dasharray var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-chart-card__ring-total {
      fill: var(--jd-color-foreground);
      font-weight: var(--jd-weight-bold);
    }
    .jd-chart-card__donut .jd-chart-card__ring-total {
      font-size: 6px;
    }
    .jd-chart-card__radial .jd-chart-card__ring-total {
      font-size: 7px;
    }
    .jd-chart-card__ring-sub {
      fill: var(--jd-color-muted);
      font-size: 3px;
    }
    .jd-chart-card__radial-detail {
      min-width: 0;
      flex: 1 1 auto;
    }
    .jd-chart-card__radial-name {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__radial-sub {
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-chart-card__radial-track {
      margin-block-start: var(--jd-space-3);
      height: 0.375rem;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-cc-track);
    }
    .jd-chart-card__radial-fill {
      height: 100%;
      border-radius: var(--jd-radius-full);
    }

    /* ── progress ── */
    .jd-chart-card__progress {
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: var(--jd-space-4);
    }
    .jd-chart-card__prog-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-1-5);
    }
    .jd-chart-card__prog-label {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-chart-card__prog-val {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-muted);
    }
    .jd-chart-card__prog-track {
      height: 0.5rem;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-cc-track);
    }
    .jd-chart-card__prog-fill {
      height: 100%;
      border-radius: var(--jd-radius-full);
      transition: width var(--jd-duration-slow) var(--jd-easing-ease-out);
    }

    /* ── 범례 ── */
    .jd-chart-card__legend {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-chart-card__legend--flex {
      flex: 1 1 auto;
    }
    .jd-chart-card__legend-item {
      display: flex;
      min-width: 0;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
    }
    /* 8px 점은 카드 배경과 명도가 가까운 계열색일 때 사라진다 — 실낱 링이 자리를 지킨다 */
    .jd-chart-card__legend-swatch {
      width: 0.5rem;
      height: 0.5rem;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      box-shadow: 0 0 0 var(--jd-border-thin) var(--jd-color-shade);
    }
    .jd-chart-card__legend-label {
      min-width: 0;
      flex: 1 1 auto;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    .jd-chart-card__legend-val {
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }

    /* ── skeleton / empty ── */
    .jd-chart-card__skeleton {
      display: flex;
      align-items: flex-end;
      gap: var(--jd-space-2);
    }
    .jd-chart-card__skeleton-bar {
      flex: 1 1 0;
      border-radius: var(--jd-radius-md) var(--jd-radius-md) 0 0;
      background: color-mix(in srgb, var(--jd-color-muted) 22%, transparent);
      animation: jd-chart-card-pulse 1.4s var(--jd-easing-ease-in-out) infinite;
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-chart-card__skeleton-bar {
        animation: none;
      }
    }
    @keyframes jd-chart-card-pulse {
      0%,
      100% {
        opacity: 1;
      }
      50% {
        opacity: 0.45;
      }
    }
    .jd-chart-card__empty {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-lg);
      border: var(--jd-border-thin) dashed var(--jd-color-border);
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
  }

  @layer junds.components {
    jd-chart-range-picker {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      --_accent: var(--jd-fin-accent, var(--jd-color-primary));
      /* 활성 글자는 틴트 위에 앉는다 — 앵커를 라이트에서는 잉크 쪽, 다크에서는 흰 쪽으로
       미는 톤 잉크 공식(DEC-044)으로 뽑아야 한 값이 양쪽 모드에서 다 읽힌다.
       --jd-fin-accent-strong를 주는 앱은 그 값이 그대로 이긴다. */
      --_accent-strong: var(
        --jd-fin-accent-strong,
        color-mix(in srgb, var(--_accent) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward))
      );
      --_soft: var(--jd-fin-soft-100, var(--jd-color-neutral-100));
      --_text: var(--jd-fin-text, var(--jd-color-foreground));
      --_border: var(--jd-fin-border, var(--jd-color-border));
    }

    .jd-chart-range-picker__pill {
      appearance: none;
      margin: 0;
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-none);
      font-family: inherit;
      cursor: pointer;
      background: var(--_soft);
      color: var(--_text);
      border: var(--jd-border-thin) solid var(--_border);
      box-shadow: var(--jd-shadow-xs);
      /* all 금지 — 대상 속성을 지목한다(DEC-039) */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-chart-range-picker__pill:hover {
      background: color-mix(in srgb, var(--_accent) 8%, var(--_soft));
      border-color: color-mix(in srgb, var(--_accent) 30%, var(--_border));
    }
    /* 눌린 면은 빛을 잃는다 */
    .jd-chart-range-picker__pill:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 선택된 칩은 강조 틴트 위 강조 글자. 12%로는 이웃한 비활성 칩과 구분이 안 붙어
     bg-strong-mix(라이트 22% / 다크 40%)를 쓴다 — 면은 앵커 하나에서만 파생하므로
     --jd-fin-accent를 바꾸는 앱은 선택 표시도 함께 따라온다. */
    .jd-chart-range-picker__pill[data-active] {
      background: color-mix(in srgb, var(--_accent) var(--jd-tone-bg-strong-mix), transparent);
      color: var(--_accent-strong);
      border-color: color-mix(in srgb, var(--_accent) 34%, transparent);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-chart-range-picker__pill:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-chart-range-picker__pill {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-chat-bubble {
      display: flex;
      gap: var(--jd-space-2);
      max-inline-size: 80%;
      font-family: var(--jd-font-sans);
    }
    jd-chat-bubble[side="right"] {
      margin-inline-start: auto;
      flex-direction: row-reverse;
    }

    .jd-chat-bubble__avatar {
      flex-shrink: 0;
      margin-block-start: auto;
    }
    .jd-chat-bubble__avatar[hidden] {
      display: none;
    }

    .jd-chat-bubble__main {
      min-inline-size: 0;
    }

    .jd-chat-bubble__sender,
    .jd-chat-bubble__time {
      display: block;
      margin: 0;
      padding-inline: var(--jd-space-1);
      font-size: 10px;
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-muted);
    }
    .jd-chat-bubble__sender {
      margin-block-end: var(--jd-space-0-5);
    }
    .jd-chat-bubble__time {
      margin-block-start: var(--jd-space-0-5);
    }
    .jd-chat-bubble__sender[hidden],
    .jd-chat-bubble__time[hidden] {
      display: none;
    }
    jd-chat-bubble[side="right"] .jd-chat-bubble__sender,
    jd-chat-bubble[side="right"] .jd-chat-bubble__time {
      text-align: end;
    }

    .jd-chat-bubble__bubble {
      padding: var(--jd-space-2) var(--jd-space-3-5);
      border-radius: var(--jd-radius-2xl);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      overflow-wrap: anywhere;
      background: color-mix(in srgb, var(--jd-color-muted) 14%, var(--jd-color-card));
      color: var(--jd-color-foreground);
      /* 꼬리 — 기본(left)은 좌하단, right는 우하단만 각진다 */
      border-end-start-radius: var(--jd-radius-sm);
    }
    jd-chat-bubble[side="right"] .jd-chat-bubble__bubble {
      border-end-start-radius: var(--jd-radius-2xl);
      border-end-end-radius: var(--jd-radius-sm);
    }
    jd-chat-bubble[variant="primary"] .jd-chat-bubble__bubble {
      background: var(--jd-color-primary);
      color: #fff;
    }
  }

  @layer junds.components {
    jd-chat-thread {
      display: flex;
      flex-direction: column;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      min-height: 0;
    }

    .jd-chat-thread__scroll {
      flex: 1;
      overflow-y: auto;
      /* 스레드 안에서 끝난 스크롤이 호스트 페이지를 이어서 밀지 않게 한다 */
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
      padding: var(--jd-space-4);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    .jd-chat-thread__groups {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }

    .jd-chat-thread__group {
      display: flex;
      gap: var(--jd-space-2);
    }
    .jd-chat-thread__group[data-mine] {
      flex-direction: row-reverse;
    }

    .jd-chat-thread__avatar {
      flex-shrink: 0;
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-full);
      overflow: hidden;
    }
    .jd-chat-thread__avatar img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .jd-chat-thread__avatar--ph {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      color: var(--jd-color-primary-ink);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
    }

    .jd-chat-thread__col {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      min-width: 0;
      max-width: 70%;
    }
    .jd-chat-thread__group[data-mine] .jd-chat-thread__col {
      align-items: flex-end;
    }
    .jd-chat-thread__name {
      margin: 0 0 0 var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }

    .jd-chat-thread__row {
      display: flex;
      align-items: flex-end;
      gap: var(--jd-space-1-5);
    }

    /* 버블은 클릭 가능한 <button> 이다 — hover/active/focus 3종을 모두 가진다(§1) */
    .jd-chat-thread__bubble {
      padding: var(--jd-space-2) var(--jd-space-3);
      border-radius: var(--jd-radius-2xl);
      font-size: var(--jd-text-sm);
      text-align: left;
      border: 0;
      cursor: pointer;
      background: color-mix(in srgb, var(--jd-color-muted) 14%, var(--jd-color-card));
      color: var(--jd-color-foreground);
      max-width: 100%;
      box-shadow: var(--jd-shadow-xs);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-chat-thread__bubble:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 22%, var(--jd-color-card));
    }
    .jd-chat-thread__bubble:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-chat-thread__group:not([data-mine]) .jd-chat-thread__bubble {
      border-bottom-left-radius: var(--jd-radius-md);
    }
    .jd-chat-thread__group[data-mine] .jd-chat-thread__bubble {
      background: var(--jd-color-primary);
      color: #fff;
      border-bottom-right-radius: var(--jd-radius-md);
      /* 채움만 있는 면은 색종이로 읽힌다 — 위에서 받는 빛을 함께 준다(§2) */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-chat-thread__group[data-mine] .jd-chat-thread__bubble:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-chat-thread__group[data-mine] .jd-chat-thread__bubble:active {
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-chat-thread__bubble[data-failed] {
      opacity: var(--jd-opacity-60);
    }
    .jd-chat-thread__bubble:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-chat-thread__text {
      white-space: pre-wrap;
      overflow-wrap: anywhere;
    }
    .jd-chat-thread__attachment {
      display: block;
      margin-top: var(--jd-space-2);
      max-width: 100%;
      border-radius: var(--jd-radius-lg);
    }

    /* 10px는 §9 하한(11px) 아래다 — 시각 하한 토큰으로 올린다 */
    .jd-chat-thread__status,
    .jd-chat-thread__time {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      margin-bottom: var(--jd-space-0-5);
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .jd-chat-thread__status {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-chat-thread__retry {
      border: 0;
      background: transparent;
      cursor: pointer;
      padding: 0;
      color: var(--jd-color-danger);
      font-size: var(--jd-text-2xs);
      border-radius: var(--jd-radius-sm);
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-chat-thread__retry:hover {
      text-decoration: underline;
    }
    .jd-chat-thread__retry:active {
      scale: 0.97;
    }
    .jd-chat-thread__retry:focus-visible {
      outline: var(--jd-focus-ring-danger);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-chat-thread__typing {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding-left: var(--jd-space-1);
    }
    .jd-chat-thread__typing[hidden] {
      display: none;
    }
    .jd-chat-thread__typing-dots {
      display: inline-flex;
      gap: var(--jd-space-1);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-radius: var(--jd-radius-2xl);
      background: color-mix(in srgb, var(--jd-color-muted) 14%, var(--jd-color-card));
    }
    .jd-chat-thread__typing-dots i {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-muted);
      animation: jd-chat-typing 1.2s infinite;
    }
    .jd-chat-thread__typing-dots i:nth-child(2) {
      animation-delay: 0.15s;
    }
    .jd-chat-thread__typing-dots i:nth-child(3) {
      animation-delay: 0.3s;
    }
    .jd-chat-thread__typing-text {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    @keyframes jd-chat-typing {
      0%,
      60%,
      100% {
        opacity: 0.3;
      }
      30% {
        opacity: 1;
      }
    }

    .jd-chat-thread__composer:empty {
      display: none;
    }
    .jd-chat-thread__composer {
      border-top: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      padding: var(--jd-space-2) var(--jd-space-3);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-chat-thread__bubble,
      .jd-chat-thread__retry {
        transition: none;
      }
      .jd-chat-thread__typing-dots i {
        animation: none;
        opacity: var(--jd-opacity-60);
      }
    }
  }

  @layer junds.components {
    jd-checkbox {
      display: inline-flex;
    }

    .jd-checkbox {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
      /* 표식 — 흰 스트로크는 primary 채움 위에서 두 모드 모두 정답 */
      --_jd-cb-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.6 8.5l2.8 2.8L12.5 5.2' fill='none' stroke='%23fff' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
      --_jd-cb-dash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.4 8h7.2' fill='none' stroke='%23fff' stroke-width='2.1' stroke-linecap='round'/%3E%3C/svg%3E");
    }
    /* disabled에 opacity를 통째로 걸면 라벨까지 흐려져 AA를 깬다 → 상자만 낮춘다 */
    jd-checkbox[disabled] > .jd-checkbox {
      cursor: not-allowed;
    }

    .jd-checkbox__input {
      appearance: none;
      -webkit-appearance: none;
      flex: none;
      margin: 0;
      padding: 0;
      cursor: inherit;
      /* 18px — v2의 16px는 14px 한글 라벨 옆에서 시각적으로 한 급 작게 읽힌다 */
      width: 1.125rem;
      height: 1.125rem;
      border: 1.5px solid var(--jd-color-neutral-300);
      border-radius: var(--jd-radius-md);
      background-color: var(--jd-color-control-surface);
      background-repeat: no-repeat;
      background-position: center;
      /* 미체크에서 표식은 크기 0 — 체크 시 100%로 자라며 나타난다 */
      background-size: 0% 0%;
      box-shadow: var(--jd-shadow-xs);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-size var(--jd-duration-snap) var(--jd-easing-overshoot),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-checkbox__input:hover:not(:disabled) {
      border-color: var(--jd-color-neutral-400);
      background-color: var(--jd-color-control-surface-hover);
    }
    /* 누르는 순간 상자가 살짝 들어간다 — 클릭이 '먹었다'는 유일한 즉시 신호 */
    .jd-checkbox__input:active:not(:disabled) {
      scale: 0.92;
    }

    .jd-checkbox__input:checked,
    .jd-checkbox__input:indeterminate {
      background-color: var(--jd-color-primary);
      border-color: var(--jd-color-primary);
      background-size: 100% 100%;
      box-shadow: 0 1px 3px -1px color-mix(in srgb, var(--jd-color-primary) 55%, transparent);
    }
    .jd-checkbox__input:checked {
      background-image: var(--_jd-cb-check);
    }
    /* indeterminate가 checked보다 뒤 — 둘이 동시에 참일 때 대시가 이긴다(OS 관례) */
    .jd-checkbox__input:indeterminate {
      background-image: var(--_jd-cb-dash);
    }

    .jd-checkbox__input:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-checkbox__input:disabled {
      background-color: var(--jd-color-control-surface-muted);
      border-color: var(--jd-color-border);
    }
    .jd-checkbox__input:disabled:checked,
    .jd-checkbox__input:disabled:indeterminate {
      background-color: var(--jd-color-neutral-400);
      border-color: var(--jd-color-neutral-400);
      box-shadow: none;
    }

    /* sm — 상자 16px, 표식·테두리도 함께 줄여 비율 유지 */
    jd-checkbox[size="sm"] .jd-checkbox__input {
      width: 1rem;
      height: 1rem;
      border-radius: var(--jd-radius-sm);
    }

    .jd-checkbox__label {
      color: var(--jd-color-foreground);
      font-size: var(--jd-text-md);
    }
    .jd-checkbox__label[hidden] {
      display: none;
    }
    jd-checkbox[size="sm"] .jd-checkbox__label {
      font-size: var(--jd-text-xs);
    }
    jd-checkbox[disabled] .jd-checkbox__label {
      color: var(--jd-color-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-checkbox__input {
        transition: none;
      }
      .jd-checkbox__input:active:not(:disabled) {
        scale: 1;
      }
    }
  }

  @layer junds.components {
    jd-checkbox-card-group {
      display: grid;
      grid-template-columns: repeat(1, minmax(0, 1fr));
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
    }
  }

  @layer junds.components {
    jd-clock {
      display: inline-flex;
      align-items: baseline;
      gap: var(--jd-space-2);
      font-family: var(--jd-font-mono);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    jd-clock[mode="analog"] {
      display: inline-block;
    }

    .jd-clock__time {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-tight);
    }

    .jd-clock__face {
      display: block;
    }
    .jd-clock__dial {
      fill: var(--jd-color-card);
      stroke: var(--jd-color-border);
      stroke-width: 2;
    }
    .jd-clock__tick {
      stroke: var(--jd-color-foreground);
      stroke-width: 1.5;
    }
    .jd-clock__hand {
      stroke: var(--jd-color-foreground);
      stroke-linecap: round;
    }
    .jd-clock__hand[data-hand="hour"] {
      stroke-width: 3;
    }
    .jd-clock__hand[data-hand="minute"] {
      stroke-width: 2;
    }
    .jd-clock__hand[data-hand="second"] {
      stroke: var(--jd-color-primary);
      stroke-width: 1;
    }
    .jd-clock__pin {
      fill: var(--jd-color-primary);
    }

    /* 초 숨김은 DOM 교체 없이 CSS로 — hide-seconds는 반전 플래그(§1.3) */
    jd-clock[hide-seconds] .jd-clock__hand[data-hand="second"] {
      display: none;
    }
  }

  @layer junds.components {
    /* 등락색을 직접 칠하지 않고 --jd-finance-* 훅을 경유한다: 한국 관례(적상승·청하락)는
     앱이 시작 시 그 변수를 1회 덮어써서 얻는 전환이라(DECISIONS "색 기본값은 웹을 따르고,
     관례 전환은 앱에 남겼다"), danger/info를 여기 박으면 앱의 override가 이 카드만 비껴가
     한 화면 안에서 등락색이 갈라진다. --jd-fin-*는 파생(limit-hits)이 함께 읽는 지역 별칭. */
    :where(jd-close-picks-card),
    :where(jd-limit-hits-card) {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
    }
    jd-close-picks-card,
    jd-limit-hits-card {
      display: block;
      font-family: var(--jd-font-sans);
    }
    jd-close-picks-card:not(:defined),
    jd-limit-hits-card:not(:defined) {
      display: block;
    }

    /* 테두리만 두른 면은 배경에 눌러 붙어 색종이로 읽힌다 — 얕은 그림자로 카드를 띄운다 */
    .jd-cpc__card {
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-xs);
    }

    .jd-cpc__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-cpc__title-wrap {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-cpc__emoji {
      font-size: 14px;
      line-height: 1;
    }
    .jd-cpc__emoji[hidden] {
      display: none;
    }
    .jd-cpc__title {
      margin: 0;
      font-size: 13.5px;
      font-weight: 800;
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-cpc__summary {
      flex-shrink: 0;
      font-size: 11px;
      font-weight: 700;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-cpc__list {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-cpc__list > li + li {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    /* ── picks 행 ─────────────────────────────────────────── */
    .jd-cpc__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-4);
    }
    .jd-cpc__badge {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 22px;
      height: 22px;
      border-radius: var(--jd-radius-md);
      font-size: 10.5px;
      font-weight: 800;
    }
    .jd-cpc__badge[data-strength="high"] {
      background: var(--jd-fin-up);
      color: #fff;
    }
    .jd-cpc__badge[data-strength="medium"] {
      background: var(--jd-color-warning);
      color: #17141f;
    } /* 원색 채움 위 잉크 — 모드 무관 */
    .jd-cpc__badge[data-strength="low"] {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-cpc__meta {
      flex: 1;
      min-width: 0;
    }
    .jd-cpc__name {
      display: block;
      font-size: 13.5px;
      font-weight: 800;
      color: var(--jd-color-foreground);
      text-decoration: none;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-cpc__name:hover {
      color: var(--jd-color-primary-ink);
      text-decoration: underline;
    }
    /* 링크가 눌린 순간을 색으로 알린다 — 행 전체가 아니라 이름만 누를 수 있기 때문 */
    .jd-cpc__name:active {
      color: var(--jd-color-primary-hover);
    }
    .jd-cpc__name:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }
    .jd-cpc__reason {
      margin-block-start: 2px;
      font-size: 11px;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-cpc__val {
      flex-shrink: 0;
      font-size: 13.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-cpc__val[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-cpc__val[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    .jd-cpc__footer {
      padding: var(--jd-space-2) var(--jd-space-4);
      font-size: 10.5px;
      color: var(--jd-color-muted);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
    }
    .jd-cpc__footer[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cpc__name {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-code {
      display: inline;
    }

    .jd-code {
      display: inline-flex;
      align-items: center;
      vertical-align: middle;
      font-family: var(--jd-font-mono);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-sm);
      background: var(--jd-color-card-hover);
      color: var(--jd-color-foreground);
      /* size 기본 md — v2 12px / 6px 10px */
      font-size: 12px;
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
    }

    jd-code[size="sm"] .jd-code {
      font-size: 11px;
      padding: 0 var(--jd-space-1);
    }
    jd-code[size="lg"] .jd-code {
      font-size: 13px;
      padding: var(--jd-space-1) var(--jd-space-2);
    }

    jd-code[variant="primary"] .jd-code {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
      border-color: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    /* 글자색은 semantic 원색이 아니라 foreground와 섞은 값이다. 원색(success #2f8f57 ·
     warning #b7791f)을 10% 틴트 위에 그대로 쓰면 3.2~3.6:1로 AA 미달 — axe 게이트가
     실측으로 잡았다(v2 text-success/warning도 같은 결함을 갖고 있었다).
     foreground와 섞으면 라이트에선 어두워지고 다크에선 밝아져 양쪽 테마가 함께 산다. */
    jd-code[variant="success"] .jd-code {
      background: color-mix(in srgb, var(--jd-color-success) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
      border-color: color-mix(in srgb, var(--jd-color-success) 30%, transparent);
    }
    jd-code[variant="warning"] .jd-code {
      background: color-mix(in srgb, var(--jd-color-warning) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-warning) 65%, var(--jd-color-foreground));
      border-color: color-mix(in srgb, var(--jd-color-warning) 30%, transparent);
    }
    jd-code[variant="danger"] .jd-code {
      background: color-mix(in srgb, var(--jd-color-danger) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-danger) 65%, var(--jd-color-foreground));
      border-color: color-mix(in srgb, var(--jd-color-danger) 30%, transparent);
    }
  }

  @layer junds.components {
    jd-code-editor {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr);
      position: relative; /* 부모의 .jd-textarea__count 절대배치 기준 */
      /* 어두운 편집면을 라이트 테두리로 두르면 상자가 둘로 보인다 — 잉크에서 뽑는다(§4) */
      border: var(--jd-border-thin) solid var(--jd-code-editor-rule);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      background: var(--jd-code-editor-bg, var(--jd-color-surface));
      box-shadow: var(--jd-shadow-sm);

      --jd-code-editor-fg: var(--jd-color-on-surface);
      --jd-code-editor-gutter-fg: var(--jd-color-on-surface-muted);
      --jd-code-editor-rule: color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      /* 번호 칸과 코드가 공유하는 줄 높이 — 아래 두 규칙이 같은 값을 쓴다 */
      --_jd-code-editor-line: calc(var(--jd-text-sm) * var(--jd-leading-relaxed));
    }

    .jd-code-editor__header {
      grid-column: 1 / -1;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: var(--jd-space-2) var(--jd-space-4);
      background: var(--jd-color-surface-raised);
      border-bottom: var(--jd-border-thin) solid var(--jd-code-editor-rule);
    }
    .jd-code-editor__header[hidden] {
      display: none;
    }

    .jd-code-editor__language {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-code-editor-gutter-fg);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wider);
    }

    .jd-code-editor__gutter {
      grid-column: 1;
      overflow: hidden; /* scrollTop 동기화용 — 스크롤바는 textarea만 갖는다 */
      padding: var(--jd-space-3) var(--jd-space-2);
      text-align: right;
      user-select: none;
      /* 번호 칸은 편집면보다 한 겹 눌린 레일이다 — 배경이 없으면 코드와 같은 평면에
       떠 있는 숫자로 읽힌다 */
      background: color-mix(in srgb, var(--jd-color-on-surface) 5%, transparent);
      border-inline-end: var(--jd-border-thin) solid var(--jd-code-editor-rule);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-xs);
      /* 줄 높이는 **비율이 아니라 절대값**을 공유한다. 번호(12px)와 코드(13px)에
       같은 배수를 걸면 줄마다 1.6px씩 어긋나 20줄 아래에서 번호가 한 줄 밀린다 —
       element.ts가 wrap=off로 확보한 1:1 정합이 CSS에서 무너지던 자리다. */
      line-height: var(--_jd-code-editor-line);
      font-variant-numeric: tabular-nums;
      color: var(--jd-code-editor-gutter-fg);
    }
    .jd-code-editor__gutter[hidden] {
      display: none;
    }
    .jd-code-editor__line {
      display: block;
    }

    /* 안내문은 aria-describedby 전용 — 화면에서는 숨고 grid 흐름에서도 빠진다 */
    .jd-code-editor__hint {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    /* jd-textarea 표면(유리 배경·테두리·radius·글로우 포커스) 상쇄.
     특이도 (0,1,1) — 부모 규칙 (0,1,0)을 이긴다. */
    jd-code-editor > .jd-textarea__input {
      grid-column: 2;
      min-height: var(--jd-code-editor-min-height, 200px);
      margin: 0;
      padding: var(--jd-space-3);
      border: 0;
      border-radius: 0;
      background: transparent;
      backdrop-filter: none;
      resize: none;
      overflow: auto;
      /* wrap=off라 긴 줄은 반드시 가로로 넘친다 — 잘린 채 끝나지 않고 굴러야 한다(§6).
       어두운 면 위 기본 스크롤바는 배경에 묻혀 "굴릴 수 있다"가 보이지 않으므로
       잉크에서 뽑은 색을 준다. */
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      scrollbar-color: color-mix(in srgb, var(--jd-color-on-surface) 30%, transparent) transparent;
      white-space: pre;
      tab-size: var(--jd-code-editor-tab-size, 2);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-sm);
      line-height: var(--_jd-code-editor-line);
      color: var(--jd-code-editor-fg);
    }
    jd-code-editor > .jd-textarea__input::placeholder {
      color: var(--jd-code-editor-gutter-fg);
    }
    jd-code-editor > .jd-textarea__input:focus {
      background: transparent;
      border-color: transparent;
      /* 유리 글로우는 어두운 면에서 보이지 않는다 — 안쪽 아웃라인으로 바꾼다 */
      box-shadow: none;
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    jd-code-editor > .jd-textarea__input:disabled {
      background: transparent;
      opacity: var(--jd-opacity-50);
    }
    jd-code-editor > .jd-textarea__input:read-only {
      cursor: default;
    }

    jd-code-editor > .jd-textarea__count {
      color: var(--jd-code-editor-gutter-fg);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-code-editor > .jd-textarea__input {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-collapsible:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-collapsible {
      display: block;
      width: 100%;
      /* 트리거는 폰트를 스스로 정하지만 본문은 페이지에서 상속받는다 —
       한 컴포넌트 안에서 서체가 갈리지 않게 호스트에서 한 번 정한다. */
      font-family: var(--jd-font-sans);
    }
    /* 열린 본문이 트리거 라벨과 같은 세로선에 서게 한다(원형은 여백을 갖지 않는다 —
     입양 골격이 각자 정하기 때문). 값은 원형 트리거 크롬의 좌우 패딩과 같다.
     padding이 아니라 margin인 이유: inner는 0fr 트랙에 stretch되는 그리드 아이템이라
     padding은 높이 0으로 눌러도 남는다(닫힌 패널이 패딩만큼 자리를 차지한다).
     margin은 트랙 밖이라 접힘이 실제로 0이 된다. */
    jd-collapsible > .jd-disclosure__panel > .jd-disclosure__inner {
      margin: var(--jd-space-1) var(--jd-space-3) var(--jd-space-3);
      line-height: var(--jd-leading-relaxed);
    }
  }

  @layer junds.components {
    jd-collection-view {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* ── 상단 바 ── */
    .jd-collection-view__bar {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-collection-view__search {
      position: relative;
      flex: 1;
      min-width: 12.5rem; /* v2 min-w-[200px] */
    }
    .jd-collection-view__search[hidden] {
      display: none;
    }
    .jd-collection-view__search-icon {
      position: absolute;
      inset-inline-start: var(--jd-space-3);
      inset-block-start: 50%;
      transform: translateY(-50%);
      pointer-events: none;
      display: inline-flex;
      color: var(--jd-color-muted);
    }
    .jd-collection-view__search-icon > svg {
      width: 1rem;
      height: 1rem;
    }
    .jd-collection-view__search-input {
      box-sizing: border-box;
      width: 100%;
      margin: 0;
      padding: var(--jd-space-2) var(--jd-space-3) var(--jd-space-2) var(--jd-space-8);
      font-family: inherit;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: var(--jd-color-background);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-collection-view__search-input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-collection-view__search-input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }

    .jd-collection-view__views {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-0-5);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }
    .jd-collection-view__view {
      display: inline-flex;
      padding: var(--jd-space-1-5);
      color: var(--jd-color-muted);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-collection-view__view > svg {
      width: 18px;
      height: 18px;
    }
    .jd-collection-view__view:hover {
      background: var(--jd-color-border-light);
    }
    .jd-collection-view__view[aria-pressed="true"] {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-primary-ink);
    }
    .jd-collection-view__view:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }

    /* ── 카테고리 칩 ── */
    .jd-collection-view__filters {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
    }
    .jd-collection-view__filters[hidden] {
      display: none;
    }
    .jd-collection-view__chip {
      padding: var(--jd-space-1) var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      background: color-mix(in srgb, var(--jd-color-card-hover) 50%, transparent);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-collection-view__chip:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-collection-view__chip[data-active] {
      color: #fff;
      background: var(--jd-color-primary);
      border-color: var(--jd-color-primary);
    }
    .jd-collection-view__chip:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    /* ── 항목 목록 ── */
    .jd-collection-view__items {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-collection-view__items[data-view="grid"] {
      display: grid;
      gap: var(--jd-space-4);
      grid-template-columns: 1fr;
    }
    .jd-collection-view__items[data-view="list"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    /* [data-view] 규칙과 특이도가 같다 — 반드시 뒤에 와야 hidden이 이긴다 */
    .jd-collection-view__items[hidden] {
      display: none;
    }
    @media (min-width: 40rem) {
      /* sm */
      .jd-collection-view__items[data-view="grid"] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
    }
    @media (min-width: 64rem) {
      /* lg */
      jd-collection-view[data-columns="3"] .jd-collection-view__items[data-view="grid"],
      jd-collection-view[data-columns="4"] .jd-collection-view__items[data-view="grid"] {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
    }
    @media (min-width: 80rem) {
      /* xl */
      jd-collection-view[data-columns="4"] .jd-collection-view__items[data-view="grid"] {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }

    .jd-collection-view__card {
      display: flex;
      width: 100%;
      box-sizing: border-box;
      font: inherit;
      color: inherit;
      text-align: start;
      text-decoration: none;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-collection-view__card[data-activatable] {
      cursor: pointer;
    }
    .jd-collection-view__card[data-activatable]:hover {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-lg);
      transform: translateY(-2px);
    }
    .jd-collection-view__card[data-disabled] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-collection-view__card:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    /* 그리드 카드 = 세로, 리스트 행 = 가로 */
    .jd-collection-view__items[data-view="grid"] .jd-collection-view__card {
      flex-direction: column;
    }
    .jd-collection-view__items[data-view="list"] .jd-collection-view__card {
      align-items: center;
      gap: var(--jd-space-4);
      padding: var(--jd-space-4);
    }
    .jd-collection-view__items[data-view="list"] .jd-collection-view__card[data-activatable]:hover {
      box-shadow: var(--jd-shadow-md);
      transform: none;
    }

    .jd-collection-view__preview {
      display: flex;
      align-items: center;
      justify-content: center;
      aspect-ratio: 4 / 3;
      overflow: hidden;
      background: color-mix(in srgb, var(--jd-color-card-hover) 60%, transparent);
    }
    .jd-collection-view__preview-fallback {
      font-size: var(--jd-text-3xl);
      color: var(--jd-color-muted-light);
    }
    .jd-collection-view__preview > * {
      max-width: 100%;
    }

    .jd-collection-view__icon {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 2.5rem;
      height: 2.5rem;
      background: var(--jd-color-border-light);
      border-radius: var(--jd-radius-lg);
    }
    .jd-collection-view__icon-fallback {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted-light);
    }

    .jd-collection-view__info {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      min-width: 0;
      flex: 1;
    }
    .jd-collection-view__items[data-view="grid"] .jd-collection-view__info {
      padding: var(--jd-space-4);
    }

    .jd-collection-view__label {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-collection-view__description {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    /* v2: 그리드는 2줄 클램프, 리스트는 1줄 말줄임 */
    .jd-collection-view__items[data-view="grid"] .jd-collection-view__description {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
    .jd-collection-view__items[data-view="list"] .jd-collection-view__label,
    .jd-collection-view__items[data-view="list"] .jd-collection-view__description {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-collection-view__tags {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
    }
    .jd-collection-view__items[data-view="list"] .jd-collection-view__tags {
      flex: 0 0 auto;
    }
    .jd-collection-view__tag {
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      font-size: 0.625rem;
      font-weight: var(--jd-weight-medium); /* v2 text-[10px] */
      color: var(--jd-color-muted);
      background: var(--jd-color-border-light);
      border-radius: var(--jd-radius-sm);
    }
    @media (max-width: 40rem) {
      .jd-collection-view__items[data-view="list"] .jd-collection-view__tags {
        display: none;
      }
    }

    .jd-collection-view__empty {
      margin: 0;
      padding: var(--jd-space-16) var(--jd-space-4);
      text-align: center;
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
    }
    .jd-collection-view__empty[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-collection-view__card,
      .jd-collection-view__chip,
      .jd-collection-view__view,
      .jd-collection-view__search-input {
        transition: none;
      }
      .jd-collection-view__card[data-activatable]:hover {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-color-picker {
      position: relative;
      display: inline-block;
      font-family: var(--jd-font-sans);
    }

    /* ── 트리거 ── */
    .jd-color-picker__trigger {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      height: 2.25rem;
      margin: 0;
      padding-inline: var(--jd-space-3);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      font-family: inherit;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-color-picker__trigger:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-color-picker__trigger:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-color-picker__trigger:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    jd-color-picker[open] > .jd-color-picker__trigger {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 트리거·입력줄이 함께 쓰는 색 미리보기 (배경색은 데이터 — JS 인라인) */
    .jd-color-picker__preview {
      flex-shrink: 0;
      box-sizing: border-box;
      width: 1.25rem;
      height: 1.25rem;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-sm);
    }
    .jd-color-picker__input-row > .jd-color-picker__preview {
      width: 1.75rem;
      height: 1.75rem;
      border-radius: var(--jd-radius-md);
    }

    /* ── 팝업 ── */
    .jd-color-picker__popup {
      position: fixed;
      top: 0;
      left: 0;
      z-index: var(--jd-z-popover);
      box-sizing: border-box;
      padding: var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
    }
    .jd-color-picker__popup[hidden] {
      display: none;
    }

    .jd-color-picker__presets {
      display: grid;
      grid-template-columns: repeat(6, 1.75rem);
      gap: var(--jd-space-1-5);
    }

    /* ── 프리셋 스와치 (네이티브 radio 위임 — 라디오는 시각적으로만 감춘다) ── */
    .jd-color-picker__swatch {
      position: relative;
      display: inline-flex;
      box-sizing: border-box;
      width: 1.75rem;
      height: 1.75rem;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-color-picker__swatch:hover {
      transform: scale(1.1);
    }
    .jd-color-picker__swatch[data-selected] {
      border-color: var(--jd-color-primary);
      box-shadow: 0 0 0 var(--jd-border-medium)
        color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-color-picker__swatch-chip {
      display: block;
      width: 100%;
      height: 100%;
      border-radius: calc(var(--jd-radius-md) - var(--jd-border-thin));
    }
    .jd-color-picker__swatch-input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-color-picker__swatch:has(.jd-color-picker__swatch-input:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    /* ── HEX 입력줄 ── */
    .jd-color-picker__input-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-2);
      padding-block-start: var(--jd-space-2);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-color-picker__input-row[hidden] {
      display: none;
    }

    .jd-color-picker__hex {
      flex: 1 1 auto;
      min-width: 0;
      box-sizing: border-box;
      height: 1.75rem;
      margin: 0;
      padding-inline: var(--jd-space-2);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-md);
    }
    .jd-color-picker__hex:focus {
      outline: none;
      border-color: var(--jd-color-primary);
    }
    .jd-color-picker__hex::placeholder {
      color: var(--jd-color-neutral-400);
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-color-picker[open] > .jd-color-picker__popup {
        animation: jd-color-picker-pop var(--jd-duration-fast) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-color-picker-pop {
      from {
        opacity: 0;
        transform: scale(0.96);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-color-picker__trigger,
      .jd-color-picker__swatch {
        transition: none;
      }
      .jd-color-picker__swatch:hover {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-color-swatch {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
    }
    /* columns>0이면 그리드 — 열 수는 update()가 인라인으로 채운다 */
    jd-color-swatch[columns]:not([columns="0"]) {
      display: grid;
      justify-content: start;
    }
    jd-color-swatch[columns]:not([columns="0"]) > .jd-color-swatch__label {
      grid-column: 1 / -1;
    }

    .jd-color-swatch__item {
      position: relative;
      display: inline-flex;
      box-sizing: border-box;
      border: var(--jd-border-medium) solid transparent;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      /* size 기본 md — v2 w-8 h-8 */
      width: 2rem;
      height: 2rem;
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-color-swatch__item:hover {
      transform: scale(1.05);
    }
    .jd-color-swatch__item[data-selected] {
      border-color: var(--jd-color-primary);
      transform: scale(1.1);
      box-shadow: var(--jd-shadow-md);
    }

    /* size — v2: sm 24px / lg 40px (md는 base) */
    jd-color-swatch[size="sm"] .jd-color-swatch__item {
      width: 1.5rem;
      height: 1.5rem;
    }
    jd-color-swatch[size="lg"] .jd-color-swatch__item {
      width: 2.5rem;
      height: 2.5rem;
    }

    .jd-color-swatch__chip {
      display: block;
      width: 100%;
      height: 100%;
      border-radius: calc(var(--jd-radius-lg) - var(--jd-border-medium));
      background: transparent;
    }

    .jd-color-swatch__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-color-swatch__item:has(.jd-color-swatch__input:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-color-swatch__label {
      display: inline-flex;
      align-items: center;
      margin-inline-start: var(--jd-space-1);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-color-swatch__label[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-color-swatch__item {
        transition: none;
      }
      .jd-color-swatch__item:hover,
      .jd-color-swatch__item[data-selected] {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-combobox {
      position: relative;
      display: flex;
      flex-direction: column;
      width: 100%;
    }

    /* ── 컨트롤 ─────────────────────────────────────────────── */
    .jd-combobox__control {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      cursor: text;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 포커스를 받는 것은 input이지만 그 input은 테두리가 없어 아웃라인을 얹을 면이
     없다 — 표시는 input을 감싼 컨트롤이 대신 낸다(§1 "대체 표시"). 컨트롤 안에
     포커스 가능한 것은 input 하나뿐이라 focus-within은 곧 input의 포커스다. */
    .jd-combobox__control:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-combobox[error] > .jd-combobox__control {
      border-color: var(--jd-color-danger);
    }
    jd-combobox[error] > .jd-combobox__control:focus-within {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-combobox[disabled] > .jd-combobox__control {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-combobox__icon {
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }

    .jd-combobox__input {
      flex: 1;
      min-width: 0;
      margin: 0;
      padding: 0;
      border: 0;
      outline: none;
      background: transparent;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }
    .jd-combobox__input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-combobox__input:disabled {
      cursor: not-allowed;
    }

    .jd-combobox__spinner {
      display: inline-flex;
      flex-shrink: 0;
      width: 14px;
      height: 14px;
      color: var(--jd-color-primary-ink);
    }
    .jd-combobox__spinner[hidden] {
      display: none;
    }
    .jd-combobox__spinner > svg,
    .jd-combobox__loading > svg {
      width: 100%;
      height: 100%;
      animation: jd-combobox-spin 1s linear infinite;
    }
    @keyframes jd-combobox-spin {
      to {
        transform: rotate(360deg);
      }
    }

    /* ── 팝업 ───────────────────────────────────────────────── */
    .jd-combobox__popup {
      position: absolute;
      top: 100%;
      inset-inline: 0;
      margin-block-start: var(--jd-space-1);
      z-index: var(--jd-z-dropdown);
      box-sizing: border-box;
      max-height: 15rem;
      overflow: auto;
      padding-block: var(--jd-space-1);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
      transform-origin: top center;
      animation: jd-combobox-pop var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-combobox__popup[hidden] {
      display: none;
    }
    @keyframes jd-combobox-pop {
      from {
        opacity: 0;
        transform: scale(0.97);
      }
    }

    .jd-combobox__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    .jd-combobox__option {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      text-align: start;
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 아래 세 규칙은 특정도가 같다 — 순서가 곧 서열이다: 눌림 > 활성 행 > 호버 */
    .jd-combobox__option:hover {
      background: var(--jd-color-card-hover);
    }
    /* 키보드 포커스는 input에 남고 이 행은 aria-activedescendant로만 지시된다 —
     즉 이 행의 표시가 §1의 :focus-visible을 대신한다. 배경 틴트만으로는 hover와
     같은 세기라 커서가 지워지므로 포커스 링을 함께 그린다. 팝업이 overflow:auto라
     바깥으로 나가는 아웃라인은 잘린다 — 안쪽으로 눕힌다. */
    .jd-combobox__option[data-active] {
      background: var(--jd-color-primary-light);
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    /* 눌린 행은 빛을 잃는다 — 포인터로 고르는 순간의 유일한 응답이다 */
    .jd-combobox__option:active {
      background: color-mix(in srgb, var(--jd-color-primary) 18%, transparent);
    }
    .jd-combobox__option[aria-selected="true"] {
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
    }
    .jd-combobox__option[data-create] {
      color: var(--jd-color-primary-ink);
    }
    .jd-combobox__option[data-disabled] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    /* 고를 수 없는 행이 호버·눌림에 응답하면 "눌리는데 안 되는" 거짓말이 된다.
     특정도가 한 칸 높아 위 세 규칙을 모두 이긴다. */
    .jd-combobox__option[data-disabled]:hover,
    .jd-combobox__option[data-disabled]:active {
      background: none;
    }

    .jd-combobox__option-icon {
      flex-shrink: 0;
    }
    .jd-combobox__option-icon[hidden] {
      display: none;
    }
    .jd-combobox__option-body {
      display: flex;
      flex-direction: column;
      flex: 1;
      min-width: 0;
    }
    .jd-combobox__option-label {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-combobox__option-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-weight: var(--jd-weight-normal);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-combobox__option-desc[hidden] {
      display: none;
    }

    .jd-combobox__option-check {
      display: inline-flex;
      flex-shrink: 0;
      margin-inline-start: auto;
      visibility: hidden;
      color: var(--jd-color-primary-ink);
    }
    .jd-combobox__option[aria-selected="true"] > .jd-combobox__option-check {
      visibility: visible;
    }

    .jd-combobox__empty {
      padding: var(--jd-space-4) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
      text-align: center;
    }
    .jd-combobox__empty[hidden] {
      display: none;
    }

    .jd-combobox__loading {
      display: flex;
      align-items: center;
      justify-content: center;
      padding-block: var(--jd-space-4);
      width: 100%;
      box-sizing: border-box;
      color: var(--jd-color-primary-ink);
    }
    .jd-combobox__loading[hidden] {
      display: none;
    }
    .jd-combobox__loading > svg {
      width: 16px;
      height: 16px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-combobox__control,
      .jd-combobox__option {
        transition: none;
      }
      .jd-combobox__popup {
        animation: none;
      }
      .jd-combobox__spinner > svg,
      .jd-combobox__loading > svg {
        animation-duration: 1.6s;
      }
    }
  }

  @layer junds.components {
    jd-command-palette {
      display: none;
    }
    jd-command-palette[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: flex-start;
      justify-content: center;
      /* v2 pt-[20vh] + 좌우 여백 */
      padding: 20vh var(--jd-space-4) var(--jd-space-4);
    }

    /* v2 백드롭은 black/40, 블러 없음 — Modal 기본(blur 2px)을 끈다 */
    jd-command-palette > .jd-modal__backdrop {
      background: rgba(0, 0, 0, 0.4);
      backdrop-filter: none;
    }

    /* max-w-lg(32rem) 고정 폭. 결과 목록만 내부 스크롤 → 패널 자체는 overflow hidden */
    jd-command-palette > .jd-modal__panel {
      max-width: min(32rem, calc(100vw - 2rem));
      max-height: calc(100vh - 24vh);
      overflow: hidden;
      box-shadow: var(--jd-shadow-2xl);
    }

    /* 검색 행 */
    .jd-command-palette__search {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-command-palette__search-icon {
      display: inline-flex;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }
    .jd-command-palette__input {
      flex: 1;
      min-width: 0;
      border: 0;
      outline: none;
      background: transparent;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
    }
    .jd-command-palette__input::placeholder {
      color: var(--jd-color-muted-light);
    }
    /* 위의 outline:none은 테두리 없는 검색줄에 UA 기본 박스가 뜨지 않게 하려는 것이지
     포커스를 지우려는 것이 아니다 — 대체 표시를 여기서 돌려준다(§1). 패널이
     overflow:hidden이지만 검색줄 패딩(space-3/4)이 링 두께+오프셋보다 넓어 잘리지 않는다. */
    .jd-command-palette__input:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }

    /* 결과 목록 — v2 max-h-[320px] 내부 스크롤 */
    .jd-command-palette__results {
      max-height: 320px;
      overflow-y: auto;
      padding-block: var(--jd-space-1);
    }
    .jd-command-palette__empty {
      padding: var(--jd-space-8) var(--jd-space-4);
      text-align: center;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    /* 10px·muted-light은 §9 하한(2xs=11px)과 대비 하한을 둘 다 밑돌았다 —
     그룹 머리는 목록을 나누는 정보라 읽혀야 한다 */
    .jd-command-palette__group-label {
      padding: var(--jd-space-1-5) var(--jd-space-4) var(--jd-space-0-5);
      font-size: var(--jd-text-2xs);
      line-height: var(--jd-leading-normal);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    .jd-command-palette__option {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      width: 100%;
      box-sizing: border-box;
      padding: var(--jd-space-2) var(--jd-space-4);
      text-align: start;
      cursor: pointer;
      color: var(--jd-color-foreground);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 활성 행(키보드/포인터 공통) — v2 bg-primary-light text-primary.
     키보드 포커스는 입력창에 남고 이 행은 aria-activedescendant로만 지시되므로
     이 표시가 §1의 :focus-visible을 대신한다. 다크에서 primary-light는 15% 알파라
     배경 틴트만으로는 커서가 사라진다 — 포커스 링을 함께 그린다. 결과 목록이
     overflow-y:auto라 바깥 아웃라인은 잘리므로 안쪽으로 눕힌다. */
    .jd-command-palette__option[aria-selected="true"] {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    /* 눌린 행은 빛을 잃는다 — 실행 직전임을 포인터에게 돌려주는 유일한 신호.
     포인터가 스치기만 해도 그 행이 aria-selected가 되므로 눌리는 행은 거의 항상
     활성 행이다 — 특정도가 같아 순서로 이긴다. 위 규칙보다 뒤에 있어야 한다. */
    .jd-command-palette__option:active {
      background: color-mix(in srgb, var(--jd-color-primary) 20%, transparent);
    }

    .jd-command-palette__option-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: var(--jd-space-5);
      height: var(--jd-space-5);
      color: var(--jd-color-muted);
    }
    .jd-command-palette__option-body {
      flex: 1;
      min-width: 0;
    }
    .jd-command-palette__option-label {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .jd-command-palette__option-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* 푸터 힌트 */
    .jd-command-palette__footer {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2) var(--jd-space-4);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border-light);
      /* 10px·muted-light은 §9 하한 미달이었다 — 조작법을 알려 주는 줄이라 읽혀야 한다 */
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }
    .jd-command-palette__hint {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
    }

    /* 진입 애니메이션 — Modal은 jd-modal 태그로 스코프돼 상속 안 됨 */
    @media (prefers-reduced-motion: no-preference) {
      jd-command-palette[open] > .jd-modal__backdrop {
        animation: jd-cmdk-fade var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-command-palette[open] > .jd-modal__panel {
        animation: jd-cmdk-pop var(--jd-duration-normal) var(--jd-easing-default);
      }
    }
    @keyframes jd-cmdk-fade {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-cmdk-pop {
      from {
        opacity: 0;
        transform: translateY(-0.5rem) scale(0.98);
      }
    }
    /* 진입 애니메이션은 no-preference로 이미 막혀 있지만 행 전이는 남아 있었다 */
    @media (prefers-reduced-motion: reduce) {
      .jd-command-palette__option {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-command-palette-host {
      display: none;
    }
    jd-command-palette-host[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: flex-start;
      justify-content: center;
      padding: 20vh var(--jd-space-4) var(--jd-space-4);
    }

    jd-command-palette-host > .jd-modal__backdrop {
      background: rgba(0, 0, 0, 0.4);
      backdrop-filter: none;
    }

    jd-command-palette-host > .jd-modal__panel {
      max-width: min(32rem, calc(100vw - 2rem));
      max-height: calc(100vh - 24vh);
      overflow: hidden;
      box-shadow: var(--jd-shadow-2xl);
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-command-palette-host[open] > .jd-modal__backdrop {
        animation: jd-cmdk-fade var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-command-palette-host[open] > .jd-modal__panel {
        animation: jd-cmdk-pop var(--jd-duration-normal) var(--jd-easing-default);
      }
    }
  }

  @layer junds.components {
    jd-comment-thread {
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-comment-thread,
    .jd-comment-thread__replies {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    .jd-comment-thread__replies {
      margin-top: var(--jd-space-2);
    }

    .jd-comment-thread__row {
      display: flex;
      gap: var(--jd-space-3);
    }

    .jd-comment-thread__avatar {
      flex-shrink: 0;
    }
    .jd-comment-thread__avatar-img,
    .jd-comment-thread__avatar-fallback {
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      display: block;
    }
    .jd-comment-thread__avatar-fallback {
      display: flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      /* 틴트 위 이니셜: 원색 대신 foreground 혼합으로 대비 확보(emoji-picker 선례·§4). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      user-select: none;
    }

    .jd-comment-thread__main {
      flex: 1;
      min-width: 0;
    }

    .jd-comment-thread__bubble {
      border-radius: var(--jd-radius-2xl);
      background: var(--jd-color-card-hover);
      padding: var(--jd-space-2) var(--jd-space-3);
    }
    .jd-comment-thread__head {
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-2);
    }
    .jd-comment-thread__author {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-comment-thread__time {
      font-size: 10px;
      color: var(--jd-color-muted);
    }
    .jd-comment-thread__body {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
      overflow-wrap: anywhere;
    }

    .jd-comment-thread__actions {
      margin-top: var(--jd-space-1);
      margin-inline-start: var(--jd-space-3);
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      font-size: 11px;
    }
    .jd-comment-thread__like,
    .jd-comment-thread__reply {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      padding: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      font: inherit;
      color: var(--jd-color-muted);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-comment-thread__like:hover,
    .jd-comment-thread__reply:hover {
      color: var(--jd-color-foreground);
    }
    .jd-comment-thread__like:focus-visible,
    .jd-comment-thread__reply:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
      border-radius: var(--jd-radius-sm);
    }
    .jd-comment-thread__like[data-liked] {
      color: #f43f5e;
    }
    .jd-comment-thread__like[data-liked]:hover {
      color: #f43f5e;
    }
  }

  @layer junds.components {
    jd-compare-slider {
      display: block;
      position: relative;
      box-sizing: border-box;
      overflow: hidden;
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
      user-select: none;
      -webkit-user-select: none;
      cursor: ew-resize;
    }

    .jd-compare-slider__image {
      display: block;
      width: 100%;
      height: auto;
      -webkit-user-drag: none;
    }

    /* 잘리는 쪽 — 오른쪽에서 (100 - pos)만큼 잘라낸다 */
    .jd-compare-slider__clip {
      position: absolute;
      inset: 0;
      clip-path: inset(0 calc(100% - var(--_jd-compare-pos, 50%)) 0 0);
    }

    .jd-compare-slider__label {
      position: absolute;
      inset-block-start: var(--jd-space-3);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: #fff;
      background: rgba(0, 0, 0, 0.5);
      border-radius: var(--jd-radius-md);
      backdrop-filter: blur(4px);
      pointer-events: none; /* 라벨을 눌러도 분할선이 움직인다 */
    }
    .jd-compare-slider__label--start {
      inset-inline-start: var(--jd-space-3);
    }
    .jd-compare-slider__label--end {
      inset-inline-end: var(--jd-space-3);
    }
    .jd-compare-slider__label[hidden] {
      display: none;
    }

    .jd-compare-slider__handle {
      position: absolute;
      inset-block: 0;
      inset-inline-start: var(--_jd-compare-pos, 50%);
      width: 4px;
      margin-inline-start: -2px;
      background: #fff;
      box-shadow: var(--jd-shadow-lg);
      cursor: ew-resize;
      touch-action: none; /* 손잡이 위에서는 페이지가 스크롤되지 않는다 */
    }
    .jd-compare-slider__handle:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-lg), var(--jd-shadow-focus-ring);
    }

    .jd-compare-slider__grip {
      position: absolute;
      inset-block-start: 50%;
      inset-inline-start: 50%;
      transform: translate(-50%, -50%);
      display: flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-full);
      /* 사진 위에 얹히는 크롬이라 모드 무관 — 흰 알약 위에는 어두운 잉크가 정답 */
      background: #fff;
      color: #17141f;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: var(--jd-shadow-lg);
    }
  }

  @layer junds.base {
    jd-comparison-grid:not(:defined) {
      display: grid;
    }
  }
  @layer junds.components {
    /* v2의 sm/md 계단을 **부모 폭 기준**으로 옮겼다. 뷰포트 미디어쿼리는 이 격자가
     좁은 칼럼 안에 놓이면 거짓말을 한다 — 화면이 넓다는 이유로 300px 칸에 4열을 그려
     "12,480,000"과 "원"이 갈라지고 카드가 오른쪽으로 넘쳤다(실측). 하한은 "요청 열
     수로 나눈 폭"과 최소 카드 폭 중 큰 쪽이라, 넓을 때는 정확히 columns 열이다.
     기본 columns=4는 attribute로 반영되지 않으므로(§1.3) base가 담당한다. */
    jd-comparison-grid {
      --jd-cg-gap: var(--jd-space-4);
      --jd-cg-cols: 4;
      --jd-cg-col-min: 14rem;
      display: grid;
      gap: var(--jd-cg-gap);
      grid-template-columns: repeat(
        auto-fit,
        minmax(
          min(
            100%,
            max(
              var(--jd-cg-col-min),
              (100% - (var(--jd-cg-cols) - 1) * var(--jd-cg-gap)) / var(--jd-cg-cols)
            )
          ),
          1fr
        )
      );
      font-family: var(--jd-font-sans);
    }
    jd-comparison-grid[columns="2"] {
      --jd-cg-cols: 2;
    }
    jd-comparison-grid[columns="3"] {
      --jd-cg-cols: 3;
    }

    .jd-comparison-grid__card {
      box-sizing: border-box;
      min-width: 0; /* 격자 자식 기본 min-width:auto가 칸을 밀어내지 못하게(§5) */
      padding: var(--jd-space-4);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      /* 쉬는 상태의 얕은 그림자가 있어야 hover의 shadow-md가 '떠오름'으로 읽힌다(§2) */
      box-shadow: var(--jd-shadow-xs);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-comparison-grid__card:hover {
      box-shadow: var(--jd-shadow-md);
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-comparison-grid__card:hover {
        transform: translateY(-2px);
      }
    }

    .jd-comparison-grid__card[data-variance] {
      border-inline-start: var(--jd-border-thick) solid var(--jd-color-warning);
      background: color-mix(in srgb, var(--jd-color-warning-light) 40%, var(--jd-color-card));
    }
    .jd-comparison-grid__card[data-variance]:hover {
      box-shadow: 0 4px 6px color-mix(in srgb, var(--jd-color-warning) 25%, transparent),
        var(--jd-shadow-xs);
    }

    /* v2 text-[10px]은 읽기의 바닥(11px, §9) 아래였다 — 토큰 계단으로 올린다 */
    .jd-comparison-grid__label {
      display: block;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-medium);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
      word-break: keep-all;
    }

    /* 값이 길면 배지가 아래로 내려간다 — 밀어내며 겹치는 것보다 낫다 */
    .jd-comparison-grid__row {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-end;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-1);
      min-width: 0;
    }

    /* 수치와 단위는 한 덩어리다 — "12,480,000"과 "원"이 갈라지면 다른 수로 읽힌다(§5) */
    .jd-comparison-grid__value {
      font-size: var(--jd-text-2xl); /* v2 text-xl = 1.25rem */
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--jd-color-foreground);
    }

    .jd-comparison-grid__change {
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      white-space: nowrap;
      margin-block-end: 2px;
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      background: var(--jd-color-border-light);
      color: var(--jd-color-muted);
    }
    .jd-comparison-grid__change[hidden] {
      display: none;
    }
    /* 증감 배지는 등락이다 — success/danger를 직접 칠하면 한국 관례(적상승)로 전환한 앱에서
     이 격자만 옛 색으로 남아 옆의 price-badge와 갈라진다. 훅을 경유하고, -light 짝은
     훅에서 파생할 수 없으므로 같은 색의 옅은 틴트로 만든다(§8). */
    .jd-comparison-grid__change[data-direction="up"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 14%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    .jd-comparison-grid__change[data-direction="down"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 14%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    .jd-comparison-grid__subtext {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      word-break: keep-all;
      overflow-wrap: break-word;
    }
    .jd-comparison-grid__subtext[hidden] {
      display: none;
    }

    /* 시각적으로만 숨긴다 — 색으로만 전달되던 정보의 텍스트 등가물 (jd-visually-hidden 관용구) */
    .jd-comparison-grid__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-comparison-grid__card {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-component-showcase {
      /* 분류색 4변수 — 카드·칩이 같은 값을 쓰고, 분류를 추가하는 소비자는
       레이어 밖에서 이 넷만 덮으면 된다(§4.4). 칩 채움(strong/on-accent)은 v2의
       무분류 폴백(bg-foreground/text-background) 그대로 두고, 미리보기 틴트를 만드는
       accent 둘만 강조색으로 올린다 — muted 회색이던 시절 미리보기가 카드 안의
       "빈 자리"로 읽혔다. */
      --jd-component-showcase-accent: var(--jd-color-primary);
      --jd-component-showcase-accent-2: var(--jd-color-accent);
      --jd-component-showcase-accent-strong: var(--jd-color-foreground);
      --jd-component-showcase-on-accent: var(--jd-color-background);
      position: relative;
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* ── 조작줄 ─────────────────────────────────────────────────────── */
    .jd-component-showcase__controls {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
      margin-block-end: var(--jd-space-8);
    }
    .jd-component-showcase__controls[hidden] {
      display: none;
    }
    @media (min-width: 640px) {
      .jd-component-showcase__controls {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
      }
    }

    .jd-component-showcase__search {
      position: relative;
      display: block;
    }
    .jd-component-showcase__search[hidden] {
      display: none;
    }

    .jd-component-showcase__search-icon {
      position: absolute;
      inset-inline-start: var(--jd-space-3-5);
      inset-block-start: 50%;
      display: inline-flex;
      translate: 0 -50%;
      color: var(--jd-color-muted);
      pointer-events: none;
    }

    .jd-component-showcase__search-input {
      box-sizing: border-box;
      width: 100%;
      height: 2.75rem; /* v2 h-11 */
      margin: 0;
      padding-inline: 2.75rem var(--jd-space-4); /* v2 pl-11 pr-4 */
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
      box-shadow: var(--jd-shadow-sm);
      font-family: inherit;
      font-size: var(--jd-text-md);
      transition: border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    @media (min-width: 640px) {
      .jd-component-showcase__search-input {
        width: 18rem;
      } /* v2 sm:w-72 */
    }
    .jd-component-showcase__search-input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-component-showcase__search-input:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 분류 칩 ───────────────────────────────────────────────────── */
    .jd-component-showcase__chips {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
    }
    .jd-component-showcase__chips[hidden] {
      display: none;
    }

    .jd-component-showcase__chip {
      position: relative;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      box-sizing: border-box;
      padding: var(--jd-space-1-5) var(--jd-space-4);
      background: var(--jd-color-card);
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      cursor: pointer;
      user-select: none;
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-component-showcase__chip:hover {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-foreground);
      border-color: color-mix(in srgb, var(--jd-color-foreground) 20%, transparent);
    }
    /* 눌린 면은 빛을 잃는다 — v2에는 :active가 아예 없었다 */
    .jd-component-showcase__chip:active {
      scale: 0.97;
      background: var(--jd-color-border-light);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }

    /* 라디오는 시각적으로만 감춘다 (jd-filter-button-group 관용구) */
    .jd-component-showcase__chip-input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-component-showcase__chip:has(.jd-component-showcase__chip-input:focus-visible) {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-component-showcase__chip-count {
      opacity: var(--jd-opacity-60);
      font-variant-numeric: tabular-nums;
    }
    .jd-component-showcase__chip-count[hidden] {
      display: none;
    }

    /* 활성 칩: 분류색 채움. "전체"·미지 분류는 변수 기본값이 foreground/background라
     v2의 catChipActive[cat] || "bg-foreground text-background" 폴백과 같아진다.
     (주의: 이 템플릿 안에서는 CSS 주석에도 백틱을 쓸 수 없다 — 리터럴이 끊긴다) */
    .jd-component-showcase__chip[data-active] {
      background: var(--jd-component-showcase-accent-strong);
      border-color: var(--jd-component-showcase-accent-strong);
      color: var(--jd-component-showcase-on-accent);
    }

    /* ── 격자 ───────────────────────────────────────────────────────── */
    .jd-component-showcase__grid {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      gap: var(--jd-space-6);
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-component-showcase__grid[hidden] {
      display: none;
    }

    /* columns는 "상한" — 좁은 화면부터 1 → 2 → 3 → 4로 열린다(v2 gridCls 동형).
     repeat() 반복 수에 calc/min을 못 써 호스트 속성 셀렉터로 분기한다.
     :where()는 세 규칙의 특이도를 맞춰 순서가 사다리를 결정하게 한다(파일 헤더 참조). */
    @media (min-width: 640px) {
      jd-component-showcase:where(:not([columns="1"])) > .jd-component-showcase__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
    }
    @media (min-width: 1024px) {
      jd-component-showcase:where(:not([columns="1"], [columns="2"]))
        > .jd-component-showcase__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
    }
    @media (min-width: 1280px) {
      jd-component-showcase:where([columns="4"]) > .jd-component-showcase__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }

    /* ── 카드 ───────────────────────────────────────────────────────── */
    .jd-component-showcase__card {
      position: relative;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
      box-shadow: var(--jd-shadow-sm);
      transition: translate var(--jd-duration-slow) var(--jd-easing-default),
        box-shadow var(--jd-duration-slow) var(--jd-easing-default),
        border-color var(--jd-duration-slow) var(--jd-easing-default);
    }
    .jd-component-showcase__card:is(:hover, :focus-within) {
      z-index: 1;
      translate: 0 -0.25rem; /* v2 -translate-y-1 */
      /* 테두리도 분류색을 따른다 — primary 고정이면 글로우(분류색)와 색이 갈려
       카드 하나가 두 색으로 빛난다 */
      border-color: color-mix(in srgb, var(--jd-component-showcase-accent) 40%, transparent);
      box-shadow: var(--jd-shadow-2xl),
        0 25px 50px -12px color-mix(in srgb, var(--jd-component-showcase-accent) 20%, transparent);
    }
    .jd-component-showcase__card:has(.jd-component-showcase__link:focus-visible) {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* 하단 악센트 라인 — v2는 --primary 고정이라 6분류가 전부 같은 보라 선으로 끝났다 */
    .jd-component-showcase__card::after {
      content: "";
      position: absolute;
      inset-inline: 0;
      inset-block-end: 0;
      z-index: 2;
      height: var(--jd-border-medium);
      background: linear-gradient(
        90deg,
        transparent,
        var(--jd-component-showcase-accent),
        transparent
      );
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-component-showcase__card:is(:hover, :focus-within)::after {
      opacity: 1;
    }

    /* 분류색(v2 catBadge/catPreviewBg/catGlow/catChipActive 네 맵의 통합).
     accent/accent-2 = 두 색상축의 이웃 — 그라데이션·글로우는 장식이라 3:1이면 된다.
     accent-strong = 흰 글자가 얹히는 유일한 자리(칩 채움·배지 글자 앵커)라 4.5:1을
     넘는 단만 고른다. hue 토큰은 이미 600~700단이라 대개 자기 자신이 strong이고,
     amber만 흰 글자 4.1:1로 모자라 같은 색상축의 hue-orange(5.1:1)를 쓴다(§4 색 대비). */
    jd-component-showcase [data-category="Foundation"] {
      --jd-component-showcase-accent: var(--jd-color-hue-violet);
      --jd-component-showcase-accent-2: var(--jd-color-hue-purple);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-violet);
      --jd-component-showcase-on-accent: #fff;
    }
    jd-component-showcase [data-category="Primitives"] {
      --jd-component-showcase-accent: var(--jd-color-hue-blue);
      --jd-component-showcase-accent-2: var(--jd-color-hue-violet);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-blue);
      --jd-component-showcase-on-accent: #fff;
    }
    jd-component-showcase [data-category="Composites"] {
      --jd-component-showcase-accent: var(--jd-color-hue-green);
      --jd-component-showcase-accent-2: var(--jd-color-hue-teal);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-green);
      --jd-component-showcase-on-accent: #fff;
    }
    jd-component-showcase [data-category="Patterns"] {
      --jd-component-showcase-accent: var(--jd-color-hue-amber);
      --jd-component-showcase-accent-2: var(--jd-color-hue-orange);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-orange);
      --jd-component-showcase-on-accent: #fff;
    }
    jd-component-showcase [data-category="Security"] {
      --jd-component-showcase-accent: var(--jd-color-hue-red);
      --jd-component-showcase-accent-2: var(--jd-color-hue-pink);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-red);
      --jd-component-showcase-on-accent: #fff;
    }
    jd-component-showcase [data-category="Advanced"] {
      --jd-component-showcase-accent: var(--jd-color-hue-rose);
      --jd-component-showcase-accent-2: var(--jd-color-hue-purple);
      --jd-component-showcase-accent-strong: var(--jd-color-hue-rose);
      --jd-component-showcase-on-accent: #fff;
    }

    /* ── 미리보기 영역 ───────────────────────────────────────────────── */
    /* 미리보기는 카드 안에서 가장 넓은 면인데 10% 틴트 한 겹만으로는 "아직 안 채운 자리"로
     읽혔다. 위에서 받는 빛(상단 돔) + 한 단 짙은 대각 틴트 + 정보 영역과의 실낱 경계 —
     세 겹이 있어야 판이 아니라 무대가 된다(§2 채움만 있는 면은 색종이로 읽힌다). */
    .jd-component-showcase__preview {
      position: relative;
      height: 200px; /* v2 h-[200px] */
      overflow: hidden;
      background: radial-gradient(120% 80% at 50% 0%, var(--jd-color-highlight), transparent 62%),
        linear-gradient(
          135deg,
          color-mix(in srgb, var(--jd-component-showcase-accent) 16%, var(--jd-color-card)),
          color-mix(in srgb, var(--jd-component-showcase-accent-2) 16%, var(--jd-color-card))
        );
      box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--jd-color-border) 76%, transparent);
    }

    .jd-component-showcase__pattern {
      position: absolute;
      inset: 0;
      opacity: 0.03;
      background-image: radial-gradient(circle, currentColor 0.5px, transparent 0.5px);
      background-size: 12px 12px;
    }

    .jd-component-showcase__still,
    .jd-component-showcase__demo {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-5);
      overflow: hidden;
      pointer-events: none;
      transition: opacity var(--jd-duration-slower) var(--jd-easing-ease-out),
        scale var(--jd-duration-slower) var(--jd-easing-ease-out),
        filter var(--jd-duration-slower) var(--jd-easing-ease-out);
    }
    .jd-component-showcase__still {
      scale: 0.8;
    } /* v2 scale-[0.8] */
    .jd-component-showcase__demo {
      opacity: 0;
      scale: 0.99;
      filter: blur(4px);
    }

    .jd-component-showcase__card[data-has-demo]:is(:hover, :focus-within)
      .jd-component-showcase__still {
      opacity: 0;
      scale: 0.72;
      filter: blur(4px);
    }
    .jd-component-showcase__card[data-has-demo]:is(:hover, :focus-within)
      .jd-component-showcase__demo {
      opacity: 1;
      scale: 0.9;
      filter: blur(0);
    }

    /* 하단 스크림 — v2 from-white/80은 다크에서 흰 띠였다 */
    .jd-component-showcase__scrim {
      position: absolute;
      inset-inline: 0;
      inset-block-end: 0;
      height: 4rem;
      background: linear-gradient(
        to top,
        color-mix(in srgb, var(--jd-color-card) 80%, transparent),
        transparent
      );
      pointer-events: none;
      transition: opacity var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-component-showcase__card:is(:hover, :focus-within) .jd-component-showcase__scrim {
      opacity: 0;
    }

    .jd-component-showcase__hint {
      position: absolute;
      inset-block-start: var(--jd-space-3);
      inset-inline-end: var(--jd-space-3);
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1) var(--jd-space-2-5);
      background: color-mix(in srgb, var(--jd-color-foreground) 80%, transparent);
      color: var(--jd-color-background);
      border-radius: var(--jd-radius-full);
      backdrop-filter: blur(4px);
      font-size: var(--jd-text-2xs); /* 11px가 하한 — v2 text-[10px]는 읽히지 않는다 */
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      opacity: 0;
      translate: 0 -0.5rem;
      pointer-events: none;
      transition: opacity var(--jd-duration-slow) var(--jd-easing-ease-out),
        translate var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-component-showcase__card:is(:hover, :focus-within) .jd-component-showcase__hint {
      opacity: 1;
      translate: 0 0;
    }

    /* ── 정보 영역 ───────────────────────────────────────────────────── */
    .jd-component-showcase__info {
      padding: var(--jd-space-3-5) var(--jd-space-4);
    }
    .jd-component-showcase__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      margin-block-end: var(--jd-space-1);
    }
    .jd-component-showcase__title {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
      line-height: var(--jd-leading-snug);
    }

    /* 카드 전면을 덮는 링크(stretched link) — 히트 영역은 카드 전체, 접근 이름은 제목 */
    .jd-component-showcase__link {
      display: inline;
      margin: 0;
      padding: 0;
      background: none;
      border: 0;
      color: inherit;
      font: inherit;
      letter-spacing: inherit;
      text-align: start;
      text-decoration: none;
      cursor: pointer;
    }
    .jd-component-showcase__link::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 1;
    }
    .jd-component-showcase__link:focus-visible {
      outline: none;
    }

    .jd-component-showcase__badge {
      flex-shrink: 0;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      background: color-mix(in srgb, var(--jd-component-showcase-accent) 12%, transparent);
      /* v2는 -600 글자색이었다. 짙은 쪽(strong)에 foreground를 섞어 라이트에서는 더 짙게,
       다크에서는 밝게 — 양쪽 테마에서 틴트 배경 대비 4.5:1 유지(§4 색 대비 공식) */
      color: color-mix(
        in srgb,
        var(--jd-component-showcase-accent-strong) 65%,
        var(--jd-color-foreground)
      );
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-component-showcase-accent) 30%, transparent);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      white-space: nowrap;
    }
    .jd-component-showcase__badge[hidden] {
      display: none;
    }

    .jd-component-showcase__desc {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2; /* v2 line-clamp-2 */
      margin: 0;
      overflow: hidden;
      color: var(--jd-color-muted);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-component-showcase__desc[hidden] {
      display: none;
    }

    /* ── 빈 상태 ─────────────────────────────────────────────────────── */
    .jd-component-showcase__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding-block: var(--jd-space-24); /* v2 py-24 */
      color: var(--jd-color-muted);
      text-align: center;
    }
    .jd-component-showcase__empty[hidden] {
      display: none;
    }
    .jd-component-showcase__empty-icon {
      display: inline-flex;
      margin-block-end: var(--jd-space-3);
      opacity: var(--jd-opacity-20);
    }
    .jd-component-showcase__empty-title {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
    }
    .jd-component-showcase__empty-hint {
      margin-block: var(--jd-space-1) 0;
      margin-inline: 0;
      font-size: var(--jd-text-xs);
    }

    /* 결과 수 통지 — 시각적으로만 숨긴다(jd-visually-hidden 관용구) */
    .jd-component-showcase__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    /* ── 등장 스태거 ─────────────────────────────────────────────────── */
    @media (prefers-reduced-motion: no-preference) {
      .jd-component-showcase__card {
        animation: jd-component-showcase-in var(--jd-duration-slow) var(--jd-easing-default) both;
        animation-delay: calc(var(--jd-component-showcase-i, 0) * 30ms); /* v2 index*30ms */
      }
    }
    /* 등장은 transform, 호버 부상은 translate — 축을 가른다(파일 헤더 참조) */
    @keyframes jd-component-showcase-in {
      from {
        opacity: 0;
        transform: translateY(0.5rem);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-component-showcase__search-input,
      .jd-component-showcase__chip,
      .jd-component-showcase__card,
      .jd-component-showcase__card::after,
      .jd-component-showcase__still,
      .jd-component-showcase__demo,
      .jd-component-showcase__scrim,
      .jd-component-showcase__hint {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* 덮개는 발사 중에만 존재한다 — 그 외에는 문서에 아무 상자도 만들지 않는다 */
    jd-confetti {
      display: none;
    }
    jd-confetti[data-running] {
      display: block;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-max);
      pointer-events: none;
      overflow: hidden;
    }

    .jd-confetti__piece {
      position: absolute;
      top: 0;
      left: var(--jd-confetti-x, 50%);
      animation: jd-confetti-fall var(--jd-confetti-fall, 3000ms)
        cubic-bezier(0.25, 0.46, 0.45, 0.94) var(--jd-confetti-delay, 0ms) forwards;
    }

    .jd-confetti__bit {
      display: block;
      width: var(--jd-confetti-w, 8px);
      height: var(--jd-confetti-h, 8px);
      background: var(--jd-confetti-color, var(--jd-color-primary));
      border-radius: 2px; /* v2 square/strip */
      animation: jd-confetti-spin var(--jd-confetti-spin, 800ms) linear infinite;
    }
    .jd-confetti__bit[data-shape="circle"] {
      border-radius: var(--jd-radius-full);
    }

    @keyframes jd-confetti-fall {
      0% {
        transform: translateY(-10vh) rotate(0deg);
        opacity: 1;
      }
      100% {
        transform: translateY(110vh) rotate(720deg);
        opacity: 0;
      }
    }
    @keyframes jd-confetti-spin {
      from {
        transform: rotate(var(--jd-confetti-rot, 0deg));
      }
      to {
        transform: rotate(calc(var(--jd-confetti-rot, 0deg) + 360deg));
      }
    }

    /* element가 감속 선호에서는 조각을 아예 만들지 않는다 — 여기 규칙은 이중 안전망 */
    @media (prefers-reduced-motion: reduce) {
      .jd-confetti__piece,
      .jd-confetti__bit {
        animation: none;
      }
      jd-confetti[data-running] {
        display: none;
      }
    }
  }

  @layer junds.components {
    jd-consensus-screener {
      display: block;
      /* 플렉스/그리드 자식으로 놓였을 때 표가 부모를 밀어내지 않게 한다 */
      min-width: 0;
      overflow: hidden;
      border: 1px solid var(--jd-fin-border, var(--jd-color-border));
      border-radius: var(--jd-radius-2xl);
      background: var(--jd-fin-surface, var(--jd-color-card));
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
      font-family: var(--jd-font-sans);
      --_accent: var(--jd-fin-accent, var(--jd-color-primary));
      --_accent-strong: var(--jd-fin-accent-strong, var(--jd-color-primary-hover));
      --_accent-soft: var(--jd-fin-accent-soft, var(--jd-color-primary-light));
      --_soft: var(--jd-fin-soft-100, var(--jd-color-neutral-100));
      --_text: var(--jd-fin-text, var(--jd-color-foreground));
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_border: var(--jd-fin-border, var(--jd-color-border));
      --_up: var(--jd-finance-up, var(--jd-color-success));
      --_down: var(--jd-finance-down, var(--jd-color-danger));
    }

    .jd-consensus-screener__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: 1px solid var(--_border);
    }
    .jd-consensus-screener__title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-sm);
      font-weight: 800;
      color: var(--_text);
    }
    .jd-consensus-screener__title-icon {
      display: inline-flex;
      color: var(--_accent-strong);
    }
    /* outline: none은 대체 표시 없이 쓰면 키보드 사용자에게서 커서를 빼앗는다.
     기본 아웃라인은 두되 :focus-visible에서 시스템 링으로 갈아끼운다. */
    .jd-consensus-screener__sort {
      height: 1.75rem;
      padding: 0 var(--jd-space-2);
      font-size: 12px;
      font-weight: var(--jd-weight-bold);
      font-family: inherit;
      white-space: nowrap;
      border-radius: var(--jd-radius-md);
      background: var(--_soft);
      border: 1px solid var(--_border);
      color: var(--_text);
      cursor: pointer;
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-consensus-screener__sort:hover {
      border-color: color-mix(in srgb, var(--_border) 70%, var(--jd-color-muted-light));
    }
    .jd-consensus-screener__sort:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-consensus-screener__bulls {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: 1px solid var(--_border);
    }
    .jd-consensus-screener__bulls-label {
      font-size: 11px;
      font-weight: 800;
      white-space: nowrap;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--_muted);
    }
    .jd-consensus-screener__bull-btns {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 6px;
    }
    .jd-consensus-screener__bull-btn {
      height: 1.75rem;
      min-width: 34px;
      padding: 0 var(--jd-space-2);
      font-size: 12px;
      font-weight: 800;
      font-family: inherit;
      white-space: nowrap;
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      background: var(--_soft);
      color: var(--_text);
      border: 1px solid var(--_border);
      /* all 금지 — 레이아웃 속성까지 대상이 되어 매 프레임 리플로우가 생긴다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 호버는 filter: brightness가 아니라 실색 전환 — brightness는 글자까지 밝힌다 */
    .jd-consensus-screener__bull-btn:hover {
      background: color-mix(in srgb, var(--_accent) 10%, var(--_soft));
      border-color: color-mix(in srgb, var(--_border) 70%, var(--jd-color-muted-light));
    }
    .jd-consensus-screener__bull-btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-consensus-screener__bull-btn:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-consensus-screener__bull-btn[data-active] {
      background: var(--_accent-strong);
      color: #fff;
      border-color: var(--_accent-strong);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-consensus-screener__bull-btn[data-active]:hover {
      background: var(--_accent);
    }
    .jd-consensus-screener__count {
      margin-inline-start: auto;
      font-size: 11.5px;
      white-space: nowrap;
      color: var(--_muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-consensus-screener__chips {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      /* 오른쪽 끝을 눅여 "더 있다"를 알린다 — 칩이 다 보이는 폭에서는 빈 공간이라 티가 안 난다 */
      mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
      border-block-end: 1px solid var(--_border);
    }
    .jd-consensus-screener__chip {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      flex-shrink: 0;
      padding: 4px var(--jd-space-2-5);
      font-size: 12px;
      font-weight: var(--jd-weight-bold);
      font-family: inherit;
      cursor: pointer;
      white-space: nowrap;
      border-radius: var(--jd-radius-full);
      background: var(--_soft);
      color: var(--_text);
      border: 1px solid transparent;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-consensus-screener__chip:hover {
      background: color-mix(in srgb, var(--_accent) 10%, var(--_soft));
      border-color: color-mix(in srgb, var(--_accent) 30%, transparent);
    }
    .jd-consensus-screener__chip:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-consensus-screener__chip:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-consensus-screener__chip[data-active] {
      background: var(--_accent-soft);
      /* 원색 글자는 다크에서 틴트 위에 가라앉는다 — 잉크(foreground)를 섞어 두 모드 모두 읽히게 */
      color: color-mix(in srgb, var(--_accent) 45%, var(--jd-color-foreground));
      border-color: var(--_accent);
    }
    .jd-consensus-screener__chip-count {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      opacity: 0.7;
    }

    /* 잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다 — 표는 스스로 구른다 */
    .jd-consensus-screener__table-wrap {
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
    }
    .jd-consensus-screener__table {
      width: 100%;
      /* 아홉 열이 다 읽히는 최소 폭 — 이보다 좁으면 열을 구기지 말고 굴린다 */
      min-width: 44rem;
      border-collapse: collapse;
      font-size: 13px;
    }
    .jd-consensus-screener__table th,
    .jd-consensus-screener__table td {
      padding: var(--jd-space-2) var(--jd-space-3);
      text-align: right;
      white-space: nowrap;
    }
    .jd-consensus-screener__table thead th {
      font-size: 11px;
      font-weight: var(--jd-weight-semibold);
      color: var(--_muted);
      border-block-end: 1px solid var(--_border);
    }
    .jd-consensus-screener__table thead th:first-child,
    .jd-consensus-screener__table tbody th {
      text-align: left;
    }
    .jd-consensus-screener__table tbody tr + tr th,
    .jd-consensus-screener__table tbody tr + tr td {
      border-block-start: 1px solid color-mix(in srgb, var(--_border) 60%, transparent);
    }
    .jd-consensus-screener__table tbody th {
      font-weight: var(--jd-weight-bold);
      color: var(--_text);
    }

    .jd-consensus-screener__num {
      font-variant-numeric: tabular-nums;
      color: var(--_text);
    }
    .jd-consensus-screener__num[data-tone="up"] {
      color: var(--_up);
    }
    .jd-consensus-screener__num[data-tone="down"] {
      color: var(--_down);
    }
    .jd-consensus-screener__num[data-tone="muted"] {
      color: var(--_muted);
    }
    .jd-consensus-screener__strong {
      font-weight: 800;
    }

    .jd-consensus-screener__name {
      appearance: none;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-sm);
      background: none;
      cursor: pointer;
      font: inherit;
      font-weight: 800;
      color: var(--_text);
      text-decoration: none;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-consensus-screener__name:hover {
      color: var(--_accent-strong);
      text-decoration: underline;
    }
    .jd-consensus-screener__name:active {
      color: var(--_accent);
    }
    .jd-consensus-screener__name:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-consensus-screener__sector {
      margin-inline-start: 6px;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--_muted);
    }

    .jd-consensus-screener__supporters {
      display: flex;
      align-items: center;
      gap: 2px;
      justify-content: flex-end;
    }
    .jd-consensus-screener__emoji {
      font-size: 14px;
      line-height: 1;
    }

    .jd-consensus-screener__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-10) var(--jd-space-4);
      text-align: center;
    }
    .jd-consensus-screener__empty-icon {
      color: var(--_muted);
    }
    .jd-consensus-screener__empty-title {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      color: var(--_text);
    }
    .jd-consensus-screener__empty-desc {
      font-size: var(--jd-text-xs);
      color: var(--_muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-consensus-screener__sort,
      .jd-consensus-screener__bull-btn,
      .jd-consensus-screener__chip,
      .jd-consensus-screener__name {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-container {
      display: block;
      box-sizing: border-box; /* DEC-014-9 */
      width: 100%;
      margin-inline: auto;
      max-width: var(--jd-container-lg);
      padding-inline: var(--jd-space-4);
    }
      jd-container[size="xs"] { max-width: var(--jd-container-xs); }
  jd-container[size="sm"] { max-width: var(--jd-container-sm); }
  jd-container[size="md"] { max-width: var(--jd-container-md); }
  jd-container[size="lg"] { max-width: var(--jd-container-lg); }
  jd-container[size="xl"] { max-width: var(--jd-container-xl); }
  jd-container[size="2xl"] { max-width: var(--jd-container-2xl); }
    jd-container[size="full"] {
      max-width: 100%;
    }
    jd-container[no-center] {
      margin-inline: 0;
    }

    @media (min-width: 640px) {
      jd-container {
        padding-inline: var(--jd-space-6);
      }
    }
  }

  @layer junds.base {
    jd-context-menu:not(:defined) {
      display: block;
    }
    jd-context-menu:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    /* 우클릭 영역을 감싸는 블록 — v2의 <div onContextMenu> 자리 */
    jd-context-menu {
      display: block;
      position: relative;
    }
    jd-context-menu > .jd-popover__trigger {
      display: block;
    }
    jd-context-menu > .jd-popover__trigger[tabindex] {
      display: block;
    }

    /* 포인터 좌표 고정 — left/top은 인라인 스타일이 채운다(#place) */
    jd-context-menu > .jd-popover__panel {
      position: fixed;
      top: 0;
      left: 0;
      right: auto;
      bottom: auto;
      margin: 0;
      --jd-popover-tx: 0;
      --jd-popover-ty: 0;
      min-width: 11.25rem;
      padding: var(--jd-space-1) 0;
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-lg);
      backdrop-filter: none;
    }
    jd-context-menu .jd-dropdown__item {
      padding-block: var(--jd-space-2);
    }
    jd-context-menu .jd-dropdown__divider {
      background: var(--jd-color-border-light);
    }
  }

  @layer junds.base {
    jd-cookie-consent:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-cookie-consent {
      position: fixed;
      z-index: var(--jd-z-toast);
      box-sizing: border-box;
      bottom: var(--jd-space-4);
      width: calc(100% - 2rem);
      max-width: 32rem; /* max-w-lg */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-2xl);
      padding: var(--jd-space-4);
    }
    jd-cookie-consent:not([data-open]) {
      display: none;
    }

    /* 위치 */
    jd-cookie-consent[position="bottom"] {
      inset-inline-start: 50%;
      transform: translateX(-50%);
    }
    jd-cookie-consent[position="bottom-left"] {
      inset-inline-start: var(--jd-space-4);
    }
    jd-cookie-consent[position="bottom-right"] {
      inset-inline-end: var(--jd-space-4);
    }

    .jd-cookie-consent__message {
      margin: 0;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-foreground);
    }
    .jd-cookie-consent__policy {
      color: var(--jd-color-primary-ink);
      text-decoration: underline;
      text-underline-offset: 2px;
    }
    .jd-cookie-consent__policy:hover {
      opacity: var(--jd-opacity-80);
    }

    .jd-cookie-consent__panel {
      margin-top: var(--jd-space-3);
      padding-top: var(--jd-space-3);
      border-top: var(--jd-border-thin) solid var(--jd-color-border);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    .jd-cookie-consent__cat {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      cursor: pointer;
    }
    .jd-cookie-consent__cat[data-required] {
      opacity: var(--jd-opacity-70);
      cursor: default;
    }
    .jd-cookie-consent__cat-check {
      margin-top: 2px;
      accent-color: var(--jd-color-primary);
    }
    .jd-cookie-consent__cat-label {
      font-weight: var(--jd-weight-medium);
    }
    .jd-cookie-consent__cat-required {
      font-size: 10px;
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }
    .jd-cookie-consent__cat-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-cookie-consent__actions {
      margin-top: var(--jd-space-4);
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: flex-end;
      gap: var(--jd-space-2);
    }
    .jd-cookie-consent__btn {
      box-sizing: border-box;
      border: var(--jd-border-thin) solid transparent;
      margin: 0;
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      background: transparent;
      color: var(--jd-color-foreground);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-cookie-consent__btn:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-cookie-consent__btn-customize:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-cookie-consent__btn-reject {
      border-color: var(--jd-color-border);
    }
    .jd-cookie-consent__btn-reject:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-cookie-consent__btn-primary {
      background: var(--jd-color-primary);
      color: #fff;
      font-weight: var(--jd-weight-semibold);
    }
    .jd-cookie-consent__btn-primary:hover {
      background: var(--jd-color-primary-hover);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cookie-consent__btn {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-copy-block {
      display: block;
      position: relative;
      box-sizing: border-box;
      /* 어두운 코드 면을 라이트 테두리로 두르면 머리글과 코드가 서로 다른 상자로
       읽힌다(실측: 모서리·이음매가 벌어져 보임). 테두리는 --jd-color-border가 아니라
       그 면의 잉크에서 뽑는다(§4) — 덩어리 하나의 윤곽이 된다. */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      background: var(--jd-color-surface);
      box-shadow: var(--jd-shadow-sm);
    }

    /* 머리글도 코드와 같은 어두운 계열이다 — 한 단만 들어 올려 '같은 덩어리의 윗면'이
     되게 한다. card-hover(라이트에서 흰색)를 쓰면 어두운 코드 위에 흰 띠가 얹힌다. */
    .jd-copy-block__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      /* 우상단 복사 버튼(32px)이 앉을 자리를 머리글이 직접 확보한다 — 겹치면
       라벨과 버튼이 한 칸을 다툰다 */
      min-height: 2.5rem;
      padding: var(--jd-space-2) var(--jd-space-12) var(--jd-space-2) var(--jd-space-4);
      background: var(--jd-color-surface-raised);
      border-block-end: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 12%, transparent);
    }
    .jd-copy-block__head[hidden] {
      display: none;
    }
    .jd-copy-block__lang {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-on-surface-muted);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wider);
    }

    .jd-copy-block__pre {
      margin: 0;
      padding: var(--jd-space-4);
      overflow-x: auto;
      /* 잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다(§6) */
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      scrollbar-color: color-mix(in srgb, var(--jd-color-on-surface) 28%, transparent) transparent;
      background: var(--jd-color-surface);
      color: var(--jd-color-on-surface); /* 항상 어두운 코드 면 (DEC-044) */
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      tab-size: 2;
    }
    .jd-copy-block__pre:focus-visible {
      outline: none;
      box-shadow: inset var(--jd-shadow-focus-ring);
    }
    .jd-copy-block__code {
      font: inherit;
    }
    /* 빈 줄도 한 행을 차지해야 한다 (v2는 높이 0으로 접혀 줄 수가 어긋났다) */
    .jd-copy-block__line {
      display: block;
      min-block-size: calc(1em * var(--jd-leading-relaxed));
    }
    jd-copy-block[show-line-numbers] .jd-copy-block__line::before {
      counter-increment: jd-copy-block-line;
      content: counter(jd-copy-block-line);
      display: inline-block;
      inline-size: 2rem;
      margin-inline-end: var(--jd-space-4);
      text-align: end;
      color: var(--jd-color-on-surface-muted);
      user-select: none;
    }
    jd-copy-block[show-line-numbers] .jd-copy-block__code {
      counter-reset: jd-copy-block-line;
    }

    /* 복사 버튼 — v2는 hover에서만 나타나 키보드·터치에서 사라졌다 */
    .jd-copy-block__copy {
      position: absolute;
      inset-block-start: var(--jd-space-2);
      inset-inline-end: var(--jd-space-2);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-2);
      border: 0;
      cursor: pointer;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-surface-overlay);
      color: var(--jd-color-on-surface-muted);
      box-shadow: inset 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      /* 안 보이는 버튼은 트리거가 아니다(§7). 쉬는 상태에서도 존재는 보이고,
       마우스가 오면 완전히 드러난다 — 0에서 시작하면 "여기 복사가 있다"를
       마우스 사용자에게만 알려 준 셈이 된다. */
      opacity: var(--jd-opacity-60);
      transition: opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-copy-block:hover .jd-copy-block__copy,
    jd-copy-block:focus-within .jd-copy-block__copy {
      opacity: 1;
    }
    @media (hover: none) {
      .jd-copy-block__copy {
        opacity: 1;
      }
    }
    .jd-copy-block__copy:hover {
      background: color-mix(
        in srgb,
        var(--jd-color-on-surface) 16%,
        var(--jd-color-surface-overlay)
      );
      color: var(--jd-color-on-surface);
    }
    .jd-copy-block__copy:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-copy-block__copy:focus-visible {
      opacity: 1;
      /* 어두운 면 위에서는 outline이 잘리지 않아도 되지만, 링 색이 배경과 붙지
       않도록 글로우 그림자를 쓴다(§1의 대체 표시) */
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-copy-block[copied] .jd-copy-block__copy {
      opacity: 1;
      background: var(--jd-color-success);
      color: #fff;
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-copy-block__icon {
      display: flex;
    }

    /* 라이브 리전 — 화면에서만 숨긴다 */
    .jd-copy-block__status {
      position: absolute;
      inline-size: 1px;
      block-size: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-copy-block__copy {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-copy-button {
      display: inline-flex;
    }

    .jd-copy-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-medium);
      border: 0;
      background: none;
      cursor: pointer;
      color: var(--jd-color-muted);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* icon 변형 기본 — md */
      width: 1.75rem;
      height: 1.75rem;
      padding: 0;
      border-radius: var(--jd-radius-md);
    }
    .jd-copy-button:hover:not(:disabled) {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    /* 눌린 면은 빛을 잃는다 — 복사는 되돌아오는 화면 변화가 2초 뒤에나 오므로
     누른 순간의 응답이 없으면 눌렸는지 알 수 없다 */
    .jd-copy-button:active:not(:disabled) {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
    }
    /* 코드 블록·표 셀 안에 끼어 사는 버튼이라 키보드로 도달했을 때가 특히 잘 안 보인다 */
    .jd-copy-button:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-copy-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-copy-button__icon {
      display: flex;
    }
    .jd-copy-button__label[hidden] {
      display: none;
    }

    jd-copy-button[size="sm"] .jd-copy-button {
      width: 1.5rem;
      height: 1.5rem;
    }
    jd-copy-button[copied] .jd-copy-button {
      color: var(--jd-color-success);
    }

    /* button 변형 — 테두리 + 라벨 */
    jd-copy-button[variant="button"] .jd-copy-button {
      width: auto;
      height: auto;
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: var(--jd-text-sm);
    }
    jd-copy-button[variant="button"][size="sm"] .jd-copy-button {
      padding: var(--jd-space-1) var(--jd-space-2);
      font-size: var(--jd-text-xs);
    }
    jd-copy-button[variant="button"][copied] .jd-copy-button {
      color: var(--jd-color-success);
      border-color: color-mix(in srgb, var(--jd-color-success) 30%, transparent);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-copy-button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-countdown {
      display: inline-flex;
      align-items: center;
      max-width: 100%;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    .jd-countdown__parts[hidden],
    .jd-countdown__done[hidden] {
      display: none;
    }
    .jd-countdown__unit[hidden],
    .jd-countdown__sep[hidden] {
      display: none;
    }

    .jd-countdown__value {
      font-variant-numeric: tabular-nums;
      font-family: var(--jd-font-mono);
    }

    /* ── full (기본) ──
     칸 폭을 내용에 맡기면 자릿수를 따라 제각각이 된다 — 1252 일 칸만 넓고 07 시 칸은
     좁아 시계가 아니라 낱개 배지처럼 읽혔다(실측). 폭이 정해지지 않은 격자에서 1fr
     트랙들은 **가장 넓은 칸에 맞춰 다 같아진다** — 등폭 세그먼트가 이 한 줄로 선다. */
    .jd-countdown__parts {
      display: inline-grid;
      grid-auto-flow: column;
      grid-auto-columns: 1fr;
      align-items: center;
      gap: var(--jd-space-3);
      max-width: 100%;
    }
    .jd-countdown__unit {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      min-width: 3rem;
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
    }
    .jd-countdown__unit > .jd-countdown__value {
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
    }
    .jd-countdown__unit > .jd-countdown__label {
      margin-top: var(--jd-space-1);
      font-size: 0.625rem;
      color: var(--jd-color-muted);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }
    .jd-countdown__sep {
      display: none;
    }

    /* ── compact ── */
    /* 등폭 격자는 칸이 상자로 보이는 full에만 뜻이 있다 — compact·minimal은 한 줄
     글줄이라 인라인 흐름으로 되돌린다 */
    jd-countdown[format="compact"] > .jd-countdown__parts {
      display: inline-flex;
      align-items: baseline;
      gap: var(--jd-space-1);
      font-family: var(--jd-font-mono);
      font-variant-numeric: tabular-nums;
    }
    jd-countdown[format="compact"] .jd-countdown__unit {
      display: inline;
      min-width: 0;
      padding: 0;
      background: none;
      border: 0;
      border-radius: 0;
    }
    jd-countdown[format="compact"] .jd-countdown__value {
      font-size: inherit;
      font-weight: var(--jd-weight-normal);
      line-height: inherit;
    }
    jd-countdown[format="compact"] .jd-countdown__label {
      margin: 0;
      font-size: inherit;
      color: inherit;
      text-transform: none;
      letter-spacing: normal;
    }

    /* ── minimal ── */
    jd-countdown[format="minimal"] > .jd-countdown__parts {
      display: inline-flex;
      gap: 0;
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-sm);
      font-variant-numeric: tabular-nums;
    }
    jd-countdown[format="minimal"] .jd-countdown__unit {
      display: inline;
      min-width: 0;
      padding: 0;
      background: none;
      border: 0;
      border-radius: 0;
    }
    jd-countdown[format="minimal"] .jd-countdown__value {
      font-size: inherit;
      font-weight: var(--jd-weight-normal);
      line-height: inherit;
    }
    /* 라벨은 지우지 않고 시각적으로만 숨긴다 — 낭독에는 단위가 남는다 */
    jd-countdown[format="minimal"] .jd-countdown__label {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    jd-countdown[format="minimal"] .jd-countdown__sep:not([hidden]) {
      display: inline;
    }

    .jd-countdown__done {
      font-size: var(--jd-text-md);
    }
  }

  @layer junds.components {
    jd-cron-expression {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
      font-family: var(--jd-font-sans);
    }

    .jd-cron__fields {
      display: flex;
      gap: var(--jd-space-2);
    }
    .jd-cron__field {
      flex: 1 1 0%;
      min-width: 0;
    }

    /* v2 text-[10px] → 2xs(11px). 칸이 좁다고 글자를 줄이면 라벨이 읽히지 않는다 —
     11px 아래로는 내려가지 않는다. 라벨은 한 줄로 유지한다(접히면 칸 높이가 어긋난다). */
    .jd-cron__label {
      display: block;
      margin-bottom: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
      white-space: nowrap;
    }

    .jd-cron__input {
      box-sizing: border-box;
      width: 100%;
      height: 2rem;
      margin: 0;
      padding-inline: var(--jd-space-2);
      text-align: center;
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-sm);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 호버 피드백 — 입력면에 호버 상태가 없으면 '쓸 수 있는 곳'이라는 신호가 없다
     (jd-text-field와 같은 관용구) */
    .jd-cron__input:hover:not(:disabled):not(:focus) {
      border-color: var(--jd-color-neutral-300);
      background: var(--jd-color-control-surface-hover);
    }
    /* 링은 DEC-039 두 줄 관용구로 — 이전의 outline:none + 옅은 box-shadow(알파 0.18)는
     흰 면 위에서 1.3:1이라 포커스가 어디 있는지 보이지 않았다 */
    .jd-cron__input:focus {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-color: var(--jd-color-primary);
    }
    /* opacity를 걸면 테두리·글자가 함께 흐려져 '고장난 칸'으로 읽힌다 → 면을 실색으로 낮춘다 */
    .jd-cron__input:disabled {
      cursor: not-allowed;
      color: var(--jd-color-muted);
      background: var(--jd-color-control-surface-muted);
      border-color: var(--jd-color-border-light);
    }

    /* 요약 행은 "앱의 본문"이지 어두운 크롬이 아니다 — 다크 분기로 surface-raised를
     따로 부르던 자리를 card-hover 한 줄로 접었다. card-hover는 양 모드에서 이미
     카드보다 한 단 눌린 면이라(#f9f8fc / #1c1932) 결과 색은 그대로이고, 모드가 늘 때
     이 컴포넌트가 다시 갈라지지 않는다(DEC-044). */
    .jd-cron__summary {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border: var(--jd-border-thin) solid var(--jd-color-border-light);
      border-radius: var(--jd-radius-lg);
    }

    .jd-cron__value {
      flex: 1 1 0%;
      min-width: 0;
      overflow-wrap: anywhere;
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-cron__desc {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-primary-ink);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cron__input {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-cta-section:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-cta-section {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      /* default */
      padding: var(--jd-space-12) var(--jd-space-4);
      background: var(--jd-color-card);
      border-block: var(--jd-border-thin) solid var(--jd-color-border);
    }
    @media (min-width: 640px) {
      jd-cta-section {
        padding: var(--jd-space-16) var(--jd-space-6);
      }
    }

    jd-cta-section[variant="gradient"] {
      background: var(--jd-gradient-primary);
      color: #fff;
      border-block: 0;
    }
    jd-cta-section[variant="subtle"] {
      background: var(--jd-color-card-hover);
      border-block: 0;
    }
    jd-cta-section[variant="split"] {
      background: transparent;
      border-block: 0;
      padding: var(--jd-space-12) var(--jd-space-4);
    }
    @media (min-width: 640px) {
      jd-cta-section[variant="split"] {
        padding: var(--jd-space-12) var(--jd-space-6);
      }
    }

    .jd-cta-section__inner {
      max-width: 48rem; /* max-w-3xl */
      margin-inline: auto;
    }
    jd-cta-section[variant="split"] .jd-cta-section__inner {
      max-width: 72rem; /* max-w-6xl */
      display: grid;
      gap: var(--jd-space-8);
      align-items: center;
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      border-radius: var(--jd-radius-2xl);
      background: var(--jd-color-card);
      /* 페이지 위에 얹힌 카드 — 면만 있으면 색종이로 읽힌다 */
      box-shadow: var(--jd-shadow-sm), inset 0 1px 0 var(--jd-color-highlight);
      padding: var(--jd-space-8);
    }
    @media (min-width: 1024px) {
      jd-cta-section[variant="split"] .jd-cta-section__inner {
        grid-template-columns: 1fr 1fr;
      }
    }

    .jd-cta-section__content {
      text-align: center;
    }
    jd-cta-section[variant="split"] .jd-cta-section__content {
      text-align: start;
    }

    .jd-cta-section__title {
      margin: 0;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
      /* 가운데 정렬 헤드라인이 마지막 줄에 한 단어만 남기지 않게 */
      text-wrap: balance;
    }
    @media (min-width: 640px) {
      .jd-cta-section__title {
        font-size: var(--jd-text-3xl);
      }
    }

    .jd-cta-section__desc {
      margin: var(--jd-space-3) 0 0;
      font-size: var(--jd-text-lg);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    jd-cta-section[variant="gradient"] .jd-cta-section__desc {
      color: rgba(255, 255, 255, 0.85);
    }

    .jd-cta-section__actions {
      margin-top: var(--jd-space-6);
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-3);
      justify-content: center;
    }
    jd-cta-section[variant="split"] .jd-cta-section__actions {
      justify-content: flex-start;
    }

    .jd-cta-section__media {
      min-width: 0;
    }

    /* 버튼 — anchor·button 공용 */
    .jd-cta-section__btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid transparent;
      margin: 0;
      padding: var(--jd-space-2-5) var(--jd-space-5);
      font-family: inherit;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      text-decoration: none;
      white-space: nowrap;
      cursor: pointer;
      user-select: none;
      border-radius: var(--jd-radius-md);
      /* filter를 전이 대상에서 뺐다 — brightness 호버는 글자까지 함께 밝혀 흰 글자가
       배경에 녹고 GPU 레이어를 새로 만든다. 호버는 실색 전환으로 한다. */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-cta-section__btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-cta-section__btn:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-cta-section__btn--primary {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-cta-section__btn--primary:hover {
      background: var(--jd-color-primary-hover);
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }

    .jd-cta-section__btn--secondary {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border-color: var(--jd-color-border);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-cta-section__btn--secondary:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }

    /* gradient(dark) 위에서의 버튼 반전 */
    jd-cta-section[variant="gradient"] .jd-cta-section__btn--primary {
      background: #fff;
      color: var(--jd-color-primary-hover);
      box-shadow: var(--jd-shadow-sm);
    }
    jd-cta-section[variant="gradient"] .jd-cta-section__btn--primary:hover {
      /* brightness 대신 실색 — 흰 면을 primary 쪽으로 아주 조금 당긴다 */
      background: color-mix(in srgb, #ffffff 90%, var(--jd-color-primary));
      box-shadow: var(--jd-shadow-md);
    }
    jd-cta-section[variant="gradient"] .jd-cta-section__btn--secondary {
      background: transparent;
      color: #fff;
      border-color: rgba(255, 255, 255, 0.4);
    }
    jd-cta-section[variant="gradient"] .jd-cta-section__btn--secondary:hover {
      background: rgba(255, 255, 255, 0.1);
    }
    jd-cta-section[variant="gradient"] .jd-cta-section__btn:focus-visible {
      outline-color: rgba(255, 255, 255, 0.7);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-cta-section__btn {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-currency-input {
      display: block;
      position: relative;
    }

    .jd-currency-input__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      font-variant-numeric: tabular-nums;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
      height: 2.25rem;
      font-size: var(--jd-text-sm);
      padding-inline: var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
    }
    .jd-currency-input__input::placeholder {
      color: var(--jd-color-muted);
    }
    .jd-currency-input__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-currency-input__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-currency-input[error] .jd-currency-input__input {
      border-color: var(--jd-color-danger);
    }
    jd-currency-input[error] .jd-currency-input__input:focus {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    jd-currency-input[size="sm"] .jd-currency-input__input {
      height: 2rem;
      font-size: var(--jd-text-xs);
      padding-inline: var(--jd-space-2-5);
      border-radius: var(--jd-radius-md);
    }
    jd-currency-input[size="lg"] .jd-currency-input__input {
      height: 2.75rem;
      font-size: var(--jd-text-md);
      padding-inline: var(--jd-space-4);
      border-radius: var(--jd-radius-xl);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-currency-input__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-daily-themes-calendar {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-accent: var(--jd-color-primary);
      --jd-fin-muted: var(--jd-color-muted);
      --jd-fin-text: var(--jd-color-foreground);
      --jd-fin-border: var(--jd-color-border);
      --jd-fin-card: var(--jd-color-card);
      --jd-fin-soft: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
      --jd-fin-warning: var(--jd-color-warning);
      /* 휴장일은 등락이 아니다 — finance 훅에 물리면 앱이 관례를 뒤집을 때 "장이 안 열림"
       표시까지 함께 뒤집힌다. 정지 상태를 뜻하는 danger에 고정한다. */
      --jd-fin-closed: var(--jd-color-danger);
      /* 오늘은 달력에서 가장 강한 강조다 — 팔레트 밖 핑크 대신 primary 계열의 accent를 쓴다.
       accent를 고른 이유: 요약 열이 이미 primary 틴트라 같은 색이면 두 강조가 겹쳐 읽힌다. */
      --jd-fin-today: var(--jd-color-accent);
      --jd-fin-cat-1: var(--jd-color-hue-violet);
      --jd-fin-cat-2: var(--jd-color-hue-pink);
      --jd-fin-cat-3: var(--jd-color-hue-teal);
      --jd-fin-cat-4: var(--jd-color-hue-amber);
      --jd-fin-cat-5: var(--jd-color-hue-purple);
      --jd-fin-cat-6: var(--jd-color-hue-cyan);
      --jd-fin-cat-7: var(--jd-color-hue-red);
      --jd-fin-cat-8: var(--jd-color-hue-green);

      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
      /* 6열 격자는 좁은 화면에서 셀을 짓눌러 글자를 한 자씩 세로로 세운다 —
       접지 말고 굴린다(§6: 잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다). */
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
    }
    jd-daily-themes-calendar * {
      box-sizing: border-box;
    }

    jd-daily-themes-calendar .jd-daily-themes-calendar__grid {
      /* 5칸 × 114 + 요약 150 — 이보다 좁아지면 셀 안 수치가 접힌다 */
      min-width: 720px;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
      box-shadow: var(--jd-shadow-xs);
    }

    /* 요일 헤더 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__header {
      display: grid;
      grid-template-columns: repeat(5, 1fr) 150px;
      text-align: center;
      background: var(--jd-fin-soft);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
      color: var(--jd-fin-muted);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__weekday {
      padding: var(--jd-space-2-5) 0;
      font-size: var(--jd-text-xs);
      font-weight: 800;
      letter-spacing: 0.06em;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-head {
      border-inline-start: var(--jd-border-thin) solid var(--jd-fin-border);
      color: var(--jd-fin-accent);
    }

    /* 주 행 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__week {
      display: grid;
      grid-template-columns: repeat(5, 1fr) 150px;
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__week[data-last] {
      border-block-end: none;
    }

    /* 셀 공통 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__cell {
      position: relative;
      min-height: 170px;
      border-inline-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__cell--blank {
      min-height: 0;
    }

    /* 휴장일 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__cell--holiday {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-3);
      background: var(--jd-fin-soft);
      opacity: 0.85;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__holiday-day {
      font-size: var(--jd-text-xs);
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__holiday-tag {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: 11px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-closed);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__holiday-dot {
      width: 6px;
      height: 6px;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-closed);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__holiday-name {
      font-size: 10.5px;
      font-weight: 700;
      line-height: var(--jd-leading-tight);
      text-align: center;
      color: var(--jd-fin-closed);
    }

    /* 미래 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__cell--future {
      padding: var(--jd-space-3);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__future-day {
      font-size: var(--jd-text-xs);
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
    }

    /* 정상 셀 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__hit {
      position: absolute;
      inset: 0;
      z-index: 0;
      cursor: pointer;
      background: transparent;
      border: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      /* background 단축이 아니라 색만 — image·position까지 전이 대상이 되면 헛돈다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day:not([data-today]):hover
      .jd-daily-themes-calendar__hit {
      background-color: var(--jd-fin-soft);
    }
    /* 셀 전체가 버튼이므로 눌림을 scale로 줄 수 없다(격자가 흔들린다) — 면을 한 단 더 눌러
     답한다. :not([data-today])를 hover와 똑같이 붙여 특이도를 맞춘다 — 안 맞추면 누르는
     동안에도 hover 규칙이 이겨 눌림이 보이지 않는다. */
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day:not([data-today]):active
      .jd-daily-themes-calendar__hit {
      background-color: color-mix(in srgb, var(--jd-color-foreground) 12%, transparent);
    }
    /* 링을 셀 안쪽에 그린다 — 격자 테두리에 딱 붙은 버튼이라 바깥 offset은 이웃 셀에 먹힌다 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__hit:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: -3px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__content {
      position: relative;
      z-index: 1;
      pointer-events: none;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3);
    }

    /* 오늘 강조 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__cell--day[data-today] {
      padding: var(--jd-space-1-5);
    }
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day[data-today]
      .jd-daily-themes-calendar__hit {
      inset: var(--jd-space-1-5);
      border: var(--jd-border-medium) solid var(--jd-fin-today);
      border-radius: var(--jd-radius-xl);
      background: color-mix(in srgb, var(--jd-fin-today) 6%, transparent);
      width: auto;
      height: auto;
    }
    /* 오늘 칸도 눌리는 버튼이다 — 위의 틴트가 일반 hover/active를 덮어쓰므로 자기 색으로
     다시 준다. 안 그러면 달력에서 유일하게 오늘만 아무 반응이 없다. */
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day[data-today]:hover
      .jd-daily-themes-calendar__hit {
      background-color: color-mix(in srgb, var(--jd-fin-today) 12%, transparent);
    }
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day[data-today]:active
      .jd-daily-themes-calendar__hit {
      background-color: color-mix(in srgb, var(--jd-fin-today) 20%, transparent);
    }
    jd-daily-themes-calendar
      .jd-daily-themes-calendar__cell--day[data-today]
      .jd-daily-themes-calendar__day-num {
      color: #fff;
      background: var(--jd-fin-today);
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
    }

    /* 날짜 헤더 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__day-head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__day-num {
      font-size: var(--jd-text-xs);
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__pct-chips {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      gap: 2px;
    }
    /* "거 +1.24%"는 라벨과 수치가 한 덩어리다 — 접히면 라벨만 남고 숫자가 아래로 떨어진다 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__pct-chip {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-size: 9.5px;
      font-weight: 700;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__pct-chip[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__pct-chip[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__pct-chip-label {
      color: var(--jd-fin-muted);
    }

    /* 데이터 행 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__data {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__data-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-1);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__data-label {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      min-width: 0;
      font-size: 10px;
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }
    /* 수치는 자릿수가 흔들리면 행마다 소수점이 어긋난다 — 등폭 + 줄바꿈 금지 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__data-value {
      font-size: 11.5px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__data-value[data-tone="up"] {
      color: var(--jd-fin-up);
    }

    /* 테마칩 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__themes {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
    }
    /* 칩 색은 element.ts가 인라인 --jd-dtc-cat 하나만 꽂고 면·글자·테두리는 여기서 뽑는다.
     v2처럼 세 속성을 인라인으로 쓰면 인라인이 시트를 이겨 hover/active를 CSS로 줄 수 없다.
     밝기 필터가 아니라 실색 전환인 이유: filter는 글자까지 함께 밝혀 틴트에 녹인다. */
    jd-daily-themes-calendar .jd-daily-themes-calendar__theme-chip {
      --_cat: var(--jd-dtc-cat, var(--jd-fin-accent));
      pointer-events: auto;
      cursor: pointer;
      font-size: 10px;
      font-weight: 800;
      white-space: nowrap;
      border-radius: var(--jd-radius-full);
      padding: 2px var(--jd-space-2);
      /* 옅은 틴트 위 원색 글자는 10px에서 AA에 못 미친다 — 잉크 쪽으로 섞어 대비 확보 */
      color: color-mix(in srgb, var(--_cat) 72%, var(--jd-color-foreground));
      background: color-mix(in srgb, var(--_cat) 10%, transparent);
      border: var(--jd-border-thin) solid color-mix(in srgb, var(--_cat) 20%, transparent);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__theme-chip:hover {
      background-color: color-mix(in srgb, var(--_cat) 18%, transparent);
      border-color: color-mix(in srgb, var(--_cat) 34%, transparent);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__theme-chip:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__theme-chip:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* 왕관 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__leaders {
      list-style: none;
      margin: 0;
      padding: 0;
      margin-block-start: auto;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: 10.5px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__crown {
      color: var(--jd-fin-warning);
      flex-shrink: 0;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader-name {
      font-weight: 700;
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader-close {
      margin-inline-start: auto;
      font-size: 10px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
      white-space: nowrap;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader-pct {
      font-size: 9.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader-pct[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__leader-pct[data-tone="down"] {
      color: var(--jd-fin-down);
    }

    /* 주간 요약 */
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-3);
      border-inline-start: var(--jd-border-thin) solid var(--jd-fin-border);
      /* 요약 열은 헤더 라벨과 같은 강조색을 옅게 깐다 — v2의 틸 리터럴은 브랜드를 벗어난다 */
      background: color-mix(in srgb, var(--jd-fin-accent) 4%, transparent);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary[data-empty] {
      align-items: center;
      justify-content: center;
      font-size: 11px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      opacity: 0.7;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-row {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-row-label {
      font-size: 10px;
      font-weight: 800;
      color: var(--jd-fin-muted);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-row-value {
      font-size: var(--jd-text-xs);
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-row-value[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-row-value[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-block {
      margin-block-start: 2px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-label {
      font-size: 9.5px;
      font-weight: 800;
      color: var(--jd-fin-muted);
      margin-block-end: 2px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-themes {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-theme {
      cursor: pointer;
      font-size: 9.5px;
      font-weight: 800;
      white-space: nowrap;
      border-radius: var(--jd-radius-full);
      padding: 1px var(--jd-space-1-5);
      color: color-mix(in srgb, var(--jd-fin-accent) 72%, var(--jd-color-foreground));
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
      border: var(--jd-border-thin) solid color-mix(in srgb, var(--jd-fin-accent) 24%, transparent);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-theme:hover {
      background-color: color-mix(in srgb, var(--jd-fin-accent) 18%, transparent);
      border-color: color-mix(in srgb, var(--jd-fin-accent) 38%, transparent);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-theme:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-theme:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-leaders {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    jd-daily-themes-calendar .jd-daily-themes-calendar__summary-leader {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      min-width: 0;
      font-size: 10px;
      font-weight: 700;
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-daily-themes-calendar .jd-daily-themes-calendar__hit,
      jd-daily-themes-calendar .jd-daily-themes-calendar__theme-chip,
      jd-daily-themes-calendar .jd-daily-themes-calendar__summary-theme {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-data-grid {
      display: block;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
    }

    /* v2 헤더 — 작은 대문자 캡션. 크기 토큰은 jd-table의 data-size 규칙을 대신한다 */
    jd-data-grid .jd-table__th {
      padding: var(--jd-space-2-5) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }
    jd-data-grid .jd-table__td {
      padding: var(--jd-space-2) var(--jd-space-3);
    }

    /* 베이스의 호스트 셀렉터(jd-table[...])는 파생 태그에 닿지 않는다 — 필요한 것만 재선언 */
    jd-data-grid[sticky-header] .jd-table__th {
      position: sticky;
      inset-block-start: 0;
      z-index: var(--jd-z-sticky);
    }
    jd-data-grid[row-clickable] .jd-table__body > .jd-table__row {
      cursor: pointer;
    }
    jd-data-grid[bordered] .jd-table__th,
    jd-data-grid[bordered] .jd-table__td {
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }

    /* 정렬 머리 — v2는 th onClick이라 탭이 닿지 않았다. 여기서는 진짜 버튼 */
    .jd-data-grid__sort {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      padding: 0;
      border: 0;
      background: none;
      font: inherit;
      letter-spacing: inherit;
      text-transform: inherit;
      color: inherit;
      cursor: pointer;
      user-select: none;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-data-grid__sort:hover {
      color: var(--jd-color-foreground);
    }
    .jd-data-grid__sort:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
      border-radius: var(--jd-radius-sm);
    }
    .jd-data-grid__sort-icon {
      display: inline-flex;
      width: 10px;
      height: 10px;
    }
    .jd-data-grid__sort-icon > svg {
      width: 10px;
      height: 10px;
    }

    /* 선택 열 — v2 w-10 */
    .jd-data-grid__select-cell {
      width: 2.5rem;
    }
    .jd-data-grid__check {
      margin: 0;
      width: 1rem;
      height: 1rem;
      cursor: pointer;
      accent-color: var(--jd-color-primary);
    }
    .jd-data-grid__check:disabled {
      cursor: not-allowed;
      opacity: var(--jd-opacity-40);
    }
    .jd-data-grid__check:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 1px;
    }

    jd-data-grid .jd-table__body > .jd-table__row:hover {
      background: var(--jd-color-card-hover);
    }
    /* v2 bg-primary/5 — 선택이 hover를 이긴다 */
    jd-data-grid .jd-table__body > .jd-table__row[data-selected],
    jd-data-grid .jd-table__body > .jd-table__row[data-selected]:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 5%, transparent);
    }

    .jd-data-grid__footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2) var(--jd-space-4);
      background: var(--jd-color-card-hover);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-data-grid__footer[hidden] {
      display: none;
    }

    .jd-data-grid__pager {
      display: flex;
      gap: var(--jd-space-1);
    }
    .jd-data-grid__pager-button {
      padding: var(--jd-space-1) var(--jd-space-2);
      font: inherit;
      color: inherit;
      background: none;
      border: 0;
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-data-grid__pager-button:hover:not(:disabled) {
      background: var(--jd-color-border-light);
    }
    .jd-data-grid__pager-button:disabled {
      opacity: var(--jd-opacity-30);
      cursor: not-allowed;
    }
    .jd-data-grid__pager-button:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-data-grid__sort,
      .jd-data-grid__pager-button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-data-table {
      display: block;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
    }

    /* ── 툴바 ── */
    .jd-data-table__toolbar {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
    }
    .jd-data-table__toolbar[hidden] {
      display: none;
    }
    .jd-data-table__toolbar > [hidden] {
      display: none;
    }
    .jd-data-table__toolbar-spacer {
      flex: 1 1 var(--jd-space-4);
    }

    /* 검색 (v2 h-8 pl-8 pr-8) */
    .jd-data-table__search {
      position: relative;
      display: inline-flex;
      align-items: center;
      flex: 1 1 12.5rem;
      min-width: 12.5rem;
      max-width: 24rem;
      color: var(--jd-color-muted);
    }
    .jd-data-table__search-icon {
      position: absolute;
      inset-inline-start: var(--jd-space-2-5);
      pointer-events: none;
    }
    .jd-data-table__search-input {
      width: 100%;
      box-sizing: border-box;
      height: var(--jd-space-8);
      padding-inline: calc(var(--jd-space-2-5) + 14px + var(--jd-space-2)) var(--jd-space-8);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      outline: none;
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-data-table__search-input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-data-table__search-input:focus-visible {
      border-color: var(--jd-color-primary);
      box-shadow: 0 0 0 var(--jd-border-medium)
        color-mix(in srgb, var(--jd-color-primary) 35%, transparent);
    }
    .jd-data-table__search-clear {
      position: absolute;
      inset-inline-end: var(--jd-space-2);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-0-5);
      color: var(--jd-color-muted);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-sm);
      cursor: pointer;
    }
    .jd-data-table__search-clear[hidden] {
      display: none;
    }
    .jd-data-table__search-clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-data-table__search-clear:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }

    /* 밀도 세그먼트 + 내보내기 */
    .jd-data-table__density,
    .jd-data-table__export {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
    }
    .jd-data-table__density-button,
    .jd-data-table__export-button {
      height: var(--jd-space-8);
      padding-inline: var(--jd-space-2-5);
      font: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      background: none;
      border: var(--jd-border-thin) solid transparent;
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-data-table__density-button:hover,
    .jd-data-table__export-button:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    .jd-data-table__density-button[data-active] {
      color: var(--jd-color-primary-ink);
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      background: color-mix(in srgb, var(--jd-color-primary) 8%, transparent);
    }
    .jd-data-table__density-button:focus-visible,
    .jd-data-table__export-button:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }

    /* ── 표 머리 타이포 (v2 대문자 캡션) ── */
    jd-data-table .jd-table__th {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    /* ── 밀도 패딩 (normal 기본 → compact/comfortable 오버라이드) ── */
    jd-data-table .jd-table__th,
    jd-data-table .jd-table__td {
      padding: var(--jd-space-3) var(--jd-space-4);
    }
    jd-data-table[density="compact"] .jd-table__th,
    jd-data-table[density="compact"] .jd-table__td {
      padding: var(--jd-space-1-5) var(--jd-space-3);
    }
    jd-data-table[density="comfortable"] .jd-table__th,
    jd-data-table[density="comfortable"] .jd-table__td {
      padding: var(--jd-space-4) var(--jd-space-5);
    }

    /* ── 모디파이어 (호스트 셀렉터라 파생 태그로 재선언) ── */
    jd-data-table[sticky-header] .jd-table__th {
      position: sticky;
      inset-block-start: 0;
      z-index: var(--jd-z-sticky);
    }
    jd-data-table[bordered] .jd-table__th,
    jd-data-table[bordered] .jd-table__td {
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    jd-data-table[striped] .jd-table__body > .jd-table__row:nth-child(even) {
      background: color-mix(in srgb, var(--jd-color-card-hover) 45%, transparent);
    }
    jd-data-table[row-clickable] .jd-table__body > .jd-table__row {
      cursor: pointer;
    }
    jd-data-table .jd-table__body > .jd-table__row:hover {
      background: var(--jd-color-card-hover);
    }
    /* 선택이 hover·striped를 이긴다 (v2 bg-primary-light) */
    jd-data-table .jd-table__body > .jd-table__row[data-selected],
    jd-data-table .jd-table__body > .jd-table__row[data-selected]:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 8%, transparent);
    }

    /* ── 행 번호 열 ── */
    .jd-data-table__num-cell {
      width: 3rem;
      text-align: center;
      color: var(--jd-color-muted-light);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    /* ── 로딩 스켈레톤 (.jd-table__row 없이 — 구분선을 직접 준다) ── */
    .jd-data-table__skeleton-row {
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-data-table__skeleton {
      display: block;
      width: 70%;
      height: 0.75rem;
      border-radius: var(--jd-radius-sm);
      background: linear-gradient(
        90deg,
        var(--jd-color-border-light) 25%,
        var(--jd-color-card-hover) 37%,
        var(--jd-color-border-light) 63%
      );
      background-size: 400% 100%;
      animation: jd-data-table-shimmer 1.4s ease infinite;
    }
    @keyframes jd-data-table-shimmer {
      0% {
        background-position: 100% 50%;
      }
      100% {
        background-position: 0 50%;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-data-table__search-input,
      .jd-data-table__density-button,
      .jd-data-table__export-button {
        transition: none;
      }
      .jd-data-table__skeleton {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-date-input {
      position: relative;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }

    .jd-date-input__label {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    .jd-date-input__label[hidden] {
      display: none;
    }
    jd-date-input[required] > .jd-date-input__label::after {
      content: "*";
      margin-inline-start: var(--jd-space-0-5);
      color: var(--jd-color-danger);
    }

    .jd-date-input__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-input__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-date-input__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
      background: var(--jd-color-card-hover);
    }
    /* 네이티브 달력 아이콘 — 다크 테마에서 검은 아이콘이 묻히는 것만 보정 */
    .jd-date-input__input::-webkit-calendar-picker-indicator {
      cursor: pointer;
    }

    jd-date-input[error] > .jd-date-input__input {
      border-color: var(--jd-color-danger);
    }
    jd-date-input[error] > .jd-date-input__input:focus {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    .jd-date-input__clear {
      position: absolute;
      inset-inline-end: 2rem;
      bottom: 0.5rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.25rem;
      height: 1.25rem;
      padding: 0;
      color: var(--jd-color-muted);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-sm);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-input__clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-date-input__clear:focus-visible {
      outline: none;
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-date-input__clear[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-date-input__input,
      .jd-date-input__clear {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-date-range-filter {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-date-range-filter__row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-date-range-filter__input {
      box-sizing: border-box;
      height: 2.25rem;
      margin: 0;
      padding-inline: var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-md);
      color: inherit;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-range-filter__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-date-range-filter__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
      background: var(--jd-color-card-hover);
    }

    .jd-date-range-filter__sep {
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
    }

    .jd-date-range-filter__apply,
    .jd-date-range-filter__reset {
      box-sizing: border-box;
      height: 2.25rem;
      margin: 0;
      padding-inline: var(--jd-space-4);
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      border: 0;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-range-filter__apply {
      color: #fff;
      background: var(--jd-color-primary);
    }
    .jd-date-range-filter__apply:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    .jd-date-range-filter__apply:active:not(:disabled) {
      scale: 0.97;
    }

    .jd-date-range-filter__reset {
      color: var(--jd-color-muted);
      background: transparent;
    }
    .jd-date-range-filter__reset:hover:not(:disabled) {
      color: var(--jd-color-foreground);
      background: var(--jd-color-border-light);
    }
    .jd-date-range-filter__reset[hidden] {
      display: none;
    }

    .jd-date-range-filter__apply:focus-visible,
    .jd-date-range-filter__reset:focus-visible,
    .jd-date-range-filter__preset:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-date-range-filter__apply:disabled,
    .jd-date-range-filter__reset:disabled,
    .jd-date-range-filter__preset:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-date-range-filter__presets {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1-5);
    }
    .jd-date-range-filter__presets[hidden] {
      display: none;
    }

    .jd-date-range-filter__preset {
      box-sizing: border-box;
      height: 1.75rem;
      margin: 0;
      padding-inline: var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      background: var(--jd-color-border-light);
      border: 0;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-range-filter__preset:hover:not(:disabled) {
      color: var(--jd-color-primary-ink);
      background: var(--jd-color-primary-light);
    }
    .jd-date-range-filter__preset[aria-pressed="true"] {
      color: #fff;
      background: var(--jd-color-primary);
    }
    .jd-date-range-filter__preset[aria-pressed="true"]:hover:not(:disabled) {
      color: #fff;
      background: var(--jd-color-primary-hover);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-date-range-filter__input,
      .jd-date-range-filter__apply,
      .jd-date-range-filter__reset,
      .jd-date-range-filter__preset {
        transition: none;
      }
      .jd-date-range-filter__apply:active:not(:disabled) {
        scale: 1;
      }
    }
  }

  @layer junds.components {
    
  [data-jd-picker-field] { position: relative; display: inline-flex; }

  /* v2: div.flex.items-center.gap-2.h-9.px-3.border.bg-white.rounded-lg — 진짜 button으로 승격 */
  .jd-picker-field__trigger {
    display: inline-flex; align-items: center; gap: var(--jd-space-2);
    height: 2.25rem; padding-inline: var(--jd-space-3); margin: 0;
    box-sizing: border-box; max-width: 100%;
    font-family: var(--jd-font-sans); font-size: var(--jd-text-md);
    color: var(--jd-color-foreground); text-align: start;
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg); cursor: pointer;
    transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
                box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-picker-field__trigger:focus-visible {
    outline: none; border-color: var(--jd-color-primary);
    box-shadow: var(--jd-shadow-focus-ring);
  }
  .jd-picker-field__trigger[aria-expanded="true"] {
    border-color: var(--jd-color-primary); box-shadow: var(--jd-shadow-focus-ring);
  }
  .jd-picker-field__trigger:disabled {
    opacity: var(--jd-opacity-50); cursor: not-allowed;
    background: var(--jd-color-card-hover);
  }
  .jd-picker-field__icon {
    display: inline-flex; flex-shrink: 0; color: var(--jd-color-muted);
  }
  .jd-picker-field__value {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .jd-picker-field__value[data-placeholder] { color: var(--jd-color-muted-light); }

  /* v2는 Portal+fixed라 스크롤하면 패널이 떨어져 나갔다 — absolute로 좌표 동기화를 브라우저에 위임 */
  .jd-picker-field__panel {
    position: absolute; top: calc(100% + var(--jd-space-1));
    inset-inline-start: 0; z-index: var(--jd-z-popover);
    box-sizing: border-box;
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg); box-shadow: var(--jd-shadow-lg);
  }
  .jd-picker-field__panel[hidden] { display: none; }
  [data-jd-picker-field][data-placement="top"] > .jd-picker-field__panel {
    top: auto; bottom: calc(100% + var(--jd-space-1));
  }

  @media (prefers-reduced-motion: no-preference) {
    .jd-picker-field__panel:not([hidden]) {
      animation: jd-picker-field-in var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
  }
  @keyframes jd-picker-field-in { from { opacity: 0; transform: scale(.97); } }


    jd-date-range-picker > .jd-picker-field__panel {
      padding: var(--jd-space-4);
    }

    .jd-date-range-picker__nav {
      display: flex;
      align-items: center;
      margin-bottom: var(--jd-space-3);
    }
    .jd-date-range-picker__nav-spacer {
      flex: 1;
    }
    .jd-date-range-picker__nav-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.75rem;
      height: 1.75rem;
      padding: 0;
      color: var(--jd-color-foreground);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-sm);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-range-picker__nav-btn:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-date-range-picker__nav-btn:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-date-range-picker__months {
      display: flex;
      gap: var(--jd-space-4);
    }

    .jd-date-range-picker__calendar {
      border-collapse: collapse;
      table-layout: fixed;
      width: 16rem;
    }
    .jd-date-range-picker__caption {
      caption-side: top;
      margin-bottom: var(--jd-space-2);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      text-align: center;
    }
    .jd-date-range-picker__calendar th {
      height: 1.75rem;
      padding: 0;
      font-weight: var(--jd-weight-normal);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-date-range-picker__calendar th abbr {
      text-decoration: none;
      border: 0;
      cursor: default;
    }
    .jd-date-range-picker__calendar td {
      padding: 0;
    }

    .jd-date-range-picker__day {
      display: block;
      width: 100%;
      height: 2rem;
      padding: 0;
      font-family: inherit;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-date-range-picker__day:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
    }
    .jd-date-range-picker__day:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-date-range-picker__day:disabled {
      opacity: var(--jd-opacity-30);
      cursor: not-allowed;
    }

    /* v2: 오늘 = font-bold text-primary (양끝일 때는 양끝 표현이 이긴다) */
    .jd-date-range-picker__day[data-today] {
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-primary-ink);
    }
    /* v2: 범위 안 = bg-primary/10 — 사이 날짜는 모서리를 붙여 띠로 읽히게 한다 */
    .jd-date-range-picker__day[data-in-range] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      border-radius: 0;
    }
    .jd-date-range-picker__day[data-range-start],
    .jd-date-range-picker__day[data-range-end] {
      font-weight: var(--jd-weight-medium);
      color: #fff;
      background: var(--jd-color-primary);
    }
    .jd-date-range-picker__day[data-range-start]:hover,
    .jd-date-range-picker__day[data-range-end]:hover {
      background: var(--jd-color-primary-hover);
    }

    /* 달 이동 통지 — 시각적으로만 숨긴다(디스플레이 none은 읽히지 않는다) */
    .jd-date-range-picker__status {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (max-width: 480px) {
      .jd-date-range-picker__months {
        flex-direction: column;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-date-range-picker__day,
      .jd-date-range-picker__nav-btn {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-day-detail-drawer:not(:defined) {
      display: none;
    }
    jd-day-detail-drawer .jd-modal__panel {
      max-width: min(480px, 95vw);
    }

    .jd-day-detail__content {
      display: block;
    }
    .jd-day-detail__content[hidden] {
      display: none;
    }

    .jd-day-detail__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4) 0;
    }
    /* 이 패널의 면들(알약·스탯·순매수 카드·줄무늬)은 드로어 카드 위에 얹힌 **본문**이지
     라이트에서도 어두워야 할 크롬이 아니다 — surface를 쓰면서 잉크는 foreground로 두어
     라이트 모드에서 검은 판에 검은 글자가 얹혔다. 카드보다 한 단 눌린 면인
     background로 내리면 잉크는 그대로 두고 두 모드 다 성립한다(DEC-044). */
    .jd-day-detail__pill {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      padding: var(--jd-space-1) var(--jd-space-2-5);
      border-radius: var(--jd-radius-full);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      background: var(--jd-color-background);
      color: var(--jd-color-foreground);
    }
    /* 오늘 표시는 팔레트 밖 핑크(#ec4899)였다 — 강조는 primary 계열이다 */
    .jd-day-detail__pill[data-today] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-day-detail__meta-sub {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }

    /* 스탯 그리드 */
    .jd-day-detail__stats {
      display: grid;
      /* minmax(0,1fr) — 기본 1fr은 최소 폭이 내용이라 긴 숫자가 칸을 밀어내고,
       밀린 칸의 말줄임은 끝내 걸리지 않는다 */
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--jd-space-3);
      padding: var(--jd-space-4);
    }
    .jd-day-detail__stat {
      padding: var(--jd-space-2) var(--jd-space-3);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-background);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      min-width: 0;
    }
    .jd-day-detail__stat-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }
    .jd-day-detail__stat-value {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-day-detail__stat-sub {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-day-detail__stat-value[data-dir="up"],
    .jd-day-detail__stat-sub[data-dir="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__stat-value[data-dir="down"],
    .jd-day-detail__stat-sub[data-dir="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }

    /* 섹션 공통 */
    .jd-day-detail__section {
      padding: 0 var(--jd-space-4) var(--jd-space-4);
    }
    .jd-day-detail__section-title {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
      margin-block-end: var(--jd-space-2);
    }

    /* 테마 */
    .jd-day-detail__theme-chips {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1-5);
    }
    .jd-day-detail__theme {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      padding: var(--jd-space-1) var(--jd-space-2-5);
      /* 칩 라벨은 접히지 않는다 — 두 줄이 되면 칩이 알약으로 읽히지 않는다 */
      white-space: nowrap;
      /* 틴트 위 글자는 foreground 쪽으로 섞어 대비 확보 */
      border-radius: var(--jd-radius-full);
      color: color-mix(in srgb, var(--jd-color-accent) 65%, var(--jd-color-foreground));
      background: color-mix(in srgb, var(--jd-color-accent) 12%, transparent);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-accent) 28%, transparent);
    }

    /* 차트 공통 — viewBox가 비율을 쥐고 있으므로 높이는 폭을 따라간다. height 속성을
     고정값으로 두면 좁은 화면에서 캔들이 옆으로 눌린다. */
    .jd-day-detail__chart {
      display: block;
      width: 100%;
      max-width: 100%;
      height: auto;
    }
    .jd-day-detail__candle--up {
      stroke: var(--jd-finance-up, var(--jd-color-success));
      fill: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__candle--down {
      stroke: var(--jd-finance-down, var(--jd-color-danger));
      fill: var(--jd-finance-down, var(--jd-color-danger));
    }
    .jd-day-detail__candle {
      stroke-width: 1;
    }
    .jd-day-detail__flow-axis {
      stroke: color-mix(in srgb, var(--jd-color-foreground) 25%, transparent);
      stroke-width: 0.5;
    }
    .jd-day-detail__flow-bar {
      fill: var(--jd-color-muted);
    }
    .jd-day-detail__flow-bar[data-neg] {
      fill-opacity: 0.55;
    }
    .jd-day-detail__flow-bar--foreign {
      fill: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__flow-bar--institution {
      fill: var(--jd-color-hue-purple);
    }
    .jd-day-detail__flow-bar--individual {
      fill: var(--jd-color-warning);
    }

    /* 순매수 카드 */
    .jd-day-detail__nets {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: var(--jd-space-2);
    }
    .jd-day-detail__net {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-2);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-background);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      min-width: 0;
    }
    .jd-day-detail__net-label {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      white-space: nowrap;
    }
    .jd-day-detail__net-dot {
      flex-shrink: 0;
      width: var(--jd-space-2);
      height: var(--jd-space-2);
      border-radius: var(--jd-radius-full);
    }
    .jd-day-detail__net-dot--foreign {
      background: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__net-dot--institution {
      background: var(--jd-color-hue-purple);
    }
    .jd-day-detail__net-dot--individual {
      background: var(--jd-color-warning);
    }
    /* "+1,840억"은 숫자와 단위가 한 덩어리다 — 접히면 단위가 다음 줄에 홀로 선다 */
    .jd-day-detail__net-value {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .jd-day-detail__net-value[data-dir="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__net-value[data-dir="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }

    /* 왕관 종목 */
    .jd-day-detail__leaders {
      list-style: none;
      margin: 0;
      padding: 0;
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-day-detail__leader {
      display: grid;
      /* 종목명 칸은 minmax(0,1fr) — 1fr의 최소 폭은 내용이라 긴 이름이 오른쪽
       수치 칸을 밀어내고 말줄임이 끝내 걸리지 않는다 */
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-day-detail__leader:last-child {
      border-block-end: 0;
    }
    /* 줄무늬는 어떤 면 위에 얹혀도 같게 읽혀야 한다 — 불투명 색이 아니라 잉크 틴트 */
    .jd-day-detail__leader[data-alt] {
      background: color-mix(in srgb, var(--jd-color-muted) 7%, transparent);
    }
    .jd-day-detail__leader-crown {
      color: var(--jd-color-warning);
      font-size: var(--jd-text-md);
    }
    .jd-day-detail__leader-name {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-day-detail__leader-right {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      line-height: var(--jd-leading-tight);
    }
    .jd-day-detail__leader-close,
    .jd-day-detail__leader-pct {
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-day-detail__leader-close {
      font-size: var(--jd-text-xs);
    }
    .jd-day-detail__leader-pct {
      font-size: var(--jd-text-2xs);
    }
    .jd-day-detail__leader-pct[data-dir="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-day-detail__leader-pct[data-dir="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
  }

  @layer junds.base {
    jd-descriptions:not(:defined) {
      display: block;
    }
    jd-descriptions:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-descriptions {
      display: block;
    }

    .jd-descriptions__box {
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    .jd-descriptions__box[data-bordered] {
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }

    .jd-descriptions__title {
      margin: 0 0 var(--jd-space-3);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-descriptions__title[hidden] {
      display: none;
    }
    .jd-descriptions__box[data-bordered] > .jd-descriptions__title {
      margin: 0;
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }

    /* 열 **수**는 소비자가 정하지만 열 **폭**은 칸이 정한다. 고정 repeat(N)은 좁은
     칼럼(카드 안·사이드바) 안에서 라벨 100px에게 칸을 다 빼앗기고, 남은 값 칸이
     한 글자씩 세로로 선다(실측). auto-fit + "요청 열 수로 나눈 폭"을 하한으로 두면
     넓을 때는 정확히 --jd-desc-cols 열이고 좁아지면 스스로 열을 접는다 — 뷰포트
     미디어쿼리와 달리 부모 폭을 본다. */
    .jd-descriptions__list {
      --jd-desc-col-gap: var(--jd-space-6);
      --jd-desc-col-min: 14rem;
      display: grid;
      margin: 0;
      grid-template-columns: repeat(
        auto-fit,
        minmax(
          min(
            100%,
            max(
              var(--jd-desc-col-min),
              (100% - (var(--jd-desc-cols, 2) - 1) * var(--jd-desc-col-gap)) /
                var(--jd-desc-cols, 2)
            )
          ),
          1fr
        )
      );
      /* 접힌 격자에서 span이 열 수를 넘으면 암시 열이 생긴다 — 폭 0으로 못 박아
       목록이 상자를 밀고 나가지 못하게 한다(§6) */
      grid-auto-columns: 0;
      column-gap: var(--jd-desc-col-gap);
      row-gap: var(--jd-space-3);
    }

    /* layout 기본 horizontal — 라벨 왼쪽 고정폭 + 값 나머지 */
    .jd-descriptions__item {
      grid-column: span var(--jd-desc-span, 1);
      display: flex;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-descriptions__box[data-layout="vertical"] .jd-descriptions__item {
      display: block;
      gap: 0;
    }

    /* 라벨 폭은 고정이되 칸의 절반을 넘지 않는다 — 넘게 두면 값 칸이 0으로 눌려
     한 글자씩 세로로 선다. keep-all은 라벨이 어절 중간에서 끊기지 않게 한다. */
    .jd-descriptions__label {
      margin: 0;
      /* v2의 w-[100px]/w-[120px]는 Tailwind preflight(border-box) 위의 **총폭**이다 —
       content-box로 두면 bordered 라벨 셀이 패딩만큼(24px) 넓어져 값 칸을 더 좁힌다 */
      box-sizing: border-box;
      flex: 0 0 var(--jd-desc-label-w, 100px);
      max-width: 45%;
      padding-block-start: var(--jd-space-0-5);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      word-break: keep-all;
    }
    .jd-descriptions__box[data-layout="vertical"] .jd-descriptions__label {
      flex: none;
      /* 라벨이 값 위에 오는 배치에서는 폭을 나눌 상대가 없다 — 상한을 되돌린다 */
      max-width: none;
      padding-block-start: 0;
      margin-block-end: var(--jd-space-0-5);
    }

    /* 값은 길이를 모른다: 어절은 지키고(keep-all) 한 어절이 칸보다 길 때만 끊는다.
     기본 CJK 줄바꿈은 글자 단위라 좁은 칸에서 세로 한 줄이 된다. */
    .jd-descriptions__value {
      margin: 0;
      box-sizing: border-box;
      flex: 1 1 auto;
      min-width: 0;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      word-break: keep-all;
      overflow-wrap: break-word;
      /* 값은 대개 수치다 — 자릿수가 흔들리면 행끼리 눈금이 어긋난다 */
      font-variant-numeric: tabular-nums;
    }

    /* ── bordered 격자 ─────────────────────────────────────────── */
    .jd-descriptions__box[data-bordered] > .jd-descriptions__list {
      /* 칸을 선으로 붙이므로 열 간격이 0 — 열 폭 계산식도 같은 값을 써야 한다 */
      --jd-desc-col-gap: 0px;
      --jd-desc-col-min: 15rem;
      row-gap: 0;
      margin-inline-end: -1px;
      margin-block-end: -1px;
      --jd-desc-label-w: 120px;
    }
    .jd-descriptions__box[data-bordered] .jd-descriptions__item {
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-descriptions__box[data-bordered] .jd-descriptions__label {
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-descriptions__box[data-bordered][data-layout="vertical"] .jd-descriptions__label {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      margin-block-end: 0;
      border-inline-end: 0;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-descriptions__box[data-bordered] .jd-descriptions__value {
      padding: var(--jd-space-2) var(--jd-space-3);
    }
  }

  @layer junds.base {
    /* 업그레이드 전에는 문서 흐름 안에 상세 내용이 통째로 나타난다 — 오버레이류 규칙 적용 */
    jd-detail-panel:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-detail-panel {
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      position: fixed;
      inset-block: 0;
      inset-inline-end: 0;
      z-index: var(--jd-z-overlay);
      width: var(--jd-detail-panel-width, 420px);
      max-width: 100vw; /* v2는 420px 고정이라 모바일에서 뷰포트를 넘었다 */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      /* 떠 있는 면의 테두리는 눅인다(§2) — 진한 선은 그림자와 겹쳐 두 겹으로 보인다 */
      border-inline-start: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      box-shadow: var(--jd-shadow-xl);
      transform: translateX(100%);
      transition: transform var(--jd-duration-slow) var(--jd-easing-default);
    }
    jd-detail-panel[open] {
      transform: translateX(0);
    }
    /* 프로그램 포커스 전용 컨테이너(tabindex=-1) — 링을 그리지 않는다 */
    jd-detail-panel:focus {
      outline: none;
    }

    .jd-detail-panel__header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-2);
      flex-shrink: 0;
      padding: var(--jd-space-4) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-detail-panel__heading {
      flex: 1 1 auto;
      min-width: 0;
    }
    .jd-detail-panel__title-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-detail-panel__title {
      margin: 0;
      font-size: var(--jd-text-lg); /* v2 text-base = 1rem */
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-detail-panel__subtitle {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-md); /* v2 text-sm = 0.875rem */
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-detail-panel__subtitle[hidden] {
      display: none;
    }

    .jd-detail-panel__status {
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      /* v2 text-[10px]는 §9 하한 밑이다 — 상태 배지는 이 패널에서 가장 짧은 글이라
       작을수록 안 읽힌다. 2xs(11px)까지 올리고 대비도 muted 이상으로 유지한다. */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      letter-spacing: var(--jd-tracking-wide);
      background: var(--jd-color-border-light);
      color: var(--jd-color-muted);
    }
    .jd-detail-panel__status[hidden] {
      display: none;
    }
    jd-detail-panel[status="success"] .jd-detail-panel__status {
      background: var(--jd-color-success-light);
      color: color-mix(
        in srgb,
        var(--jd-color-success) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-detail-panel[status="warning"] .jd-detail-panel__status {
      background: var(--jd-color-warning-light);
      color: color-mix(
        in srgb,
        var(--jd-color-warning) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-detail-panel[status="danger"] .jd-detail-panel__status {
      background: var(--jd-color-danger-light);
      color: color-mix(
        in srgb,
        var(--jd-color-danger) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-detail-panel[status="info"] .jd-detail-panel__status {
      background: var(--jd-color-info-light);
      color: color-mix(
        in srgb,
        var(--jd-color-info) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    .jd-detail-panel__close {
      display: flex;
      flex-shrink: 0;
      padding: var(--jd-space-1);
      margin-inline-start: var(--jd-space-2);
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      border-radius: var(--jd-radius-lg);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-detail-panel__close:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-border-light);
    }
    /* 눌린 면은 빛을 잃는다(§1) — hover/focus만 있던 자리에 세 번째 상태를 채운다 */
    .jd-detail-panel__close:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-detail-panel__close:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-detail-panel__tabs {
      display: flex;
      flex-shrink: 0;
      gap: 0;
      padding-inline: var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-detail-panel__tabs[hidden] {
      display: none;
    }

    .jd-detail-panel__tab {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin: 0 0 calc(-1 * var(--jd-border-thin));
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border: 0;
      border-block-end: var(--jd-border-medium) solid transparent;
      background: transparent;
      cursor: pointer;
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      color: var(--jd-color-muted);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-detail-panel__tab:hover {
      color: var(--jd-color-foreground);
      border-block-end-color: var(--jd-color-border);
    }
    .jd-detail-panel__tab:active {
      color: var(--jd-color-primary-ink);
    }
    /* 탭은 패널 안쪽이라 잘릴 조상이 없다 — outline이 radius를 따라간다 */
    .jd-detail-panel__tab:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
      border-radius: var(--jd-radius-md);
    }
    .jd-detail-panel__tab[aria-selected="true"] {
      color: var(--jd-color-primary-ink);
      border-block-end-color: var(--jd-color-primary);
    }

    .jd-detail-panel__tab-badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      /* 11px 숫자가 들어가려면 18px 원으로는 좁다 — 20px로 키운다 */
      min-width: 1.25rem;
      height: 1.25rem;
      padding-inline: var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      background: var(--jd-color-border-light);
      color: var(--jd-color-muted);
    }
    .jd-detail-panel__tab-badge[hidden] {
      display: none;
    }
    .jd-detail-panel__tab[aria-selected="true"] > .jd-detail-panel__tab-badge {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }

    .jd-detail-panel__body {
      flex: 1 1 auto;
      overflow-y: auto;
      /* 패널 끝까지 굴린 뒤의 휠이 뒤 페이지를 밀지 않게 — 오버레이의 기본 예의 */
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
      padding: var(--jd-space-5);
      /* 이 패널의 본문은 상세 정보다. 상속으로 흘러온 크기에 맡기면 소비자 마크업이
       10~11px로 내려앉는다(실측) — 하한을 여기서 못 박는다(§9). */
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
    }
    .jd-detail-panel__body:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    .jd-detail-panel__body > [data-tab][hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-detail-panel {
        transition: none;
      }
      .jd-detail-panel__tab,
      .jd-detail-panel__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-diff-viewer {
      display: block;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-sm);
      background: var(--jd-color-card);
    }

    .jd-diff-viewer__header {
      display: flex;
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card-hover);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-diff-viewer__header[hidden] {
      display: none;
    }

    .jd-diff-viewer__title {
      flex: 1 1 0;
      min-width: 0;
      padding: var(--jd-space-2) var(--jd-space-3);
    }
    .jd-diff-viewer__title[hidden] {
      display: none;
    }
    /* v2는 첫 칸에만 세로 구분선을 뒀다 — 두 칸이 다 있을 때만 그린다 */
    .jd-diff-viewer__title + .jd-diff-viewer__title {
      border-inline-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-diff-viewer__scroll {
      overflow-x: auto;
    }
    .jd-diff-viewer__scroll:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: -2px;
    }

    .jd-diff-viewer__table {
      width: 100%;
      border-collapse: collapse;
      table-layout: auto;
    }

    /* 요약은 표의 접근 이름으로만 쓴다(시각적으로 숨김 — jd-visually-hidden 관용구) */
    .jd-diff-viewer__caption,
    .jd-diff-viewer__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-diff-viewer__num,
    .jd-diff-viewer__marker,
    .jd-diff-viewer__content {
      padding: 0;
      vertical-align: top;
      line-height: var(--jd-leading-relaxed);
    }

    /* 번호·부호는 드래그 복사에 섞이지 않는다 — 코드만 깨끗하게 붙는다 */
    .jd-diff-viewer__num {
      width: 2.5rem;
      text-align: right;
      padding-inline-end: var(--jd-space-2);
      font-size: 10px;
      color: var(--jd-color-muted);
      user-select: none;
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-diff-viewer__marker {
      width: 1.25rem;
      text-align: center;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      user-select: none;
    }

    .jd-diff-viewer__content {
      padding-inline: var(--jd-space-2);
      white-space: pre;
    }

    .jd-diff-viewer__row[data-type="add"] {
      background: color-mix(in srgb, var(--jd-color-success) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
    }
    .jd-diff-viewer__row[data-type="remove"] {
      background: color-mix(in srgb, var(--jd-color-danger) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-danger) 65%, var(--jd-color-foreground));
    }
  }

  @layer junds.base {
    jd-disclosure:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-disclosure {
      display: block;
    }

    .jd-disclosure__trigger {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      border: 0;
      background: transparent;
      font-family: var(--jd-font-sans);
      font-size: inherit;
      line-height: inherit;
      color: var(--jd-color-foreground);
      text-align: start;
      cursor: pointer;
    }
    .jd-disclosure__trigger:disabled,
    .jd-disclosure__trigger[aria-disabled="true"] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-disclosure__trigger:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 홀로 쓰이는 트리거의 크롬 ──
     입양 골격(자기 셰브런을 갖고 오는 것)은 여기서 빠진다. 셀렉터가 (0,3,0)이라
     위의 원형 리셋과 아래 파생 시트 어느 쪽이 뒤에 채택되든 특이도로 이긴다. */
    .jd-disclosure__trigger:not(:has([class*="__chevron"])) {
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      font-weight: var(--jd-weight-medium);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-disclosure__trigger:not(:has([class*="__chevron"])):hover:not(
        :disabled,
        [aria-disabled="true"]
      ) {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    /* 폭 100% 행이라 scale로 줄이면 부모에서 떨어져 보인다 — 눌린 면이 빛을 잃는
     신호만 남긴다 (button link variant가 scale을 빼는 것과 같은 판단). */
    .jd-disclosure__trigger:not(:has([class*="__chevron"])):active:not(
        :disabled,
        [aria-disabled="true"]
      ) {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-disclosure__trigger:not(:has([class*="__chevron"])):focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      box-shadow: none;
    }

    /* 셰브런 — 접히는 것에는 셰브런이 있고 열림에 따라 180° 돈다. 골격에 span을
     새로 끼우지 않고 ::after로 그려 공개 DOM 표면을 그대로 둔다. 아래를 가리키는
     캐럿이 45°이므로 열림은 225°(=+180°)다. */
    .jd-disclosure__trigger:not(:has([class*="__chevron"]))::after {
      content: "";
      flex-shrink: 0;
      /* justify-between의 자리 — 라벨은 왼쪽, 셰브런은 오른쪽 끝 */
      margin-inline-start: auto;
      width: 0.45em;
      height: 0.45em;
      border-inline-end: var(--jd-border-medium) solid currentColor;
      border-block-end: var(--jd-border-medium) solid currentColor;
      color: var(--jd-color-muted);
      rotate: 45deg;
      /* 45° 회전한 캐럿은 무게중심이 아래로 쏠린다 — 광학 중앙으로 되올린다 */
      translate: 0 -0.12em;
      transition: rotate var(--jd-duration-normal) var(--jd-easing-ease-out),
        translate var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-disclosure__trigger[data-state="open"]:not(:has([class*="__chevron"]))::after {
      rotate: 225deg;
      translate: 0 0.12em;
    }

    .jd-disclosure__label {
      min-width: 0;
    }

    .jd-disclosure__panel {
      display: grid;
      grid-template-rows: 0fr;
      opacity: var(--jd-opacity-0);
      visibility: hidden;
      transition: grid-template-rows var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        visibility 0s linear var(--jd-duration-normal);
    }
    .jd-disclosure__panel[data-state="open"] {
      grid-template-rows: 1fr;
      opacity: var(--jd-opacity-100);
      visibility: visible;
      transition-delay: 0s;
    }
    /* 0fr↔1fr 보간은 min-height:0 + overflow:hidden 자식이 있어야 성립한다 */
    .jd-disclosure__inner {
      overflow: hidden;
      min-height: 0;
    }

    /* 감속 요청 시엔 전이를 끈다 — visibility도 즉시 뒤집혀 지연 이유가 사라진다 */
    @media (prefers-reduced-motion: reduce) {
      .jd-disclosure__panel,
      .jd-disclosure__panel[data-state="open"],
      .jd-disclosure__trigger:not(:has([class*="__chevron"])),
      .jd-disclosure__trigger:not(:has([class*="__chevron"]))::after {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-disclosure-tone-badge {
      --jd-fin-up: var(--bm-up, var(--jd-color-success));
      --jd-fin-down: var(--bm-down, var(--jd-color-danger));
      --jd-fin-up-soft: var(
        --bm-up-soft,
        color-mix(in srgb, var(--jd-color-success) 14%, transparent)
      );
      --jd-fin-down-soft: var(
        --bm-down-soft,
        color-mix(in srgb, var(--jd-color-danger) 14%, transparent)
      );
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      /* tone 기본 = neutral */
      --jd-dtb-fg: var(--jd-fin-muted);
      --jd-dtb-bg: var(--jd-fin-soft);

      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      height: 28px;
      padding: 0 var(--jd-space-2-5);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-dtb-bg);
      white-space: nowrap;
      font-family: var(--jd-font-sans);
      line-height: var(--jd-leading-none);
    }
    jd-disclosure-tone-badge[tone="positive"] {
      --jd-dtb-fg: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
      --jd-dtb-bg: var(--jd-fin-up-soft);
    }
    jd-disclosure-tone-badge[tone="negative"] {
      --jd-dtb-fg: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
      --jd-dtb-bg: var(--jd-fin-down-soft);
    }
    jd-disclosure-tone-badge[tone="neutral"] {
      --jd-dtb-fg: var(--jd-fin-muted);
      --jd-dtb-bg: var(--jd-fin-soft);
    }

    jd-disclosure-tone-badge .jd-disclosure-tone-badge__tone {
      color: var(--jd-dtb-fg);
      font-size: 11px;
      font-weight: 800;
      letter-spacing: var(--jd-tracking-wide);
    }
    jd-disclosure-tone-badge .jd-disclosure-tone-badge__cat {
      color: var(--jd-dtb-fg);
      opacity: 0.85;
      font-size: 10.5px;
      font-weight: 700;
    }
    jd-disclosure-tone-badge .jd-disclosure-tone-badge__conf {
      color: var(--jd-dtb-fg);
      opacity: 0.6;
      font-size: 10px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
    }

    /* compact — 톤 라벨만 */
    jd-disclosure-tone-badge[compact] {
      height: 20px;
      gap: 0;
      padding: 0 var(--jd-space-1-5);
      border-radius: var(--jd-radius-sm);
    }
    jd-disclosure-tone-badge[compact] .jd-disclosure-tone-badge__tone {
      font-size: 10.5px;
    }
    jd-disclosure-tone-badge[compact] .jd-disclosure-tone-badge__cat,
    jd-disclosure-tone-badge[compact] .jd-disclosure-tone-badge__conf {
      display: none;
    }
  }

  @layer junds.components {
    jd-disclosures {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-disclosures:not(:defined) {
      display: block;
    }

    /* 요약 */
    .jd-disclosures__summary {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: var(--jd-space-3);
      margin-block-start: var(--jd-space-1);
    }
    .jd-disclosures__card {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-inline-start: 3px solid var(--accent, var(--jd-color-accent));
    }
    .jd-disclosures__card-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 36px;
      height: 36px;
      font-size: 18px;
      border-radius: var(--jd-radius-xl);
      background: color-mix(in srgb, var(--accent, var(--jd-color-accent)) 12%, transparent);
    }
    .jd-disclosures__card-text {
      min-width: 0;
    }
    /* 10.5px는 §9 하한(11px) 아래다 — 요약 카드 라벨은 본문 정보다 */
    .jd-disclosures__card-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-disclosures__card-value {
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      /* 원색 그대로면 sky/warning/info가 흰 카드에서 대비 미달 → foreground 쪽으로 섞는다 */
      color: color-mix(
        in srgb,
        var(--accent, var(--jd-color-accent)) 65%,
        var(--jd-color-foreground)
      );
    }
    .jd-disclosures__card-hint {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      white-space: nowrap;
    }

    /* 검색 */
    .jd-disclosures__search {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-3);
      padding: var(--jd-space-2);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 입력이 outline: none 이라 포커스 표시는 감싼 바가 대신 진다 — 대체 없이 지우면
       키보드 사용자에게서 커서를 빼앗는 것이다(§1) */
    .jd-disclosures__search:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-disclosures__search-icon {
      flex-shrink: 0;
      font-size: var(--jd-text-md);
    }
    .jd-disclosures__search-input {
      flex: 1;
      min-width: 0;
      border: 0;
      background: transparent;
      outline: none;
      padding: var(--jd-space-1-5) 0;
      font: inherit;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
    }
    .jd-disclosures__search-input::placeholder {
      color: var(--jd-color-muted);
    }
    /* --jd-color-surface 는 라이트에서도 어두운 크롬용이다 — 흰 검색 바 안의 작은 지우기
       칩에 쓰면 검은 알약 위에 모드추종 잉크가 얹혀 라이트에서 글자가 사라진다(§4).
       카드 위 "한 톤 뜬 면"은 muted 혼합으로 만든다. */
    .jd-disclosures__search-clear {
      flex-shrink: 0;
      border: 0;
      cursor: pointer;
      padding: var(--jd-space-1) var(--jd-space-2-5);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-muted) 14%, var(--jd-color-card));
      color: var(--jd-color-muted);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-disclosures__search-clear[hidden] {
      display: none;
    }
    .jd-disclosures__search-clear:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 22%, var(--jd-color-card));
      color: var(--jd-color-foreground);
    }
    .jd-disclosures__search-clear:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-disclosures__search-clear:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 분류 칩 — overflow-x:auto 는 세로축도 함께 스크롤 컨테이너로 만든다. 여백이 없으면
       칩 자신과 포커스 링이 위아래로 잘려 나가고(실측), 블록 시작 방향 오버플로는
       스크롤로도 되돌릴 수 없다. 안쪽 여백으로 링이 살 자리를 준다. */
    .jd-disclosures__chips {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-2);
      padding-block: var(--jd-space-1-5);
      overflow-x: auto;
      /* 행 끝에서 멈춘 스크롤이 페이지를 이어서 밀지 않게 한다(§6) */
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      -webkit-overflow-scrolling: touch;
      /* 오른쪽 끝을 흐려 "더 있다"를 알린다 — 잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다 */
      -webkit-mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
      mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
    }
    .jd-disclosures__chip {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      cursor: pointer;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card);
      color: color-mix(
        in srgb,
        var(--accent, var(--jd-color-foreground)) 65%,
        var(--jd-color-foreground)
      );
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--accent, var(--jd-color-border)) 33%, transparent);
      box-shadow: var(--jd-shadow-xs);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-disclosures__chip:not([data-active]):hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--accent, var(--jd-color-border)) 55%, transparent);
    }
    .jd-disclosures__chip[data-active] {
      /* 원색 배경 + 흰 글자 → 배경을 foreground 쪽 80% 혼합으로 어둡혀 대비 확보 */
      background: color-mix(
        in srgb,
        var(--accent, var(--jd-color-foreground)) 80%,
        var(--jd-color-foreground)
      );
      color: #fff;
      border-color: transparent;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-disclosures__chip[data-active]:hover {
      background: color-mix(
        in srgb,
        var(--accent, var(--jd-color-foreground)) 60%,
        var(--jd-color-foreground)
      );
    }
    /* 선택 여부와 무관하게 눌린 면은 빛을 잃는다 — [data-active] 뒤에 둬야 덮이지 않는다(§1) */
    .jd-disclosures__chip:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 행이 스크롤 컨테이너라 바깥 아웃라인은 잘린다 — 링을 그림자로 준다(§1) */
    .jd-disclosures__chip:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-disclosures__chip-count {
      font-variant-numeric: tabular-nums;
      /* 10.5px는 §9 하한(11px) 아래다 */
      font-size: var(--jd-text-2xs);
      opacity: var(--jd-opacity-80);
    }

    /* 목록 */
    .jd-disclosures__list {
      display: block;
      margin-block-start: var(--jd-space-3);
      padding: var(--jd-space-4);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-disclosures__desc {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-1);
    }
    .jd-disclosures__desc-meta {
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }

    .jd-disclosures__empty {
      padding: var(--jd-space-10) 0;
      text-align: center;
    }
    .jd-disclosures__empty[hidden] {
      display: none;
    }
    .jd-disclosures__empty-icon {
      font-size: var(--jd-text-4xl);
    }
    .jd-disclosures__empty-title {
      margin: var(--jd-space-1-5) 0 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
    }
    .jd-disclosures__empty-sub {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }

    .jd-disclosures__note {
      margin: var(--jd-space-3) 0 0;
      padding-inline: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }

    .jd-disclosures__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (min-width: 48rem) {
      .jd-disclosures__summary {
        grid-template-columns: repeat(4, 1fr);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-disclosures__chip,
      .jd-disclosures__search,
      .jd-disclosures__search-clear {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-divider {
      display: block;
      height: var(--jd-border-thin);
      background-color: var(--jd-color-border);
      margin-block: var(--jd-space-4);
    }
    jd-divider[orientation="vertical"] {
      display: inline-block;
      width: var(--jd-border-thin);
      height: auto;
      /* 플렉스 부모에서는 stretch가 높이를 준다. 그 밖(블록·인라인 문맥)에서는
       height:auto가 0이 되어 선이 통째로 사라진다 — 최소 한 줄 높이는 남긴다. */
      min-height: 1em;
      align-self: stretch;
      margin-block: 0;
    }
    /* 라벨 모드는 축을 **전부 리셋**한다: orientation 규칙이 남긴 width/min-height가
     함께 걸리면 3분할 행이 1px 기둥으로 찌그러진다 (popover 시트의 "속성 규칙은
     전부 리셋을 포함한다" 규약과 동형). */
    jd-divider[label]:not([label=""]) {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      width: auto;
      height: auto;
      min-height: 0;
      background-color: transparent;
    }
    /* flex-basis 0으로 자라기만 하면 부모가 폭을 shrink-wrap 할 때(플렉스/그리드 자식,
     인라인 문맥) 0폭이 되어 **선이 아예 안 보인다**(실측). 라벨 달린 구분선은 선이
     보이는 것이 존재 이유이므로 최소 길이를 준다. */
    .jd-divider__line {
      flex: 1 1 auto;
      min-width: var(--jd-space-6);
      height: var(--jd-border-thin);
      background-color: var(--jd-color-border);
    }
    .jd-divider__label {
      flex-shrink: 0;
      /* 좁아지면 줄어드는 것은 선이지 라벨이 아니다 — 접히면 글자가 세로로 선다 */
      white-space: nowrap;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      color: var(--jd-color-muted);
    }
  }

  @layer junds.components {
    jd-dock {
      display: inline-flex;
      align-items: flex-end;
      box-sizing: border-box;
      gap: var(--jd-space-1);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      background: color-mix(in srgb, var(--jd-color-card) 80%, transparent);
      backdrop-filter: blur(24px);
      /* 떠 있는 판의 테두리는 눅인다 — 실선 border는 유리면 위에서 오려낸 종이처럼 뜬다 */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      border-radius: var(--jd-radius-2xl);
      box-shadow: var(--jd-shadow-lg);
    }

    jd-dock-item {
      display: block;
    }

    .jd-dock-item__button {
      position: relative; /* v2는 이게 없어 라벨 툴팁의 기준이 엉뚱했다 */
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 0;
      border: 0;
      background: none;
      font: inherit;
      color: inherit;
      cursor: pointer;
      transform: scale(var(--jd-dock-scale, 1));
      transform-origin: bottom center;
      /* scale 프로퍼티는 transform과 곱해진다 — 확대 배율(transform)을 건드리지 않고
       누름 반응을 따로 얹을 수 있다 */
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* v2에도 v3 이식본에도 :active가 없었다 — 독 아이콘은 눌러도 아무 일이 없었다 */
    .jd-dock-item__button:active {
      scale: 0.97;
    }

    .jd-dock-item__tile {
      display: flex;
      align-items: center;
      justify-content: center;
      /* width/height + border 동시 사용 → 자기 선언 (v2는 Tailwind 전역 리셋이 담당했다) */
      box-sizing: border-box;
      width: 2.5rem;
      height: 2.5rem;
      color: var(--jd-color-foreground);
      background: linear-gradient(180deg, var(--jd-color-card-hover), var(--jd-color-card));
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      /* 인셋 하이라이트가 '위에서 빛을 받는 타일'을 만든다 */
      box-shadow: var(--jd-shadow-sm), inset 0 1px 0 var(--jd-color-highlight);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-dock-item__button:hover > .jd-dock-item__tile {
      box-shadow: var(--jd-shadow-md), inset 0 1px 0 var(--jd-color-highlight);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    /* :hover 뒤에 둔다 — 누르는 동안에도 커서는 위에 있으므로 앞에 두면 호버가 이긴다.
     눌린 면은 빛을 잃는다: 상단 하이라이트를 걷어내고 그림자를 안으로 넣는다. */
    .jd-dock-item__button:active > .jd-dock-item__tile {
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 아웃라인은 버튼이 아니라 타일에 — 버튼은 라벨까지 감싸고 있어 링이 툴팁 자리까지
     늘어난다. outline은 border-radius를 따라가므로 둥근 타일에서 각지지 않는다. */
    .jd-dock-item__button:focus-visible {
      outline: none;
    }
    .jd-dock-item__button:focus-visible > .jd-dock-item__tile {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-dock-item__label {
      position: absolute;
      bottom: 100%;
      margin-bottom: var(--jd-space-1);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      white-space: nowrap;
      pointer-events: none;
      /* v2 text-[10px]은 읽기 하한(2xs=11px) 아래였다 — 툴팁이라고 글자를 줄이지 않는다 */
      font-size: var(--jd-text-2xs);
      line-height: var(--jd-leading-normal);
      /* 항상 어두운 툴팁 면의 짝은 on-surface다 (DEC-044) */
      color: var(--jd-color-on-surface);
      background: var(--jd-color-surface-overlay);
      border-radius: var(--jd-radius-md);
      /* 떠 있는 것은 그림자로 뜬다 — 그림자 없는 알약은 타일에 붙은 스티커로 읽힌다 */
      box-shadow: var(--jd-shadow-lg);
      opacity: 0;
      transition: opacity var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-dock-item__label[hidden] {
      display: none;
    }
    /* v2는 scale > 1.2일 때만 — 키보드로는 볼 수 없었다 */
    .jd-dock-item__button:hover > .jd-dock-item__label,
    .jd-dock-item__button:focus-visible > .jd-dock-item__label {
      opacity: 1;
    }

    @media (prefers-reduced-motion: reduce) {
      /* 커서를 따라 계속 움직이는 확대는 저감 대상 — 배율 자체를 끈다 */
      .jd-dock-item__button {
        transform: none;
        transition: none;
      }
      .jd-dock-item__tile,
      .jd-dock-item__label {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-donut-chart {
      /* 계열색은 hue 팔레트에서만(§8). 공용 기본값은 success/warning/danger를 조각색으로
       써서 "3번 조각"과 "경고"가 한 화면에서 같은 색이 된다 — 구성비는 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 링 220px + 범례가 카드보다 넓으면 범례가 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 정사각
     비율을 대신 말하므로 폭만 줄여도 링이 타원이 되지 않는다. */
    jd-donut-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 9rem);
    }
    jd-donut-chart:not(:defined) {
      display: inline-flex;
    }

    .jd-donut-chart__track {
      fill: none;
      stroke: var(--jd-color-border);
      stroke-opacity: 0.5;
    }
    .jd-donut-chart__seg {
      fill: none;
      stroke: var(--jd-series-color);
      stroke-linecap: butt;
    }
    .jd-donut-chart__center-label {
      fill: var(--jd-color-muted);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
    .jd-donut-chart__center-value {
      fill: var(--jd-color-foreground);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
  }

  @layer junds.components {
    jd-drawer {
      display: none;
    }
    jd-drawer[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      padding: 0; /* 가장자리에 붙는다 — 모달의 여백 없음 */
    }
    /* side 기본 right */
    jd-drawer[open] {
      align-items: stretch;
      justify-content: flex-end;
    }
    jd-drawer[side="left"][open] {
      justify-content: flex-start;
    }
    jd-drawer[side="bottom"][open] {
      align-items: flex-end;
      justify-content: stretch;
    }

    jd-drawer .jd-modal__panel {
      max-height: 100%;
      height: 100%;
      border-radius: 0;
      /* size 기본 md — v2 420px */
      max-width: min(420px, 100vw);
      animation: jd-drawer-in var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-drawer[size="sm"] .jd-modal__panel {
      max-width: min(320px, 100vw);
    }
    jd-drawer[size="lg"] .jd-modal__panel {
      max-width: min(560px, 100vw);
    }
    jd-drawer[size="xl"] .jd-modal__panel {
      max-width: min(720px, 100vw);
    }

    jd-drawer[side="left"] .jd-modal__panel {
      animation-name: jd-drawer-in-left;
    }
    jd-drawer[side="bottom"] .jd-modal__panel {
      width: 100%;
      max-width: 100%;
      height: auto;
      /* v2 bottom size: sm 12rem / md 18rem / lg 24rem / xl 30rem */
      height: 18rem;
      max-height: 90vh;
      border-radius: var(--jd-radius-2xl) var(--jd-radius-2xl) 0 0;
      animation-name: jd-drawer-in-bottom;
    }
    jd-drawer[side="bottom"][size="sm"] .jd-modal__panel {
      height: 12rem;
    }
    jd-drawer[side="bottom"][size="lg"] .jd-modal__panel {
      height: 24rem;
    }
    jd-drawer[side="bottom"][size="xl"] .jd-modal__panel {
      height: 30rem;
    }

    @keyframes jd-drawer-in {
      from {
        transform: translateX(100%);
      }
    }
    @keyframes jd-drawer-in-left {
      from {
        transform: translateX(-100%);
      }
    }
    @keyframes jd-drawer-in-bottom {
      from {
        transform: translateY(100%);
      }
    }

    .jd-drawer__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      flex-shrink: 0;
      padding: var(--jd-space-4) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-drawer__header[hidden] {
      display: none;
    }
    .jd-drawer__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-drawer__close {
      display: flex;
      padding: var(--jd-space-1);
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
    }
    .jd-drawer__close:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    .jd-drawer__close:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-drawer .jd-modal__panel {
        animation: none;
      }
    }
  }

  @layer junds.base {
    jd-dropdown:not(:defined) {
      display: inline-block;
    }
    jd-dropdown:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-dropdown {
      position: relative;
      display: inline-block;
    }

    /* ── 트리거 ──
     원형은 포커스 가능한 자식이 없을 때만 래퍼를 승격한다 — 그래서 [tabindex] 가
     곧 "소비자가 자기 버튼을 넣지 않았다"는 표식이다. 그 경우 트리거는 맨 텍스트로
     남아 메뉴를 여는 것으로 보이지 않았다(실측). 소비자가 <jd-button>을 넣으면
     래퍼는 display:contents로 남아 이 규칙에 걸리지 않는다.
     치수·상태는 jd-button secondary와 같은 어휘를 쓴다. */
    jd-dropdown > .jd-popover__trigger[tabindex] {
      box-sizing: border-box;
      gap: var(--jd-space-2);
      height: 2.25rem;
      padding-inline: var(--jd-space-3-5);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      user-select: none;
      cursor: pointer;
      box-shadow: var(--jd-shadow-xs);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    jd-dropdown > .jd-popover__trigger[tabindex]:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    jd-dropdown > .jd-popover__trigger[tabindex]:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    jd-dropdown > .jd-popover__trigger[tabindex]:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      /* 원형의 합성 트리거 포커스 규칙이 radius를 md로 되돌린다 — 링이 면보다
       각지지 않게 여기서 다시 못 박는다 */
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-xs);
    }
    /* 메뉴가 달려 있다는 표시 — 열리면 180° 돈다(아래 캐럿이 45°이므로 225°) */
    jd-dropdown > .jd-popover__trigger[tabindex]::after {
      content: "";
      flex-shrink: 0;
      width: 0.4em;
      height: 0.4em;
      border-inline-end: var(--jd-border-medium) solid currentColor;
      border-block-end: var(--jd-border-medium) solid currentColor;
      color: var(--jd-color-muted);
      rotate: 45deg;
      /* 45° 회전한 캐럿은 무게중심이 아래로 쏠린다 — 광학 중앙으로 되올린다 */
      translate: 0 -0.1em;
      transition: rotate var(--jd-duration-normal) var(--jd-easing-ease-out),
        translate var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-dropdown[open] > .jd-popover__trigger[tabindex]::after {
      rotate: 225deg;
      translate: 0 0.1em;
    }

    /* 파생 기본값(0,1,1) — v2 기본 정렬 right. 디폴트는 attribute로 반영되지 않으므로
     (§1.3) CSS가 담당한다. 명시 align attribute(0,2,0)가 언제나 이긴다. */
    jd-dropdown > .jd-popover__panel {
      left: auto;
      right: 0;
      --jd-popover-tx: 0;
      min-width: 10rem;
      padding: var(--jd-space-1) 0;
      border-radius: var(--jd-radius-lg);
      /* 떠 있는 면은 테두리를 눅이고 그림자로 띄운다 — 실선 테두리는 문서 안의
       구획으로 읽힌다 */
      border-color: color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      backdrop-filter: none;
    }

    /* ── 메뉴 목록 원형 ── */
    .jd-dropdown__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      width: 100%;
      box-sizing: border-box;
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border: 0;
      background: none;
      cursor: pointer;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      text-align: start;
      color: var(--jd-color-foreground);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-dropdown__item:hover:not(:disabled),
    .jd-dropdown__item:focus-visible {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
    }
    /* 항목은 폭 전체를 차지하는 행이라 scale로 줄이면 메뉴에서 떨어져 보인다 —
     눌린 면이 더 짙어지는 것으로 대신한다(button link variant 선례) */
    .jd-dropdown__item:active:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-primary) 18%, transparent);
    }
    /* 패널이 잘라 내는 자리라 outline은 좌우가 사라진다 — 링을 box-shadow로 (§1) */
    .jd-dropdown__item:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-dropdown__item[data-danger] {
      color: var(--jd-color-danger);
    }
    .jd-dropdown__item[data-danger]:hover:not(:disabled),
    .jd-dropdown__item[data-danger]:focus-visible {
      background: color-mix(in srgb, var(--jd-color-danger) 10%, transparent);
    }
    .jd-dropdown__item[data-danger]:active:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-danger) 18%, transparent);
    }
    .jd-dropdown__item:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }

    .jd-dropdown__icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 1rem;
      height: 1rem;
    }
    .jd-dropdown__icon > svg {
      width: 100%;
      height: 100%;
    }
    .jd-dropdown__label {
      flex: 1 1 auto;
      min-width: 0;
    }
    .jd-dropdown__shortcut {
      flex-shrink: 0;
      margin-inline-start: var(--jd-space-4);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-dropdown__divider {
      height: var(--jd-border-thin);
      margin-block: var(--jd-space-1);
      background: var(--jd-color-border);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-dropdown > .jd-popover__trigger[tabindex],
      jd-dropdown > .jd-popover__trigger[tabindex]::after,
      .jd-dropdown__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-email-inbox {
      display: grid;
      grid-template-columns: 1fr;
      height: 640px;
      box-sizing: border-box; /* height + border 병용 — 실측 640px 유지(DEC-014-9) */
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      background: var(--jd-color-card);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    @media (min-width: 1024px) {
      jd-email-inbox {
        grid-template-columns: 200px 360px 1fr;
      }
    }

    /* 폴더 패널 */
    .jd-email-inbox__folders {
      display: none;
      border-right: var(--jd-border-thin) solid var(--jd-color-border);
      padding: var(--jd-space-2);
      overflow-y: auto;
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
    }
    @media (min-width: 1024px) {
      .jd-email-inbox__folders {
        display: block;
      }
    }
    .jd-email-inbox__folder-list {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .jd-email-inbox__folder {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      border: 0;
      background: transparent;
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
      text-align: left;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-email-inbox__folder:not([data-active]):hover {
      background: var(--jd-color-card-hover);
    }
    .jd-email-inbox__folder[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-email-inbox__folder[data-active]:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 16%, transparent);
    }
    /* 선택 여부와 무관하게 눌린다 — [data-active] 뒤에 둬야 덮이지 않는다(§1) */
    .jd-email-inbox__folder:active {
      scale: 0.98;
    }
    /* 오프셋은 음수 — 패널이 overflow:hidden 이라 바깥으로 그린 링은 잘려 사라진다 */
    .jd-email-inbox__folder:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-email-inbox__folder-label {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-email-inbox__folder-name {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-email-inbox__folder-count {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      padding: 0 var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      font-variant-numeric: tabular-nums;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      color: var(--jd-color-primary-ink);
    }

    /* 리스트 패널 */
    .jd-email-inbox__list {
      display: flex;
      flex-direction: column;
      min-height: 0;
      border-right: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-email-inbox__search {
      padding: var(--jd-space-2);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-email-inbox__search-input {
      width: 100%;
      height: 2.25rem;
      padding: 0 var(--jd-space-3);
      font-size: var(--jd-text-sm);
      font-family: inherit;
      color: inherit;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      background: var(--jd-color-control-surface);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* outline을 지우면 같은 규칙 안에서 대체 표시를 준다 — 테두리색만으로는
       색각 이상 사용자에게 포커스가 보이지 않는다(§1) */
    .jd-email-inbox__search-input:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-email-inbox__items {
      flex: 1;
      overflow-y: auto;
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-email-inbox__item {
      width: 100%;
      padding: var(--jd-space-2-5) var(--jd-space-3);
      text-align: left;
      border: 0;
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
      background: var(--jd-color-card);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
    }
    .jd-email-inbox__item:not([data-active]):hover {
      background: var(--jd-color-card-hover);
    }
    .jd-email-inbox__item[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
    }
    .jd-email-inbox__item[data-active]:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 16%, transparent);
    }
    /* 목록 행은 scale로 눌리면 이웃 행과 어긋나 보인다 — 눌린 면은 빛만 잃는다(§1).
       [data-active] 뒤에 둬야 선택된 행에서도 눌림이 보인다. */
    .jd-email-inbox__item:active {
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-email-inbox__item:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-email-inbox__item-dot {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      margin-top: 6px;
      flex-shrink: 0;
      background: transparent;
    }
    .jd-email-inbox__item[data-unread] .jd-email-inbox__item-dot {
      background: var(--jd-color-primary);
    }
    .jd-email-inbox__item-main {
      min-width: 0;
      flex: 1;
    }
    .jd-email-inbox__item-top {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-email-inbox__item-from {
      font-size: var(--jd-text-sm);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-email-inbox__item[data-unread] .jd-email-inbox__item-from {
      font-weight: var(--jd-weight-semibold);
    }
    .jd-email-inbox__item-time {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-email-inbox__item-subject {
      margin: 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-email-inbox__item[data-unread] .jd-email-inbox__item-subject {
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-medium);
    }
    .jd-email-inbox__item-preview {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-email-inbox__star {
      flex-shrink: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      padding: 0;
      font-size: var(--jd-text-sm);
      /* muted-light는 라이트에서 2.7:1 — 아이콘 어포던스로도 흐리다(§9) */
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-none);
      border-radius: var(--jd-radius-sm);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-email-inbox__star:hover {
      color: var(--jd-color-warning);
    }
    .jd-email-inbox__star:active {
      scale: 0.9;
    }
    .jd-email-inbox__star[data-on] {
      color: var(--jd-color-warning);
    }
    .jd-email-inbox__star:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* 본문 패널 */
    .jd-email-inbox__reader {
      display: none;
      flex-direction: column;
      min-height: 0;
    }
    @media (min-width: 1024px) {
      .jd-email-inbox__reader {
        display: flex;
      }
    }
    .jd-email-inbox__reader-header {
      padding: var(--jd-space-4);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-email-inbox__reader-subject {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-email-inbox__reader-meta {
      margin-top: var(--jd-space-2);
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-email-inbox__reader-avatar {
      width: 1.75rem;
      height: 1.75rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
    }
    .jd-email-inbox__reader-avatar--ph {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      color: var(--jd-color-primary-ink);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-email-inbox__reader-from {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-email-inbox__reader-labels {
      margin-top: var(--jd-space-2);
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
    }
    .jd-email-inbox__reader-label {
      display: inline-flex;
      align-items: center;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      background: color-mix(in srgb, var(--jd-color-muted) 14%, var(--jd-color-card));
      color: var(--jd-color-foreground);
    }
    .jd-email-inbox__reader-body {
      flex: 1;
      overflow-y: auto;
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
      padding: var(--jd-space-4);
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-email-inbox__reader-body p {
      margin: 0 0 var(--jd-space-4);
      white-space: pre-wrap;
    }
    .jd-email-inbox__reader-fallback {
      color: var(--jd-color-muted);
    }

    /* 빈 상태 공용 */
    .jd-email-inbox__list-empty,
    .jd-email-inbox__reader-empty {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      text-align: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-8) var(--jd-space-4);
    }
    .jd-email-inbox__list-empty[hidden] {
      display: none;
    }
    .jd-email-inbox__empty-icon {
      font-size: var(--jd-text-3xl);
    }
    .jd-email-inbox__empty-title {
      margin: 0;
      font-weight: var(--jd-weight-semibold);
    }
    .jd-email-inbox__empty-desc {
      margin: 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-email-inbox__item,
      .jd-email-inbox__folder,
      .jd-email-inbox__star,
      .jd-email-inbox__search-input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-emoji-picker {
      display: block;
      box-sizing: border-box;
      width: 18rem;
      max-width: 100%;
      overflow: hidden;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-lg);
      font-family: var(--jd-font-sans);
    }

    /* ── 검색줄 ── */
    .jd-emoji-picker__search {
      padding: var(--jd-space-2);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-emoji-picker__search-input {
      box-sizing: border-box;
      width: 100%;
      height: 1.75rem;
      margin: 0;
      padding-inline: var(--jd-space-2-5);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      font-family: inherit;
      font-size: var(--jd-text-xs);
    }
    .jd-emoji-picker__search-input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
    }
    .jd-emoji-picker__search-input::placeholder {
      color: var(--jd-color-neutral-400);
    }

    /* ── 분류줄 ── */
    .jd-emoji-picker__tabs {
      display: flex;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-1-5) var(--jd-space-2);
      overflow-x: auto;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-emoji-picker__tabs[hidden] {
      display: none;
    }

    .jd-emoji-picker__tab {
      flex-shrink: 0;
      margin: 0;
      padding: var(--jd-space-1) var(--jd-space-2);
      background: transparent;
      color: var(--jd-color-muted);
      border: 0;
      border-radius: var(--jd-radius-md);
      font-family: inherit;
      font-size: 10px; /* v2 text-[10px] — 대응 토큰 없음(badge 선례) */
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-emoji-picker__tab:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-emoji-picker__tab[data-active] {
      background: var(--jd-color-primary-light);
      /* v2는 text-primary 원색이었다 — 다크에서 틴트 배경 대비가 2.6:1로 무너진다.
       foreground를 섞어 양쪽 테마에서 4.5:1을 넘긴다(§4 색 대비 규칙) */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
    }
    .jd-emoji-picker__tab:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }

    /* ── 격자 ── */
    .jd-emoji-picker__grid {
      display: grid;
      /* 열 수는 update()가 --jd-emoji-picker-columns로 넘긴다 (기본 8 = v2 grid-cols-8) */
      grid-template-columns: repeat(var(--jd-emoji-picker-columns, 8), minmax(0, 1fr));
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-2);
      max-height: 12rem;
      overflow-y: auto;
    }
    .jd-emoji-picker__grid[hidden] {
      display: none;
    }

    .jd-emoji-picker__emoji {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      margin: 0;
      padding: 0;
      background: transparent;
      border: 0;
      border-radius: var(--jd-radius-lg);
      font-family: inherit;
      font-size: var(--jd-text-xl);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-emoji-picker__emoji:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-emoji-picker__emoji:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: -1px;
    }

    .jd-emoji-picker__empty {
      margin: 0;
      padding: var(--jd-space-6) var(--jd-space-2);
      text-align: center;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-emoji-picker__empty[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-emoji-picker__tab,
      .jd-emoji-picker__emoji {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-emoji-reaction {
      display: inline-flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
      font-family: var(--jd-font-sans);
    }

    .jd-emoji-reaction__item {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-emoji-reaction__item:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-emoji-reaction__item:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-emoji-reaction__item[data-reacted] {
      border-color: var(--jd-color-primary);
      background: var(--jd-color-primary-light);
      /* v2는 text-primary 원색이었다 — 다크 틴트 배경에서 대비가 4.5:1 아래로 무너진다
       (emoji-picker 선례). foreground를 섞어 양쪽 테마에서 대비 확보(§4 색 대비). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
    }

    .jd-emoji-reaction__emoji {
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-none);
    }
    .jd-emoji-reaction__count {
      font-weight: var(--jd-weight-medium);
      font-variant-numeric: tabular-nums;
    }

    .jd-emoji-reaction__add {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      padding: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 28px;
      height: 24px;
      box-sizing: border-box; /* 테두리 포함 28×24 유지(§6) */
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-muted);
      font-size: var(--jd-text-sm);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-emoji-reaction__add:hover {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-foreground);
    }
    .jd-emoji-reaction__add:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-emoji-reaction__add[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-empty-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      padding: var(--jd-space-12) var(--jd-space-6);
      text-align: center;
      font-family: var(--jd-font-sans);
    }

    .jd-empty-state__icon {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 3rem;
      height: 3rem;
      margin-block-end: var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card-hover);
      color: var(--jd-color-muted);
    }
    .jd-empty-state__title {
      margin: 0 0 var(--jd-space-1);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-empty-state__title[hidden] {
      display: none;
    }
    .jd-empty-state__desc {
      margin: 0;
      max-width: 22rem;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-empty-state__desc[hidden] {
      display: none;
    }
    jd-empty-state > [slot="action"] {
      margin-block-start: var(--jd-space-4);
    }
  }

  @layer junds.components {
    jd-error-boundary {
      display: block;
    }

    .jd-error-boundary__fallback {
      display: none;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-8);
      box-sizing: border-box;
      text-align: center;
      font-family: var(--jd-font-sans);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-danger) 20%, transparent);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-danger-light);
    }
    /* 실패 시에만 폴백 노출 + 나머지 children 은닉 */
    jd-error-boundary[failed] > .jd-error-boundary__fallback {
      display: flex;
    }
    jd-error-boundary[failed] > *:not(.jd-error-boundary__fallback) {
      display: none;
    }

    .jd-error-boundary__icon {
      font-size: var(--jd-text-2xl);
      line-height: var(--jd-leading-none);
      color: var(--jd-color-danger);
    }
    .jd-error-boundary__heading {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-error-boundary__message {
      margin: 0 0 var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-error-boundary__message[hidden] {
      display: none;
    }

    .jd-error-boundary__retry {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: #ffffff;
      background: var(--jd-color-danger);
      border: 0;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-error-boundary__retry:hover {
      background: var(--jd-color-danger-hover);
    }
    .jd-error-boundary__retry:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-error-boundary__retry {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-exif-panel:not(:defined) {
      display: block;
    }
    jd-exif-panel:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-exif-panel {
      display: block;
    }

    jd-exif-panel .jd-descriptions__list {
      --jd-desc-label-w: 4rem;
      column-gap: var(--jd-space-4);
      row-gap: var(--jd-space-1);
    }
    jd-exif-panel .jd-descriptions__label {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }
    jd-exif-panel .jd-descriptions__value {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }

    /* ── compact — 같은 dl을 한 줄로 흘린다 ─────────────────────── */
    jd-exif-panel[compact] .jd-descriptions__list {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      column-gap: var(--jd-space-3);
      row-gap: var(--jd-space-1);
    }
    jd-exif-panel[compact] .jd-descriptions__item {
      display: inline-flex;
      align-items: baseline;
      gap: var(--jd-space-1);
    }
    jd-exif-panel[compact] .jd-descriptions__label {
      flex: none;
      padding-block-start: 0;
      color: var(--jd-color-muted-light);
    }
    jd-exif-panel[compact] .jd-descriptions__value {
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }
  }

  @layer junds.base {
    jd-faq:not(:defined) {
      display: block;
    }
    jd-faq:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-faq {
      display: block;
      box-sizing: border-box;
      max-width: 48rem; /* max-w-3xl */
      margin-inline: auto;
      padding: var(--jd-space-12) var(--jd-space-4); /* py-12 px-4 */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    @media (min-width: 640px) {
      jd-faq {
        padding: var(--jd-space-20) var(--jd-space-6);
      } /* sm:py-20 sm:px-6 */
    }

    /* ── 헤더 ─────────────────────────────────────────────────── */
    .jd-faq__header {
      text-align: center;
      margin-block-end: var(--jd-space-10);
    } /* mb-10 */
    .jd-faq__header[hidden] {
      display: none;
    }

    .jd-faq__title {
      margin: 0;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
    }
    .jd-faq__title[hidden] {
      display: none;
    }
    @media (min-width: 640px) {
      .jd-faq__title {
        font-size: var(--jd-text-3xl);
      }
    }

    .jd-faq__subtitle {
      margin: var(--jd-space-3) 0 0; /* mt-3 */
      font-size: var(--jd-text-lg); /* text-base */
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    .jd-faq__subtitle[hidden] {
      display: none;
    }

    /* ── 컨트롤 (검색 + 필터) ─────────────────────────────────── */
    .jd-faq__controls {
      margin-block-end: var(--jd-space-6); /* mb-6 */
      display: flex;
      flex-direction: column; /* flex-col */
      gap: var(--jd-space-3); /* gap-3 */
    }
    .jd-faq__controls[hidden] {
      display: none;
    }
    @media (min-width: 640px) {
      .jd-faq__controls {
        flex-direction: row;
      } /* sm:flex-row */
    }

    .jd-faq__search {
      flex: 1 1 auto; /* flex-1 */
      box-sizing: border-box;
      min-width: 0;
      margin: 0;
      padding: var(--jd-space-2) var(--jd-space-3); /* px-3 py-2 */
      font-family: inherit;
      font-size: var(--jd-text-md); /* text-sm */
      color: var(--jd-color-foreground);
      background: var(--jd-color-card); /* bg-surface */
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md); /* rounded-md */
    }
    .jd-faq__search[hidden] {
      display: none;
    }
    .jd-faq__search::placeholder {
      color: var(--jd-color-muted);
    }
    .jd-faq__search:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring); /* ring-ring */
    }

    .jd-faq__filters {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1); /* gap-1 */
    }
    .jd-faq__filters[hidden] {
      display: none;
    }

    .jd-faq__chip {
      box-sizing: border-box;
      margin: 0;
      padding: var(--jd-space-1) var(--jd-space-3); /* px-3 py-1 */
      font-family: inherit;
      font-size: var(--jd-text-xs); /* text-xs */
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full); /* rounded-full */
      cursor: pointer;
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-faq__chip:hover {
      background: var(--jd-color-card-hover);
    } /* hover:bg-surface-soft */
    .jd-faq__chip[data-active] {
      border-color: var(--jd-color-primary);
      background: var(--jd-color-primary);
      color: #fff;
    }
    .jd-faq__chip:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* ── 목록 (분리형 카드, space-y-2) ────────────────────────── */
    .jd-faq__list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2); /* space-y-2 */
    }

    /* 원형 jd-disclosure { display:block } 위에서 필터 숨김이 이기도록 (0,2,0) */
    .jd-faq__item {
      box-sizing: border-box;
      background: var(--jd-color-card); /* bg-surface */
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg); /* rounded-lg */
      overflow: hidden;
    }
    .jd-faq__item[hidden] {
      display: none;
    }

    /* 트리거 — 원형 .jd-disclosure__trigger 위에 얹는다(.jd-faq__item 접두로 특이도↑) */
    .jd-faq__item .jd-faq__trigger {
      justify-content: space-between; /* justify-between */
      gap: var(--jd-space-3); /* gap-3 */
      padding: var(--jd-space-3) var(--jd-space-4); /* px-4 py-3 */
      font-size: var(--jd-text-lg); /* font-medium base */
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-faq__item .jd-faq__trigger:hover:not(:disabled) {
      background: var(--jd-color-card-hover); /* hover:bg-surface-soft */
    }

    .jd-faq__item .jd-faq__question {
      flex: 1 1 auto;
      min-width: 0;
    }

    .jd-faq__item .jd-faq__chevron {
      display: inline-flex;
      flex-shrink: 0;
      color: var(--jd-color-muted);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-faq__item .jd-faq__chevron > svg {
      width: 1rem;
      height: 1rem;
    }
    .jd-faq__item .jd-faq__trigger[data-state="open"] .jd-faq__chevron {
      transform: rotate(180deg);
    }

    .jd-faq__item .jd-faq__answer {
      padding: 0 var(--jd-space-4) var(--jd-space-3); /* px-4 pb-3 */
      font-size: var(--jd-text-md); /* text-sm */
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-relaxed);
    }

    /* ── 빈 상태 ──────────────────────────────────────────────── */
    .jd-faq__empty {
      padding: var(--jd-space-8) 0; /* py-8 */
      text-align: center;
      font-size: var(--jd-text-md); /* text-sm */
      color: var(--jd-color-muted);
    }
    .jd-faq__empty[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-faq__chip,
      .jd-faq__item .jd-faq__trigger,
      .jd-faq__item .jd-faq__chevron {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-feature-grid:not(:defined) {
      display: block;
    }
    jd-feature-grid:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-feature-grid {
      display: block;
      box-sizing: border-box;
      max-width: 80rem; /* max-w-7xl */
      margin-inline: auto;
      padding: var(--jd-space-12) var(--jd-space-4); /* py-12 px-4 */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    @media (min-width: 640px) {
      jd-feature-grid {
        padding: var(--jd-space-20) var(--jd-space-6);
      } /* sm:py-20 sm:px-6 */
    }

    /* ── 헤더 (cta-section 섹션 헤더 관용구와 일치) ─────────────── */
    .jd-feature-grid__header {
      max-width: 42rem; /* max-w-2xl */
      margin: 0 auto var(--jd-space-10); /* mb-10 */
      text-align: center;
    }
    .jd-feature-grid__header[hidden] {
      display: none;
    }

    .jd-feature-grid__title {
      margin: 0;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
    }
    .jd-feature-grid__title[hidden] {
      display: none;
    }
    @media (min-width: 640px) {
      .jd-feature-grid__title {
        font-size: var(--jd-text-3xl);
      }
    }

    .jd-feature-grid__subtitle {
      margin: var(--jd-space-3) 0 0; /* mt-3 */
      font-size: var(--jd-text-lg); /* text-base */
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    .jd-feature-grid__subtitle[hidden] {
      display: none;
    }

    /* ── 격자 ─────────────────────────────────────────────────── */
    /* v2의 sm/lg 미디어쿼리를 **부모 폭 기준**으로 옮긴 것. 뷰포트 미디어쿼리는 이
     섹션이 좁은 칼럼(카드·사이드바·미리보기) 안에 놓이면 거짓말을 한다 — 화면이
     1024px이라는 이유로 300px 칸에 3열을 그려 본문이 단어마다 줄이 바뀌었다(실측).
     하한은 "요청 열 수로 나눈 폭"과 최소 카드 폭 중 큰 쪽이라, 넓을 때는 정확히
     columns 열이고 좁아지면 스스로 2열 → 1열로 접힌다. */
    .jd-feature-grid__grid {
      --jd-fg-gap: var(--jd-space-6); /* gap-6 */
      --jd-fg-cols: 3;
      --jd-fg-col-min: 16rem;
      display: grid;
      grid-template-columns: repeat(
        auto-fit,
        minmax(
          min(
            100%,
            max(
              var(--jd-fg-col-min),
              (100% - (var(--jd-fg-cols) - 1) * var(--jd-fg-gap)) / var(--jd-fg-cols)
            )
          ),
          1fr
        )
      );
      gap: var(--jd-fg-gap);
    }
    jd-feature-grid[columns="2"] .jd-feature-grid__grid {
      --jd-fg-cols: 2;
    }
    jd-feature-grid[columns="4"] .jd-feature-grid__grid {
      --jd-fg-cols: 4;
    }

    /* ── 아이템 (기본 = card) ─────────────────────────────────── */
    .jd-feature-grid__item {
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      min-width: 0; /* 격자 자식 기본 min-width:auto가 칸을 밀어내지 못하게(§5) */
      padding: var(--jd-space-6); /* p-6 */
      background: var(--jd-color-card); /* bg-surface */
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl); /* rounded-xl */
      /* 면만 있는 카드는 색종이로 읽힌다 — 쉬는 상태에도 얕은 그림자를 얹어야
       hover의 shadow-md가 '떠오름'으로 읽힌다(§2) */
      box-shadow: var(--jd-shadow-xs);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-feature-grid__item:hover {
      box-shadow: var(--jd-shadow-md);
    }
    .jd-feature-grid__item[data-highlighted] {
      border-color: var(--jd-color-primary); /* border-primary */
      box-shadow: 0 0 0 1px color-mix(in srgb, var(--jd-color-primary) 30%, transparent),
        var(--jd-shadow-xs); /* ring-1 ring-primary/30 */
    }
    .jd-feature-grid__item[data-highlighted]:hover {
      box-shadow: 0 0 0 1px color-mix(in srgb, var(--jd-color-primary) 30%, transparent),
        var(--jd-shadow-md);
    }

    /* 링크 카드 — hover:no-underline, 색 상속 */
    a.jd-feature-grid__item {
      text-decoration: none;
      color: inherit;
      /* 누를 수 있는 카드는 눌리는 것이 보여야 한다(§1) */
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    a.jd-feature-grid__item:hover {
      text-decoration: none;
    }
    a.jd-feature-grid__item:active {
      scale: 0.99;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 링은 outline으로 — border-radius를 따라가고 카드의 그림자를 지우지 않는다(DEC-039) */
    a.jd-feature-grid__item:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* minimal — 카드 크롬 제거, px-2만 */
    jd-feature-grid[layout="minimal"] .jd-feature-grid__item {
      padding: 0 var(--jd-space-2); /* px-2 */
      background: none;
      border: 0;
      border-radius: 0;
      box-shadow: none;
    }
    jd-feature-grid[layout="minimal"] .jd-feature-grid__item:hover {
      box-shadow: none;
    }

    /* iconLeft — 카드 크롬 제거, 가로 배치 */
    jd-feature-grid[layout="iconLeft"] .jd-feature-grid__item {
      flex-direction: row;
      align-items: flex-start; /* items-start */
      gap: var(--jd-space-4); /* gap-4 */
      padding: 0;
      background: none;
      border: 0;
      border-radius: 0;
      box-shadow: none;
    }
    jd-feature-grid[layout="iconLeft"] .jd-feature-grid__item:hover {
      box-shadow: none;
    }

    /* ── 아이콘 ───────────────────────────────────────────────── */
    .jd-feature-grid__icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      align-self: flex-start; /* 세로 배치에서 늘어나지 않게 */
      box-sizing: border-box;
      flex-shrink: 0;
      width: 3rem; /* w-12 */
      height: 3rem;
      margin-block-end: var(--jd-space-4); /* mb-4 */
      color: var(--jd-color-primary-ink); /* text-primary */
      background: var(--jd-color-primary-light); /* bg-primary-soft */
      border-radius: var(--jd-radius-md); /* rounded-md */
      font-size: var(--jd-text-3xl); /* text-2xl */
    }
    .jd-feature-grid__icon[hidden] {
      display: none;
    }
    .jd-feature-grid__icon > svg {
      width: 1.5rem;
      height: 1.5rem;
    }
    jd-feature-grid[layout="iconLeft"] .jd-feature-grid__icon {
      width: 2.5rem; /* w-10 */
      height: 2.5rem;
      margin-block-end: 0; /* mb-0 */
      font-size: var(--jd-text-lg);
    }
    jd-feature-grid[layout="iconLeft"] .jd-feature-grid__icon > svg {
      width: 1.25rem;
      height: 1.25rem;
    }

    /* ── 본문 ─────────────────────────────────────────────────── */
    /* flex-1 min-w-0 — 카드 높이 채움(격자 stretch) + iconLeft 가로 채움 */
    .jd-feature-grid__body {
      flex: 1 1 auto;
      min-width: 0;
    }

    /* 제목·본문은 어절을 지킨다 — 기본 CJK 줄바꿈은 글자 단위라 칸이 좁아지는 순간
     "웹소/켓 시/세를"처럼 낱말이 조각난다(§5) */
    .jd-feature-grid__item-title {
      margin: 0 0 var(--jd-space-1); /* mb-1 */
      font-size: var(--jd-text-lg); /* text-base */
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
      word-break: keep-all;
      overflow-wrap: break-word;
      text-wrap: balance;
    }

    .jd-feature-grid__item-desc {
      margin: 0;
      font-size: var(--jd-text-md); /* text-sm */
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted); /* text-muted */
      word-break: keep-all;
      overflow-wrap: break-word;
    }
    .jd-feature-grid__item-desc[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      /* 링크 카드 규칙(a.…)이 더 구체적이라 함께 적지 않으면 전이가 살아남는다 */
      .jd-feature-grid__item,
      a.jd-feature-grid__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-file-upload {
      display: block;
      width: 100%;
    }

    /* 네이티브 피커는 시각적으로 숨기되 접근성 트리에는 남긴다 */
    .jd-file-upload__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-file-upload__zone {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-8);
      box-sizing: border-box;
      cursor: pointer;
      border: var(--jd-border-medium) dashed var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      transition: border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-file-upload__zone:hover {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      background: color-mix(in srgb, var(--jd-color-primary-light) 30%, transparent);
    }
    .jd-file-upload__zone:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-file-upload__zone[data-drag] {
      border-color: var(--jd-color-primary);
      background: color-mix(in srgb, var(--jd-color-primary-light) 40%, transparent);
    }
    .jd-file-upload__zone[aria-disabled="true"] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    jd-file-upload[error]:not([error=""]) .jd-file-upload__zone {
      border-color: color-mix(in srgb, var(--jd-color-danger) 40%, transparent);
    }

    .jd-file-upload__icon {
      display: flex;
      color: var(--jd-color-muted-light);
    }
    .jd-file-upload__desc {
      margin: 0;
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-file-upload__hint {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-file-upload__hint[hidden] {
      display: none;
    }

    .jd-file-upload__trigger {
      display: inline-flex;
      cursor: pointer;
    }

    .jd-file-upload__error {
      margin: var(--jd-space-1-5) 0 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-danger);
    }
    .jd-file-upload__error[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-file-upload__zone {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-filter-bar {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
      font-family: var(--jd-font-sans);
    }
    jd-filter-bar > [hidden] {
      display: none;
    }

    /* ── 검색 (v2 w-64 = 16rem) ── */
    .jd-filter-bar__search {
      position: relative;
      display: inline-flex;
      align-items: center;
      width: 16rem;
      max-width: 100%;
      color: var(--jd-color-muted);
    }
    .jd-filter-bar__search-icon {
      position: absolute;
      inset-inline-start: var(--jd-space-2-5);
      pointer-events: none;
    }
    .jd-filter-bar__input {
      width: 100%;
      box-sizing: border-box;
      height: var(--jd-space-8);
      padding-inline: calc(var(--jd-space-2-5) + 14px + var(--jd-space-2)) var(--jd-space-2-5);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      outline: none;
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-filter-bar__input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-filter-bar__input:focus-visible {
      border-color: var(--jd-color-primary);
      box-shadow: 0 0 0 var(--jd-border-medium)
        color-mix(in srgb, var(--jd-color-primary) 35%, transparent);
    }

    /* ── 초기화 (v2 ghost xs) ── */
    .jd-filter-bar__reset {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      height: var(--jd-space-8);
      padding-inline: var(--jd-space-2-5);
      margin: 0;
      font: inherit;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-filter-bar__reset:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    .jd-filter-bar__reset:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
    }
    /* v2 배지 — 원형 pill */
    .jd-filter-bar__badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1rem;
      height: 1rem;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      line-height: 1;
      /* 솔리드 primary 위 글자는 흰색 고정 — button/chat-bubble/pagination과 동일 관용구.
       primary는 테마 불변(#5b4cc7)이라 --jd-color-background(다크에서 #0c0a14)를 쓰면
       다크에서 대비가 ~2.96:1로 깨진다(v2 FilterBar 배지 bg-primary text-white). */
      color: #fff;
      background: var(--jd-color-primary);
      border-radius: var(--jd-radius-full);
    }

    /* ── 액션 (v2 ml-auto) ── */
    .jd-filter-bar__actions {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-inline-start: auto;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-filter-bar__input,
      .jd-filter-bar__reset {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-filter-button-group {
      display: inline-flex;
      align-items: center;
      font-family: var(--jd-font-sans);
    }

    .jd-filter-button-group__item {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      box-sizing: border-box;
      height: 2.25rem;
      padding-inline: var(--jd-space-4);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      cursor: pointer;
      user-select: none;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-filter-button-group__item:hover {
      background: var(--jd-color-card-hover);
    }

    /* v2 -ml-px: 인접 테두리를 한 겹으로 겹친다 */
    .jd-filter-button-group__item + .jd-filter-button-group__item {
      margin-inline-start: calc(var(--jd-space-px) * -1);
    }
    .jd-filter-button-group__item:first-of-type {
      border-start-start-radius: var(--jd-radius-lg);
      border-end-start-radius: var(--jd-radius-lg);
    }
    .jd-filter-button-group__item:last-of-type {
      border-start-end-radius: var(--jd-radius-lg);
      border-end-end-radius: var(--jd-radius-lg);
    }

    .jd-filter-button-group__item[data-active] {
      z-index: 1;
      background: var(--jd-color-primary);
      border-color: var(--jd-color-primary);
      color: #fff;
    }
    .jd-filter-button-group__item[data-active]:hover {
      background: var(--jd-color-primary-hover);
    }

    .jd-filter-button-group__item[data-disabled] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-filter-button-group__item[data-disabled]:hover {
      background: var(--jd-color-card);
    }

    /* 라디오는 시각적으로만 감춘다 (star-rating 관용구) */
    .jd-filter-button-group__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-filter-button-group__item:has(.jd-filter-button-group__input:focus-visible) {
      z-index: 2;
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-filter-button-group__count {
      font-size: 10px; /* v2 text-[10px] — 대응 토큰 없음(badge 선례) */
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-muted);
    }
    .jd-filter-button-group__item[data-active] .jd-filter-button-group__count {
      color: color-mix(in srgb, #fff 80%, transparent);
    }
    .jd-filter-button-group__count[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-filter-button-group__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-flex {
      display: flex;
    }
    jd-flex[inline] {
      display: inline-flex;
    }
  }

  @layer junds.components {
    /* 기본 = bottom-right. 디폴트값은 attribute로 반영되지 않으므로(§1.3) base가 담당 */
    jd-floating-action-button {
      position: fixed;
      z-index: var(--jd-z-overlay);
      display: flex;
      flex-direction: column-reverse;
      gap: var(--jd-space-2);
      bottom: var(--jd-space-6);
      right: var(--jd-space-6);
      top: auto;
      left: auto;
      font-family: var(--jd-font-sans);
    }
    jd-floating-action-button[position="bottom-left"] {
      right: auto;
      left: var(--jd-space-6);
    }
    jd-floating-action-button[position="top-right"] {
      flex-direction: column;
      bottom: auto;
      top: var(--jd-space-6);
    }
    jd-floating-action-button[position="top-left"] {
      flex-direction: column;
      bottom: auto;
      top: var(--jd-space-6);
      right: auto;
      left: var(--jd-space-6);
    }

    .jd-floating-action-button__row {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      animation: jd-floating-action-button-in var(--jd-duration-normal) var(--jd-easing-ease-out)
        backwards;
      animation-delay: calc(var(--jd-floating-action-button-i, 0) * 50ms);
    }
    jd-floating-action-button[position="bottom-left"] .jd-floating-action-button__row,
    jd-floating-action-button[position="top-left"] .jd-floating-action-button__row {
      justify-content: flex-start;
    }
    @keyframes jd-floating-action-button-in {
      from {
        opacity: 0;
        transform: scale(0.8);
      }
    }

    .jd-floating-action-button__button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      box-sizing: border-box;
      /* 부(副) 액션 기본 — v2 w-11 h-11 text-sm */
      width: 2.75rem;
      height: 2.75rem;
      /* 손가락 하한은 물리 치수다 — rem은 호스트의 루트 글꼴을 따라 줄어들어(실측
       28px) 누를 수 없는 원반이 된다. rem으로 밀도는 따라가되 px 바닥을 함께 깐다. */
      min-width: 40px;
      min-height: 40px;
      padding: 0;
      border: 0;
      font-family: inherit;
      font-size: var(--jd-text-sm);
      color: #ffffff;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      /* all 금지 — width·height까지 대상이 되면 주/부 전환이 흐른다 (DEC-039) */
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 주(主) 액션 = 첫 액션 — v2 w-14 h-14 text-lg.
     :first-child는 쓸 수 없다: 아이콘 <template>이 호스트의 첫 자식이라 빗나간다 */
    .jd-floating-action-button__row[data-primary] > .jd-floating-action-button__button {
      width: 3.5rem;
      height: 3.5rem;
      min-width: 48px;
      min-height: 48px;
      font-size: var(--jd-text-lg);
    }
    /* 눌린 면은 빛을 잃는다 — 원반이 손끝을 따라 들어가야 눌렸다는 것이 보인다 */
    .jd-floating-action-button__button:active:not(:disabled) {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-floating-action-button__button:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-floating-action-button__button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-lg);
    }

    .jd-floating-action-button__icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      line-height: 1;
    }
    .jd-floating-action-button__icon > svg {
      width: 1.25em;
      height: 1.25em;
    }

    /* variant — 배경·호버·색 그림자 3종 (v2 variantStyles) */
    .jd-floating-action-button__button[data-variant="primary"] {
      background: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-lg),
        0 8px 18px color-mix(in srgb, var(--jd-color-primary) 25%, transparent);
    }
    .jd-floating-action-button__button[data-variant="primary"]:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    /* surface 3단은 라이트에서도 어두운 면이다 — 그 위의 잉크는 모드를 따라가지 않고
     on-surface로 고정한다 (DEC-044) */
    .jd-floating-action-button__button[data-variant="secondary"] {
      background: var(--jd-color-surface-overlay);
      color: var(--jd-color-on-surface);
      box-shadow: var(--jd-shadow-lg),
        0 8px 18px color-mix(in srgb, var(--jd-color-surface-overlay) 25%, transparent);
    }
    /* 라이트에선 더 어둡게, 다크에선 더 밝게 — 어느 테마에서도 호버가 보인다 */
    .jd-floating-action-button__button[data-variant="secondary"]:hover:not(:disabled) {
      background: color-mix(
        in srgb,
        var(--jd-color-surface-overlay) 80%,
        var(--jd-color-foreground)
      );
    }
    .jd-floating-action-button__button[data-variant="danger"] {
      background: color-mix(in srgb, var(--jd-color-danger) 85%, #000000);
      box-shadow: var(--jd-shadow-lg),
        0 8px 18px color-mix(in srgb, var(--jd-color-danger) 25%, transparent);
    }
    .jd-floating-action-button__button[data-variant="danger"]:hover:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-danger) 70%, #000000);
    }

    .jd-floating-action-button__tooltip {
      position: absolute;
      right: 100%;
      margin-right: var(--jd-space-2);
      padding: var(--jd-space-1) var(--jd-space-2);
      white-space: nowrap;
      pointer-events: none;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-on-surface);
      background: var(--jd-color-surface-overlay);
      border-radius: var(--jd-radius-md);
      /* 어두운 면 위의 테두리는 border 토큰이 아니라 잉크에서 뽑는다 — 라이트 모드의
       밝은 border는 알약을 흰 실로 두른 것처럼 보인다 */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      box-shadow: var(--jd-shadow-md);
      opacity: 0;
      transition: opacity var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-floating-action-button[position="bottom-left"] .jd-floating-action-button__tooltip,
    jd-floating-action-button[position="top-left"] .jd-floating-action-button__tooltip {
      right: auto;
      margin-right: 0;
      left: 100%;
      margin-left: var(--jd-space-2);
    }
    /* v2는 마우스 hover 전용이었다 — 포커스에도 뜬다 */
    .jd-floating-action-button__row:hover > .jd-floating-action-button__tooltip,
    .jd-floating-action-button__row:focus-within > .jd-floating-action-button__tooltip {
      opacity: 1;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-floating-action-button__row {
        animation: none;
      }
      .jd-floating-action-button__button,
      .jd-floating-action-button__tooltip {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-flow-diagram:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-flow-diagram {
      display: block;
      position: relative;
      box-sizing: border-box;
      width: 100%;
      /* flex/grid 부모 안에서 width:100%가 기준 폭을 넘겨 캔버스가 컨테이너 밖으로
         비어져 나가는 것을 막는다(§6). 장면 자체의 화면 맞춤은 element.ts가 담당한다. */
      max-width: 100%;
      min-width: 0;
      min-height: 400px;
      overflow: hidden;
      background: var(--jd-color-surface); /* 항상 어두운 캔버스 — 모드 무관 (DEC-044) */
      font-family: var(--jd-font-sans);
      outline: none;
      touch-action: none;
      cursor: default;
    }
    /* 캔버스는 overflow:hidden 이라 바깥 아웃라인이 잘린다 — 링을 안쪽 그림자로 준다(§1) */
    jd-flow-diagram:focus-visible {
      outline: none;
      box-shadow: inset 0 0 0 var(--jd-border-medium) var(--jd-color-ring-primary);
    }
    jd-flow-diagram[data-grabbing] {
      cursor: grabbing;
    }
    jd-flow-diagram[data-space] {
      cursor: grab;
    }

    /* 격자 */
    .jd-flow__grid {
      position: absolute;
      inset: 0;
      pointer-events: none;
      background-image: radial-gradient(circle, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
    }
    .jd-flow__grid[hidden] {
      display: none;
    }

    /* 변환 레이어 */
    .jd-flow__viewport {
      position: absolute;
      top: 0;
      left: 0;
      transform-origin: 0 0;
    }
    .jd-flow__nodes,
    .jd-flow__groups {
      position: absolute;
      top: 0;
      left: 0;
    }

    /* 연결선 SVG */
    .jd-flow__links {
      position: absolute;
      top: 0;
      left: 0;
      width: 1px;
      height: 1px;
      overflow: visible;
      pointer-events: none;
    }
    .jd-flow__link-hit {
      stroke: transparent;
      stroke-width: 14;
      fill: none;
      pointer-events: stroke;
      cursor: pointer;
    }
    .jd-flow__link-line {
      stroke: var(--jd-color-on-surface-muted);
      stroke-width: 2;
      fill: none;
      stroke-linecap: round;
      pointer-events: none;
    }
    .jd-flow__link-line[data-animate] {
      stroke-dasharray: 6 4;
      animation: jd-flow-dash 0.8s linear infinite;
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-flow__link-line[data-animate] {
        animation: none;
      }
    }
    @keyframes jd-flow-dash {
      to {
        stroke-dashoffset: -20;
      }
    }
    .jd-flow__link-arrow {
      fill: var(--jd-color-on-surface-muted);
      pointer-events: none;
    }
    /* 선택 강조는 primary 계열이되, 어두운 캔버스 위에서는 원색만으로 대비가 서지 않아
       잉크를 섞어 띄운다 — marquee·선택 노드와 같은 배합이라 강조색이 갈라지지 않는다 */
    .jd-flow__link[data-selected] .jd-flow__link-line {
      stroke: color-mix(in srgb, var(--jd-color-primary) 55%, var(--jd-color-on-surface));
      stroke-width: 3;
    }
    .jd-flow__link[data-selected] .jd-flow__link-arrow {
      fill: color-mix(in srgb, var(--jd-color-primary) 55%, var(--jd-color-on-surface));
    }
    .jd-flow__link-label-bg {
      fill: var(--jd-color-surface-raised);
      stroke: var(--jd-color-surface-overlay);
      stroke-width: 1;
      pointer-events: none;
    }
    /* neutral-300은 모드추종이라 다크에서 #3a3656 — 같은 어두운 라벨판 위에서 사라진다.
       라벨 폭은 element.ts가 10px 기준으로 계산하므로 글자 크기는 건드리지 않는다. */
    .jd-flow__link-label {
      fill: var(--jd-color-on-surface);
      font-size: 10px;
      font-family: var(--jd-font-sans);
      pointer-events: none;
    }

    /* 노드 카드 */
    .jd-flow__node {
      position: absolute;
      user-select: none;
      overflow: visible;
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-on-surface) 30%, transparent);
      background: var(--jd-color-surface-raised);
      color: var(--jd-color-on-surface);
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
    }
    .jd-flow__node[data-selected] {
      box-shadow: 0 0 0 var(--jd-border-medium)
          color-mix(in srgb, var(--jd-color-primary) 55%, var(--jd-color-on-surface)),
        0 4px 24px rgba(0, 0, 0, 0.4);
      z-index: 10;
    }
    .jd-flow__node[data-variant="success"] {
      border-color: var(--jd-color-success);
    }
    .jd-flow__node[data-variant="warning"] {
      border-color: var(--jd-color-warning);
    }
    .jd-flow__node[data-variant="danger"] {
      border-color: var(--jd-color-danger);
    }
    .jd-flow__node[data-variant="info"] {
      border-color: var(--jd-color-primary);
    }

    .jd-flow__node-header {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      border-block-end: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 30%, transparent);
      border-start-start-radius: 10px;
      border-start-end-radius: 10px;
      background: var(--jd-color-surface-overlay);
      /* 헤더는 노드의 제목줄이다 — 보조 잉크로는 흐리다 */
      color: var(--jd-color-on-surface);
    }
    .jd-flow__node[data-variant="success"] .jd-flow__node-header {
      background: color-mix(in srgb, var(--jd-color-success) 30%, var(--jd-color-surface-overlay));
      color: var(--jd-color-on-surface);
      border-color: var(--jd-color-success);
    }
    .jd-flow__node[data-variant="warning"] .jd-flow__node-header {
      background: color-mix(in srgb, var(--jd-color-warning) 30%, var(--jd-color-surface-overlay));
      color: var(--jd-color-on-surface);
      border-color: var(--jd-color-warning);
    }
    .jd-flow__node[data-variant="danger"] .jd-flow__node-header {
      background: color-mix(in srgb, var(--jd-color-danger) 30%, var(--jd-color-surface-overlay));
      color: var(--jd-color-on-surface);
      border-color: var(--jd-color-danger);
    }
    .jd-flow__node[data-variant="info"] .jd-flow__node-header {
      background: color-mix(in srgb, var(--jd-color-primary) 34%, var(--jd-color-surface-overlay));
      color: var(--jd-color-on-surface);
      border-color: var(--jd-color-primary);
    }
    .jd-flow__node-icon {
      flex-shrink: 0;
      font-size: var(--jd-text-md);
    }
    .jd-flow__node-icon[hidden] {
      display: none;
    }
    .jd-flow__node-title {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-flow__node-body {
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-on-surface-muted);
    }
    .jd-flow__node-body[hidden] {
      display: none;
    }

    /* 포트 */
    .jd-flow__ports {
      position: absolute;
      inset: 0;
      pointer-events: none;
    }
    .jd-flow__port {
      position: absolute;
      width: 12px;
      height: 12px;
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-medium) solid var(--jd-color-surface-overlay);
      background: var(--jd-color-info);
      z-index: 20;
      cursor: crosshair;
      pointer-events: auto;
      transition: transform var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-flow__port:hover {
      transform: scale(1.5);
    }
    .jd-flow__port[data-readonly] {
      cursor: default;
      opacity: 0.4;
    }
    .jd-flow__port[data-readonly]:hover {
      transform: none;
    }

    /* 그룹 */
    .jd-flow__group {
      position: absolute;
      pointer-events: none;
      border-radius: var(--jd-radius-2xl);
      background: color-mix(in srgb, var(--jd-flow-group, #818cf8) 8%, transparent);
      border: var(--jd-border-medium) dashed
        color-mix(in srgb, var(--jd-flow-group, #818cf8) 40%, transparent);
    }
    .jd-flow__group-label {
      position: absolute;
      top: 6px;
      left: 12px;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-flow-group, #818cf8);
    }

    /* 범위 선택 박스 — 강조는 primary 계열이다. 임의의 핑크는 팔레트 밖이고(§8),
       선택된 노드·연결선이 이미 primary라 한 화면에서 강조색이 갈라졌다.
       어두운 캔버스 위에서 primary만으로는 어두우니 잉크를 섞어 띄운다. */
    .jd-flow__marquee {
      position: absolute;
      pointer-events: none;
      border-radius: var(--jd-radius-lg);
      border: var(--jd-border-medium) dashed
        color-mix(in srgb, var(--jd-color-primary) 55%, var(--jd-color-on-surface));
      background: color-mix(in srgb, var(--jd-color-primary) 22%, transparent);
    }
    .jd-flow__marquee[hidden] {
      display: none;
    }

    /* 미니맵 */
    .jd-flow__minimap {
      position: absolute;
      top: var(--jd-space-3);
      right: var(--jd-space-3);
      z-index: 20;
      width: 150px;
      height: 90px;
      border-radius: var(--jd-radius-lg);
      border: var(--jd-border-thin) solid var(--jd-color-surface-overlay);
      background: color-mix(in srgb, var(--jd-color-surface) 90%, transparent);
      -webkit-backdrop-filter: blur(4px);
      backdrop-filter: blur(4px);
    }
    .jd-flow__minimap[hidden] {
      display: none;
    }
    .jd-flow__mini-link {
      stroke: var(--jd-color-on-surface-muted);
      stroke-width: 0.8;
    }
    .jd-flow__mini-node {
      fill: var(--jd-color-surface-overlay);
      stroke: var(--jd-color-on-surface-muted);
      stroke-width: 0.5;
    }
    .jd-flow__mini-view {
      fill: none;
      stroke: color-mix(in srgb, var(--jd-color-primary) 55%, var(--jd-color-on-surface));
      stroke-width: 1.5;
    }

    /* 줌 컨트롤 */
    .jd-flow__zoom {
      position: absolute;
      bottom: var(--jd-space-4);
      right: var(--jd-space-4);
      z-index: 20;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
    }
    .jd-flow__zoom-btn {
      width: 2rem;
      height: 2rem;
      border: 0;
      border-radius: var(--jd-radius-lg);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-surface-overlay) 90%, transparent);
      color: var(--jd-color-on-surface);
      cursor: pointer;
      font-family: inherit;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-none);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-flow__zoom-btn:hover {
      background: var(--jd-color-surface-overlay);
    }
    .jd-flow__zoom-btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-flow__zoom-btn:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-flow__zoom-label {
      font-size: var(--jd-text-2xs);
      font-variant-numeric: tabular-nums;
    }

    /* 단축키 힌트 */
    .jd-flow__hint {
      position: absolute;
      bottom: var(--jd-space-4);
      left: var(--jd-space-4);
      z-index: 20;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-on-surface-muted);
      user-select: none;
      pointer-events: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-flow__port,
      .jd-flow__zoom-btn {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-follow-button {
      display: inline-flex;
    }

    .jd-follow-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      border: 0;
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-semibold);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
      color: #ffffff;
      transition: filter var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md */
      height: 2.25rem;
      padding-inline: var(--jd-space-4);
      font-size: var(--jd-text-sm);
    }
    .jd-follow-button:hover:not(:disabled) {
      filter: brightness(1.1);
    }
    .jd-follow-button:active:not(:disabled) {
      transform: scale(0.98);
    }
    .jd-follow-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-follow-button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    jd-follow-button[size="sm"] .jd-follow-button {
      height: 1.75rem;
      padding-inline: var(--jd-space-3);
      font-size: var(--jd-text-xs);
    }
    jd-follow-button[size="lg"] .jd-follow-button {
      height: 2.75rem;
      padding-inline: var(--jd-space-5);
      font-size: var(--jd-text-md);
    }

    /* 라벨 선택 — 기본은 "팔로우"만 */
    .jd-follow-button__following,
    .jd-follow-button__unfollow {
      display: none;
    }

    jd-follow-button[following] .jd-follow-button {
      background: transparent;
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    jd-follow-button[following] .jd-follow-button:hover:not(:disabled) {
      filter: none;
    }
    jd-follow-button[following] .jd-follow-button__follow {
      display: none;
    }
    jd-follow-button[following] .jd-follow-button__following {
      display: inline;
    }

    /* 팔로잉 + 호버/포커스 → 언팔로우 강조 (v2 rose-500) */
    /* 테두리는 그래픽이라 rose 원색, 글자는 텍스트라 foreground와 섞는다(AA — DEC-030-7).
     호버에서만 보이는 상태라 axe 정지 감사에는 잡히지 않는다 — 같은 처방을 선제 적용. */
    jd-follow-button[following]:not([no-unfollow-hover]) .jd-follow-button:hover:not(:disabled),
    jd-follow-button[following]:not([no-unfollow-hover]) .jd-follow-button:focus-visible {
      border-color: #f43f5e;
      color: color-mix(in srgb, #f43f5e 65%, var(--jd-color-foreground));
    }
    jd-follow-button[following]:not([no-unfollow-hover])
      .jd-follow-button:hover:not(:disabled)
      .jd-follow-button__following,
    jd-follow-button[following]:not([no-unfollow-hover])
      .jd-follow-button:focus-visible
      .jd-follow-button__following {
      display: none;
    }
    jd-follow-button[following]:not([no-unfollow-hover])
      .jd-follow-button:hover:not(:disabled)
      .jd-follow-button__unfollow,
    jd-follow-button[following]:not([no-unfollow-hover])
      .jd-follow-button:focus-visible
      .jd-follow-button__unfollow {
      display: inline;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-follow-button {
        transition: none;
      }
      .jd-follow-button:active:not(:disabled) {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-form {
      display: block;
    }
    .jd-form {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    jd-form-array {
      display: block;
    }
    jd-form-array > template {
      display: none;
    }

    .jd-form-array {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }

    .jd-form-array__list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }

    .jd-form-array__item {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
    }
    .jd-form-array__control {
      flex: 1;
      min-width: 0;
    }

    .jd-form-array__remove {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-block-start: var(--jd-space-1);
      padding: var(--jd-space-2);
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-form-array__remove[hidden] {
      display: none;
    }
    .jd-form-array__remove:hover {
      color: var(--jd-color-danger);
    }
    .jd-form-array__remove:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-danger) 40%, transparent);
      outline-offset: 2px;
    }

    .jd-form-array__add {
      align-self: flex-start;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-primary-ink);
      background: none;
      cursor: pointer;
      border: var(--jd-border-thin) dashed
        color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
      border-radius: var(--jd-radius-lg);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-form-array__add[hidden] {
      display: none;
    }
    .jd-form-array__add:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 5%, transparent);
    }
    .jd-form-array__add:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-form-array__add > svg {
      flex-shrink: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-form-array__remove,
      .jd-form-array__add {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-form-builder {
      display: block;
    }
    .jd-form-builder {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }

    .jd-form-builder__grid {
      display: grid;
      gap: var(--jd-space-4);
      grid-template-columns: 1fr;
    }
    @media (min-width: 40rem) {
      jd-form-builder[columns="2"] .jd-form-builder__grid {
        grid-template-columns: 1fr 1fr;
      }
      jd-form-builder[columns="2"] .jd-form-builder__grid > [data-span] {
        grid-column: 1 / -1;
      }
    }

    .jd-form-builder__footer {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding-block-start: var(--jd-space-2);
    }

    /* 네이티브 입력 — jd-text-field[md] 입력 시각과 동일 */
    .jd-form-builder__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
      height: 2.5rem;
      padding-inline: var(--jd-space-3-5);
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-xl);
    }
    .jd-form-builder__input::placeholder {
      color: var(--jd-color-neutral-400);
    }
    .jd-form-builder__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-xs);
    }
    .jd-form-builder__input:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
      background: var(--jd-color-card-hover);
    }
    /* jd-form-field가 aria-invalid를 세우면 danger 테두리 */
    .jd-form-builder__input[aria-invalid="true"] {
      border-color: var(--jd-color-danger);
    }
    .jd-form-builder__input[aria-invalid="true"]:focus {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger), var(--jd-shadow-xs);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-form-builder__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-form-field {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
    }

    .jd-form-field__label {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-tight);
      color: var(--jd-color-foreground);
    }
    .jd-form-field__label[hidden] {
      display: none;
    }
    jd-form-field[required] > .jd-form-field__label::after {
      content: "*";
      margin-inline-start: var(--jd-space-0-5);
      color: var(--jd-color-danger);
    }

    .jd-form-field__error {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-danger);
    }
    .jd-form-field__error[hidden] {
      display: none;
    }
    .jd-form-field__error > svg {
      flex-shrink: 0;
    }

    .jd-form-field__hint {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-muted);
    }
    .jd-form-field__hint[hidden] {
      display: none;
    }

    /* 컨트롤이 하나도 없는 필드는 라벨·설명만 떠 있는 **빈 껍데기**로 읽힌다(실측).
     컨트롤이 설 자리를 md 컨트롤과 같은 높이의 점선 상자로 남겨 "여기에 무엇이
     온다"를 보이게 한다. 조건은 "골격 3종(label·error·hint) 말고 자식 요소가 하나도
     없을 때"라 실제 사용(컨트롤을 넣은 경우)에는 절대 걸리지 않는다.
     ::after인 이유: ::before는 라벨보다 앞에 오는 플렉스 아이템이 된다. order로
     에러·힌트 뒤에서 되돌린다(자리는 라벨과 설명 사이). */
    jd-form-field:not(
        :has(> :not(.jd-form-field__label):not(.jd-form-field__error):not(.jd-form-field__hint))
      )::after {
      content: "";
      order: 1;
      height: 2.25rem;
      box-sizing: border-box;
      border: var(--jd-border-thin) dashed
        color-mix(in srgb, var(--jd-color-border) 60%, var(--jd-color-muted));
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-control-surface-muted);
    }
    .jd-form-field__error,
    .jd-form-field__hint {
      order: 2;
    }
  }

  @layer junds.components {
    jd-form-wizard {
      display: block;
    }
    jd-form-wizard > [slot="step"] {
      display: block;
    }
    .jd-form-wizard {
      width: 100%;
    }

    /* ── 스텝 인디케이터 ── */
    .jd-form-wizard__stepper {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin-block-end: var(--jd-space-6);
    }
    .jd-form-wizard__seg {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      flex: 1 1 0;
      min-width: 0; /* 연결선이 칸을 밀어내지 않게 — 원은 flex-shrink:0으로 지킨다 */
    }
    .jd-form-wizard__seg:last-child {
      flex: 0 0 auto;
    }

    .jd-form-wizard__step {
      flex-shrink: 0;
      width: 2rem;
      height: 2rem;
      border: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-full);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      background: var(--jd-color-border);
      color: var(--jd-color-muted);
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-form-wizard__step[data-state="done"] {
      /* success 원색(#2f8f57) + #fff = 4.04:1(<4.5) — 배경을 foreground로 20% 눌러 대비 확보(체크 글리프는 white 승계) */
      background: color-mix(in srgb, var(--jd-color-success) 80%, var(--jd-color-foreground));
      color: #fff;
      cursor: pointer;
    }
    .jd-form-wizard__step[data-state="current"] {
      background: var(--jd-color-primary);
      color: #fff;
    }
    .jd-form-wizard__step:disabled {
      cursor: default;
    }
    .jd-form-wizard__step[data-state="done"]:disabled {
      cursor: pointer;
    }
    /* 되돌아갈 수 있는 단계는 눌린다 — 세 상태를 다 준다(§1). 배경을 밝히지 않고
     후광으로 알리는 이유: 위 규칙의 혼합비는 흰 글자와 4.5:1을 맞춘 값이라 손대면
     대비가 무너지고, 혼합 방향(foreground)은 모드마다 반대로 움직인다. */
    .jd-form-wizard__step[data-state="done"]:hover {
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--jd-color-success) 25%, transparent);
    }
    .jd-form-wizard__step[data-state="done"]:active {
      scale: 0.94;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-form-wizard__step:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-form-wizard__line {
      flex: 1;
      height: 2px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border);
    }
    .jd-form-wizard__line[data-state="done"] {
      background: var(--jd-color-success);
    }

    /* ── 헤더 ── */
    .jd-form-wizard__head {
      margin-block-end: var(--jd-space-4);
    }
    /* 제목·설명은 어절을 지킨다 — 기본 CJK 줄바꿈은 글자 단위라 좁은 폭에서 조각난다(§5) */
    .jd-form-wizard__title {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      word-break: keep-all;
      overflow-wrap: break-word;
    }
    .jd-form-wizard__desc {
      margin: var(--jd-space-0-5) 0 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      word-break: keep-all;
      overflow-wrap: break-word;
    }
    .jd-form-wizard__desc[hidden] {
      display: none;
    }

    /* ── 콘텐츠 ── */
    .jd-form-wizard__content {
      margin-block-end: var(--jd-space-6);
    }

    .jd-form-wizard__error {
      margin: 0 0 var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-danger);
    }
    .jd-form-wizard__error[hidden] {
      display: none;
    }

    /* ── 네비게이션 ──
     간격이 없으면 세 조각(이전 / n / m / 다음)이 좁은 폭에서 서로를 밀어 겹친다(실측).
     버튼은 줄이지 않고, 정말 모자라면 줄을 바꾼다. */
    .jd-form-wizard__nav {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
    }
    .jd-form-wizard__count {
      /* 단계 표시는 수치다 — 자릿수가 바뀌어도 좌우 버튼이 흔들리지 않게 */
      flex: 1 1 auto;
      min-width: 0;
      text-align: center;
      white-space: nowrap;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-muted);
    }

    .jd-form-wizard__prev,
    .jd-form-wizard__next {
      flex-shrink: 0;
      white-space: nowrap;
      padding: var(--jd-space-2) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      /* all 금지 — 대상을 지목한다(§3). 눌림(scale)은 press 속도로 따로 잡는다. */
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-form-wizard__prev {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: transparent;
      color: var(--jd-color-foreground);
    }
    .jd-form-wizard__prev:hover:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-muted) 8%, transparent);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    .jd-form-wizard__prev:disabled {
      opacity: var(--jd-opacity-30);
      cursor: not-allowed;
    }
    .jd-form-wizard__next {
      border: 0;
      background: var(--jd-color-primary);
      color: #fff;
      /* 채움만 있는 면은 색종이로 읽힌다 — 위에서 받는 빛을 함께 준다(§2) */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-form-wizard__next:hover {
      background: var(--jd-color-primary-hover);
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 눌린 면은 빛을 잃는다(§1) — v2에는 눌림 상태 자체가 없었다 */
    .jd-form-wizard__prev:active:not(:disabled),
    .jd-form-wizard__next:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-form-wizard__prev:focus-visible,
    .jd-form-wizard__next:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-form-wizard__step,
      .jd-form-wizard__prev,
      .jd-form-wizard__next {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-forum-thread {
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-forum-thread {
      max-width: 48rem;
      margin-inline: auto;
      padding: var(--jd-space-4);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }

    .jd-forum-thread__title {
      margin: 0;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
      overflow-wrap: anywhere;
    }
    .jd-forum-thread__tags {
      margin-top: var(--jd-space-1);
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1);
    }
    .jd-forum-thread__tags[hidden] {
      display: none;
    }
    .jd-forum-thread__tag {
      display: inline-flex;
      align-items: center;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, var(--jd-color-card));
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      white-space: nowrap;
    }

    .jd-forum-thread__answers-heading {
      margin: 0 0 var(--jd-space-2);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }
    .jd-forum-thread__answers-list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }

    .jd-forum-thread__post {
      display: flex;
      gap: var(--jd-space-3);
      padding: var(--jd-space-4);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-forum-thread__post:not([data-depth="0"]) {
      margin-inline-start: var(--jd-space-6);
    }
    /* 투명 혼합이 아니라 카드 위 혼합 — 페이지 배경색이 비쳐 톤이 흔들리지 않는다 */
    .jd-forum-thread__post[data-accepted] {
      border-color: color-mix(in srgb, var(--jd-color-success) 40%, transparent);
      background: color-mix(in srgb, var(--jd-color-success) 6%, var(--jd-color-card));
    }

    .jd-forum-thread__votes {
      flex-shrink: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-forum-thread__vote {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      padding: 0;
      border: 0;
      width: 1.75rem;
      height: 1.75rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-md);
      background: transparent;
      color: var(--jd-color-foreground);
      font: inherit;
      line-height: 1;
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-forum-thread__vote:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    .jd-forum-thread__vote:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-forum-thread__vote:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-forum-thread__vote[data-dir="up"][aria-pressed="true"] {
      color: var(--jd-color-primary-ink);
    }
    .jd-forum-thread__vote[data-dir="down"][aria-pressed="true"] {
      color: var(--jd-color-danger);
    }

    .jd-forum-thread__score {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    .jd-forum-thread__accepted-mark {
      margin-top: var(--jd-space-1);
      font-size: var(--jd-text-xl);
      line-height: 1;
      color: var(--jd-color-success);
    }

    .jd-forum-thread__body-col {
      flex: 1;
      min-width: 0;
    }

    .jd-forum-thread__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-forum-thread__avatar-img,
    .jd-forum-thread__avatar-fallback {
      width: 1.25rem;
      height: 1.25rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      flex-shrink: 0;
    }
    .jd-forum-thread__avatar-img {
      display: block;
    }
    .jd-forum-thread__avatar-fallback {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      user-select: none;
    }
    .jd-forum-thread__author {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-forum-thread__role {
      padding: var(--jd-space-0-5) 0.375rem;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      white-space: nowrap;
    }
    .jd-forum-thread__time {
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }

    .jd-forum-thread__accept {
      appearance: none;
      -webkit-appearance: none;
      margin: 0 0 0 auto;
      padding: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      font: inherit;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-success);
      border-radius: var(--jd-radius-sm);
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-forum-thread__accept:hover {
      text-decoration: underline;
    }
    .jd-forum-thread__accept:active {
      scale: 0.97;
    }
    .jd-forum-thread__accept:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-success);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-forum-thread__content {
      margin-top: var(--jd-space-2);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
      overflow-wrap: anywhere;
      white-space: pre-wrap;
    }

    .jd-forum-thread__replies {
      margin-top: var(--jd-space-3);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    .jd-forum-thread__composer {
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-xs);
      padding: var(--jd-space-4);
    }
    .jd-forum-thread__composer-title {
      margin: 0 0 var(--jd-space-2);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-forum-thread__vote,
      .jd-forum-thread__accept {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-funnel-chart {
      display: block;
      width: 100%;
      /* 퍼널은 **양의 감소**를 말하지 범주를 말하지 않는다. v2의 보라·파랑·초록·주황·
       빨강 계단은 단계마다 다른 뜻이 있다고 읽히고(info=안내, success=성공,
       danger=위험) 한 화면에서 팔레트가 흔들렸다 — 한 색상의 명도 계단으로 바꾼다.
       계단이 **어두워지는** 방향인 이유는 두 가지다: 막대 위 글자가 #fff라 밝히는
       쪽으로 가면 4.5:1 아래로 떨어지고, 아래로 갈수록 좁아지는 면은 같은 무게로
       읽히려면 더 진해야 한다. primary는 모드 간에 불변이라 계단도 불변이다. */
      --jd-chart-1: var(--jd-color-primary);
      --jd-chart-2: color-mix(in srgb, var(--jd-color-primary) 90%, #000);
      --jd-chart-3: color-mix(in srgb, var(--jd-color-primary) 80%, #000);
      --jd-chart-4: color-mix(in srgb, var(--jd-color-primary) 71%, #000);
      --jd-chart-5: color-mix(in srgb, var(--jd-color-primary) 63%, #000);
      --jd-chart-6: color-mix(in srgb, var(--jd-color-primary) 56%, #000);
      --jd-chart-7: color-mix(in srgb, var(--jd-color-primary) 50%, #000);
    }
    jd-funnel-chart:not(:defined) {
      display: block;
    }

    .jd-funnel-chart__steps {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-funnel-chart__step {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-funnel-chart__track {
      flex: 1;
      display: flex;
      justify-content: center;
      min-width: 0;
    }
    .jd-funnel-chart__bar {
      display: flex;
      align-items: center;
      justify-content: center;
      min-width: 60px;
      box-sizing: border-box;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-series-color);
      color: #fff;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      /* 채움만 있는 면은 색종이로 읽힌다(§2) — 상단 인셋 하이라이트가 '위에서 빛을
       받는 면'을 만든다. 명도 계단만으로는 단계들이 한 장의 색지처럼 붙어 보인다. */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      transition: width var(--jd-duration-slower) var(--jd-easing-default);
    }
    .jd-funnel-chart__meta {
      width: 8rem;
      flex-shrink: 0;
      text-align: right;
    }
    .jd-funnel-chart__label {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      /* 8rem 고정 칸이라 긴 단계 이름은 넘친다 — 끊을 자리가 없어도 끊는다(§5) */
      overflow-wrap: anywhere;
    }
    .jd-funnel-chart__rate {
      margin: 0;
      /* v2는 10px였다 — 2xs(11px) 아래로는 내려가지 않는다(§9) */
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-funnel-chart__bar {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-fx-board {
      display: block;
      font-family: var(--jd-font-sans);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
    }
    jd-fx-board:not(:defined) {
      display: block;
    }

    .jd-fx-board__head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fx-board__pulse {
      position: relative;
      width: 0.625rem;
      height: 0.625rem;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fx-board__pulse::after {
      content: "";
      position: absolute;
      inset: 0;
      border-radius: inherit;
      background: inherit;
      opacity: 0.75;
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-fx-board__pulse::after {
        animation: jd-fx-pulse 1.4s var(--jd-easing-ease-out) infinite;
      }
    }
    @keyframes jd-fx-pulse {
      to {
        transform: scale(2.2);
        opacity: 0;
      }
    }

    /* v2가 남긴 반픽셀 글자 크기(8.5·9·9.5·10.5·12.5px)는 전부 토큰 계단으로 올렸다 —
     11px(--jd-text-2xs)이 읽기의 바닥이고(§9), 반픽셀은 기기마다 다르게 반올림된다. */
    .jd-fx-board__live {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-wider);
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fx-board__title {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
    }
    .jd-fx-board__status {
      margin-inline-start: auto;
      flex-shrink: 0;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    /* 셀 수만큼 1열씩 나누되(--jd-fx-count는 element.ts가 넣는다) 셀 폭에 하한을 둔다 —
     하한이 없으면 종목이 늘어날수록 칸이 눌려 "비트코인"이 두 줄로 접히고 칩까지
     접힌다(실측). 좁으면 다음 줄로 흘려보내는 편이 읽힌다(§5). */
    .jd-fx-board__grid {
      display: grid;
      grid-template-columns: repeat(
        auto-fit,
        minmax(min(100%, max(9.5rem, 100% / var(--jd-fx-count, 1))), 1fr)
      );
    }

    .jd-fx-cell {
      display: flex;
      flex-direction: column;
      gap: 2px;
      min-width: 0; /* 격자 자식 기본 min-width:auto가 칸을 밀어내지 못하게(§5) */
      padding: var(--jd-space-2) var(--jd-space-3);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fx-cell[data-last] {
      border-inline-end: 0;
    }

    .jd-fx-cell__top {
      display: flex;
      align-items: center;
      gap: 6px;
      min-width: 0;
    }
    .jd-fx-cell__dot {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fx-cat, var(--jd-color-accent));
      flex-shrink: 0;
    }
    /* 종목명은 접히지 않는다 — 두 줄이 되면 셀 높이가 서로 어긋난다. 넘치면 말줄임 */
    .jd-fx-cell__label {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }
    .jd-fx-cell__cat {
      margin-inline-start: auto;
      /* 분류 칩은 낱말 하나짜리 원자다 — 줄이거나 접지 않는다 */
      flex-shrink: 0;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      padding: 1px 6px;
      border-radius: var(--jd-radius-full);
      /* 틴트 위 글자는 원색이 아니라 foreground 쪽으로 섞어 대비 확보(jd-tag 700레벨 관행) */
      color: color-mix(
        in srgb,
        var(--jd-fx-cat, var(--jd-color-accent)) 65%,
        var(--jd-color-foreground)
      );
      background: color-mix(in srgb, var(--jd-fx-cat, var(--jd-color-accent)) 10%, transparent);
    }

    /* 화살표·수치·단위는 한 덩어리다 — 갈라지면 "1,384 / 원"으로 읽힌다(§5) */
    .jd-fx-cell__value-row {
      display: flex;
      align-items: baseline;
      gap: 4px;
      min-width: 0;
      white-space: nowrap;
    }
    .jd-fx-cell__arrow,
    .jd-fx-cell__value {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    .jd-fx-cell[data-trend="up"] .jd-fx-cell__arrow,
    .jd-fx-cell[data-trend="up"] .jd-fx-cell__value {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fx-cell[data-trend="down"] .jd-fx-cell__arrow,
    .jd-fx-cell[data-trend="down"] .jd-fx-cell__value {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
    .jd-fx-cell__unit {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-fx-cell__pct {
      font-size: var(--jd-text-2xs);
      white-space: nowrap;
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
    .jd-fx-cell__pct[data-dir="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fx-cell__pct[data-dir="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
    .jd-fx-cell__symbol {
      font-size: var(--jd-text-2xs);
      white-space: nowrap;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }

    /* 화살표 방향의 낱말은 시각적으로만 숨긴다(색·글리프뿐이던 방향을 AT에 싣는다) */
    .jd-fx-cell__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-fzone-card {
      display: block;
    }
    jd-fzone-card:not(:defined) {
      display: block;
    }

    .jd-fzone-card__link {
      display: block;
      overflow: hidden;
      text-decoration: none;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      transition: box-shadow var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-fzone-card__link[hidden] {
      display: none;
    }
    .jd-fzone-card__link:hover {
      box-shadow: var(--jd-shadow-md);
    }
    .jd-fzone-card__link:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-fzone-card__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      /* DEC-044 톤 레시피 — kind 4종은 앵커만 바꾼다 */
      --jd-tone: var(--jd-color-hue-teal); /* kind=F 기본 */
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
    }
    .jd-fzone-card__header[data-kind="SF"] {
      --jd-tone: var(--jd-color-hue-orange);
    }
    .jd-fzone-card__header[data-kind="G"] {
      --jd-tone: var(--jd-color-hue-amber);
    }
    .jd-fzone-card__header[data-kind="J"] {
      --jd-tone: var(--jd-color-hue-rose);
    }
    .jd-fzone-card__name {
      font-size: 14px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
    }
    .jd-fzone-card__status {
      font-size: 12px;
      font-weight: var(--jd-weight-bold);
      padding: 2px 10px;
      border-radius: var(--jd-radius-full);
      /* 원색 배경 + 흰 글자는 대비 미달(성공색 3.6:1) → 배경을 foreground 쪽으로 80% 섞는다 */
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 80%,
        var(--jd-color-foreground)
      );
      color: #fff;
    }

    .jd-fzone-card__body {
      display: grid;
      grid-template-columns: 1fr 18px;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-3) var(--jd-space-2);
    }
    .jd-fzone-card__info {
      min-width: 0;
    }

    .jd-fzone-card__row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      margin-block-start: 2px;
    }
    .jd-fzone-card__row:first-child {
      margin-block-start: 0;
    }
    .jd-fzone-card__row-label {
      font-size: 12px;
      color: var(--jd-color-muted);
    }
    .jd-fzone-card__meta {
      font-size: 12px;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-fzone-card__price {
      font-size: 14px;
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
    .jd-fzone-card__pct {
      font-size: 12px;
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
    .jd-fzone-card__price[data-dir="up"],
    .jd-fzone-card__pct[data-dir="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fzone-card__price[data-dir="down"],
    .jd-fzone-card__pct[data-dir="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }

    .jd-fzone-card__levels {
      display: flex;
      flex-direction: column;
      gap: 4px;
      margin-block-start: var(--jd-space-2);
    }
    .jd-fzone-card__level {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 12.5px;
    }
    .jd-fzone-card__level-label {
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      padding: 1px 4px;
      border-radius: var(--jd-radius-sm);
    }
    .jd-fzone-card__level[data-muted] .jd-fzone-card__level-label {
      color: var(--jd-color-muted);
    }
    .jd-fzone-card__level[data-highlight] .jd-fzone-card__level-label {
      color: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 65%,
        var(--jd-color-foreground)
      );
      font-size: 11px;
      padding: 1px 8px;
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 12%,
        transparent
      );
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-finance-up, var(--jd-color-success)) 55%, transparent);
    }
    .jd-fzone-card__level-value {
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-fzone-card__level[data-muted] .jd-fzone-card__level-value {
      color: var(--jd-color-muted);
    }

    .jd-fzone-card__marker {
      display: block;
      align-self: start;
    }
    .jd-fzone-card__marker-guide {
      stroke: color-mix(in srgb, var(--jd-color-foreground) 15%, transparent);
    }
    .jd-fzone-card__marker-seg {
      fill: transparent;
    }
    .jd-fzone-card__marker-seg[data-on][data-dir="up"] {
      fill: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-fzone-card__marker-seg[data-on][data-dir="down"] {
      fill: var(--jd-finance-down, var(--jd-color-danger));
    }
  }

  @layer junds.components {
    jd-fzone-help-modal:not(:defined) {
      display: none;
    }

    .jd-fzone-help__header {
      position: sticky;
      top: 0;
      z-index: 1;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-4) var(--jd-space-5);
      flex-shrink: 0;
      background: var(--jd-color-card);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fzone-help__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-bold);
    }
    .jd-fzone-help__close {
      display: flex;
      padding: var(--jd-space-1);
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-fzone-help__close:hover {
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    /* 눌린 면은 빛을 잃는다 — 닫기도 누를 수 있는 것이므로 상태 3종을 다 갖는다 */
    .jd-fzone-help__close:active {
      scale: 0.94;
      background: color-mix(in srgb, var(--jd-color-muted) 20%, transparent);
    }
    .jd-fzone-help__close:focus-visible {
      /* 헤더가 sticky + 패널 overflow 안이라 outline이 잘린다 — 링을 그림자로 그린다 */
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-fzone-help__scroll {
      display: block;
    }

    /* Hero — 패널(card) 안에서 살짝 꺼진 띠다. --jd-color-surface는 라이트에서도
     어두운 크롬이라, 그 위에 foreground/muted 글자를 얹으면 라이트 모드에서 검은
     글자가 검은 띠에 묻힌다. 은은한 recessed 면은 background가 맡는다
     (jd-product-card의 미디어 영역과 같은 번역). */
    .jd-fzone-help__hero {
      padding: var(--jd-space-5) var(--jd-space-6);
      background: var(--jd-color-background);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fzone-help__hero-row {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-4);
    }
    .jd-fzone-help__hero-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 3.5rem;
      height: 3.5rem;
      font-size: var(--jd-text-4xl);
      border-radius: var(--jd-radius-2xl);
      background: var(--jd-color-warning);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-fzone-help__hero-text {
      min-width: 0;
    }
    .jd-fzone-help__hero-head {
      margin: 0;
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
    }
    .jd-fzone-help__hero-sub {
      margin: var(--jd-space-1-5) 0 0;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    .jd-fzone-help__hero-strong {
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-bold);
    }
    .jd-fzone-help__chips {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-4);
    }
    .jd-fzone-help__chip {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      padding: var(--jd-space-0-5) var(--jd-space-2-5);
      /* 틴트 위 글자는 foreground 쪽으로 섞어 대비 확보 */
      border-radius: var(--jd-radius-full);
      color: color-mix(in srgb, var(--tab, var(--jd-color-accent)) 65%, var(--jd-color-foreground));
      background: color-mix(in srgb, var(--tab, var(--jd-color-accent)) 12%, transparent);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--tab, var(--jd-color-accent)) 20%, transparent);
    }

    .jd-fzone-help__sections {
      padding: var(--jd-space-5);
    }

    .jd-fzone-help__section {
      margin-block-start: var(--jd-space-5);
    }
    .jd-fzone-help__section:first-child {
      margin-block-start: 0;
    }
    .jd-fzone-help__section-title {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin: 0 0 var(--jd-space-3);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
    }
    .jd-fzone-help__section-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 1.375rem;
      height: 1.375rem;
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-md);
      background: color-mix(in srgb, var(--accent, var(--jd-color-accent)) 12%, transparent);
    }

    /* 카드 읽는 법 */
    .jd-fzone-help__read-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--jd-space-2-5);
    }
    .jd-fzone-help__read-card {
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
    }
    .jd-fzone-help__read-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin-block-end: var(--jd-space-1);
    }
    .jd-fzone-help__read-dot {
      width: 0.375rem;
      height: 0.375rem;
      border-radius: var(--jd-radius-full);
      background: var(--tab, var(--jd-color-accent));
      flex-shrink: 0;
    }
    .jd-fzone-help__read-title {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
    }
    .jd-fzone-help__read-body {
      margin: 0;
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }

    /* 탭별 의미 */
    .jd-fzone-help__tabs {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    .jd-fzone-help__tab {
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fzone-help__tab[data-first] {
      border-color: color-mix(in srgb, var(--tab) 33%, transparent);
      box-shadow: 0 4px 14px color-mix(in srgb, var(--tab) 10%, transparent);
    }
    .jd-fzone-help__tab-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      background: color-mix(in srgb, var(--tab) 6%, transparent);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fzone-help__tab-emoji {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 1.875rem;
      height: 1.875rem;
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-lg);
      background: var(--tab);
      color: #fff;
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-fzone-help__tab-pill {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      padding: var(--jd-space-0-5) var(--jd-space-2-5);
      /* 원색 배경 + 흰 글자 → 배경을 foreground 쪽 80% 혼합으로 어둡혀 대비 확보 */
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--tab) 80%, var(--jd-color-foreground));
      color: #fff;
    }
    .jd-fzone-help__tab-current {
      /* 11px 아래로 내려가지 않는다 — '현재 탭'은 장식이 아니라 위치 정보다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      flex-shrink: 0;
      padding: var(--jd-space-px) var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-success-light);
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
      display: none;
    }
    .jd-fzone-help__tab[data-first] .jd-fzone-help__tab-current {
      display: inline-block;
    }
    .jd-fzone-help__tab-headline {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-bold);
      margin-inline-start: var(--jd-space-1);
      /* 플렉스 자식 기본 min-width:auto라 헤드라인이 헤더를 밀어낸다 — 0으로 풀어야
       말줄임이 실제로 걸리고, 배지들이 한 글자씩 세로로 서지 않는다 */
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-fzone-help__tab-body {
      padding: var(--jd-space-3) var(--jd-space-3-5);
    }
    .jd-fzone-help__tab-oneliner {
      margin: 0;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    .jd-fzone-help__tab-bullets {
      list-style: none;
      margin: var(--jd-space-2) 0 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-fzone-help__tab-bullet {
      display: flex;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-fzone-help__tab-bullet-dot {
      flex-shrink: 0;
      width: 0.375rem;
      height: 0.375rem;
      border-radius: var(--jd-radius-full);
      background: var(--tab);
      /* 첫 줄 가운데에 맞춘다 — relaxed(1.625) × sm 기준 */
      margin-block-start: 0.4375rem;
    }
    .jd-fzone-help__tab-example {
      display: flex;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-3);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
      border-radius: var(--jd-radius-lg);
      background: color-mix(in srgb, var(--tab) 4%, transparent);
      border: var(--jd-border-thin) dashed color-mix(in srgb, var(--tab) 33%, transparent);
    }
    .jd-fzone-help__tab-example-label {
      flex-shrink: 0;
      min-width: 2rem;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: color-mix(in srgb, var(--tab) 65%, var(--jd-color-foreground));
    }
    .jd-fzone-help__tab-example-text {
      color: var(--jd-color-foreground);
    }

    /* 용어 사전 */
    .jd-fzone-help__term-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--jd-space-2);
    }
    /* 용어 줄도 hero와 같은 이유로 surface가 아니다 — 그 위 meaning이 foreground라
     라이트 모드에서 검은 글자가 검은 줄에 묻혔다 */
    .jd-fzone-help__term {
      display: flex;
      gap: var(--jd-space-2-5);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-background);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-fzone-help__term-pill {
      align-self: flex-start;
      flex-shrink: 0;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      color: color-mix(in srgb, var(--tab, var(--jd-color-accent)) 65%, var(--jd-color-foreground));
      background: color-mix(in srgb, var(--tab, var(--jd-color-accent)) 12%, transparent);
    }
    .jd-fzone-help__term-meaning {
      /* 플렉스 자식 기본 min-width:auto — 길이를 모르는 뜻풀이가 줄을 밀어낸다 */
      min-width: 0;
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
    }

    .jd-fzone-help__disclaimer {
      display: flex;
      gap: var(--jd-space-2);
      margin-block-start: var(--jd-space-5);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-warning-light);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-warning) 30%, transparent);
      color: color-mix(in srgb, var(--jd-color-warning) 45%, var(--jd-color-foreground));
    }
    .jd-fzone-help__disclaimer-icon {
      flex-shrink: 0;
    }

    @media (min-width: 40rem) {
      .jd-fzone-help__read-grid,
      .jd-fzone-help__term-grid {
        grid-template-columns: 1fr 1fr;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-fzone-help__close {
        transition: none;
      }
      .jd-fzone-help__close:active {
        scale: none;
      }
    }
  }

  @layer junds.base {
    jd-gantt-chart:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-gantt-chart {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-gantt__scroll {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      /* 타임라인은 부모 폭을 넘긴다 — 잘린 채 끝나는 대신 스스로 구른다(§6) */
      overflow: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      background: var(--jd-color-card);
    }

    .jd-gantt__empty {
      margin: 0;
      padding: var(--jd-space-6);
      text-align: center;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-gantt__inner {
      display: flex;
    }

    /* 좌측 라벨 열 — 가로 스크롤에도 고정. 배경은 불투명이어야 아래로 흐르는 막대를 가린다 */
    .jd-gantt__labels {
      position: sticky;
      left: 0;
      z-index: 1;
      background: var(--jd-color-card);
      border-right: var(--jd-border-thin) solid var(--jd-color-border);
      flex-shrink: 0;
    }
    .jd-gantt__label-head {
      display: flex;
      align-items: center;
      padding: 0 var(--jd-space-3);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }
    /* flex 컨테이너였다면 태스크 이름(익명 flex 아이템)에 text-overflow가 걸리지 않아
       말줄임이 죽고 글자가 중간에서 잘린다 — 블록 컨테이너 + align-content로 바꿔
       세로 중앙 정렬은 유지하면서 말줄임을 되살린다(§5) */
    .jd-gantt__label-row {
      display: block;
      align-content: center;
      padding: 0 var(--jd-space-3);
      font-size: var(--jd-text-sm);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* 타임라인 */
    .jd-gantt__timeline {
      position: relative;
    }
    .jd-gantt__timeline-header {
      position: relative;
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-gantt__week {
      position: absolute;
      top: 0;
      height: 100%;
      display: flex;
      align-items: center;
      padding: 0 var(--jd-space-1);
      border-left: var(--jd-border-thin) solid var(--jd-color-border-light);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    .jd-gantt__row {
      position: relative;
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
    }

    .jd-gantt__bar {
      box-sizing: border-box; /* JS가 준 width(일수*dayWidth)에 좌우 패딩이 더해지면 종료일을 넘친다 */
      position: absolute;
      top: var(--jd-space-1);
      bottom: var(--jd-space-1);
      display: flex;
      align-items: center;
      padding: 0 var(--jd-space-2);
      border: 0;
      border-radius: var(--jd-radius-md);
      overflow: hidden;
      background: var(--jd-bar-color, var(--jd-color-primary));
      color: #fff;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      cursor: pointer;
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* filter: brightness는 막대 안 흰 글자와 진행 오버레이까지 함께 밝혀 글자가 배경에
       녹고 GPU 레이어를 새로 만든다 — 실색 전환으로 옮긴다(§1) */
    .jd-gantt__bar:hover {
      background: color-mix(in srgb, #fff 14%, var(--jd-bar-color, var(--jd-color-primary)));
    }
    .jd-gantt__bar:active {
      scale: 0.98;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 스크롤 컨테이너 안이라 바깥 아웃라인은 잘린다 — 링을 그림자로 준다(§1) */
    .jd-gantt__bar:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 진행 오버레이 — v2 bg-black/20, 좌측부터 채움 */
    .jd-gantt__fill {
      position: absolute;
      inset: 0 auto 0 0;
      background: rgba(0, 0, 0, 0.2);
    }
    .jd-gantt__bar-text {
      position: relative;
      min-width: 0;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-gantt__bar {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-gauge-chart:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-gauge-chart {
      display: inline-block;
      line-height: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      /* size가 카드보다 크면 다이얼 오른쪽이 잘린 채 끝났다(§6) */
      max-width: 100%;
    }

    .jd-gauge-chart__svg {
      display: block;
      overflow: visible;
      /* width/height는 표시 속성이라 CSS가 이긴다 — height:auto면 viewBox가 비율을
       대신 말하므로 폭만 줄여도 다이얼이 찌그러지지 않는다. */
      max-width: 100%;
      height: auto;
    }

    .jd-gauge-chart__segment {
      fill: none;
      stroke: var(--jd-gauge-chart-segment, var(--jd-color-border));
      stroke-width: 10;
      stroke-linecap: round;
      opacity: var(--jd-opacity-20);
    }
    .jd-gauge-chart__value-arc {
      fill: none;
      stroke: var(--jd-gauge-chart-active, var(--jd-color-primary));
      stroke-width: 10;
      stroke-linecap: round;
      transition: stroke var(--jd-duration-normal) var(--jd-easing-default);
    }

    .jd-gauge-chart__needle {
      stroke: var(--jd-color-foreground);
      stroke-width: 2;
      stroke-linecap: round;
    }
    .jd-gauge-chart__pivot {
      fill: var(--jd-color-foreground);
    }

    .jd-gauge-chart__value-text {
      fill: currentColor;
      font-size: var(--jd-text-xl); /* v2 text-lg = 1.125rem */
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
    }
    .jd-gauge-chart__label-text {
      fill: var(--jd-color-muted);
      /* v2는 10px였다 — 2xs(11px) 아래로는 내려가지 않는다(§9). 게이지가 작다고
       글자를 줄이는 게 아니라, 작으면 라벨을 밖에 두는 게 맞다. */
      font-size: var(--jd-text-2xs);
    }
    .jd-gauge-chart__label-text[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-gauge-chart__value-arc {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-global-kis-seeder {
      display: none;
    }
  }

  @layer junds.components {
    jd-globe {
      display: block;
      position: relative;
      width: var(--jd-globe-size, 300px);
      height: var(--jd-globe-size, 300px);
      perspective: calc(var(--jd-globe-size, 300px) * 2);
    }

    .jd-globe__glow {
      position: absolute;
      inset: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-globe-color, var(--jd-color-primary));
      opacity: var(--jd-opacity-20);
      filter: blur(24px);
    }

    .jd-globe__outline {
      position: absolute;
      inset: 0;
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-medium) solid var(--jd-globe-color, var(--jd-color-primary));
      opacity: var(--jd-opacity-20);
    }

    .jd-globe__sphere {
      position: absolute;
      inset: 0;
      transform-style: preserve-3d;
      animation: jd-globe-spin var(--jd-globe-duration, 20s) linear infinite;
    }

    .jd-globe__dot {
      position: absolute;
      left: 50%;
      top: 50%;
      width: 3px;
      height: 3px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-globe-dot-color, var(--jd-color-primary-light));
      opacity: var(--jd-globe-dim, 1);
      transform: translate(-50%, -50%)
        translate3d(var(--jd-globe-x, 0px), var(--jd-globe-y, 0px), var(--jd-globe-z, 0px));
    }

    .jd-globe__equator {
      position: absolute;
      left: 50%;
      top: 50%;
      width: var(--jd-globe-size, 300px);
      height: var(--jd-globe-size, 300px);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-thin) solid var(--jd-globe-color, var(--jd-color-primary));
      opacity: var(--jd-opacity-10);
      transform: translate(-50%, -50%) rotateX(75deg);
    }

    /* 화면 밖(data-offscreen)·명시적 정지·감속 선호 — 셋 다 합성 비용을 끊는다 */
    jd-globe[paused] > .jd-globe__sphere,
    jd-globe[data-offscreen] > .jd-globe__sphere {
      animation-play-state: paused;
    }

    @keyframes jd-globe-spin {
      from {
        transform: rotateY(0deg);
      }
      to {
        transform: rotateY(360deg);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-globe__sphere {
        animation: none;
      }
    }
  }

  @layer junds.base {
    jd-gradient-border:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-gradient-border {
      --jd-gradient-border-default: linear-gradient(
        90deg,
        var(--jd-color-primary) 0%,
        var(--jd-color-accent) 50%,
        var(--jd-color-primary) 100%
      );
      --jd-gradient-border-radius: var(--jd-radius-xl); /* v2 기본 rounded-xl = 12px */

      display: block;
      position: relative;
      box-sizing: border-box;
      padding: var(--jd-gradient-border-width, 2px);
      border-radius: var(--jd-gradient-border-radius);
      background-image: var(--jd-gradient-border-image, var(--jd-gradient-border-default));
      background-size: 100% 100%;
    }

    jd-gradient-border[radius="none"] {
      --jd-gradient-border-radius: var(--jd-radius-none);
    }
    jd-gradient-border[radius="sm"] {
      --jd-gradient-border-radius: var(--jd-radius-sm);
    }
    jd-gradient-border[radius="md"] {
      --jd-gradient-border-radius: var(--jd-radius-md);
    }
    jd-gradient-border[radius="lg"] {
      --jd-gradient-border-radius: var(--jd-radius-lg);
    }
    jd-gradient-border[radius="2xl"] {
      --jd-gradient-border-radius: var(--jd-radius-2xl);
    }
    jd-gradient-border[radius="full"] {
      --jd-gradient-border-radius: var(--jd-radius-full);
    }

    .jd-gradient-border__inner {
      position: relative;
      border-radius: inherit; /* v2: 바깥과 같은 rounded 클래스 */
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
    }

    jd-gradient-border[animated] {
      background-size: 200% 200%;
    }
    @media (prefers-reduced-motion: no-preference) {
      jd-gradient-border[animated] {
        animation: jd-gradient-border-shift 3s var(--jd-easing-ease-in-out) infinite;
      }
    }
    @keyframes jd-gradient-border-shift {
      0%,
      100% {
        background-position: 0% 50%;
      }
      50% {
        background-position: 100% 50%;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: cols=1, gap=4(16px) — jd-grid-layout과 동형 (별칭 파생) */
    jd-grid {
      display: grid;
      grid-template-columns: repeat(1, 1fr);
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    /* v2 기본값: cols=1, gap="md"(16px) */
    jd-grid-layout {
      display: grid;
      grid-template-columns: repeat(1, 1fr);
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    /* v2 기본값: direction=row, wrap=wrap, gap="sm"(8px), align=center */
    jd-group {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-2);
    }
    jd-group[no-wrap] {
      flex-wrap: nowrap;
    }
  }

  @layer junds.components {
    jd-hashtag {
      display: inline;
    }

    .jd-hashtag {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
      text-decoration: none;
      border-radius: var(--jd-radius-sm);
    }
    .jd-hashtag:hover {
      text-decoration: underline;
    }
    .jd-hashtag:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-hashtag__trending {
      font-size: 11px;
    }
    .jd-hashtag__trending[hidden] {
      display: none;
    }
    .jd-hashtag__count {
      font-size: 11px;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-hashtag__count[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-heading {
      display: block;
      color: var(--jd-color-foreground);
      /* 기본 = level 2: xl→md:2xl, bold, tight, tracking tight, mb 16px */
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
      margin-bottom: var(--jd-space-4);
    }
    .jd-heading {
      margin: 0;
      font-size: inherit;
      font-weight: inherit;
      line-height: inherit;
    }

    jd-heading[level="1"] {
      font-size: var(--jd-text-3xl);
      margin-bottom: var(--jd-space-6);
    }
    jd-heading[level="3"] {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      letter-spacing: var(--jd-tracking-normal);
      margin-bottom: var(--jd-space-3);
    }
    jd-heading[level="4"],
    jd-heading[level="5"],
    jd-heading[level="6"] {
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      letter-spacing: var(--jd-tracking-normal);
      margin-bottom: var(--jd-space-2);
    }
    jd-heading[level="4"] {
      font-size: var(--jd-text-xl);
    }
    jd-heading[level="5"] {
      font-size: var(--jd-text-lg);
    }
    jd-heading[level="6"] {
      font-size: var(--jd-text-md);
      text-transform: uppercase;
      margin-bottom: var(--jd-space-1-5);
    }

    /* level 1·2만 반응형 기본 — 3~6은 attr 셀렉터(특이도 우위)가 그대로 유지된다 */
    @media (min-width: 768px) {
      jd-heading {
        font-size: var(--jd-text-3xl);
      } /* level 2 기본 */
      jd-heading[level="1"] {
        font-size: var(--jd-text-4xl);
      }
    }

    jd-heading[truncate] {
      overflow: hidden;
    }
    jd-heading[truncate] > .jd-heading {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  @layer junds.base {
    jd-heatmap:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-heatmap {
      display: inline-block;
      font-family: var(--jd-font-sans);
      --jd-heatmap-cell-size: 12px;
      --jd-heatmap-gap: 2px;

      /* 잔디 5단 — element.ts는 슬롯 이름만 들고 색은 여기서 정한다.
       GitHub 초록 리터럴은 팔레트 밖(§8)인 데다 라이트/다크 어느 쪽도 따라가지
       못했다. primary를 card와 섞으면 두 모드 모두에서 "빈 칸 → 가득" 방향이
       그대로 유지된다(다크에서는 어두운 카드에서 브랜드색으로 차오른다). */
      --jd-heatmap-step-0: var(--jd-color-border-light);
      --jd-heatmap-step-1: color-mix(in srgb, var(--jd-color-primary) 22%, var(--jd-color-card));
      --jd-heatmap-step-2: color-mix(in srgb, var(--jd-color-primary) 45%, var(--jd-color-card));
      --jd-heatmap-step-3: color-mix(in srgb, var(--jd-color-primary) 70%, var(--jd-color-card));
      --jd-heatmap-step-4: var(--jd-color-primary);

      /* 1년치 잔디는 53열(≈740px)이라 어떤 카드보다 넓다 — 잘린 채 끝나지 않고
       스스로 구른다(§6). 세로는 항상 7행이라 자를 것이 없다.
       격자의 음수 마진(위/왼쪽 2px)은 이 스크롤 상자 밖으로 나가 가려지는데,
       그 2px는 border-spacing이 만든 **빈 여백**이라 보이는 것은 잃지 않는다. */
      max-width: 100%;
      overflow-x: auto;
      overflow-y: hidden;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
    }

    .jd-heatmap__grid {
      border-collapse: separate;
      border-spacing: var(--jd-heatmap-gap);
      table-layout: fixed;
      /* border-spacing이 만드는 바깥 여백 상쇄 — v2 flex gap과 같은 바운딩 박스 */
      margin: calc(var(--jd-heatmap-gap) * -1);
    }

    .jd-heatmap__cell {
      width: var(--jd-heatmap-cell-size);
      height: var(--jd-heatmap-cell-size);
      padding: 0;
      border-radius: 2px; /* v2 borderRadius: 2 — 토큰 사다리(sm=4px)보다 작다 */
      background: var(--jd-heatmap-cell, var(--jd-color-border-light));
    }

    .jd-heatmap__legend {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin-block-start: var(--jd-space-2);
      /* v2는 10px였다 — 2xs(11px) 아래로는 내려가지 않는다(§9) */
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }
    .jd-heatmap__legend[hidden] {
      display: none;
    }

    .jd-heatmap__swatch {
      flex-shrink: 0;
      width: var(--jd-heatmap-cell-size);
      height: var(--jd-heatmap-cell-size);
      border-radius: 2px; /* v2 borderRadius: 2 — 토큰 사다리(sm=4px)보다 작다 */
      background: var(--jd-heatmap-cell, var(--jd-color-border-light));
    }

    /* 색으로만 전달되던 값의 텍스트 등가물 (jd-comparison-grid 관용구) */
    .jd-heatmap__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.base {
    jd-hero-section:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-hero-section {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      margin-inline: auto;
      max-width: 64rem; /* centered 기본 */
      padding-block: var(--jd-space-16);
      padding-inline: var(--jd-space-4);
    }
    @media (min-width: 640px) {
      jd-hero-section {
        padding-block: var(--jd-space-24);
        padding-inline: var(--jd-space-6);
      }
    }

    .jd-hero__inner {
      display: block;
    }
    .jd-hero__content {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-5);
    }

    .jd-hero__eyebrow {
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-primary-ink);
    }
    .jd-hero__eyebrow[hidden],
    .jd-hero__title[hidden],
    .jd-hero__subtitle[hidden],
    .jd-hero__actions[hidden],
    .jd-hero__media[hidden] {
      display: none;
    }

    .jd-hero__title {
      margin: 0;
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
      line-height: var(--jd-leading-tight);
      font-size: var(--jd-text-3xl);
    }
    @media (min-width: 640px) {
      .jd-hero__title {
        font-size: var(--jd-text-4xl);
      }
    }
    @media (min-width: 1024px) {
      .jd-hero__title {
        font-size: var(--jd-text-5xl);
      }
    }

    .jd-hero__subtitle {
      margin: 0;
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
      max-width: 42rem;
      line-height: var(--jd-leading-relaxed);
    }
    @media (min-width: 640px) {
      .jd-hero__subtitle {
        font-size: var(--jd-text-lg);
      }
    }

    .jd-hero__actions {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-3);
    }

    .jd-hero__footer {
      margin-block-start: var(--jd-space-4);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-hero__footer:empty {
      display: none;
    }

    .jd-hero__media {
      display: none;
    } /* split에서만 노출 */

    /* CTA — v2 CtaButton. 전이 대상은 지목한다: all이면 padding·font-size까지 대상이 되어
     반응형 브레이크포인트를 넘을 때 버튼이 흐르고 매 프레임 리플로우가 생긴다(DEC-039). */
    .jd-hero__cta {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-md);
      font-weight: var(--jd-weight-semibold);
      padding: var(--jd-space-2-5) var(--jd-space-5);
      font-size: var(--jd-text-sm);
      text-decoration: none;
      white-space: nowrap;
      cursor: pointer;
      border: var(--jd-border-thin) solid transparent;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 채움만 있는 버튼은 색종이처럼 읽힌다 — 상단 인셋 하이라이트로 면에 빛을 준다 */
    .jd-hero__cta[data-cta="primary"] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-hero__cta[data-cta="primary"]:hover {
      background: var(--jd-color-primary-hover);
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 보조 CTA는 "앱의 본문" 위에 서는 버튼이지 어두운 크롬이 아니다 — surface를 쓰면
     라이트 모드에서 어두운 판에 검은 글자가 얹혀 라벨이 사라졌다. jd-button secondary와
     같은 card/card-hover 짝을 쓴다(DEC-044). imageBg에서도 어두운 히어로 위의 밝은
     칩으로 읽혀 의도와 어긋나지 않는다. */
    .jd-hero__cta[data-cta="secondary"] {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border-color: var(--jd-color-border);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-hero__cta[data-cta="secondary"]:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    /* 눌린 면은 빛을 잃는다 — v2 CtaButton에는 :active가 없었다.
     [data-cta]를 함께 무는 이유: 누르는 동안에도 커서는 위에 있으므로 위의 hover
     규칙(특이도 0,3,0)과 겨뤄야 한다. 맨 .jd-hero__cta:active는 0,2,0이라 진다. */
    .jd-hero__cta[data-cta]:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-hero__cta:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* ── centered (기본) ── */
    jd-hero-section[variant="centered"] .jd-hero__content {
      align-items: center;
      text-align: center;
    }
    jd-hero-section[variant="centered"] .jd-hero__actions {
      justify-content: center;
    }

    /* ── minimal ── */
    jd-hero-section[variant="minimal"] {
      max-width: 56rem;
      padding-block: var(--jd-space-10);
    }
    @media (min-width: 640px) {
      jd-hero-section[variant="minimal"] {
        padding-block: var(--jd-space-10);
      }
    }

    /* ── split ── */
    jd-hero-section[variant="split"] {
      max-width: 80rem;
      padding-block: var(--jd-space-12);
    }
    @media (min-width: 640px) {
      jd-hero-section[variant="split"] {
        padding-block: var(--jd-space-20);
      }
    }
    jd-hero-section[variant="split"] .jd-hero__inner {
      display: grid;
      gap: var(--jd-space-10);
      align-items: center;
    }
    jd-hero-section[variant="split"] .jd-hero__content {
      max-width: 36rem;
    }
    jd-hero-section[variant="split"] .jd-hero__media {
      display: block;
      order: -1;
    }
    @media (min-width: 1024px) {
      jd-hero-section[variant="split"] .jd-hero__inner {
        grid-template-columns: 1fr 1fr;
      }
      jd-hero-section[variant="split"] .jd-hero__media {
        order: 1;
      }
    }

    /* ── imageBg (풀블리드) ── */
    jd-hero-section[variant="imageBg"] {
      max-width: none;
      padding: 0;
    }
    jd-hero-section[variant="imageBg"] .jd-hero__inner {
      position: relative;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: center;
      color: #fff;
      padding-block: var(--jd-space-20);
      padding-inline: var(--jd-space-4);
      /* bgImage 없어도 흰 글자가 보이도록 어두운 폴백 위에 오버레이 */
      background-color: var(--jd-color-surface); /* 이미지 뒤 항상 어두운 면 (DEC-044) */
      background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
        var(--jd-hero-bg, none);
      background-size: cover;
      background-position: center;
    }
    @media (min-width: 640px) {
      jd-hero-section[variant="imageBg"] .jd-hero__inner {
        padding-block: var(--jd-space-24);
        padding-inline: var(--jd-space-6);
      }
    }
    jd-hero-section[variant="imageBg"] .jd-hero__content {
      align-items: center;
      text-align: center;
      max-width: 56rem;
    }
    jd-hero-section[variant="imageBg"] .jd-hero__eyebrow {
      color: #fff;
    }
    jd-hero-section[variant="imageBg"] .jd-hero__subtitle {
      color: color-mix(in srgb, #fff 90%, transparent);
    }
    jd-hero-section[variant="imageBg"] .jd-hero__footer {
      color: color-mix(in srgb, #fff 80%, transparent);
    }
    jd-hero-section[variant="imageBg"] .jd-hero__actions {
      justify-content: center;
    }
    jd-hero-section[variant="imageBg"] .jd-hero__media {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-hero__cta {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-highlight {
      display: inline;
    }

    .jd-highlight__mark {
      padding-inline: var(--jd-space-0-5);
      border-radius: var(--jd-radius-sm);
      /* v2 yellow-200 리터럴은 다크에서 형광 슬래브 + 흰 글자로 뒤집혔다 — 톤 레시피로 (DEC-044) */
      --jd-tone: var(--jd-color-hue-amber);
      --jd-tone-ink-mix: 68%;
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-strong-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }
    [data-jd-theme="dark"] .jd-highlight__mark,
    [data-theme="dark"] .jd-highlight__mark {
      background: rgb(234 179 8 / 0.3);
    }

    jd-highlight[variant="primary"] .jd-highlight__mark {
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-semibold);
    }
    jd-highlight[variant="underline"] .jd-highlight__mark {
      padding-inline: 0;
      background: transparent;
      color: inherit;
      text-decoration: underline;
      text-decoration-thickness: 2px;
      text-underline-offset: 2px;
      text-decoration-color: var(--jd-color-primary-ink);
    }
  }

  @layer junds.components {
    jd-hint {
      display: inline-flex;
      align-items: flex-start;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-snug);
      /* variant 기본 muted — 디폴트는 attribute로 반영되지 않으므로 base가 담당(§1.3) */
      color: var(--jd-color-muted);
    }
    jd-hint[variant="info"] {
      color: color-mix(
        in srgb,
        var(--jd-color-info) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-hint[variant="tip"] {
      color: color-mix(
        in srgb,
        var(--jd-color-success) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-hint[variant="warning"] {
      color: color-mix(
        in srgb,
        var(--jd-color-warning) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    /* v2 mt-px — 글리프를 첫 줄 x-height에 맞춘다 */
    .jd-hint__icon {
      flex-shrink: 0;
      margin-block-start: var(--jd-space-px);
    }

    /* 변형명 접두 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다) */
    .jd-hint__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-holding-form-modal:not(:defined) {
      display: none;
    }
    jd-holding-form-modal {
      display: none;
    }
    jd-holding-form-modal[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-4);
    }
    /* v2 백드롭 톤(slate-900/45) */
    jd-holding-form-modal > .jd-modal__backdrop {
      background: rgba(15, 23, 42, 0.45);
    }
    jd-holding-form-modal > .jd-modal__panel {
      max-width: min(28rem, calc(100vw - 2rem));
      overflow: hidden;
      font-variant-numeric: tabular-nums;
    }

    .jd-hfm__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 14px var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-hfm__title {
      margin: 0;
      font-size: 15px;
      font-weight: 800;
    }
    .jd-hfm__close {
      display: inline-grid;
      place-items: center;
      width: 28px;
      height: 28px;
      padding: 0;
      border: none;
      border-radius: var(--jd-radius-full);
      background: transparent;
      color: var(--jd-color-muted);
      cursor: pointer;
    }
    .jd-hfm__close:hover {
      background: var(--jd-color-card-hover);
    }

    .jd-hfm__body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
      padding: var(--jd-space-5);
    }
    .jd-hfm__field {
      position: relative;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-hfm__label {
      font-size: 11.5px;
      font-weight: 700;
      color: var(--jd-color-muted);
    }
    .jd-hfm__label--row {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .jd-hfm__input {
      width: 100%;
      height: 40px;
      padding: 0 var(--jd-space-3);
      font-family: inherit;
      font-size: 13.5px;
      font-weight: 700;
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      outline: none;
    }
    .jd-hfm__input:focus-visible {
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-hfm__input[data-locked],
    .jd-hfm__input:disabled {
      background: var(--jd-color-card-hover);
      cursor: not-allowed;
    }
    .jd-hfm__num {
      text-align: right;
      font-variant-numeric: tabular-nums;
      -moz-appearance: textfield;
    }
    .jd-hfm__num::-webkit-outer-spin-button,
    .jd-hfm__num::-webkit-inner-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }

    .jd-hfm__fill {
      padding: 0;
      border: none;
      background: transparent;
      cursor: pointer;
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-color-primary-ink);
    }
    .jd-hfm__fill[hidden] {
      display: none;
    }

    .jd-hfm__suggest {
      position: absolute;
      inset-inline: 0;
      top: calc(100% + var(--jd-space-1));
      margin: 0;
      padding: 0;
      list-style: none;
      z-index: var(--jd-z-dropdown);
      max-height: 240px;
      overflow-y: auto;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
    }
    .jd-hfm__suggest[hidden] {
      display: none;
    }
    .jd-hfm__suggest-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      width: 100%;
      padding: var(--jd-space-2) var(--jd-space-3);
      border: none;
      background: transparent;
      cursor: pointer;
      text-align: start;
      font-family: inherit;
    }
    .jd-hfm__suggest-item:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-hfm__suggest-left {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-hfm__suggest-name {
      font-size: 13px;
      font-weight: 700;
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-hfm__suggest-sector {
      font-size: 11px;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-hfm__suggest-price {
      flex-shrink: 0;
      font-size: 12px;
      font-weight: 600;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-hfm__selected {
      font-size: 11px;
      font-weight: 600;
      color: var(--jd-color-muted);
    }
    .jd-hfm__selected[hidden] {
      display: none;
    }
    .jd-hfm__selected strong {
      font-weight: 700;
      color: var(--jd-color-foreground);
    }

    .jd-hfm__grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: var(--jd-space-3);
    }

    .jd-hfm__summary {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 10px var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border-radius: var(--jd-radius-lg);
    }
    .jd-hfm__summary[hidden] {
      display: none;
    }
    .jd-hfm__summary-label {
      font-size: 12px;
      font-weight: 700;
      color: var(--jd-color-muted);
    }
    .jd-hfm__summary-value {
      font-size: 15px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }

    .jd-hfm__footer {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: var(--jd-space-2);
      padding: 14px var(--jd-space-5);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card-hover);
    }
    .jd-hfm__btn {
      height: 36px;
      padding: 0 var(--jd-space-4);
      font-family: inherit;
      font-size: 13px;
      font-weight: 700;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
    }
    .jd-hfm__btn--cancel {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-hfm__btn--cancel:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-hfm__btn--submit {
      border: none;
      color: var(--jd-color-card);
      background: var(--jd-color-muted);
      opacity: 0.6;
    }
    .jd-hfm__btn--submit[data-valid] {
      background: var(--jd-color-primary);
      opacity: 1;
    }
    .jd-hfm__btn--submit[data-valid]:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-hfm__btn--submit:disabled {
      cursor: not-allowed;
    }
  }

  @layer junds.components {
    jd-hot-pct-chip {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      white-space: nowrap;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-none);
      padding: var(--jd-space-1) var(--jd-space-2-5);
      border-radius: var(--jd-radius-full);
      color: #fff;
      background: linear-gradient(
        180deg,
        var(--jd-finance-up, var(--jd-color-success)) 0%,
        color-mix(
            in srgb,
            var(--jd-finance-up, var(--jd-color-success)) 80%,
            var(--jd-color-foreground)
          )
          100%
      );
      /* 알약은 실체가 있는 면이다 — 상단 인셋 하이라이트가 없으면 색종이로 읽힌다 */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
  }

  @layer junds.base {
    jd-hover-card:not(:defined) {
      display: inline-flex;
    }
    jd-hover-card:not(:defined) > :not([slot="trigger"]) {
      display: none;
    }
  }
  @layer junds.components {
    jd-hover-card {
      position: relative;
      display: inline-flex;
      align-items: center;
      /* 본문 한가운데 섞여 앉는 앵커다 — 글줄 위에 서고, 부모 폭을 넘지 않는다 */
      vertical-align: middle;
      max-width: 100%;
      font-family: var(--jd-font-sans);
    }

    /* ── 트리거 ──
     원형은 포커스 가능한 자식이 없을 때만 래퍼를 승격한다 — 그래서 [tabindex] 가
     곧 "소비자가 자기 링크·버튼을 넣지 않았다"는 표식이다. 그 경우 트리거는 본문과
     구별되지 않아 카드가 있다는 사실 자체가 보이지 않았다(실측).
     밑줄을 text-decoration이 아니라 border로 긋는 이유: 승격된 래퍼는 inline-flex라
     텍스트 장식이 플렉스 아이템(=글줄)으로 전파되지 않는다. */
    jd-hover-card > .jd-popover__trigger[tabindex] {
      gap: var(--jd-space-1);
      border-block-end: var(--jd-border-thin) dashed
        color-mix(in srgb, var(--jd-color-muted) 60%, transparent);
      color: inherit;
      cursor: default;
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-hover-card > .jd-popover__trigger[tabindex]:hover,
    jd-hover-card[open] > .jd-popover__trigger[tabindex] {
      border-block-end-color: var(--jd-color-primary);
      color: var(--jd-color-primary-ink);
    }
    jd-hover-card > .jd-popover__trigger[tabindex]:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      box-shadow: none;
    }

    /* 파생 기본값(0,1,1) — 명시 align attribute(0,2,0)가 언제나 이긴다 */
    jd-hover-card > .jd-popover__panel {
      --jd-popover-offset: var(--jd-space-2);
      left: 50%;
      right: auto;
      --jd-popover-tx: -50%;

      width: 16rem;
      /* 중앙 정렬이라 앵커 기준 좌우로 반씩 뻗는다 — 좁은 화면에서 밖으로 나가지 않게 */
      max-width: min(16rem, calc(100vw - 2rem));
      /* 떠 있는 면은 테두리를 눅이고 그림자로 띄운다 — 실선 테두리는 문서 안의
       구획으로 읽힌다 */
      border-color: color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      box-shadow: var(--jd-shadow-lg);
      backdrop-filter: none;
      line-height: var(--jd-leading-normal);
    }
    /* 프로필 카드는 보통 블록 몇 개가 쌓인 것이다 — 서로 붙어 한 덩어리로 읽히지
     않게 사이만 벌린다. 텍스트 노드의 인라인 흐름은 건드리지 않는다. */
    jd-hover-card > .jd-popover__panel > * + * {
      margin-block-start: var(--jd-space-2);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-hover-card > .jd-popover__trigger[tabindex] {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: gap="sm"(8px), align=center */
    jd-hstack {
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: var(--jd-space-2);
    }
  }

  @layer junds.components {
    jd-icon {
      display: inline-flex;
      flex-shrink: 0;
    }
    .jd-icon {
      display: block;
    }
  }

  @layer junds.components {
    jd-icon-button {
      display: inline-flex;
    }

    .jd-icon-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      margin: 0;
      padding: 0;
      background: transparent;
      cursor: pointer;
      user-select: none;
      color: var(--jd-color-muted);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md — 32px */
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-lg);
    }
    .jd-icon-button:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
      color: var(--jd-color-foreground);
    }
    /* 아이콘 버튼도 jd-button과 같은 프레스 응답 — 같은 제품 안에서 어떤 버튼은
     눌리고 어떤 버튼은 안 눌리면 '만들다 만' 인상이 된다 (DEC-039) */
    .jd-icon-button:active {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      scale: 0.92;
    }
    .jd-icon-button:disabled {
      opacity: var(--jd-opacity-50);
      pointer-events: none;
    }
    .jd-icon-button:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    /* 아이콘은 광학 중심이 기하 중심과 어긋나기 쉬우므로 축소·정렬을 고정한다 */
    .jd-icon-button > svg {
      flex-shrink: 0;
      display: block;
    }

    jd-icon-button[size="xs"] > .jd-icon-button {
      width: 1.5rem;
      height: 1.5rem;
      border-radius: var(--jd-radius-md);
    }
    jd-icon-button[size="sm"] > .jd-icon-button {
      width: 1.75rem;
      height: 1.75rem;
      border-radius: var(--jd-radius-lg);
    }
    jd-icon-button[size="lg"] > .jd-icon-button {
      width: 2.5rem;
      height: 2.5rem;
      border-radius: var(--jd-radius-xl);
    }

    jd-icon-button[variant="outline"] > .jd-icon-button {
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    jd-icon-button[variant="outline"] > .jd-icon-button:hover {
      background: var(--jd-color-card-hover);
    }

    jd-icon-button[variant="filled"] > .jd-icon-button {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    jd-icon-button[variant="filled"] > .jd-icon-button:hover {
      background: var(--jd-color-primary-hover);
      color: #fff;
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }
    jd-icon-button[variant="filled"] > .jd-icon-button:active {
      background: var(--jd-color-primary-hover);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-icon-button {
        transition: none;
      }
      .jd-icon-button:active {
        scale: 1;
      }
    }
  }

  @layer junds.components {
    jd-image {
      position: relative;
      display: block;
      overflow: hidden;
      box-sizing: border-box; /* ratio·width에 padding/border 병용 시 총치수 유지(DEC-014-9) */
      background: var(--jd-color-card-hover); /* v2 bg-surface-soft */
    }

    .jd-image__img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover; /* fit 기본 */
      transition: opacity var(--jd-duration-normal) var(--jd-easing-ease-out);
      opacity: var(--jd-opacity-0);
    }
    jd-image[status="loaded"] .jd-image__img {
      opacity: var(--jd-opacity-100);
    }
    jd-image[status="error"] .jd-image__img {
      display: none;
    }

    jd-image[fit="contain"] .jd-image__img {
      object-fit: contain;
    }
    jd-image[fit="fill"] .jd-image__img {
      object-fit: fill;
    }
    jd-image[fit="none"] .jd-image__img {
      object-fit: none;
    }
    jd-image[fit="scale-down"] .jd-image__img {
      object-fit: scale-down;
    }

    jd-image[radius="sm"] {
      border-radius: var(--jd-radius-sm);
    }
    jd-image[radius="md"] {
      border-radius: var(--jd-radius-md);
    }
    jd-image[radius="lg"] {
      border-radius: var(--jd-radius-lg);
    }
    jd-image[radius="full"] {
      border-radius: var(--jd-radius-full);
    }

    /* 슬롯: placeholder는 로딩 중에만, fallback은 실패 시에만 */
    jd-image > [slot="placeholder"],
    jd-image > [slot="fallback"] {
      display: none;
      align-items: center;
      justify-content: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      background: var(--jd-color-card-hover);
    }
    /* placeholder는 로딩 중인 img 위에 겹친다 — 박스는 img가 준다 */
    jd-image > [slot="placeholder"] {
      position: absolute;
      inset: 0;
    }
    jd-image[status="loading"] > [slot="placeholder"] {
      display: flex;
    }
    /* fallback은 흐름 배치다(v2 동형): 실패 시 img가 사라지므로 절대배치면 높이가 0이 되어
     ratio·height를 주지 않은 사용처에서 아무것도 보이지 않는다(e2e 실증). */
    jd-image[status="error"] > [slot="fallback"] {
      display: flex;
      width: 100%;
      height: 100%;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-image__img {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-image-compare {
      aspect-ratio: var(--_jd-image-compare-ratio, 16 / 9);
      background: #000;
    }

    /* 원형은 바탕 이미지가 흐름 배치라 높이를 스스로 준다.
     여기는 컨테이너가 종횡비로 높이를 정하므로 둘 다 절대 배치 + cover. */
    jd-image-compare .jd-compare-slider__image {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    jd-image-compare .jd-compare-slider__label {
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: rgba(0, 0, 0, 0.6);
      font-size: 11px;
      font-weight: var(--jd-weight-semibold);
    }
  }

  @layer junds.components {
    jd-image-cropper {
      display: inline-block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    .jd-image-cropper__frame {
      position: relative;
      overflow: hidden;
      border-radius: var(--jd-radius-xl);
      user-select: none;
      -webkit-user-select: none;
    }

    .jd-image-cropper__image {
      display: block;
      width: 100%;
      height: auto;
      -webkit-user-drag: none;
    }

    .jd-image-cropper__dim {
      position: absolute;
      inset: 0;
      background: rgba(0, 0, 0, 0.4);
    }

    .jd-image-cropper__area {
      position: absolute;
      overflow: hidden;
      inset-inline-start: calc(var(--_jd-crop-x, 25) * 1%);
      inset-block-start: calc(var(--_jd-crop-y, 25) * 1%);
      width: calc(var(--_jd-crop-size, 50) * 1%);
      aspect-ratio: var(--_jd-crop-ratio, 1);
      border: var(--jd-border-medium) solid #fff;
      box-sizing: border-box;
      cursor: move;
      /* 상자·손잡이 위에서 시작한 터치만 드래그로 삼킨다 — 사진의 나머지 부분에서는
       페이지가 정상 스크롤된다(touch-action은 터치가 시작된 요소의 것이 적용된다) */
      touch-action: none;
    }
    .jd-image-cropper__area:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-image-cropper__preview {
      position: absolute;
      inset-block-start: 0;
      inset-inline-start: 0;
      width: calc(100% * 100 / var(--_jd-crop-size, 50));
      height: auto;
      max-width: none;
      transform: translate(calc(var(--_jd-crop-x, 25) * -1%), calc(var(--_jd-crop-y, 25) * -1%));
      -webkit-user-drag: none;
      pointer-events: none; /* 상자 자체가 드래그 대상이다 */
    }

    .jd-image-cropper__handle {
      position: absolute;
      touch-action: none;
      width: 0.75rem;
      height: 0.75rem;
      background: #fff;
      border: var(--jd-border-thin) solid var(--jd-color-neutral-400);
      border-radius: var(--jd-radius-sm);
    }
    .jd-image-cropper__handle[data-corner="nw"] {
      inset-block-start: 0;
      inset-inline-start: 0;
      transform: translate(-50%, -50%);
      cursor: nwse-resize;
    }
    .jd-image-cropper__handle[data-corner="ne"] {
      inset-block-start: 0;
      inset-inline-end: 0;
      transform: translate(50%, -50%);
      cursor: nesw-resize;
    }
    .jd-image-cropper__handle[data-corner="sw"] {
      inset-block-end: 0;
      inset-inline-start: 0;
      transform: translate(-50%, 50%);
      cursor: nesw-resize;
    }
    .jd-image-cropper__handle[data-corner="se"] {
      inset-block-end: 0;
      inset-inline-end: 0;
      transform: translate(50%, 50%);
      cursor: nwse-resize;
    }

    /* 상태 문구는 화면에는 두되 조용하게 — v2에는 없던 층이다 */
    .jd-image-cropper__status {
      margin: var(--jd-space-2) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-image-cropper__crop {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-block-start: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-4);
      border: 0;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-primary);
      color: #fff;
      font-family: inherit;
      font-size: var(--jd-text-sm);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-image-cropper__crop:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-image-cropper__crop:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-image-cropper__crop {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-image-lightbox {
      display: inline-block;
      /* 자리의 하한은 호스트가 갖는다 — 안쪽 img에 걸면 고유 크기가 없는 이미지에서
       버튼과 이미지가 서로 폭을 물어보다 몇 px로 접힌다 */
      min-width: var(--jd-image-lightbox-thumb-min, 10rem);
      max-width: 100%;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    /* 닫힌 상태의 이 컴포넌트는 **썸네일 그 자체**다. v2는 버튼에 아무 치수도 주지
     않아, 이미지가 아직 없거나 고유 크기가 없으면 좌상단에 몇 px짜리 점으로
     박혔다(실측). 자리를 먼저 세우고 그 안을 이미지가 채운다. */
    .jd-image-lightbox__trigger {
      display: block;
      width: 100%;
      padding: 0;
      border: 0;
      overflow: hidden;
      background: var(--jd-color-border-light);
      color: inherit;
      font: inherit;
      cursor: zoom-in;
      border-radius: var(--jd-radius-lg);
      /* 눌리는 면이라는 것을 쉬는 상태에서도 보여야 한다(§7·§2) */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-image-lightbox__trigger:hover {
      box-shadow: var(--jd-shadow-md), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-image-lightbox__trigger:active {
      scale: 0.98;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-image-lightbox__trigger:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-image-lightbox__thumb {
      display: block;
      width: 100%;
      height: auto;
      /* auto <ratio> — 고유 비율이 있으면 그것이 이기고, 없을 때만(로딩 전·깨진
       링크) 대체 비율이 자리를 잡는다. 소비자는 --jd-image-lightbox-thumb-ratio로 바꾼다. */
      aspect-ratio: auto var(--jd-image-lightbox-thumb-ratio, 4 / 3);
      object-fit: cover;
      border-radius: inherit;
    }

    /* 닫혀 있을 때 오버레이는 없는 것과 같다 */
    jd-image-lightbox:not([open]) > .jd-modal__backdrop,
    jd-image-lightbox:not([open]) > .jd-modal__panel {
      display: none;
    }

    jd-image-lightbox > .jd-modal__backdrop {
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      background: rgba(0, 0, 0, 0.8);
      backdrop-filter: blur(4px);
    }

    /* 패널이 곧 오버레이 무대다 — 카드 표면(배경·그림자·max-width)을 전부 벗긴다 */
    jd-image-lightbox > .jd-modal__panel {
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      display: flex;
      align-items: center;
      justify-content: center;
      width: auto;
      max-width: none;
      max-height: none;
      padding: 0;
      overflow: visible;
      background: transparent;
      box-shadow: none;
      border-radius: 0;
    }

    .jd-image-lightbox__zoom {
      position: absolute;
      inset-block-start: var(--jd-space-4);
      inset-inline-end: var(--jd-space-4);
      display: flex;
      gap: var(--jd-space-2);
    }

    .jd-image-lightbox__button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 2.5rem;
      height: 2.5rem;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: rgba(255, 255, 255, 0.1);
      color: #fff;
      font-size: var(--jd-text-lg);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-image-lightbox__button:hover:not(:disabled) {
      background: rgba(255, 255, 255, 0.2);
    }
    /* 눌린 면은 빛을 잃는다(§1) — v2에는 세 상태 중 active가 없었다 */
    .jd-image-lightbox__button:active:not(:disabled) {
      scale: 0.97;
      background: rgba(255, 255, 255, 0.28);
    }
    .jd-image-lightbox__button:disabled {
      opacity: var(--jd-opacity-40);
      cursor: default;
    }
    /* 백드롭 위라 outline이 배경에 묻는다 — 흰 링 + 보라 글로우 두 겹으로 세운다 */
    .jd-image-lightbox__button:focus-visible {
      outline: none;
      box-shadow: 0 0 0 var(--jd-border-medium) rgba(255, 255, 255, 0.9),
        var(--jd-shadow-focus-ring);
    }
    .jd-image-lightbox__close {
      font-size: var(--jd-text-2xl);
    }

    .jd-image-lightbox__figure {
      max-width: 90vw;
      max-height: 90vh;
      object-fit: contain;
      transform: scale(var(--_jd-lightbox-scale, 1));
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-image-lightbox[open] > .jd-modal__backdrop {
        animation: jd-image-lightbox-fade var(--jd-duration-fast) var(--jd-easing-ease-out);
      }
      jd-image-lightbox[open] > .jd-modal__panel > .jd-image-lightbox__figure {
        animation: jd-image-lightbox-pop var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-image-lightbox-fade {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-image-lightbox-pop {
      from {
        opacity: 0;
        transform: scale(0.94);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-image-lightbox__figure,
      .jd-image-lightbox__button,
      .jd-image-lightbox__trigger {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-image-with-fallback {
      position: relative;
      display: block;
      overflow: hidden;
      box-sizing: border-box; /* ratio·width에 padding/border 병용 시 총치수 유지(DEC-014-9) */
      background: var(--jd-color-card-hover); /* v2 bg-gray-100 dark:bg-gray-800 */
    }

    /* 상태 훅 — image.css의 같은 규칙은 jd-image 태그에 묶여 있다 */
    jd-image-with-fallback[status="loaded"] .jd-image__img {
      opacity: var(--jd-opacity-100);
    }
    jd-image-with-fallback[status="error"] .jd-image__img {
      display: none;
    }

    jd-image-with-fallback[fit="contain"] .jd-image__img {
      object-fit: contain;
    }
    jd-image-with-fallback[fit="fill"] .jd-image__img {
      object-fit: fill;
    }
    jd-image-with-fallback[fit="none"] .jd-image__img {
      object-fit: none;
    }
    jd-image-with-fallback[fit="scale-down"] .jd-image__img {
      object-fit: scale-down;
    }

    jd-image-with-fallback[radius="sm"] {
      border-radius: var(--jd-radius-sm);
    }
    jd-image-with-fallback[radius="md"] {
      border-radius: var(--jd-radius-md);
    }
    jd-image-with-fallback[radius="lg"] {
      border-radius: var(--jd-radius-lg);
    }
    jd-image-with-fallback[radius="full"] {
      border-radius: var(--jd-radius-full);
    }

    /* 로딩 스켈레톤 — 반짝임(색·박자·다크·감속 선호)은 .jd-skeleton-block에서 온다 */
    .jd-image-with-fallback__skeleton.jd-skeleton-block {
      display: none;
      position: absolute;
      inset: 0;
      border-radius: 0; /* 모서리는 호스트가 자른다 */
      background: linear-gradient(
        90deg,
        var(--jd-color-card-hover) 0%,
        var(--jd-skeleton-color, var(--jd-color-neutral-200)) 50%,
        var(--jd-color-card-hover) 100%
      );
    }
    jd-image-with-fallback[status="loading"]:not([no-skeleton])
      > .jd-image-with-fallback__skeleton.jd-skeleton-block:not([hidden]) {
      display: block;
    }

    /* 주소를 다 소진했을 때의 자리표시자 */
    .jd-image-with-fallback__empty {
      display: none;
      box-sizing: border-box;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      line-height: 1.4;
      text-align: center;
      color: var(--jd-color-muted);
      background: var(--jd-color-card-hover);
    }
    jd-image-with-fallback[status="error"] > .jd-image-with-fallback__empty:not([hidden]) {
      display: flex;
      width: 100%;
      height: 100%;
    }
    .jd-image-with-fallback__empty-icon {
      display: inline-flex;
      color: var(--jd-color-muted-light);
    }

    /* 슬롯 규약(DEC-014-4) 계승 — 소비자 노드가 내장 자리표시자를 대신한다 */
    jd-image-with-fallback > [slot="placeholder"],
    jd-image-with-fallback > [slot="fallback"] {
      display: none;
      align-items: center;
      justify-content: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      background: var(--jd-color-card-hover);
    }
    jd-image-with-fallback > [slot="placeholder"] {
      position: absolute;
      inset: 0;
    }
    jd-image-with-fallback[status="loading"] > [slot="placeholder"] {
      display: flex;
    }
    jd-image-with-fallback[status="error"] > [slot="fallback"] {
      display: flex;
      width: 100%;
      height: 100%;
    }
  }

  @layer junds.components {
    jd-image-zoom {
      display: block;
      position: relative;
      box-sizing: border-box;
      overflow: hidden;
      border-radius: var(--jd-radius-xl);
      aspect-ratio: var(--_jd-zoom-ratio, 16 / 9);
      background: #000;
      font-family: var(--jd-font-sans);
      user-select: none;
      -webkit-user-select: none;
      cursor: zoom-in;
      /* 확대되지 않았으면 이동할 것이 없다 — 세로 스크롤을 페이지에 돌려준다.
       확대된 뒤에만 드래그를 이동으로 삼킨다(전 구간 none이면 모바일에서
       이미지가 스크롤 블랙홀이 된다). */
      touch-action: pan-y;
    }
    jd-image-zoom[data-zoomed] {
      cursor: grab;
      touch-action: none;
    }
    jd-image-zoom:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-image-zoom__image {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: contain;
      -webkit-user-drag: none;
      transform: translate(var(--_jd-zoom-x, 0px), var(--_jd-zoom-y, 0px))
        scale(var(--_jd-zoom-scale, 1));
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }

    .jd-image-zoom__controls {
      position: absolute;
      inset-block-end: var(--jd-space-3);
      inset-inline-end: var(--jd-space-3);
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: rgba(0, 0, 0, 0.6);
      backdrop-filter: blur(4px);
      color: #fff;
      font-size: var(--jd-text-xs);
    }

    .jd-image-zoom__button {
      padding: 0 var(--jd-space-2);
      border: 0;
      background: none;
      color: inherit;
      font: inherit;
      line-height: 1.5;
      cursor: pointer;
      border-radius: var(--jd-radius-sm);
    }
    .jd-image-zoom__button:hover:not(:disabled) {
      opacity: var(--jd-opacity-80);
    }
    .jd-image-zoom__button:disabled {
      opacity: var(--jd-opacity-40);
      cursor: default;
    }
    .jd-image-zoom__button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-image-zoom__value {
      width: 2.5rem;
      text-align: center;
      font-variant-numeric: tabular-nums;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-image-zoom__image {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-infinite-list {
      display: flex;
      flex-direction: column;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-infinite-list > [hidden] {
      display: none;
    }

    .jd-infinite-list__items {
      display: flex;
      flex-direction: column;
    }
    /* v2는 항목에 아무 규약이 없어 renderItem이 텍스트만 돌려주면 목록 전체가 한
     문단으로 흘렀다 — 어디서 한 항목이 끝나는지 볼 수 없었다. 행에 여백과
     머리카락 구분선을 준다. 자기 카드/여백을 가진 renderItem은
     --jd-infinite-list-row-padding: 0 · --jd-infinite-list-rule: transparent 로 끈다. */
    .jd-infinite-list__item {
      padding-block: var(--jd-infinite-list-row-padding, var(--jd-space-3));
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-snug);
    }
    .jd-infinite-list__item + .jd-infinite-list__item {
      border-block-start: var(--jd-border-thin) solid
        var(--jd-infinite-list-rule, var(--jd-color-border-light));
    }
    .jd-infinite-list__sentinel {
      height: var(--jd-space-px);
    }

    .jd-infinite-list__spinner {
      display: flex;
      justify-content: center;
      padding-block: var(--jd-space-4);
      color: var(--jd-color-muted);
    }
    .jd-infinite-list__spinner-svg {
      width: 1.25rem;
      height: 1.25rem;
      animation: jd-infinite-list-spin var(--jd-duration-slower, 0.7s) linear infinite;
    }
    @keyframes jd-infinite-list-spin {
      to {
        transform: rotate(360deg);
      }
    }

    /* v2 text-muted-light는 라이트에서 2.7:1이라 AA 미달이다(§9) — muted까지만 내린다 */
    .jd-infinite-list__end {
      margin: 0;
      padding-block: var(--jd-space-4);
      text-align: center;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-infinite-list__empty {
      margin: 0;
      padding-block: var(--jd-space-12);
      text-align: center;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-infinite-list__spinner-svg {
        animation-duration: 1.6s;
      }
    }
  }

  @layer junds.components {
    jd-inline-edit {
      display: inline-block;
    }

    .jd-inline-edit__display {
      display: inline-block;
      margin: 0;
    }
    .jd-inline-edit__display[hidden] {
      display: none;
    }

    .jd-inline-edit__trigger {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin: 0;
      /* 강조 배경이 글자에 달라붙지 않게 좌우로 벌리고, 같은 만큼 음수 마진으로
       되당겨 앞뒤 본문과의 글줄 정렬을 유지한다 */
      padding-inline: var(--jd-space-1);
      margin-inline: calc(var(--jd-space-1) * -1);
      padding-block: 0;
      background: none;
      border-radius: var(--jd-radius-sm);
      font: inherit;
      color: inherit;
      text-align: inherit;
      border: 0;
      border-block-end: var(--jd-border-medium) dashed
        color-mix(in srgb, var(--jd-color-muted) 45%, transparent);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-inline-edit__trigger:hover:not(:disabled) {
      border-block-end-style: solid;
      border-block-end-color: var(--jd-color-primary);
      background: color-mix(in srgb, var(--jd-color-primary) 8%, transparent);
    }
    /* 글줄 안에 앉은 텍스트라 scale로 줄이면 앞뒤 본문이 흔들린다 — 눌린 신호는
     면을 짙게 하는 것으로 낸다 (button link variant가 scale을 빼는 것과 같은 판단) */
    .jd-inline-edit__trigger:active:not(:disabled) {
      border-block-end-style: solid;
      border-block-end-color: var(--jd-color-primary-hover);
      background: color-mix(in srgb, var(--jd-color-primary) 16%, transparent);
    }
    .jd-inline-edit__trigger:focus-visible {
      border-block-end-style: solid;
      border-block-end-color: var(--jd-color-primary);
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-inline-edit__trigger:disabled {
      border-block-end-color: transparent;
      background: none;
      cursor: default;
    }

    /* 빈 값 안내 — muted-light(2.7:1)는 AA 미달이라 muted (DEC-027) */
    .jd-inline-edit__trigger[data-empty] .jd-inline-edit__text {
      color: var(--jd-color-muted);
      font-style: italic;
    }

    .jd-inline-edit__pencil {
      flex-shrink: 0;
      color: var(--jd-color-muted);
      /* v2는 쉼 상태 0이라 편집 가능하다는 사실이 포인터를 올리기 전엔 보이지 않았다.
       흐리게라도 남겨 둔다 — 자리는 어차피 잡고 있으므로(opacity만 오간다) 나타날 때
       글자가 밀리지 않는다. */
      opacity: var(--jd-opacity-30);
      transition: opacity var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-inline-edit__trigger:hover > .jd-inline-edit__pencil,
    .jd-inline-edit__trigger:focus-visible > .jd-inline-edit__pencil {
      color: var(--jd-color-primary-ink);
      opacity: var(--jd-opacity-100);
    }
    .jd-inline-edit__trigger:disabled > .jd-inline-edit__pencil {
      display: none;
    }

    .jd-inline-edit__input {
      margin: 0;
      padding-inline: var(--jd-space-1);
      margin-inline: calc(var(--jd-space-1) * -1);
      background: transparent;
      font: inherit;
      color: inherit;
      border: 0;
      border-block-end: var(--jd-border-medium) solid var(--jd-color-primary);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-inline-edit__input[hidden] {
      display: none;
    }
    .jd-inline-edit__input:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-inline-edit__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-inline-edit__trigger,
      .jd-inline-edit__pencil,
      .jd-inline-edit__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-investor-council:not(:defined) {
      display: block;
    }

    :where(jd-investor-council) {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
    }
    jd-investor-council {
      display: block;
      /* 열 배분의 기준은 뷰포트가 아니라 이 카드가 실제로 받은 폭이다 */
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-council / inline-size;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-council__card {
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-council__card[hidden] {
      display: none;
    }

    /* 상태(로딩/에러) */
    .jd-council__state {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-6) var(--jd-space-4);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      font-size: 12px;
      color: var(--jd-color-muted);
    }
    .jd-council__state[hidden] {
      display: none;
    }
    .jd-council__state[data-kind="error"] {
      text-align: center;
    }
    .jd-council__state-text {
      margin: 0;
      font-size: 13px;
    }
    .jd-council__state-dot {
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-council__state-dot {
        animation: jd-council-pulse 1.2s ease-in-out infinite;
      }
    }
    @keyframes jd-council-pulse {
      50% {
        opacity: 0.35;
      }
    }

    /* 헤더 */
    .jd-council__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-council__brand {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-council__brand-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 28px;
      height: 28px;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }
    .jd-council__title {
      margin: 0;
      font-size: 14px;
      font-weight: 800;
    }
    .jd-council__tag {
      font-size: 11px;
      font-weight: 700;
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card-hover);
      color: var(--jd-color-muted);
    }

    .jd-council__consensus {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: 6px var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card-hover);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-council__consensus-up,
    .jd-council__consensus-down {
      font-size: 11px;
      font-weight: 800;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-council__consensus-down {
      color: var(--jd-fin-down);
    }
    .jd-council__consensus[data-tone="up"] .jd-council__consensus-up,
    .jd-council__consensus[data-tone="up"] .jd-council__consensus-label {
      color: var(--jd-fin-up);
    }
    .jd-council__consensus[data-tone="down"] .jd-council__consensus-up,
    .jd-council__consensus[data-tone="down"] .jd-council__consensus-label {
      color: var(--jd-fin-down);
    }
    .jd-council__consensus[data-tone="neutral"] .jd-council__consensus-up,
    .jd-council__consensus[data-tone="neutral"] .jd-council__consensus-label {
      color: var(--jd-color-muted);
    }
    .jd-council__consensus-sep {
      color: var(--jd-color-border);
    }
    .jd-council__consensus-div {
      width: 1px;
      height: 12px;
      background: var(--jd-color-border);
    }
    .jd-council__consensus-label {
      font-size: 11px;
      font-weight: 800;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }

    /* 본문 그리드 — 1fr은 minmax(auto,1fr)이라 min-content 아래로 줄지 않는다.
     상세 열 안의 표·바가 넓어지면 그대로 카드를 밀어냈다. minmax(0,·)로 못 박는다. */
    .jd-council__body {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
    }
    @container jd-council (min-width: 58rem) {
      .jd-council__body {
        grid-template-columns: 260px minmax(0, 1fr);
      }
    }
    .jd-council__aside {
      min-width: 0;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    @container jd-council (min-width: 58rem) {
      .jd-council__aside {
        border-block-end: none;
        border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      }
    }
    .jd-council__list {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-council__list > li + li {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-council__investor {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      width: 100%;
      padding: var(--jd-space-3) var(--jd-space-4);
      text-align: start;
      cursor: pointer;
      background: transparent;
      border: none;
      border-inline-start: var(--jd-border-thick) solid transparent;
      font-family: inherit;
      color: inherit;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 누를 수 있는 것은 세 상태를 전부 가진다 — 없으면 마우스도 키보드도 여기가 어디인지 모른다 */
    .jd-council__investor:hover {
      background: var(--jd-color-card-hover);
      border-inline-start-color: color-mix(
        in srgb,
        var(--_accent, var(--jd-color-primary)) 45%,
        transparent
      );
    }
    /* 세로로 긴 행은 scale이 옆 행과 어긋나 보인다 — 눌림은 안쪽 그림자로 말한다 */
    .jd-council__investor:active {
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-council__investor:focus-visible {
      outline: var(--jd-focus-ring);
      /* 카드가 overflow:hidden이라 바깥 offset은 잘린다 — 안쪽으로 접는다 */
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-council__investor[data-active] {
      background: var(--jd-color-card-hover);
      border-inline-start-color: var(--_accent, var(--jd-color-primary));
    }
    .jd-council__investor-emoji {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 36px;
      height: 36px;
      border-radius: var(--jd-radius-xl);
      font-size: 18px;
      background: color-mix(in srgb, var(--_accent, var(--jd-color-primary)) 10%, transparent);
    }
    .jd-council__investor-meta {
      min-width: 0;
      flex: 1;
    }
    .jd-council__investor-name {
      font-size: 13.5px;
      font-weight: 800;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-council__investor-tagline {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-council__investor-right {
      text-align: end;
      flex-shrink: 0;
    }
    .jd-council__investor-verdict {
      font-size: 12px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .jd-council__investor-score {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    /* 상세 */
    .jd-council__detail {
      padding: var(--jd-space-5);
    }
    .jd-council__profile {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-4);
    }
    .jd-council__profile-emoji {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 48px;
      height: 48px;
      border-radius: var(--jd-radius-2xl);
      font-size: 26px;
      background: color-mix(in srgb, var(--_accent, var(--jd-color-primary)) 10%, transparent);
    }
    .jd-council__profile-meta {
      min-width: 0;
      flex: 1;
    }
    .jd-council__profile-namerow {
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
    }
    .jd-council__profile-korean {
      margin: 0;
      font-size: 18px;
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
    }
    .jd-council__profile-name {
      font-size: 12px;
      font-weight: 700;
      color: var(--jd-color-muted);
    }
    .jd-council__profile-tagline {
      margin: 2px 0 0;
      font-size: 11.5px;
      font-weight: 700;
      color: var(--_accent, var(--jd-color-primary));
    }
    .jd-council__profile-context {
      margin: var(--jd-space-1) 0 0;
      font-size: 11.5px;
      line-height: 1.625;
      color: var(--jd-color-muted);
    }

    .jd-council__verdict-box {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      margin-block-end: var(--jd-space-4);
      border-radius: var(--jd-radius-xl);
      background: color-mix(in srgb, var(--_verdict, var(--jd-color-muted)) 8%, transparent);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--_verdict, var(--jd-color-muted)) 25%, transparent);
    }
    .jd-council__verdict-circle {
      display: grid;
      place-items: center;
      flex-shrink: 0;
      width: 48px;
      height: 48px;
      border-radius: var(--jd-radius-full);
      background: var(--_verdict, var(--jd-color-muted));
      color: #fff;
    }
    .jd-council__verdict-main {
      flex: 1;
    }
    .jd-council__verdict-label {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--_verdict, var(--jd-color-muted));
    }
    .jd-council__verdict-big {
      font-size: 20px;
      font-weight: 800;
      line-height: 1.1;
      color: var(--_verdict, var(--jd-color-muted));
    }
    .jd-council__verdict-stats {
      text-align: end;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .jd-council__stat {
      text-align: end;
    }
    .jd-council__stat-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }
    .jd-council__stat-value {
      font-size: 14px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .jd-council__stat-value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-council__stat-value[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    /* 성향 바 — 7열을 못 박으면 좁은 자리에서 한 칸이 40px가 되어 "가치"가 세로로 선다.
     내재적 auto-fit이라 실제로 7칸이 들어갈 폭에서만 7열이 된다. */
    .jd-council__bars {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 7rem), 1fr));
      gap: var(--jd-space-2);
    }
    .jd-council__bar {
      min-width: 0;
    }
    .jd-council__bar-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-1);
      min-width: 0;
      font-size: var(--jd-text-2xs);
      font-weight: 700;
    }
    .jd-council__bar-label {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: var(--jd-color-muted);
    }
    .jd-council__bar-value {
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--_accent, var(--jd-color-primary));
    }
    .jd-council__bar-value[data-neg] {
      color: var(--jd-color-muted);
    }
    .jd-council__bar-track {
      display: flex;
      height: 6px;
      margin-block-start: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      overflow: hidden;
      background: var(--jd-color-card-hover);
    }
    .jd-council__bar-spacer {
      width: 50%;
    }
    .jd-council__bar-fill-pos {
      height: 100%;
      background: var(--_accent, var(--jd-color-primary));
      border-start-end-radius: var(--jd-radius-full);
      border-end-end-radius: var(--jd-radius-full);
    }
    .jd-council__bar-half {
      width: 50%;
      height: 100%;
    }
    .jd-council__bar-fill-neg {
      /* v2 음수 성향 바 = slate-400 리터럴(중립 회색). muted 토큰은 보라 기가 있어 부적합 */
      height: 100%;
      background: var(--jd-color-neutral-400);
      border-start-start-radius: var(--jd-radius-full);
      border-end-start-radius: var(--jd-radius-full);
    }

    /* 근거 / 리스크 */
    .jd-council__lists {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
      gap: var(--jd-space-4);
      margin-block-start: var(--jd-space-4);
    }
    .jd-council__reasons {
      min-width: 0;
      padding: var(--jd-space-3) 14px;
      background: var(--jd-color-card-hover);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }
    .jd-council__reasons-title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin: 0 0 var(--jd-space-2);
      font-size: 12px;
      font-weight: 800;
      color: var(--_tone, var(--jd-color-foreground));
    }
    .jd-council__reasons-list {
      margin: 0;
      padding: 0;
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-council__reasons-item {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-1-5);
      font-size: 12.5px;
      line-height: 1.625;
    }
    .jd-council__reasons-bullet {
      flex-shrink: 0;
      margin-block-start: 7px;
      width: 4px;
      height: 4px;
      border-radius: var(--jd-radius-full);
      background: var(--_tone, var(--jd-color-muted));
    }
    .jd-council__reasons-empty {
      font-size: 12px;
      color: var(--jd-color-muted);
    }

    /* 매매 플랜 */
    .jd-council__plan {
      margin-block-start: var(--jd-space-4);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-color-card-hover);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }
    .jd-council__plan-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-block-end: var(--jd-space-2);
    }
    .jd-council__plan-title {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin: 0;
      font-size: 13px;
      font-weight: 800;
      color: var(--_accent, var(--jd-color-primary));
    }
    .jd-council__plan-horizon {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: var(--_accent, var(--jd-color-primary));
      color: #fff;
    }
    .jd-council__plan-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
      gap: var(--jd-space-3);
      font-variant-numeric: tabular-nums;
    }
    .jd-council__plan-cell {
      min-width: 0;
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }
    .jd-council__plan-cell-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    /* 값 + 단위는 한 덩어리 — 접히면 "68,400"과 "원"이 다른 줄에 선다 */
    .jd-council__plan-cell-value {
      margin-block-start: 2px;
      font-size: 13.5px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .jd-council__plan-cell-value[data-big] {
      font-size: 16px;
    }
    .jd-council__plan-cell-value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-council__plan-cell-value[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    /* 인용 */
    .jd-council__quotes {
      margin-block-start: var(--jd-space-4);
    }
    .jd-council__quotes-summary {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      cursor: pointer;
      font-size: 11.5px;
      font-weight: 700;
      border-radius: var(--jd-radius-sm);
      color: var(--jd-color-muted);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-council__quotes-summary:hover {
      color: var(--jd-color-foreground);
    }
    .jd-council__quotes-summary:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    /* 접히는 것에는 셰브런이 있어야 한다 — inline-flex가 기본 마커를 지웠으므로 대신 그린다 */
    .jd-council__quotes-summary::after {
      content: "";
      flex-shrink: 0;
      width: 6px;
      height: 6px;
      margin-inline-start: 2px;
      border-inline-end: var(--jd-border-medium) solid currentColor;
      border-block-end: var(--jd-border-medium) solid currentColor;
      rotate: 45deg;
      transition: rotate var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-council__quotes[open] > .jd-council__quotes-summary::after {
      rotate: -135deg;
    }
    .jd-council__quotes-list {
      margin: var(--jd-space-2) 0 0;
      padding-inline-start: var(--jd-space-4);
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
    }
    .jd-council__quote {
      font-size: 11.5px;
      line-height: 1.625;
      font-style: italic;
      color: var(--jd-color-muted);
    }
    .jd-council__quotes-source {
      margin-block-start: 6px;
      font-size: var(--jd-text-2xs);
      font-style: normal;
      color: var(--jd-color-muted);
    }

    /* 면책 */
    .jd-council__disclaimer {
      margin-block-start: var(--jd-space-4);
      font-size: var(--jd-text-2xs);
      line-height: 1.625;
      color: var(--jd-color-muted);
    }
    .jd-council__more {
      color: inherit;
      border-radius: var(--jd-radius-sm);
      text-decoration: underline;
    }
    .jd-council__more:hover {
      color: var(--jd-color-primary-ink);
    }
    .jd-council__more:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-council__consensus-up,
      .jd-council__consensus-down,
      .jd-council__consensus-label,
      .jd-council__investor,
      .jd-council__quotes-summary,
      .jd-council__quotes-summary::after {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-investor-flow-chart:not(:defined) {
      display: block;
    }

    :where(jd-investor-flow-chart) {
      --jd-fin-foreign: var(--jd-color-hue-blue);
      --jd-fin-foreign-neg: color-mix(in srgb, var(--jd-color-hue-blue) 42%, var(--jd-color-card));
      --jd-fin-institution: var(--jd-color-hue-violet);
      --jd-fin-institution-neg: color-mix(
        in srgb,
        var(--jd-color-hue-violet) 42%,
        var(--jd-color-card)
      );
      --jd-fin-individual: var(--jd-color-hue-amber);
      --jd-fin-individual-neg: color-mix(
        in srgb,
        var(--jd-color-hue-amber) 42%,
        var(--jd-color-card)
      );
    }
    /* v2는 svg 단독 블록 — HTML 범례를 옆에 붙이지 않도록 host를 block으로 되돌린다 */
    jd-investor-flow-chart {
      display: block;
    }

    .jd-ifc__svg {
      display: block;
      max-width: 100%;
      height: auto;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
    }
    .jd-ifc__gridline {
      stroke: var(--jd-color-border);
      stroke-opacity: 0.5;
    }
    .jd-ifc__zero {
      stroke: var(--jd-color-muted);
      stroke-opacity: 0.55;
    }
    .jd-ifc__bar {
      fill: var(--_c, var(--jd-color-muted));
    }
    .jd-ifc__swatch {
      fill: var(--_c, var(--jd-color-muted));
    }
    .jd-ifc__tick,
    .jd-ifc__date {
      font-size: 10px;
      fill: var(--jd-color-muted);
    }
    .jd-ifc__legend-t {
      font-size: 10.5px;
      font-weight: 700;
      fill: var(--jd-color-foreground);
    }
  }

  @layer junds.components {
    jd-investor-ranking:not(:defined) {
      display: block;
    }

    :where(jd-investor-ranking) {
      /* 투자자 3구분은 의미색(success/danger/…)이 아니라 **계열색**이다 — hue 팔레트에서
       뽑아야 danger가 '위험'이 아니라 '외국인'을 뜻하는 혼선이 생기지 않는다. */
      --jd-fin-foreign: var(--jd-color-hue-red);
      --jd-fin-institution: var(--jd-color-hue-purple);
      --jd-fin-individual: var(--jd-color-hue-amber);
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
    }
    jd-investor-ranking {
      display: block;
      /* 열 배분의 기준은 뷰포트가 아니라 이 카드가 실제로 받은 폭이다 */
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-ir / inline-size;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-ir__card {
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }

    /* 좁아지면 제목과 주석을 **줄로 접는다** — 글자를 세로로 세우지 않는다 */
    .jd-ir__head {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-2);
      min-width: 0;
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-ir__title {
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-ir__sub-note {
      margin-inline-start: var(--jd-space-2);
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-ir__grid {
      display: grid;
      grid-template-columns: 1fr;
    }
    /* 42rem = 한 열이 (순위 16 + 이름 최소 6rem + 순매수) 를 감당하는 최소 카드 폭.
     이보다 좁으면 3열로 쪼개는 순간 이름이 남지 않는다 — 세로로 쌓는다. */
    @container jd-ir (min-width: 42rem) {
      .jd-ir__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
    }

    .jd-ir__col {
      min-width: 0;
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-ir__col[data-last] {
      border-inline-end: none;
    }
    @container jd-ir (max-width: 41.999rem) {
      .jd-ir__col {
        border-inline-end: none;
        border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      }
      .jd-ir__col[data-last] {
        border-block-end: none;
      }
    }

    .jd-ir__col-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: 6px var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-ir__dot {
      width: 8px;
      height: 8px;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: var(--_c, var(--jd-color-muted));
    }
    .jd-ir__col-label {
      font-size: 11.5px;
      font-weight: 800;
      white-space: nowrap;
    }

    .jd-ir__list {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    /* 이름 트랙에 바닥을 준다 — 1fr(=minmax(auto,1fr))은 남는 폭을 순매수 열에 다 내주고
     "삼…"처럼 두세 글자만 남긴다. 말줄임은 정보가 남을 때만 말줄임이다. */
    .jd-ir__row {
      display: grid;
      grid-template-columns: 16px minmax(6rem, 1fr) auto;
      gap: 6px;
      align-items: center;
      padding: 6px var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-ir__row:last-child {
      border-block-end: none;
    }

    .jd-ir__rank {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      line-height: 1;
      font-variant-numeric: tabular-nums;
      background: var(--jd-color-card-hover);
      color: var(--jd-color-muted);
    }
    .jd-ir__rank[data-first] {
      background: var(--_c, var(--jd-color-primary));
      color: #fff;
    }

    .jd-ir__meta {
      min-width: 0;
    }
    .jd-ir__name {
      font-size: 11.5px;
      font-weight: 800;
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-ir__row-sub {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      min-width: 0;
      margin-block-start: 2px;
    }
    /* 값 + 단위는 한 덩어리다 — 접히면 "1,840"과 "억"이 다른 줄에 선다 */
    .jd-ir__close {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-ir__pct {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .jd-ir__net {
      font-size: 11.5px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    /* live 틱마다 방향이 바뀐다 — 색이 튀지 않게 짧게 건너간다 */
    .jd-ir__pct,
    .jd-ir__net {
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-ir__pct[data-dir="up"],
    .jd-ir__net[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-ir__pct[data-dir="down"],
    .jd-ir__net[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-ir__pct,
      .jd-ir__net {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-json-viewer {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-3);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-surface);
      color: var(--jd-color-on-surface); /* 항상 어두운 코드 면 (DEC-044) */
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-normal);
      overflow: auto;
      --_jd-json-key: color-mix(in srgb, var(--jd-color-primary) 35%, #ffffff);
      --_jd-json-string: color-mix(in srgb, var(--jd-color-success) 55%, #ffffff);
      --_jd-json-number: color-mix(in srgb, var(--jd-color-primary) 45%, #ffffff);
      --_jd-json-boolean: color-mix(in srgb, var(--jd-color-warning) 55%, #ffffff);
      --_jd-json-null: color-mix(in srgb, var(--jd-color-danger) 55%, #ffffff);
    }
    jd-json-viewer:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-json-viewer__leaf {
      display: flex;
      white-space: pre;
    }

    .jd-json-viewer__name {
      color: var(--_jd-json-key);
    }
    .jd-json-viewer__value {
      color: var(--jd-color-on-surface);
    }
    .jd-json-viewer__value[data-kind="string"] {
      color: var(--_jd-json-string);
    }
    .jd-json-viewer__value[data-kind="number"] {
      color: var(--_jd-json-number);
    }
    .jd-json-viewer__value[data-kind="boolean"] {
      color: var(--_jd-json-boolean);
    }
    .jd-json-viewer__value[data-kind="null"] {
      color: var(--_jd-json-null);
    }

    /* 개폐는 네이티브 details — 마커만 지우고 셰브론을 우리가 그린다 */
    .jd-json-viewer__summary {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding-inline: var(--jd-space-1);
      margin-inline-start: calc(var(--jd-space-1) * -1);
      border-radius: var(--jd-radius-sm);
      cursor: pointer;
      list-style: none;
      white-space: pre;
    }
    .jd-json-viewer__summary::-webkit-details-marker {
      display: none;
    }
    .jd-json-viewer__summary:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 20%, transparent);
    }
    .jd-json-viewer__summary:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-json-viewer__count {
      color: var(--jd-color-muted-light);
    }

    .jd-json-viewer__chevron {
      flex-shrink: 0;
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    details[open] > .jd-json-viewer__summary > .jd-json-viewer__chevron {
      transform: rotate(90deg);
    }

    .jd-json-viewer__children {
      padding-inline-start: var(--jd-space-4);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-json-viewer__chevron {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-kanban:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-kanban {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* 카드 이동 지시문 — 시각적으로만 숨긴다(AT에는 남긴다) */
    .jd-kanban__hint {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-kanban__board {
      display: flex;
      gap: var(--jd-space-4);
      overflow-x: auto;
      /* 보드 끝에서 멈춘 스크롤이 호스트 페이지를 이어서 밀지 않게 한다(§6) */
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      padding-bottom: var(--jd-space-4);
    }

    .jd-kanban__column {
      display: flex;
      flex-direction: column;
      width: 18rem;
      flex-shrink: 0;
      min-width: 0;
      border-radius: var(--jd-radius-xl);
      background: color-mix(in srgb, var(--jd-color-muted) 8%, var(--jd-color-card));
      border: var(--jd-border-thin) solid var(--jd-color-border-light);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 드롭 대상 강조 — v2 ring-2 ring-primary/30 + bg-primary-light/20 */
    .jd-kanban__column[data-drop-target] {
      background: color-mix(in srgb, var(--jd-color-primary-light) 40%, var(--jd-color-card));
      box-shadow: 0 0 0 var(--jd-border-medium)
        color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }

    .jd-kanban__column-header {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-kanban__column-dot {
      width: 0.5rem;
      height: 0.5rem;
      border-radius: var(--jd-radius-full);
      flex-shrink: 0;
    }
    .jd-kanban__column-dot[hidden] {
      display: none;
    }
    /* 컬럼 제목은 두 줄로 접히면 안 된다 — 넘치면 말줄임(§5) */
    .jd-kanban__column-title {
      min-width: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    /* 카운트 배지 — jd-badge default·sm 표면 */
    .jd-kanban__column-count {
      margin-left: auto;
      min-width: 1.25rem;
      padding: 0 var(--jd-space-1-5);
      height: 1.25rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-muted) 15%, transparent);
      color: var(--jd-color-muted);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      font-variant-numeric: tabular-nums;
    }

    .jd-kanban__list {
      list-style: none;
      margin: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2);
      flex: 1;
      min-height: 100px;
    }

    .jd-kanban__card {
      cursor: grab;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border-light);
      border-radius: var(--jd-radius-lg);
      padding: var(--jd-space-3);
      /* 카드는 트레이 위에 실제로 얹힌 면이다 — 면 + 위에서 받는 빛(§2) */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        opacity var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-kanban__card:hover {
      box-shadow: var(--jd-shadow-sm), inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 보드가 overflow-x:auto 라 바깥 아웃라인은 잘린다 — 링을 그림자로 준다(§1) */
    .jd-kanban__card:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-sm);
    }
    .jd-kanban__card:active {
      cursor: grabbing;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-kanban__card--dragging {
      opacity: var(--jd-opacity-40);
    }

    /* 길이를 모르는 사용자 문자열 — 컬럼 폭(18rem)을 밀어내지 않게 끊는다(§5) */
    .jd-kanban__card-title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      overflow-wrap: anywhere;
    }
    .jd-kanban__card-desc {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      overflow-wrap: anywhere;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-kanban__column,
      .jd-kanban__card {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-kbd {
      display: inline-flex;
    }

    .jd-kbd {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-sm);
      background: var(--jd-color-neutral-25);
      font-family: var(--jd-font-mono);
      font-size: 11px;
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      box-shadow: 0 1px 0 1px rgba(0, 0, 0, 0.04);
    }
  }

  @layer junds.components {
    jd-key-cap {
      display: inline-flex;
    }

    .jd-key-cap {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-md);
      font-family: var(--jd-font-mono);
      font-weight: var(--jd-weight-medium);
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md — 24px */
      height: 1.5rem;
      min-width: 1.5rem;
      padding-inline: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      /* variant 기본 default */
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06), inset 0 -1px 0 rgba(0, 0, 0, 0.04);
    }
    jd-key-cap[size="sm"] > .jd-key-cap {
      height: 1.25rem;
      min-width: 1.25rem;
      padding-inline: var(--jd-space-1);
      font-size: 10px;
    }
    jd-key-cap[size="lg"] > .jd-key-cap {
      height: 2rem;
      min-width: 2rem;
      padding-inline: var(--jd-space-2);
      font-size: var(--jd-text-md);
    }

    jd-key-cap[variant="primary"] > .jd-key-cap {
      background: var(--jd-color-primary);
      color: #fff;
      border-color: var(--jd-color-primary);
      box-shadow: none;
    }
    jd-key-cap[variant="muted"] > .jd-key-cap {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-muted);
      border-color: var(--jd-color-border-light);
      box-shadow: none;
    }

    jd-key-cap[pressed] > .jd-key-cap {
      transform: translateY(1px);
      box-shadow: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-key-cap {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-key-value-grid:not(:defined) {
      display: block;
    }
    jd-key-value-grid:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-key-value-grid {
      display: block;
    }

    /* 열 계단(1 → sm 2 → md columns)을 뷰포트 미디어쿼리로 세우면, 넓은 화면의 좁은
     칼럼 안에서 3~4열을 그대로 그려 라벨과 값이 한 글자씩 접혔다(§5·§6). 원형의
     격자 규칙은 이미 "요청 열 수로 나눈 폭"을 하한으로 둔 auto-fit이다 — 고정
     repeat(N)으로 덮어쓰던 것을 걷어내고 원형에 열 수(--jd-desc-cols는 element가
     columns 프롭에서 인라인으로 실어 준다)와 v2 간격만 넘긴다. 넓으면 columns 열,
     좁아지면 스스로 접힌다. span도 원형이 --jd-desc-span으로 처리한다. */
    jd-key-value-grid .jd-descriptions__list {
      /* v2 gap-4 */
      --jd-desc-col-gap: var(--jd-space-4);
      /* 10px 라벨 + 14px 값 한 쌍이 접히지 않고 서는 최소 칸 폭 */
      --jd-desc-col-min: 10rem;
      row-gap: var(--jd-space-4);
    }
    /* bordered는 칸을 선으로 붙여 간격이 0이다(원형이 0px로 덮는다) — 칸이 카드라
     최소 폭만 이 스킨 쪽으로 당긴다. 원형의 (0,2,0)을 이겨야 해서 box를 함께 건다. */
    jd-key-value-grid .jd-descriptions__box[data-bordered] .jd-descriptions__list {
      --jd-desc-col-min: 11rem;
    }

    /* 타이포 — 원형의 vertical 규칙(0,2,0)을 이겨야 하므로 box를 함께 건다 */
    jd-key-value-grid .jd-descriptions__box .jd-descriptions__label {
      margin-block-end: var(--jd-space-1);
      font-size: 0.625rem;
      font-weight: var(--jd-weight-medium);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--jd-color-muted);
    }
    jd-key-value-grid .jd-descriptions__box .jd-descriptions__value {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      border-radius: var(--jd-radius-sm);
      padding-inline: var(--jd-space-1);
      margin-inline: calc(-1 * var(--jd-space-1));
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-key-value-grid .jd-descriptions__box .jd-descriptions__value:hover {
      background: var(--jd-color-card-hover);
    }

    /* bordered — 라벨 셀 틴트 대신 항목 전체가 카드다 (v2 bg-white p-3) */
    jd-key-value-grid .jd-descriptions__box[data-bordered] .jd-descriptions__item {
      padding: var(--jd-space-3);
      background: var(--jd-color-card);
    }
    jd-key-value-grid .jd-descriptions__box[data-bordered] .jd-descriptions__label {
      padding: 0;
      background: none;
      border: 0;
    }
    jd-key-value-grid .jd-descriptions__box[data-bordered] .jd-descriptions__value {
      padding-block: 0;
      padding-inline: var(--jd-space-1);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-key-value-grid .jd-descriptions__box .jd-descriptions__value {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-key-value-grid-client:not(:defined) {
      display: block;
    }
    jd-key-value-grid-client:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-key-value-grid-client {
      display: block;
    }

    jd-key-value-grid-client .jd-descriptions__list {
      grid-template-columns: minmax(0, 1fr);
      column-gap: var(--jd-space-4);
      row-gap: var(--jd-space-4);
    }
    jd-key-value-grid-client .jd-descriptions__item {
      grid-column: span 1;
    }

    @media (min-width: 640px) {
      jd-key-value-grid-client .jd-descriptions__list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
      jd-key-value-grid-client .jd-descriptions__item[data-span="2"],
      jd-key-value-grid-client .jd-descriptions__item[data-span="3"],
      jd-key-value-grid-client .jd-descriptions__item[data-span="4"] {
        grid-column: span 2;
      }
    }
    @media (min-width: 768px) {
      jd-key-value-grid-client .jd-descriptions__list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
      jd-key-value-grid-client[columns="2"] .jd-descriptions__list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
      jd-key-value-grid-client[columns="4"] .jd-descriptions__list {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
      jd-key-value-grid-client .jd-descriptions__item[data-span="3"] {
        grid-column: span 3;
      }
      jd-key-value-grid-client .jd-descriptions__item[data-span="4"] {
        grid-column: span 4;
      }
    }

    jd-key-value-grid-client .jd-descriptions__box .jd-descriptions__label {
      margin-block-end: var(--jd-space-1);
      font-size: 0.625rem;
      font-weight: var(--jd-weight-medium);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--jd-color-muted);
    }
    jd-key-value-grid-client .jd-descriptions__box .jd-descriptions__value {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      border-radius: var(--jd-radius-sm);
      padding-inline: var(--jd-space-1);
      margin-inline: calc(-1 * var(--jd-space-1));
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-key-value-grid-client .jd-descriptions__box .jd-descriptions__value:hover {
      background: var(--jd-color-card-hover);
    }

    jd-key-value-grid-client .jd-descriptions__box[data-bordered] .jd-descriptions__item {
      padding: var(--jd-space-3);
      background: var(--jd-color-card);
    }
    jd-key-value-grid-client .jd-descriptions__box[data-bordered] .jd-descriptions__label {
      padding: 0;
      background: none;
      border: 0;
    }
    jd-key-value-grid-client .jd-descriptions__box[data-bordered] .jd-descriptions__value {
      padding-block: 0;
      padding-inline: var(--jd-space-1);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-key-value-grid-client .jd-descriptions__box .jd-descriptions__value {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-label {
      display: inline-block;
    }

    .jd-label {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      cursor: inherit;
    }
    jd-label[required] > .jd-label::after {
      content: "*";
      margin-inline-start: var(--jd-space-0-5);
      color: var(--jd-color-danger);
    }
  }

  @layer junds.components {
    jd-like-button {
      display: inline-flex;
    }

    .jd-like-button {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      box-sizing: border-box;
      border: 0;
      background: none;
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-full);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md */
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      font-size: var(--jd-text-sm);
    }
    .jd-like-button:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
    }
    .jd-like-button:active:not(:disabled) {
      transform: scale(0.95);
    }
    .jd-like-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-like-button:focus-visible {
      outline: var(--jd-border-medium) solid #f43f5e;
      outline-offset: 2px; /* v2 rose-500 */
    }

    jd-like-button[size="sm"] .jd-like-button {
      height: 1.75rem;
      padding-inline: var(--jd-space-2);
      font-size: var(--jd-text-xs);
    }
    jd-like-button[size="lg"] .jd-like-button {
      height: 2.75rem;
      padding-inline: var(--jd-space-4);
      font-size: var(--jd-text-md);
    }

    .jd-like-button__icon {
      width: 1rem;
      height: 1rem;
      flex-shrink: 0;
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-like-button[size="sm"] .jd-like-button__icon {
      width: 0.875rem;
      height: 0.875rem;
    }
    jd-like-button[size="lg"] .jd-like-button__icon {
      width: 1.25rem;
      height: 1.25rem;
    }

    jd-like-button[liked] .jd-like-button {
      color: #f43f5e;
    } /* v2 rose-500 */
    jd-like-button[liked] .jd-like-button__icon {
      fill: currentColor;
      transform: scale(1.1);
    }
    /* 하트는 그래픽(3:1)이라 rose 원색이 충분하지만 **숫자는 텍스트**라 3.3:1로 AA 미달이다
     (axe 게이트 실측). 글자만 foreground와 섞는다 — DEC-030-7과 같은 처방. */
    jd-like-button[liked] .jd-like-button__count {
      color: color-mix(in srgb, #f43f5e 65%, var(--jd-color-foreground));
    }

    .jd-like-button__count {
      font-variant-numeric: tabular-nums;
    }
    .jd-like-button__count[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-like-button,
      .jd-like-button__icon {
        transition: none;
      }
      .jd-like-button:active:not(:disabled) {
        transform: none;
      }
      jd-like-button[liked] .jd-like-button__icon {
        transform: none;
      }
    }
  }

  @layer junds.components {
    .jd-lhc__row {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-4);
    }

    .jd-lhc__main {
      min-width: 0;
      flex: 1;
    }
    .jd-lhc__nameline {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-wrap: wrap;
    }
    .jd-lhc__name {
      font-size: 13.5px;
      font-weight: 800;
      color: var(--jd-color-foreground);
      text-decoration: none;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lhc__name:hover {
      color: var(--jd-color-primary-ink);
      text-decoration: underline;
    }
    /* 밑줄만으로는 눌린 순간이 안 보인다 — 행 안에서 누를 수 있는 건 이름뿐이므로 색으로 답한다 */
    .jd-lhc__name:active {
      color: var(--jd-color-primary-hover);
    }
    .jd-lhc__name:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }
    .jd-lhc__catalyst {
      margin-block-start: 2px;
      font-size: 11px;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-lhc__pill {
      display: inline-flex;
      align-items: center;
      gap: 3px;
      padding: 1px 7px;
      border-radius: var(--jd-radius-full);
      font-size: 10.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-lhc__pill[data-clean="true"] {
      background: color-mix(in srgb, var(--jd-fin-up) 14%, transparent);
      color: var(--jd-fin-up);
      border-color: color-mix(in srgb, var(--jd-fin-up) 35%, transparent);
    }
    .jd-lhc__pill-icon {
      display: inline-flex;
    }

    .jd-lhc__figures {
      flex-shrink: 0;
      text-align: end;
    }
    .jd-lhc__pct {
      font-size: 13.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-lhc__pct[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lhc__pct[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-lhc__amount {
      margin-block-start: 2px;
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-lhc__name {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-line-chart {
      /* 계열색은 hue 팔레트에서만 뽑는다(§8). 공용 기본값은 success/warning/danger를
       계열색으로 쓰고 있어, 같은 화면에서 "3번 시리즈"와 "경고"가 같은 색이 된다 —
       계열은 범주일 뿐 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 480px 뷰박스가 카드보다 넓으면 오른쪽 끝 x축 라벨이 잘린 채 끝났다(§6).
       범례까지 한 줄에 못 들어가면 줄을 바꾼다 — 눌러 담으면 둘 다 못 읽는다. */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* SVG의 width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가
     비율을 대신 말하므로 폭만 줄여도 그림이 찌그러지지 않는다. */
    jd-line-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      /* 플렉스 자식의 min-width:auto는 내용 폭(480)이 바닥이라 실제로는 줄지 않는다.
       그렇다고 0까지 풀면 범례 옆에서 실선 한 줄로 뭉개진다 — 컨테이너가 이보다
       좁을 때만 양보한다. */
      min-width: min(100%, 15rem);
    }
    jd-line-chart:not(:defined) {
      display: inline-block;
    }
  }

  @layer junds.components {
    jd-link {
      display: inline;
    }

    .jd-link {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      border-radius: var(--jd-radius-sm);
      cursor: pointer;
      color: var(--jd-color-primary-ink);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* underline 기본 hover — 기본값은 attribute 미반영(§1.3)이라 base가 담당 */
      text-decoration: none;
      text-underline-offset: 2px;
    }
    .jd-link:hover {
      color: var(--jd-color-primary-hover);
      text-decoration: underline;
    }
    .jd-link:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-link__external {
      display: inline-flex;
    }

    jd-link[variant="subtle"] .jd-link {
      color: var(--jd-color-foreground);
    }
    jd-link[variant="subtle"] .jd-link:hover {
      color: var(--jd-color-primary-ink);
    }
    jd-link[variant="muted"] .jd-link {
      color: var(--jd-color-muted);
    }
    jd-link[variant="muted"] .jd-link:hover {
      color: var(--jd-color-foreground);
    }
    jd-link[variant="danger"] .jd-link {
      color: var(--jd-color-danger);
    }
    jd-link[variant="danger"] .jd-link:hover {
      color: var(--jd-color-danger);
      opacity: var(--jd-opacity-80);
    }

    jd-link[underline="always"] .jd-link {
      text-decoration: underline;
    }
    jd-link[underline="none"] .jd-link,
    jd-link[underline="none"] .jd-link:hover {
      text-decoration: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-link {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-live-index-card {
      --jd-fin-up: var(--jd-finance-up, var(--bm-up, var(--jd-color-success)));
      --jd-fin-down: var(--jd-finance-down, var(--bm-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-flat: var(--jd-finance-flat, var(--jd-fin-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));

      display: block;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-index-card * {
      box-sizing: border-box;
    }
    jd-live-index-card[data-dir="up"] {
      --jd-lic-dir: var(--jd-fin-up);
    }
    jd-live-index-card[data-dir="down"] {
      --jd-lic-dir: var(--jd-fin-down);
    }

    jd-live-index-card .jd-live-index-card__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-live-index-card .jd-live-index-card__label {
      font-weight: 800;
      font-size: 10px;
      color: var(--jd-fin-text);
    }
    jd-live-index-card[large] .jd-live-index-card__label {
      font-size: 13px;
    }
    jd-live-index-card .jd-live-index-card__pct {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-size: 11px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-lic-dir, var(--jd-fin-flat));
    }

    jd-live-index-card .jd-live-index-card__body {
      padding: var(--jd-space-2-5) var(--jd-space-3-5) var(--jd-space-3);
    }
    jd-live-index-card .jd-live-index-card__value {
      font-weight: 800;
      font-size: 18px;
      line-height: var(--jd-leading-tight);
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-live-index-card[large] .jd-live-index-card__value {
      font-size: 28px;
    }
    jd-live-index-card .jd-live-index-card__diff {
      margin-block-start: 2px;
      font-weight: 700;
      font-size: 12px;
      font-variant-numeric: tabular-nums;
      color: var(--jd-lic-dir, var(--jd-fin-flat));
    }

    jd-live-index-card .jd-live-index-card__spark {
      display: block;
      margin-block-start: var(--jd-space-2);
    }
    jd-live-index-card .jd-live-index-card__spark-area {
      fill: var(--jd-lic-dir, var(--jd-fin-flat));
      fill-opacity: 0.12;
      stroke: none;
    }
    jd-live-index-card .jd-live-index-card__spark-line {
      fill: none;
      stroke: var(--jd-lic-dir, var(--jd-fin-flat));
      stroke-width: 1.5;
    }
  }

  @layer junds.components {
    jd-live-investor-board:not(:defined) {
      display: block;
    }

    :where(jd-live-investor-board) {
      /* 투자자 3구분은 의미색이 아니라 **계열색**이다 — hue 팔레트에서 뽑아야 danger가
       '위험'이 아니라 '외국인'을 뜻하는 혼선이 생기지 않는다. */
      --jd-fin-foreign: var(--jd-color-hue-red);
      --jd-fin-institution: var(--jd-color-hue-purple);
      --jd-fin-individual: var(--jd-color-hue-amber);
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      /* 장 개장 여부는 등락이 아니라 상태다 — 의미색 그대로 */
      --jd-fin-open: var(--jd-color-success);
    }
    jd-live-investor-board {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-lib__card {
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }

    /* 헤더 */
    .jd-lib__head {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-2);
      min-width: 0;
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-lib__live {
      position: relative;
      display: inline-flex;
      width: 10px;
      height: 10px;
      flex-shrink: 0;
    }
    .jd-lib__ping {
      position: absolute;
      inset: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-muted);
      opacity: 0.75;
    }
    .jd-lib__dot {
      position: relative;
      display: inline-flex;
      width: 10px;
      height: 10px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-muted);
    }
    .jd-lib__live[data-open] .jd-lib__ping,
    .jd-lib__live[data-open] .jd-lib__dot {
      background: var(--jd-fin-open);
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-lib__live[data-open] .jd-lib__ping {
        animation: jd-lib-pulse 1.4s var(--jd-easing-ease-out) infinite;
      }
    }
    @keyframes jd-lib-pulse {
      0% {
        transform: scale(1);
        opacity: 0.8;
      }
      80%,
      100% {
        transform: scale(2.4);
        opacity: 0;
      }
    }
    .jd-lib__live-word {
      font-size: 11px;
      font-weight: 800;
      letter-spacing: 0.06em;
      color: var(--jd-color-muted);
    }
    .jd-lib__live-word[data-open] {
      color: var(--jd-fin-open);
    }
    .jd-lib__title {
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-lib__clock {
      margin-inline-start: auto;
      font-size: 11.5px;
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    /* 시장 합계 요약 — 3열을 못 박으면 좁은 자리에서 "외국인 시장합계"가 글자로 흩어진다.
     내재적 auto-fit이라 폭이 나올 때만 3열이 된다. */
    .jd-lib__totals {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
      gap: var(--jd-space-1) var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-lib__total {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-lib__total-dot {
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      flex-shrink: 0;
      background: var(--_c, var(--jd-color-muted));
    }
    .jd-lib__total-label {
      font-size: 11px;
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    /* 값 + 단위는 한 덩어리 — 접히면 "1.84"와 "조"가 다른 줄에 선다 */
    .jd-lib__total-value {
      margin-inline-start: auto;
      font-size: 13px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lib__total-value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lib__total-value[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    /* 격자 — 열이 0까지 줄면 셀 내용이 밖으로 새어 표가 오른쪽으로 넘친다.
     최소 폭을 못 박고, 그 합이 카드보다 넓어지면 격자 자신이 가로로 구른다. */
    .jd-lib__grid {
      display: grid;
      grid-template-columns: minmax(7rem, 1fr) repeat(3, minmax(9rem, 1.4fr));
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
    }
    .jd-lib__headcell {
      padding: 6px var(--jd-space-2);
      font-size: 12px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-lib__headcell[data-variant="center"] {
      text-align: center;
    }
    .jd-lib__headcell[data-variant="muted"] {
      color: var(--jd-color-muted);
      border-block-end: none;
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-lib__rowhead {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-2);
      font-size: 12px;
      font-weight: 800;
      white-space: nowrap;
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-lib__rowhead-dot {
      width: 8px;
      height: 8px;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: var(--_c, var(--jd-color-muted));
    }

    .jd-lib__cell {
      min-width: 0;
      padding: 6px var(--jd-space-2);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      font-variant-numeric: tabular-nums;
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-lib__cell[data-flash="up"] {
        animation: jd-lib-flash-up 1.6s var(--jd-easing-ease-out);
      }
      .jd-lib__cell[data-flash="down"] {
        animation: jd-lib-flash-down 1.6s var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-lib-flash-up {
      0% {
        background-color: color-mix(in srgb, var(--jd-fin-up) 18%, transparent);
      }
      100% {
        background-color: transparent;
      }
    }
    @keyframes jd-lib-flash-down {
      0% {
        background-color: color-mix(in srgb, var(--jd-fin-down) 18%, transparent);
      }
      100% {
        background-color: transparent;
      }
    }

    .jd-lib__spark {
      display: block;
      width: 100%;
      height: 22px;
    }
    .jd-lib__spark-zero {
      stroke: var(--jd-color-border);
      stroke-width: 1;
    }
    .jd-lib__spark-area {
      fill: var(--_c, var(--jd-color-muted));
      fill-opacity: 0.12;
      stroke: none;
    }
    .jd-lib__spark-line {
      fill: none;
      stroke: var(--_c, var(--jd-color-muted));
      stroke-width: 1.5;
      stroke-linejoin: round;
      stroke-linecap: round;
    }
    .jd-lib__spark-head {
      fill: var(--_c, var(--jd-color-muted));
    }

    .jd-lib__netrow {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: var(--jd-space-1);
      min-width: 0;
      margin-block-start: 2px;
    }
    .jd-lib__net {
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lib__net[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lib__net[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-lib__net[data-dir="flat"] {
      color: var(--jd-color-foreground);
    }
    .jd-lib__delta {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      display: inline-flex;
      align-items: center;
      gap: 1px;
      white-space: nowrap;
    }
    .jd-lib__delta[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lib__delta[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-lib__delta[data-dir="flat"] {
      color: var(--jd-color-muted);
      font-weight: 700;
    }

    .jd-lib__bsrow {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-1);
      min-width: 0;
      margin-block-start: var(--jd-space-1);
    }
    .jd-lib__buy {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-up);
    }
    .jd-lib__sell {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-down);
    }

    .jd-lib__bar {
      display: flex;
      overflow: hidden;
      height: 6px;
      margin-block-start: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card-hover);
    }
    .jd-lib__bar-buy {
      background: var(--jd-fin-up);
    }
    .jd-lib__bar-sell {
      background: var(--jd-fin-down);
    }

    .jd-lib__raterow {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-1);
      min-width: 0;
      margin-block-start: 2px;
    }
    .jd-lib__rate-buy {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-up);
    }
    .jd-lib__rate-sell {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-down);
    }

    .jd-lib__volume {
      padding: 6px var(--jd-space-2);
      text-align: center;
      font-size: 12px;
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      font-variant-numeric: tabular-nums;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-lib__total-value,
      .jd-lib__net {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* 등락색은 --jd-finance-up/down 훅을 **반드시 경유**한다(§8). 앱이 한국 관례
     (적상승·청하락)로 뒤집을 때 이 한 컴포넌트만 훅을 비껴가면 한 화면 안에서
     등락색이 갈라진다. --bm-*은 v2 앱이 이미 쓰던 우선 덮개라 앞에 남긴다. */
    jd-live-investor-flow-cards {
      display: contents;
      --jd-fin-up: var(--bm-up, var(--jd-finance-up, var(--jd-color-success)));
      --jd-fin-down: var(--bm-down, var(--jd-finance-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
    }

    jd-live-investor-flow-cards .jd-live-investor-flow-cards__card {
      box-sizing: border-box;
      /* 부모 격자의 칸이 좁아도 카드가 칸을 밀어내지 않게(§5) */
      min-width: 0;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      /* 면만 있는 카드는 색종이로 읽힌다 — 위에서 받는 빛을 함께 준다(§2) */
      box-shadow: var(--jd-shadow-xs);
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__card * {
      box-sizing: border-box;
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__card[data-dir="up"] {
      --jd-ifc-dir: var(--jd-fin-up);
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__card[data-dir="down"] {
      --jd-ifc-dir: var(--jd-fin-down);
    }

    jd-live-investor-flow-cards .jd-live-investor-flow-cards__top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    /* 투자자 구분("외국인")은 접히지 않는다 — 두 줄이 되면 카드끼리 값 위치가 어긋난다 */
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__label {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-fin-muted);
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      /* 10px은 읽기의 바닥(11px, §9) 아래였다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-none);
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      /* 틴트 위 글리프: 원색 그대로면 pale 틴트에서 대비 부족 → foreground로 65% 혼합(§ 대비) */
      color: color-mix(in srgb, var(--jd-ifc-dir, var(--jd-fin-muted)) 65%, var(--jd-fin-text));
      background: color-mix(in srgb, var(--jd-ifc-dir, var(--jd-fin-muted)) 12%, transparent);
    }

    /* 수치와 단위는 한 덩어리다 — "+1,840"과 "억"이 갈라지면 다른 수로 읽힌다(§5) */
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__value {
      margin-block-start: var(--jd-space-1-5);
      font-size: var(--jd-text-3xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--jd-ifc-dir, var(--jd-fin-text));
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__note {
      font-size: var(--jd-text-2xs);
      color: var(--jd-fin-muted);
      word-break: keep-all;
      overflow-wrap: break-word;
    }

    jd-live-investor-flow-cards .jd-live-investor-flow-cards__spark {
      display: block;
      max-width: 100%; /* 차트는 카드 폭 안에서 끝난다(§6) */
      margin-block-start: var(--jd-space-2);
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__spark-area {
      fill: var(--jd-ifc-dir, var(--jd-fin-muted));
      fill-opacity: 0.15;
      stroke: none;
    }
    jd-live-investor-flow-cards .jd-live-investor-flow-cards__spark-line {
      fill: none;
      stroke: var(--jd-ifc-dir, var(--jd-fin-muted));
      stroke-width: 1.5;
    }
  }

  @layer junds.components {
    jd-live-market-stats {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-accent: var(--bm-accent, var(--jd-color-primary));
      --jd-fin-accent-strong: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: grid;
      /* min(100%, …)이 없으면 호스트가 13rem보다 좁을 때 트랙이 호스트를 밀어낸다 */
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-4);
      box-sizing: border-box;
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-lms / inline-size;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-market-stats * {
      box-sizing: border-box;
    }
    /* 56rem이면 auto-fit이 4트랙을 깐다 — 가운데를 2칸 주면 1:2:1(v2 lg 레이아웃)이 된다.
     남는 트랙은 auto-fit이 스스로 접으므로 더 넓어져도 비율은 그대로다. */
    @container jd-lms (min-width: 56rem) {
      jd-live-market-stats .jd-live-market-stats__panel:nth-child(2) {
        grid-column: span 2;
      }
    }
    jd-live-market-stats[data-sentiment="up"] {
      --jd-lms-sent: var(--jd-fin-up);
    }
    jd-live-market-stats[data-sentiment="neutral"] {
      --jd-lms-sent: var(--jd-fin-muted);
    }
    jd-live-market-stats[data-sentiment="down"] {
      --jd-lms-sent: var(--jd-fin-down);
    }
    jd-live-market-stats[data-wavg="up"] {
      --jd-lms-wavg: var(--jd-fin-up);
    }
    jd-live-market-stats[data-wavg="down"] {
      --jd-lms-wavg: var(--jd-fin-down);
    }

    jd-live-market-stats .jd-live-market-stats__panel {
      /* 그리드 자식의 기본 min-width는 auto라 내용이 칸을 밀어낸다 — 밀린 칸이 세로 글자를 만든다 */
      min-width: 0;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }
    /* 좁아지면 제목과 배지를 **줄로 접는다** — 글자를 세로로 세우지 않는다 */
    jd-live-market-stats .jd-live-market-stats__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-2);
      min-width: 0;
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-live-market-stats .jd-live-market-stats__title {
      font-size: 13px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-text);
    }
    jd-live-market-stats .jd-live-market-stats__meta {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }
    jd-live-market-stats .jd-live-market-stats__pill {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      /* 틴트 위 라벨: 원색 그대로면 pale 틴트에서 대비 부족 → foreground로 65% 혼합(§ 대비) */
      color: color-mix(in srgb, var(--jd-lms-sent, var(--jd-fin-muted)) 65%, var(--jd-fin-text));
      background: color-mix(in srgb, var(--jd-lms-sent, var(--jd-fin-muted)) 12%, transparent);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-live-market-stats .jd-live-market-stats__nxt {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      border-radius: var(--jd-radius-sm);
      text-decoration: none;
      color: var(--jd-fin-accent-strong);
    }
    jd-live-market-stats .jd-live-market-stats__nxt:hover {
      text-decoration: underline;
    }
    /* 키보드로 온 사람에게도 여기가 어디인지 보여야 한다 */
    jd-live-market-stats .jd-live-market-stats__nxt:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    jd-live-market-stats .jd-live-market-stats__body {
      padding: var(--jd-space-3) var(--jd-space-4);
    }

    /* 분위기 */
    jd-live-market-stats .jd-live-market-stats__score-row {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
    }
    jd-live-market-stats .jd-live-market-stats__score {
      font-size: 28px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-lms-sent, var(--jd-fin-muted));
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-live-market-stats .jd-live-market-stats__out-of {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }
    jd-live-market-stats .jd-live-market-stats__gauge {
      margin-block-start: var(--jd-space-2);
      height: 8px;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
    }
    jd-live-market-stats .jd-live-market-stats__gauge-fill {
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: linear-gradient(
        90deg,
        var(--jd-fin-down) 0%,
        var(--jd-fin-accent) 50%,
        var(--jd-fin-up) 100%
      );
    }
    jd-live-market-stats .jd-live-market-stats__scale {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-1);
      margin-block-start: var(--jd-space-1-5);
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      color: var(--jd-fin-muted);
    }
    /* "약세 0" 같은 눈금은 낱말과 숫자가 한 덩어리다 — 접히면 눈금이 아니라 낙서가 된다 */
    jd-live-market-stats .jd-live-market-stats__scale > * {
      white-space: nowrap;
    }
    jd-live-market-stats .jd-live-market-stats__wavg-a {
      margin-block-start: var(--jd-space-1-5);
      font-size: var(--jd-text-2xs);
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }

    /* 폭 */
    jd-live-market-stats .jd-live-market-stats__counts {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-3);
      min-width: 0;
      font-size: 14px;
      font-weight: 800;
      margin-block-end: var(--jd-space-2);
    }
    /* "↑ 128"은 기호와 수가 한 덩어리다 */
    jd-live-market-stats .jd-live-market-stats__counts > * {
      white-space: nowrap;
    }
    jd-live-market-stats .jd-live-market-stats__count-up {
      color: var(--jd-fin-up);
    }
    jd-live-market-stats .jd-live-market-stats__count-down {
      color: var(--jd-fin-down);
    }
    jd-live-market-stats .jd-live-market-stats__count-flat {
      color: var(--jd-fin-muted);
    }
    jd-live-market-stats .jd-live-market-stats__wavg-b {
      margin-inline-start: auto;
      font-size: 13px;
      font-variant-numeric: tabular-nums;
      color: var(--jd-lms-wavg, var(--jd-fin-muted));
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    jd-live-market-stats .jd-live-market-stats__breadth {
      display: flex;
      height: 8px;
      overflow: hidden;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
    }
    jd-live-market-stats .jd-live-market-stats__breadth-up {
      background: var(--jd-fin-up);
    }
    jd-live-market-stats .jd-live-market-stats__breadth-flat {
      background: var(--jd-fin-muted);
    }
    jd-live-market-stats .jd-live-market-stats__breadth-down {
      background: var(--jd-fin-down);
    }

    /* 거래대금 */
    /* "1.84" + "조"는 한 덩어리 — 접히면 단위만 다음 줄에 남는다 */
    jd-live-market-stats .jd-live-market-stats__turnover {
      font-size: 20px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-live-market-stats .jd-live-market-stats__split {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-2);
      margin-block-start: var(--jd-space-1-5);
      font-size: var(--jd-text-2xs);
      color: var(--jd-fin-muted);
    }
    jd-live-market-stats .jd-live-market-stats__split > * {
      white-space: nowrap;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-live-market-stats .jd-live-market-stats__pill,
      jd-live-market-stats .jd-live-market-stats__score,
      jd-live-market-stats .jd-live-market-stats__wavg-b {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-live-micro-kpi-row {
      display: contents;
      --jd-fin-up: var(--jd-finance-up, var(--bm-up, var(--jd-color-success)));
      --jd-fin-down: var(--jd-finance-down, var(--bm-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-flat: var(--jd-finance-flat, var(--jd-fin-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
    }

    jd-live-micro-kpi-row .jd-live-micro-kpi-row__cell {
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__cell * {
      box-sizing: border-box;
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__cell[data-dir="up"] {
      --jd-mkr-dir: var(--jd-fin-up);
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__cell[data-dir="down"] {
      --jd-mkr-dir: var(--jd-fin-down);
    }

    jd-live-micro-kpi-row .jd-live-micro-kpi-row__inner {
      padding: var(--jd-space-2-5) var(--jd-space-3);
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__label {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
    }
    /* 값과 단위(1,840 + 억)는 한 덩어리 — 좁은 셀에서 단위만 다음 줄로 떨어지면
     숫자가 미완성으로 읽힌다(§5) */
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__value {
      font-size: 16px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--jd-fin-text);
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__unit {
      margin-inline-start: 2px;
      font-size: 10.5px;
      font-weight: 600;
    }
    jd-live-micro-kpi-row .jd-live-micro-kpi-row__sub {
      margin-block-start: 2px;
      font-size: 10px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--jd-mkr-dir, var(--jd-fin-flat));
    }
  }

  @layer junds.components {
    jd-live-order-book {
      --jd-fin-up: var(--jd-finance-up, var(--bm-up, var(--jd-color-success)));
      --jd-fin-down: var(--jd-finance-down, var(--bm-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));

      display: block;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-order-book * {
      box-sizing: border-box;
    }

    .jd-lob__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-lob__meta {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-lob__title {
      font-size: 12.5px;
      font-weight: 800;
    }
    .jd-lob__source {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-lob__source[hidden] {
      display: none;
    }

    .jd-lob__table {
      width: 100%;
      border-collapse: collapse;
      font-size: 12px;
      font-variant-numeric: tabular-nums;
    }
    .jd-lob__th {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      width: 33.333%;
    }
    .jd-lob__th--ask {
      text-align: right;
    }
    .jd-lob__th--mid {
      text-align: center;
    }
    .jd-lob__th--bid {
      text-align: left;
    }

    .jd-lob__row {
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }

    .jd-lob__qty {
      position: relative;
      padding: var(--jd-space-1) var(--jd-space-3);
      color: var(--jd-fin-muted);
      font-weight: 700;
      overflow: hidden;
    }
    .jd-lob__qty--ask {
      text-align: right;
    }
    .jd-lob__qty--bid {
      text-align: left;
    }
    .jd-lob__bar {
      position: absolute;
      top: 0;
      height: 100%;
    }
    .jd-lob__qty--ask .jd-lob__bar {
      right: 0;
      background: color-mix(in srgb, var(--jd-fin-down) 12%, transparent);
    }
    .jd-lob__qty--bid .jd-lob__bar {
      left: 0;
      background: color-mix(in srgb, var(--jd-fin-up) 12%, transparent);
    }
    .jd-lob__qty-val {
      position: relative;
    }

    .jd-lob__price {
      padding: var(--jd-space-1) var(--jd-space-2);
      text-align: center;
      font-weight: 800;
    }
    .jd-lob__price--ask {
      color: var(--jd-fin-down);
      background: color-mix(in srgb, var(--jd-fin-down) 5%, transparent);
    }
    .jd-lob__price--bid {
      color: var(--jd-fin-up);
      background: color-mix(in srgb, var(--jd-fin-up) 5%, transparent);
    }
    .jd-lob__spacer {
      padding: var(--jd-space-1) var(--jd-space-3);
    }

    .jd-lob__current {
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
    }
    .jd-lob__current td {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      text-align: center;
      font-weight: 800;
      font-size: 13px;
    }

    .jd-lob__empty {
      padding: var(--jd-space-6) var(--jd-space-4);
      text-align: center;
      font-size: 12px;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
    }

    .jd-lob__totals {
      background: var(--jd-fin-soft);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-lob__total {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-weight: 800;
    }
    .jd-lob__total--ask {
      text-align: right;
      color: var(--jd-fin-down);
    }
    .jd-lob__total--bid {
      text-align: left;
      color: var(--jd-fin-up);
    }
    .jd-lob__total-label {
      padding: var(--jd-space-1-5) var(--jd-space-2);
      text-align: center;
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
    }
  }

  @layer junds.components {
    jd-live-pct-badge {
      display: inline;
      font-size: var(--jd-text-xs); /* 12px */
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-finance-flat, var(--jd-color-muted));
    }
    jd-live-pct-badge[data-trend="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    jd-live-pct-badge[data-trend="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
    jd-live-pct-badge[data-trend="flat"] {
      color: var(--jd-finance-flat, var(--jd-color-muted));
    }
  }

  @layer junds.components {
    jd-live-pct-text {
      display: inline;
      font-variant-numeric: tabular-nums;
    }
  }

  @layer junds.components {
    jd-live-price {
      display: inline-flex;
      align-items: center;
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--jd-finance-up, var(--jd-color-success));
      font-size: var(--jd-text-md); /* md = 14px */
      line-height: var(--jd-leading-tight);
      border-radius: var(--jd-radius-sm); /* 4px */
      padding: 0;
      transition: background-color 0.35s ease, padding 0.35s ease;
    }
    jd-live-price[size="sm"] {
      font-size: var(--jd-text-xs);
    } /* 12px */
    jd-live-price[size="lg"] {
      font-size: var(--jd-text-xl);
    } /* 18px */

    jd-live-price[data-flash="up"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 16%,
        transparent
      );
      padding: 1px 4px;
    }
    jd-live-price[data-flash="down"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 16%,
        transparent
      );
      padding: 1px 4px;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-live-price {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-live-price-text {
      display: inline;
      font-variant-numeric: tabular-nums;
    }
  }

  @layer junds.components {
    jd-live-sector-strength {
      --jd-fin-up: var(--jd-finance-up, var(--bm-up, var(--jd-color-success)));
      --jd-fin-down: var(--jd-finance-down, var(--bm-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-flat: var(--jd-finance-flat, var(--jd-fin-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-sector-strength * {
      box-sizing: border-box;
    }
    jd-live-sector-strength .jd-live-sector-strength__row[data-dir="up"] {
      --jd-lss-dir: var(--jd-fin-up);
    }
    jd-live-sector-strength .jd-live-sector-strength__row[data-dir="down"] {
      --jd-lss-dir: var(--jd-fin-down);
    }

    jd-live-sector-strength .jd-live-sector-strength__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-live-sector-strength .jd-live-sector-strength__title {
      font-size: 13px;
      font-weight: 800;
      color: var(--jd-fin-text);
    }
    jd-live-sector-strength .jd-live-sector-strength__caption {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
    }

    jd-live-sector-strength .jd-live-sector-strength__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    jd-live-sector-strength .jd-live-sector-strength__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-4);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-live-sector-strength .jd-live-sector-strength__row:first-child {
      border-block-start: none;
    }

    jd-live-sector-strength .jd-live-sector-strength__rank {
      flex-shrink: 0;
      width: 16px;
      font-size: 10.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
    }
    jd-live-sector-strength .jd-live-sector-strength__name {
      flex: 1;
      min-width: 0;
      font: inherit;
      font-size: 12.5px;
      font-weight: 700;
      text-align: start;
      color: var(--jd-fin-text);
      text-decoration: none;
      background: none;
      border: 0;
      padding: 0;
      cursor: pointer;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    jd-live-sector-strength a.jd-live-sector-strength__name:hover,
    jd-live-sector-strength button.jd-live-sector-strength__name:hover {
      text-decoration: underline;
    }
    jd-live-sector-strength .jd-live-sector-strength__name:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }

    jd-live-sector-strength .jd-live-sector-strength__track {
      flex-shrink: 0;
      width: 50px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
      overflow: hidden;
    }
    /* 강도가 낮아도 막대가 사라지지 않게 하한 46% — 위쪽은 방향색 원색까지 간다 */
    jd-live-sector-strength .jd-live-sector-strength__fill {
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: color-mix(
        in srgb,
        var(--jd-lss-dir, var(--jd-fin-flat)) calc(46% + 54% * var(--jd-lss-t, 1)),
        transparent
      );
    }

    jd-live-sector-strength .jd-live-sector-strength__pct {
      min-width: 52px;
      text-align: end;
      font-size: 12px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-lss-dir, var(--jd-fin-flat));
      white-space: nowrap;
    }
  }

  @layer junds.components {
    jd-live-stacked-cell {
      display: block;
      text-align: right;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
      line-height: var(--jd-leading-tight);
      color: var(--jd-finance-flat, var(--jd-color-muted));
    }
    .jd-live-stacked-cell__price {
      font-size: 13px;
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
    }
    .jd-live-stacked-cell__pct {
      font-size: 10.5px;
      font-weight: var(--jd-weight-semibold);
      white-space: nowrap;
    }
    jd-live-stacked-cell[data-trend="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    jd-live-stacked-cell[data-trend="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
  }

  @layer junds.components {
    jd-live-status-dot {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-family: var(--jd-font-sans);
      font-size: 11px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }
    .jd-live-status-dot__dot {
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-muted);
    }

    jd-live-status-dot[live] {
      color: var(--jd-color-success);
    }
    jd-live-status-dot[live] .jd-live-status-dot__dot {
      background: var(--jd-color-success);
      animation: jd-live-status-pulse 1.6s ease-out infinite;
    }

    /* 확장-소멸 글로우 링 — v2 box-shadow 토글의 키프레임 이식 */
    @keyframes jd-live-status-pulse {
      0% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--jd-color-success) 45%, transparent);
      }
      70% {
        box-shadow: 0 0 0 5px color-mix(in srgb, var(--jd-color-success) 0%, transparent);
      }
      100% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--jd-color-success) 0%, transparent);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      jd-live-status-dot[live] .jd-live-status-dot__dot {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-live-stock-hero-chart {
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));

      position: relative;
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-lshc__badge {
      position: absolute;
      top: var(--jd-space-2);
      left: var(--jd-space-2);
      z-index: 1;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-fin-card) 80%, transparent);
      backdrop-filter: blur(4px);
    }
    .jd-lshc__source {
      font-size: 10px;
      font-weight: 800;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-lshc__source[hidden] {
      display: none;
    }

    .jd-lshc__chart {
      display: block;
    }
    /* 안쪽 캔들 SVG를 컨테이너에 맞춰 유동화(비율 유지) */
    jd-live-stock-hero-chart .jd-candle-chart__svg {
      max-width: 100%;
      height: auto;
    }
  }

  @layer junds.components {
    jd-live-stock-table {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      /* 거래대금은 등락이 아니라 제3의 계열 — 팔레트 안의 hue에서 뽑는다 */
      --jd-fin-neutral: var(--jd-color-hue-purple);
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));

      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-stock-table * {
      box-sizing: border-box;
    }

    .jd-lst__card {
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }

    .jd-lst__bar {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-lst__count {
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
    }

    .jd-lst__search,
    .jd-lst__select {
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lst__search:hover,
    .jd-lst__select:hover {
      border-color: color-mix(in srgb, var(--jd-fin-border) 70%, var(--jd-color-muted-light));
    }
    .jd-lst__search:focus-visible,
    .jd-lst__select:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-lst__search {
      flex: 1 1 200px;
      min-width: 160px;
      padding: 4px var(--jd-space-2-5);
      font: inherit;
      font-size: 11.5px;
      color: var(--jd-fin-text);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-md);
    }

    .jd-lst__toggle {
      display: inline-flex;
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-md);
    }
    .jd-lst__toggle-btn {
      padding: 2px var(--jd-space-2);
      font: inherit;
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      background: transparent;
      color: var(--jd-fin-muted);
      border: 0;
      cursor: pointer;
      /* all 금지 — 레이아웃 속성까지 대상이 되어 매 프레임 리플로우가 생긴다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 호버는 filter: brightness가 아니라 실색 전환 — brightness는 글자까지 밝힌다 */
    .jd-lst__toggle-btn:hover {
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
      color: var(--jd-fin-text);
    }
    .jd-lst__toggle-btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-lst__toggle-btn:focus-visible {
      outline: var(--jd-focus-ring);
      /* 세그먼트가 overflow:hidden 안이라 바깥 offset은 잘린다 — 안쪽으로 접는다 */
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-lst__toggle-btn[data-active] {
      background: var(--jd-fin-accent);
      /* 카드색은 다크에서 어두워져 accent 위에서 읽히지 않는다 — 흰 글자로 고정 */
      color: #fff;
    }
    .jd-lst__toggle-btn[data-active]:hover {
      background: var(--jd-color-primary-hover);
      color: #fff;
    }

    .jd-lst__select {
      padding: 4px var(--jd-space-2);
      font: inherit;
      font-size: 11px;
      color: var(--jd-fin-text);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-md);
    }

    /* 잘린 채 끝나는 것과 굴릴 수 있는 것은 다르다 — 표는 스스로 구른다 */
    .jd-lst__scroll {
      overflow-y: auto;
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
    }
    .jd-lst__table {
      width: 100%;
      /* 여섯 열이 다 읽히는 최소 폭 — 이보다 좁으면 셀을 구기지 말고 굴린다 */
      min-width: 34rem;
      border-collapse: collapse;
      font-size: 11.5px;
      font-variant-numeric: tabular-nums;
    }
    /* 헤더 셀이 접히면 "섹/터"가 된다 — 열 이름은 한 줄이다 */
    .jd-lst__th {
      position: sticky;
      top: 0;
      z-index: 1;
      padding: var(--jd-space-1-5) var(--jd-space-3);
      text-align: left;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-lst__th[data-right] {
      text-align: right;
    }

    .jd-lst__row {
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lst__row:nth-child(even) {
      background: var(--jd-fin-soft);
    }
    .jd-lst__row:hover {
      background: color-mix(in srgb, var(--jd-fin-accent) 6%, transparent);
    }
    /* 눌린 면은 빛을 잃는다. <tr>은 scale이 표 레이아웃을 깨므로 눌림을 색으로 말한다 */
    .jd-lst__row:active {
      background: color-mix(in srgb, var(--jd-fin-accent) 14%, transparent);
    }
    .jd-lst__row:focus-visible {
      outline: var(--jd-focus-ring);
      /* 스크롤 컨테이너 안이라 바깥 offset은 잘린다 — 안쪽으로 접는다 */
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }

    .jd-lst__num,
    .jd-lst__name-cell,
    .jd-lst__sector,
    .jd-lst__price,
    .jd-lst__pct,
    .jd-lst__vol {
      padding: var(--jd-space-1-5) var(--jd-space-3);
    }
    .jd-lst__num {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }

    .jd-lst__name-cell {
      display: flex;
      flex-direction: column;
      line-height: 1.25;
    }
    /* 종목명은 접히면 "SK하이/닉스"가 된다 — 한 줄로 두고, 정 모자라면 표가 구른다 */
    .jd-lst__name {
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-text);
    }
    .jd-lst__sub {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-lst__sector {
      color: var(--jd-fin-muted);
    }
    .jd-lst__tag {
      display: inline-block;
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-full);
      padding: 1px var(--jd-space-1-5);
    }

    /* 수치 열: 자릿수가 흔들리지 않게 tabular, 단위가 다음 줄로 떨어지지 않게 nowrap */
    .jd-lst__price,
    .jd-lst__pct,
    .jd-lst__vol {
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-lst__price[data-right],
    .jd-lst__pct[data-right],
    .jd-lst__vol[data-right] {
      text-align: right;
    }
    .jd-lst__price[data-trend="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lst__price[data-trend="down"] {
      color: var(--jd-fin-down);
    }
    .jd-lst__price[data-trend="flat"] {
      color: var(--jd-fin-text);
    }
    .jd-lst__pct[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lst__pct[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-lst__vol {
      color: var(--jd-fin-neutral);
      font-weight: 700;
    }

    .jd-lst__empty {
      padding: var(--jd-space-6) var(--jd-space-3);
      text-align: center;
      font-size: 12px;
      font-weight: 700;
      color: var(--jd-fin-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-lst__search,
      .jd-lst__select,
      .jd-lst__toggle-btn,
      .jd-lst__row,
      .jd-lst__price,
      .jd-lst__pct,
      .jd-lst__vol {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-live-ticker {
      --jd-fin-up: var(--jd-finance-up, var(--bm-up, var(--jd-color-success)));
      --jd-fin-down: var(--jd-finance-down, var(--bm-down, var(--jd-color-danger)));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));

      display: flex;
      align-items: stretch;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-lg);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-ticker * {
      box-sizing: border-box;
    }

    .jd-lt__badge {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-shrink: 0;
      z-index: 1;
      padding-inline: var(--jd-space-3);
      background: linear-gradient(90deg, var(--jd-fin-card) 80%, transparent);
      border-inline-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-lt__dot {
      flex-shrink: 0;
    }
    .jd-lt__caption {
      font-size: 10.5px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-lt__stage {
      position: relative;
      flex: 1 1 auto;
      min-width: 0;
      overflow: hidden;
      /* 오른쪽 24px을 투명으로 녹여 항목이 잘린 단면이 아니라 흘러 나가는 것으로 읽히게 */
      mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
    }
    .jd-lt__marquee {
      display: block;
      padding-block: var(--jd-space-2);
    }

    .jd-lt__item {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-size: 12px;
      white-space: nowrap;
    }
    .jd-lt__name {
      font-weight: 800;
      color: var(--jd-fin-text);
    }
    .jd-lt__price,
    .jd-lt__pct {
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-lt__price[data-dir="up"],
    .jd-lt__pct[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-lt__price[data-dir="down"],
    .jd-lt__pct[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    /* 거래대금도 숫자+단위 한 덩어리(1,840 + 억) — 항목 안에서 갈리면 안 된다(§5) */
    .jd-lt__vol {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
  }

  @layer junds.components {
    jd-live-top-movers {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      /* 거래대금 열은 등락이 아니라 제3의 계열 — 팔레트 안의 hue에서 뽑는다 */
      --jd-fin-neutral: var(--jd-color-hue-purple);
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));

      display: block;
      /* 열 배분의 기준은 뷰포트가 아니라 이 카드가 실제로 받은 폭이다 */
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-ltm / inline-size;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-live-top-movers * {
      box-sizing: border-box;
    }

    .jd-ltm__card {
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }

    .jd-ltm__head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-ltm__title {
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-ltm__source {
      margin-inline-start: auto;
      font-size: 11.5px;
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-ltm__source[hidden] {
      display: none;
    }

    .jd-ltm__toggle {
      display: inline-flex;
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-md);
    }
    .jd-ltm__toggle-btn {
      padding: 2px var(--jd-space-2);
      font: inherit;
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
      background: transparent;
      color: var(--jd-fin-muted);
      border: 0;
      cursor: pointer;
      /* all 금지 — 레이아웃 속성까지 대상이 되어 매 프레임 리플로우가 생긴다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 호버는 filter: brightness가 아니라 실색 전환 — brightness는 글자까지 밝힌다 */
    .jd-ltm__toggle-btn:hover {
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
      color: var(--jd-fin-text);
    }
    .jd-ltm__toggle-btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-ltm__toggle-btn:focus-visible {
      outline: var(--jd-focus-ring);
      /* 세그먼트가 overflow:hidden 안이라 바깥 offset은 잘린다 — 안쪽으로 접는다 */
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-ltm__toggle-btn[data-active] {
      background: var(--jd-fin-accent);
      /* 카드색은 다크에서 어두워져 accent 위에서 읽히지 않는다 — 흰 글자로 고정 */
      color: #fff;
    }
    .jd-ltm__toggle-btn[data-active]:hover {
      background: var(--jd-color-primary-hover);
      color: #fff;
    }

    .jd-ltm__grid {
      display: grid;
      grid-template-columns: 1fr;
    }
    /* 44rem = 한 열이 (순위 + 이름 최소 6.5rem + 값) 을 감당하는 최소 카드 폭.
     이보다 좁으면 3열로 쪼개는 순간 이름이 남지 않는다 — 세로로 쌓는다. */
    @container jd-ltm (min-width: 44rem) {
      .jd-ltm__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
    }

    .jd-ltm__col {
      --_tone: var(--jd-fin-muted);
      min-width: 0;
      border-inline-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-ltm__col[data-tone="up"] {
      --_tone: var(--jd-fin-up);
    }
    .jd-ltm__col[data-tone="down"] {
      --_tone: var(--jd-fin-down);
    }
    .jd-ltm__col[data-tone="neutral"] {
      --_tone: var(--jd-fin-neutral);
    }
    .jd-ltm__col[data-last] {
      border-inline-end: none;
    }
    @container jd-ltm (max-width: 43.999rem) {
      .jd-ltm__col {
        border-inline-end: none;
        border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
      }
      .jd-ltm__col[data-last] {
        border-block-end: none;
      }
    }

    .jd-ltm__col-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: 6px var(--jd-space-3);
      background: var(--jd-fin-soft);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-ltm__col-dot {
      width: 8px;
      height: 8px;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: var(--_tone);
    }
    .jd-ltm__col-label {
      font-size: 11.5px;
      font-weight: 800;
      white-space: nowrap;
    }

    .jd-ltm__list {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    /* 이름 트랙에 바닥을 준다 — 1fr(=minmax(auto,1fr))은 남는 폭을 값 열에 다 내주고
     "S…"처럼 한두 글자만 남긴다. 말줄임은 정보가 남을 때만 말줄임이다. */
    .jd-ltm__row {
      display: grid;
      grid-template-columns: 16px minmax(6.5rem, 1fr) auto;
      gap: var(--jd-space-2);
      align-items: center;
      padding: 6px var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-ltm__row:last-child {
      border-block-end: none;
    }
    .jd-ltm__empty {
      padding: var(--jd-space-4) var(--jd-space-3);
      font-size: 11.5px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      text-align: center;
    }

    .jd-ltm__rank {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      line-height: 1;
      font-variant-numeric: tabular-nums;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
    }
    /* 원색 배경 + 흰 글자는 성공색(#2f8f57)에서 4.1:1로 AA에 못 미친다 —
     잉크를 15% 섞어 눅여 세 톤 모두 AA를 넘긴다. */
    .jd-ltm__rank[data-first] {
      background: color-mix(in srgb, var(--_tone) 85%, var(--jd-color-foreground));
      color: #fff;
    }

    .jd-ltm__meta {
      min-width: 0;
    }
    .jd-ltm__name {
      font-size: 11.5px;
      font-weight: 800;
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-ltm__row-sub {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      min-width: 0;
      margin-block-start: 2px;
    }
    .jd-ltm__price {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }
    /* 코드는 길이가 고정이라 줄어들 이유가 없다 — 이름이 먼저 양보한다 */
    .jd-ltm__code {
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      border-radius: var(--jd-radius-full);
      padding-inline: var(--jd-space-1);
      font-variant-numeric: tabular-nums;
    }
    .jd-ltm__value {
      font-size: 12px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      /* 값이 갱신될 때마다 방향이 바뀐다 — 색이 튀지 않게 짧게 건너간다 */
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-ltm__value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-ltm__value[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-ltm__value[data-dir="neutral"] {
      color: var(--jd-fin-neutral);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-ltm__toggle-btn,
      .jd-ltm__value {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-loading-button {
      display: inline-flex;
    }
    jd-loading-button[full-width] {
      display: flex;
    }
    jd-loading-button[full-width] > .jd-button {
      width: 100%;
    }

    /* loading ≠ disabled (DEC-039). 베이스의 이 예외는 jd-button[loading] 이라는
     **태그** 셀렉터라 파생 태그를 놓친다 — 그래서 이 컴포넌트는 정작 자기 존재
     이유인 로딩 상태에서 opacity .4 로 흐려져 '비활성'과 구분되지 않았다(실측).
     로딩은 **작동 중**이라는 신호다 — 색을 유지하고 커서만 진행형으로 바꾼다. */
    jd-loading-button[loading] > .jd-button:disabled {
      opacity: 1;
      cursor: progress;
      /* :disabled의 pointer-events:none을 되돌려야 progress 커서가 실제로 보인다.
       클릭은 네이티브 disabled가 이미 막고 있으므로 안전하다. */
      pointer-events: auto;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }

    /* size — button.css.ts와 동일(md는 .jd-button base) */
    jd-loading-button[size="xs"] > .jd-button {
      height: 1.75rem;
      padding-inline: var(--jd-space-2-5);
      gap: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
    }
    jd-loading-button[size="sm"] > .jd-button {
      height: 2rem;
      padding-inline: var(--jd-space-3-5);
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
    }
    jd-loading-button[size="lg"] > .jd-button {
      height: 2.75rem;
      padding-inline: var(--jd-space-6);
      gap: var(--jd-space-2-5);
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-xl);
    }

    /* variant — v2 LoadingButton은 primary/secondary/ghost/danger 4종이지만,
     상속된 프로퍼티 표면이 거짓말하지 않도록 jd-button의 6종을 전부 건다. */
    jd-loading-button[variant="secondary"] > .jd-button {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: var(--jd-shadow-xs);
      filter: none;
    }
    jd-loading-button[variant="secondary"] > .jd-button:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    }
    jd-loading-button[variant="secondary"] > .jd-button:active {
      background: var(--jd-color-border-light);
      box-shadow: none;
      scale: 0.98;
    }

    jd-loading-button[variant="danger"] > .jd-button {
      background: var(--jd-color-danger);
      color: #fff;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15);
    }
    jd-loading-button[variant="danger"] > .jd-button:hover {
      box-shadow: 0 4px 12px color-mix(in srgb, var(--jd-color-danger) 25%, transparent),
        0 1px 2px rgba(0, 0, 0, 0.1);
      filter: brightness(1.1);
    }
    jd-loading-button[variant="danger"] > .jd-button:active {
      filter: brightness(0.95);
      scale: 0.98;
    }
    jd-loading-button[variant="danger"] > .jd-button:focus-visible {
      outline-color: color-mix(in srgb, var(--jd-color-danger) 40%, transparent);
    }

    jd-loading-button[variant="ghost"] > .jd-button {
      background: transparent;
      color: var(--jd-color-foreground);
      box-shadow: none;
      filter: none;
    }
    jd-loading-button[variant="ghost"] > .jd-button:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    jd-loading-button[variant="ghost"] > .jd-button:active {
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      scale: 0.98;
    }

    jd-loading-button[variant="outline"] > .jd-button {
      background: transparent;
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      box-shadow: none;
      filter: none;
    }
    jd-loading-button[variant="outline"] > .jd-button:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 6%, transparent);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    jd-loading-button[variant="outline"] > .jd-button:active {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      scale: 0.98;
    }

    jd-loading-button[variant="link"] > .jd-button {
      background: transparent;
      box-shadow: none;
      filter: none;
      height: auto;
      padding: 0;
      color: var(--jd-color-primary-ink);
      text-underline-offset: 2px;
      text-decoration-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    jd-loading-button[variant="link"] > .jd-button:hover {
      text-decoration-line: underline;
      text-decoration-color: var(--jd-color-primary-ink);
    }
    jd-loading-button[variant="link"] > .jd-button:active {
      scale: none;
    }

    /* 스피너 크기 분기(md·lg는 .jd-button__spinner base가 16px) */
    jd-loading-button[size="xs"] .jd-button__spinner {
      width: 12px;
      height: 12px;
    }
    jd-loading-button[size="sm"] .jd-button__spinner {
      width: 14px;
      height: 14px;
    }

    /* 라벨 교체 — 보이는 칸이 곧 접근 이름이다(display:none은 a11y 트리에서도 제외).
     data-swap = loadingText가 있을 때만 켜진다(없으면 v2처럼 children 유지). */
    jd-loading-button > .jd-button > .jd-loading-button__busy {
      display: none;
    }
    jd-loading-button[loading][data-swap] > .jd-button > .jd-loading-button__label {
      display: none;
    }
    jd-loading-button[loading][data-swap] > .jd-button > .jd-loading-button__busy {
      display: inline;
    }
  }

  @layer junds.components {
    jd-loading-overlay {
      position: relative;
      display: block;
    }
    /* 감쌀 본문이 없으면 호스트가 0×0 이 되고, inset:0 인 덮개도 0 폭이 되어
     라벨이 한 글자씩 세로로 선다(실측: "시세를 불러오는 중…"이 세로 한 줄).
     덮개만 단독으로 쓰는 자리(문서·미리보기·빈 목록 위)를 위해 활성일 때만
     바닥을 깐다 — 감쌀 본문이 있으면 본문이 이 값을 넘으므로 무해하다. */
    jd-loading-overlay[active] {
      min-width: 12rem;
      min-height: 6rem;
    }

    /* 본문 래퍼는 박스를 만들지 않는다 — children의 레이아웃이 v2(래퍼 직속)와 동일 */
    .jd-loading-overlay__content {
      display: contents;
    }

    .jd-loading-overlay__veil {
      position: absolute;
      inset: 0;
      z-index: var(--jd-z-overlay);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      /* 덮개는 본문 크기를 그대로 받으므로 좁은 본문 위에서는 라벨이 벽에 붙는다 —
       패딩이 없으면 남는 폭이 0에 수렴해 글자가 세로로 선다 */
      padding: var(--jd-space-4);
      box-sizing: border-box;
      text-align: center;
      background: color-mix(in srgb, var(--jd-color-card) 70%, transparent);
    }
    jd-loading-overlay:not([active]) > .jd-loading-overlay__veil {
      display: none;
    }
    /* 덮개가 툭 나타나면 '무엇이 바뀌었나'를 눈이 놓친다 — 짧은 페이드로 알린다 */
    @media (prefers-reduced-motion: no-preference) {
      jd-loading-overlay[active] > .jd-loading-overlay__veil {
        animation: jd-loading-overlay-in var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-loading-overlay-in {
      from {
        opacity: 0;
      }
    }
    jd-loading-overlay[blur] > .jd-loading-overlay__veil {
      backdrop-filter: blur(4px);
    }

    .jd-loading-overlay__spinner {
      width: 1.5rem;
      height: 1.5rem;
      flex-shrink: 0;
      color: var(--jd-color-primary-ink);
      animation: jd-spin 1s linear infinite;
    }

    /* "시세를 불러오는 중…"이 한 글자씩 세로로 서던 자리 — 기본 CJK 줄바꿈은 글자
     단위라 폭이 모자라면 세로 한 줄이 된다. 어절은 지키고 줄 수로 버틴다(§9). */
    .jd-loading-overlay__label {
      margin: 0;
      max-width: 100%;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-muted);
      word-break: keep-all;
      overflow-wrap: break-word;
      text-wrap: balance;
    }
    .jd-loading-overlay__label[hidden] {
      display: none;
    }

    /* jd-button/jd-spinner와 같은 이름·같은 본문 — 단독 로드에서도 자족한다 */
    @keyframes jd-spin {
      to {
        transform: rotate(360deg);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-loading-overlay__spinner {
        animation-duration: 1.6s;
      }
      .jd-loading-overlay__veil {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-loading-screen {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-4);
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      /* 기본은 풀스크린 — v2 fullscreen=true 승계 */
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      min-height: 100vh;
      background: color-mix(in srgb, var(--jd-color-background) 80%, transparent);
      backdrop-filter: blur(4px);
    }
    /* v2 fullscreen=false — 기본이 true인 프롭은 부정형으로 뒤집는다(jd-number-input 선례) */
    jd-loading-screen[contained] {
      position: static;
      inset: auto;
      z-index: auto;
      min-height: 200px;
      width: 100%;
    }
    jd-loading-screen[transparent] {
      background: none;
      backdrop-filter: none;
    }

    .jd-loading-screen__visual {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .jd-loading-screen__art {
      display: flex;
      align-items: flex-end;
      justify-content: center;
    }
    .jd-loading-screen__art[hidden] {
      display: none;
    }
    /* 로고는 소비자 노드다 — 변형이 바뀌어도 파괴하지 않고 감추기만 한다 */
    jd-loading-screen:not([variant="logo"]) .jd-loading-screen__visual > [slot="logo"] {
      display: none;
    }

    /* spinner — jd-spinner·jd-button과 같은 SVG(치수만 40px) */
    .jd-loading-screen__spinner {
      width: 40px;
      height: 40px;
      color: var(--jd-color-primary-ink);
      animation: jd-spin 1s linear infinite;
    }

    /* bars */
    .jd-loading-screen__bars {
      display: flex;
      align-items: flex-end;
      gap: var(--jd-space-1);
      height: 2.5rem;
    }
    .jd-loading-screen__bar {
      width: 0.375rem;
      height: 100%;
      background: var(--jd-color-primary);
      border-radius: var(--jd-radius-full);
      animation: jd-loading-screen-bars 1s ease-in-out infinite;
      animation-delay: calc(var(--jd-bar-index, 0) * 0.1s);
    }

    /* pulse */
    .jd-loading-screen__pulse {
      position: relative;
      width: 3rem;
      height: 3rem;
    }
    .jd-loading-screen__ping {
      position: absolute;
      inset: 0;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
      animation: jd-loading-screen-ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
    }
    .jd-loading-screen__core {
      position: absolute;
      inset: var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
    }

    .jd-loading-screen__message {
      margin: 0;
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
      text-align: center;
    }
    .jd-loading-screen__message[hidden] {
      display: none;
    }

    .jd-loading-screen__progress {
      width: 12rem;
      height: 0.25rem;
      overflow: hidden;
      background: var(--jd-color-border-light);
      border-radius: var(--jd-radius-full);
    }
    .jd-loading-screen__progress[hidden] {
      display: none;
    }
    .jd-loading-screen__fill {
      height: 100%;
      background: var(--jd-color-primary);
      transition: width var(--jd-duration-slow) var(--jd-easing-default);
    }

    @keyframes jd-spin {
      to {
        transform: rotate(360deg);
      }
    }
    @keyframes jd-loading-screen-bars {
      0%,
      100% {
        transform: scaleY(0.4);
      }
      50% {
        transform: scaleY(1);
      }
    }
    @keyframes jd-loading-screen-ping {
      75%,
      100% {
        transform: scale(2);
        opacity: 0;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-loading-screen__spinner {
        animation-duration: 1.6s;
      }
      .jd-loading-screen__bar,
      .jd-loading-screen__ping {
        animation: none;
      }
      .jd-loading-screen__fill {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-login-form {
      display: block;
    }

    .jd-login-form {
      width: 100%;
      max-width: 24rem;
      margin-inline: auto;
    }

    /* ── 헤더 ── */
    .jd-login-form__header {
      text-align: center;
      margin-block-end: var(--jd-space-6);
    }
    .jd-login-form__logo {
      display: flex;
      justify-content: center;
      margin-block-end: var(--jd-space-3);
    }
    .jd-login-form__logo[hidden] {
      display: none;
    }
    .jd-login-form__title {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
    }
    .jd-login-form__subtitle {
      margin: var(--jd-space-1) 0 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-login-form__subtitle[hidden] {
      display: none;
    }

    .jd-login-form__alert {
      display: block;
      margin-block-end: var(--jd-space-4);
    }
    .jd-login-form__alert[hidden] {
      display: none;
    }

    /* ── 폼 ── */
    .jd-login-form__form {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
    .jd-login-form__field {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-login-form__field[hidden] {
      display: none;
    }

    .jd-login-form__label {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-login-form__label[data-required]::after {
      content: "*";
      margin-inline-start: var(--jd-space-0-5);
      color: var(--jd-color-danger);
    }
    .jd-login-form__label-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .jd-login-form__forgot {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-primary-ink);
      text-decoration: none;
    }
    .jd-login-form__forgot[hidden] {
      display: none;
    }
    .jd-login-form__forgot:hover {
      text-decoration: underline;
    }

    /* 이메일 입력 — jd-text-field[md] 계승 */
    .jd-login-form__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
      height: 2.5rem;
      padding-inline: var(--jd-space-3-5);
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-xl);
    }
    .jd-login-form__input::placeholder {
      color: var(--jd-color-neutral-400);
    }
    .jd-login-form__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-xs);
    }
    .jd-login-form__input[data-error] {
      border-color: var(--jd-color-danger);
    }
    .jd-login-form__input[data-error]:focus {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger), var(--jd-shadow-xs);
    }

    .jd-login-form__mismatch {
      margin: 0;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-danger);
    }
    .jd-login-form__mismatch[hidden] {
      display: none;
    }

    .jd-login-form__remember-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    /* ── 소셜 ── */
    .jd-login-form__social {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    .jd-login-form__social[hidden] {
      display: none;
    }
    .jd-login-form__social-list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    /* ── 회원가입 링크 ── */
    .jd-login-form__signup {
      margin: 0;
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-login-form__signup[hidden] {
      display: none;
    }
    .jd-login-form__signup-link {
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
      text-decoration: none;
    }
    .jd-login-form__signup-link:hover {
      text-decoration: underline;
    }

    /* ── 보안 안내 ── */
    .jd-login-form__notice {
      margin-block-start: var(--jd-space-6);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      font-size: 0.625rem;
      color: var(--jd-color-muted);
    }
    .jd-login-form__notice > svg {
      flex-shrink: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-login-form__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-logo {
      display: inline-flex;
      align-items: center;
      --jd-logo-text: var(--bm-text, var(--jd-color-foreground));
      --jd-logo-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-logo-brand: var(--bm-brand, #f5b800);
      font-family: var(--jd-font-sans);
    }

    .jd-logo__link {
      display: inline-flex;
      align-items: center;
      color: inherit;
      text-decoration: none;
    }

    .jd-logo__brand {
      display: inline-flex;
      align-items: baseline;
      font-weight: 800;
      letter-spacing: -0.02em;
      color: var(--jd-logo-text);
    }
    .jd-logo__dot {
      display: inline-block;
      flex-shrink: 0;
      margin-inline-start: 2px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-logo-brand);
    }
    .jd-logo__subtitle {
      margin-inline-start: var(--jd-space-2);
      font-size: 11px;
      font-weight: var(--jd-weight-bold);
      letter-spacing: 0.05em;
      color: var(--jd-logo-muted);
    }
    .jd-logo__subtitle[hidden] {
      display: none;
    }

    /* 크기 3종 — v2 SIZE 맵의 상수 이식 */
    jd-logo[size="sm"] .jd-logo__brand {
      font-size: 18px;
    }
    jd-logo[size="sm"] .jd-logo__link {
      gap: 6px;
    }
    jd-logo[size="sm"] .jd-logo__dot {
      width: 4px;
      height: 4px;
    }

    jd-logo[size="md"] .jd-logo__brand,
    jd-logo:not([size]) .jd-logo__brand {
      font-size: 20px;
    }
    jd-logo[size="md"] .jd-logo__link,
    jd-logo:not([size]) .jd-logo__link {
      gap: 8px;
    }
    jd-logo[size="md"] .jd-logo__dot,
    jd-logo:not([size]) .jd-logo__dot {
      width: 4px;
      height: 4px;
    }

    jd-logo[size="lg"] .jd-logo__brand {
      font-size: 24px;
    }
    jd-logo[size="lg"] .jd-logo__link {
      gap: 10px;
    }
    jd-logo[size="lg"] .jd-logo__dot {
      width: 5px;
      height: 5px;
    }
  }

  @layer junds.base {
    jd-logo-cloud:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-logo-cloud {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      padding: var(--jd-space-10) var(--jd-space-4);
    }
    @media (min-width: 640px) {
      jd-logo-cloud {
        padding-inline: var(--jd-space-6);
      }
    }

    .jd-logo-cloud__title {
      text-align: center;
      margin-bottom: var(--jd-space-6);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }

    /* ── grid (기본 배치) ──
     기본값 layout="grid"는 attribute로 반영되지 않는다(§1.3 reflect는 set 시점) —
     [layout="grid"] 셀렉터에 배치를 걸어 두면 **아무것도 지정하지 않은 기본 사용에서
     규칙이 통째로 빠져** 로고가 한 열로 세로로 쌓인다(실측). 기본은 base가 담당하고
     호스트 속성 셀렉터는 비기본값(marquee·columns)만 덮는다 — jd-button과 같은 규약.

     격자에서 흐름으로 바꾼 이유: auto-fit 격자는 "요청 열 수로 나눈 폭"을 트랙 하한으로
     삼는데, 로고 한 칸은 그 하한보다 훨씬 좁다(이름 몇 글자 + 여백). 그래서 좁은
     칼럼에서 트랙이 두 개밖에 안 서고 나머지가 세로로 쌓였다(실측 — 로고 구름의 형태가
     아니다). wrap + 가운데 정렬이면 칸은 제 내용 폭만 쓰고 줄이 찰 때만 다음 줄로
     넘어간다 — 좁아져도 가로로 흐른다. columns는 한 칸이 가질 수 있는 **폭 상한**으로
     남아 넓은 곳에서 v2와 같은 열 수를 만든다. */
    .jd-logo-cloud__viewport {
      --jd-lc-gap: var(--jd-space-6);
      --jd-lc-cols: 5;
      max-width: 64rem; /* max-w-5xl */
      margin-inline: auto;
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-lc-gap);
      align-items: center;
      justify-content: center;
    }
    jd-logo-cloud[columns="3"] .jd-logo-cloud__viewport {
      --jd-lc-cols: 3;
    }
    jd-logo-cloud[columns="4"] .jd-logo-cloud__viewport {
      --jd-lc-cols: 4;
    }
    jd-logo-cloud[columns="6"] .jd-logo-cloud__viewport {
      --jd-lc-cols: 6;
    }

    /* ── marquee ── */
    jd-logo-cloud[layout="marquee"] .jd-logo-cloud__viewport {
      display: block; /* 격자를 되돌린다 — 흐르는 것은 트랙 하나뿐이다 */
      position: relative;
      overflow: hidden;
      max-width: 80rem; /* max-w-7xl */
      margin-inline: auto;
      /* 가장자리에서 흐려져야 "더 있다"가 읽힌다(§6) */
      mask-image: linear-gradient(
        90deg,
        transparent 0,
        #000 var(--jd-space-10),
        #000 calc(100% - var(--jd-space-10)),
        transparent 100%
      );
    }
    .jd-logo-cloud__track {
      display: flex;
      gap: var(--jd-space-10);
      white-space: nowrap;
      width: max-content;
      animation: jd-logo-cloud-marquee 30s linear infinite;
    }
    @keyframes jd-logo-cloud-marquee {
      from {
        transform: translateX(0);
      }
      to {
        transform: translateX(-50%);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-logo-cloud__track {
        animation: none;
      }
    }

    /* 흐름 배치에서 칸은 제 내용 폭을 쓴다(basis auto). 상한만 columns에서 뽑아
     한 칸이 요청 열 수의 몫보다 넓어지지 않게 한다 — 로고 하나가 줄을 독식하지 않는다.
     href가 없는 항목은 링크 껍질 없이 item이 바로 칸이라 둘 다 건다. marquee의
     칸은 트랙 안(자손)이라 이 규칙에 걸리지 않는다 — 트랙은 흐르지 접히지 않는다. */
    .jd-logo-cloud__viewport > .jd-logo-cloud__link,
    .jd-logo-cloud__viewport > .jd-logo-cloud__item {
      flex: 0 1 auto;
      max-width: min(100%, (100% - (var(--jd-lc-cols) - 1) * var(--jd-lc-gap)) / var(--jd-lc-cols));
    }

    /* ── 셀 ── */
    .jd-logo-cloud__link {
      display: block;
      max-width: 100%;
      min-width: 0;
      text-decoration: none;
      border-radius: var(--jd-radius-md);
    }
    /* 링은 단일 레시피로 — 두께·색·간격이 컴포넌트마다 갈라지지 않게(DEC-039) */
    .jd-logo-cloud__link:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-logo-cloud__item {
      display: flex;
      align-items: center;
      justify-content: center;
      min-width: 0;
      max-width: 100%;
      height: 3rem; /* h-12 */
      padding-inline: var(--jd-space-4);
    }
    .jd-logo-cloud__img {
      height: 2rem; /* h-8 */
      width: auto;
      max-width: 100%; /* 가로로 긴 로고가 칸을 밀고 나가지 않게(§6) */
      object-fit: contain;
    }
    /* 회사 이름은 접히지 않는다 — 두 줄이 되면 로고 줄의 기준선이 어긋난다 */
    .jd-logo-cloud__label {
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
    }

    /* 회색조 — 기본 ON, 호버 시 원색 복원 */
    jd-logo-cloud[data-grayscale] .jd-logo-cloud__item {
      filter: grayscale(1);
      opacity: var(--jd-opacity-60);
      transition: filter var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-logo-cloud[data-grayscale] .jd-logo-cloud__item:hover {
      filter: grayscale(0);
      opacity: 1;
    }
    @media (prefers-reduced-motion: reduce) {
      jd-logo-cloud[data-grayscale] .jd-logo-cloud__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-mark {
      display: inline;
      --_jd-mark-hue: var(--jd-color-hue-amber); /* yellow 기본 */
    }
    jd-mark[color="blue"] {
      --_jd-mark-hue: var(--jd-color-hue-blue);
    }
    jd-mark[color="green"] {
      --_jd-mark-hue: var(--jd-color-hue-green);
    }
    jd-mark[color="pink"] {
      --_jd-mark-hue: var(--jd-color-hue-pink);
    }
    jd-mark[color="purple"] {
      --_jd-mark-hue: var(--jd-color-hue-purple);
    }
    jd-mark[color="orange"] {
      --_jd-mark-hue: var(--jd-color-hue-orange);
    }

    .jd-mark {
      --jd-tone: var(--_jd-mark-hue);
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      padding-inline: var(--jd-space-0-5);
      border-radius: var(--jd-radius-sm);
      /* 형광펜은 옅게 칠한 면 — bg-strong-mix가 v2 200/70·500/30 두 값을 한 공식으로 덮는다 */
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-strong-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }
    /* 밑줄형은 글자색을 물려받으므로 선 자체가 색을 말한다 — 면(face)에서 뽑아
     라이트에서는 짙게, 다크에서는 들어 올려진 값으로 자동 대응한다. */
    jd-mark[underline] .jd-mark {
      padding-inline: 0;
      background: transparent;
      color: inherit;
      text-decoration: underline;
      text-decoration-thickness: var(--jd-border-medium);
      text-underline-offset: 2px;
      text-decoration-color: color-mix(in srgb, var(--jd-tone-face) 76%, transparent);
    }
  }

  @layer junds.components {
    jd-markdown-viewer {
      display: block;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
    }

    .jd-markdown-viewer__h1,
    .jd-markdown-viewer__h2,
    .jd-markdown-viewer__h3 {
      color: var(--jd-color-foreground);
    }
    .jd-markdown-viewer__h1 {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      margin-block: var(--jd-space-6) var(--jd-space-3);
    }
    .jd-markdown-viewer__h2 {
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-snug);
      margin-block: var(--jd-space-5) var(--jd-space-2);
    }
    .jd-markdown-viewer__h3 {
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      margin-block: var(--jd-space-4) var(--jd-space-2);
    }
    /* 첫 블록의 위쪽 여백은 접는다 — 뷰어가 카드 안에 들어가는 것이 기본 사용처다 */
    .jd-markdown-viewer__body > :first-child {
      margin-block-start: 0;
    }
    .jd-markdown-viewer__body > :last-child {
      margin-block-end: 0;
    }

    .jd-markdown-viewer__p {
      margin-block: var(--jd-space-2);
    }

    .jd-markdown-viewer__list {
      margin-block: var(--jd-space-2);
      padding-inline-start: var(--jd-space-6);
    }
    .jd-markdown-viewer__item {
      margin-block: var(--jd-space-1);
    }

    .jd-markdown-viewer__code {
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-sm);
      background: var(--jd-color-card-hover);
      color: var(--jd-color-primary-ink);
      font-family: var(--jd-font-mono);
      font-size: var(--jd-text-xs);
    }

    .jd-markdown-viewer__link {
      color: var(--jd-color-primary-ink);
      text-decoration: underline;
    }
    .jd-markdown-viewer__link:focus-visible {
      outline: none;
      border-radius: var(--jd-radius-sm);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-markdown-viewer__quote {
      margin-block: var(--jd-space-2);
      margin-inline: 0;
      padding-inline-start: var(--jd-space-4);
      border-inline-start: var(--jd-border-heavy) solid
        color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
      color: var(--jd-color-muted);
      font-style: italic;
    }
    .jd-markdown-viewer__quote .jd-markdown-viewer__p {
      margin-block: var(--jd-space-1);
    }

    .jd-markdown-viewer__rule {
      margin-block: var(--jd-space-4);
      border: 0;
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
  }

  @layer junds.components {
    :where(jd-market-alert-banner) {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-warning: var(--jd-color-warning);
      /* 배경 틴트도 같은 훅에서 뽑는다 — 글자만 따라 바뀌면 알약이 두 색으로 갈린다 */
      --jd-fin-up-soft: color-mix(in srgb, var(--jd-fin-up) 14%, transparent);
      --jd-fin-down-soft: color-mix(in srgb, var(--jd-fin-down) 14%, transparent);
    }
    jd-market-alert-banner {
      display: block;
      font-family: var(--jd-font-sans);
    }
    jd-market-alert-banner:not(:defined) {
      display: block;
    }

    .jd-mab {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2-5);
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: inherit;
      text-decoration: none;
      overflow: hidden;
      /* 시간·감속도 토큰으로 말한다 — 리터럴 0.2s/ease는 밀도·모션 설정을 따라가지 못하고
       이 배너만 다른 속도로 움직인다. 대상은 속성별로 지목한다(DEC-039). */
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-mab:hover {
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-md);
    }
    /* 눌린 면은 빛을 잃는다 — 배너 전체가 링크라 누름이 면 단위로 보여야 한다 */
    .jd-mab:active {
      scale: 0.99;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-mab:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-mab__icon {
      display: grid;
      place-items: center;
      flex-shrink: 0;
      width: 28px;
      height: 28px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-warning);
      color: #fff;
    }

    .jd-mab__body {
      flex: 1;
      min-width: 0;
    }
    .jd-mab__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-wrap: wrap;
    }
    .jd-mab__time {
      font-size: 11.5px;
      font-weight: 800;
      padding: 1px 6px;
      border-radius: var(--jd-radius-sm);
      font-variant-numeric: tabular-nums;
      background: color-mix(in srgb, var(--jd-fin-warning) 12%, transparent);
      color: color-mix(in srgb, var(--jd-fin-warning) 55%, var(--jd-color-foreground));
    }
    .jd-mab__label {
      font-size: 11.5px;
      font-weight: 800;
      color: color-mix(in srgb, var(--jd-fin-warning) 55%, var(--jd-color-foreground));
    }

    .jd-mab__headline {
      margin: 2px 0 0;
      font-size: 12.5px;
      font-weight: 700;
      line-height: 1.35;
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-mab__symbol {
      font-weight: 800;
    }
    .jd-mab__dot {
      margin: 0 4px;
      color: var(--jd-color-muted);
    }

    .jd-mab__pct {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-size: 12.5px;
      font-weight: 800;
      padding: var(--jd-space-1) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-variant-numeric: tabular-nums;
    }
    /* 14% 틴트 위 원색 글자는 12.5px 굵기에서 AA에 못 미친다 — hue는 유지하고 글자만
     foreground 쪽으로 섞어 대비를 올린다(jd-theme-card hot pill·jd-fx-board 선례). */
    .jd-mab__pct[data-dir="up"] {
      background: var(--jd-fin-up-soft);
      color: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
    }
    .jd-mab__pct[data-dir="down"] {
      background: var(--jd-fin-down-soft);
      color: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-mab {
        transition: none;
      }
    }
  }

  @layer junds.components {
    :where(jd-market-header-badge) {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-accent: var(--jd-color-primary);
      --jd-fin-accent-strong: var(--jd-color-primary);
    }
    jd-market-header-badge {
      display: inline-block;
      font-family: var(--jd-font-sans);
    }
    jd-market-header-badge:not(:defined) {
      display: inline-block;
    }

    /* 헤더 배지는 한 줄짜리 알약이다 — 좁은 헤더에서 "코스피 2,480 +12(+0.5%)"가 접히면
     지수명과 숫자가 따로 놀아 읽히지 않는다. 줄바꿈을 막고 폭은 내용이 정한다. */
    .jd-mhb {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border-radius: var(--jd-radius-xl);
      font-size: 12.5px;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      background: var(--jd-color-card);
    }
    .jd-mhb[data-state="ready"] {
      background: color-mix(in srgb, var(--jd-fin-accent) 10%, transparent);
    }
    .jd-mhb[data-state="loading"],
    .jd-mhb[data-state="empty"] {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }

    .jd-mhb__msg {
      font-weight: 800;
      color: var(--jd-color-muted);
    }
    .jd-mhb__ready {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-mhb__name {
      font-weight: 800;
      color: var(--jd-fin-accent-strong);
    }
    .jd-mhb__value {
      font-weight: 800;
      color: var(--jd-color-foreground);
    }

    .jd-mhb__tag {
      padding: 1px 6px;
      border-radius: var(--jd-radius-sm);
      font-size: 11px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    /* 12% 틴트 위 원색 글자는 11px에서 AA에 못 미친다 — hue는 유지하고 글자만 foreground
     쪽으로 섞어 대비를 올린다(jd-fx-board·jd-theme-card 선례). */
    .jd-mhb__tag[data-dir="up"] {
      background: color-mix(in srgb, var(--jd-fin-up) 12%, transparent);
      color: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
    }
    .jd-mhb__tag[data-dir="down"] {
      background: color-mix(in srgb, var(--jd-fin-down) 12%, transparent);
      color: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
    }

    .jd-mhb__status {
      font-size: 10px;
      font-weight: 700;
      color: var(--jd-color-muted);
    }
    .jd-mhb__status[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-market-heatmap {
      display: block;
      font-family: var(--jd-font-sans);
    }
    jd-market-heatmap:not(:defined) {
      display: block;
    }

    .jd-mh__svg {
      display: block;
      max-width: 100%;
      height: auto;
      font-variant-numeric: tabular-nums;
    }
    .jd-mh__bg {
      fill: var(--jd-color-card);
    }

    .jd-mh__cell {
      cursor: pointer;
    }
    .jd-mh__cell-rect {
      fill: var(
        --jd-mh-fill,
        color-mix(in srgb, var(--jd-color-muted) 30%, var(--jd-color-surface))
      );
      stroke: color-mix(in srgb, var(--jd-color-card) 85%, transparent);
      stroke-width: 1;
      /* all 금지 — x/y/width/height까지 대상이 되어 리사이즈마다 칸이 흘러간다 */
      transition: stroke var(--jd-duration-snap) var(--jd-easing-ease-out),
        stroke-width var(--jd-duration-snap) var(--jd-easing-ease-out),
        fill-opacity var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 칸 색은 데이터라 hover에서 색을 바꿀 수 없다(등락률을 거짓말하게 된다) —
     대신 칸 경계를 카드색에서 잉크로 올려 "지금 이 칸"을 테두리로 말한다.
     filter: brightness는 쓰지 않는다 — 흰 라벨까지 밝혀 칸 안에서 글자가 녹는다. */
    .jd-mh__cell:hover .jd-mh__cell-rect {
      stroke: var(--jd-color-foreground);
      stroke-width: 2;
    }
    /* 눌린 면은 빛을 잃는다 — 칸 자체가 면이므로 채도를 낮춰 눌림을 만든다 */
    .jd-mh__cell:active .jd-mh__cell-rect {
      fill-opacity: 0.78;
    }
    .jd-mh__cell-text {
      fill: #fff;
      pointer-events: none;
      filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55));
    }
    .jd-mh__cell-price {
      fill: rgba(255, 255, 255, 0.78);
      filter: none;
    }

    .jd-mh__group-bg {
      fill: color-mix(in srgb, var(--jd-color-card) 96%, transparent);
    }
    .jd-mh__group-divider {
      fill: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
    }
    .jd-mh__group-label {
      fill: var(--jd-color-foreground);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-wide);
      pointer-events: none;
    }

    .jd-mh__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-mh__cell-rect {
        transition: none;
      }
    }
  }

  @layer junds.components {
    :where(jd-market-index-chart) {
      --jd-fin-accent: var(--jd-color-primary);
      --jd-fin-accent-strong: var(--jd-color-primary);
    }
    jd-market-index-chart {
      display: block;
      font-family: var(--jd-font-sans);
    }
    jd-market-index-chart:not(:defined) {
      display: block;
    }

    .jd-mic {
      padding: var(--jd-space-3);
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
    }

    .jd-mic__toolbar {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-end: var(--jd-space-1);
      flex-wrap: wrap;
      font-size: 11px;
    }
    .jd-mic__tabs {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }
    .jd-mic__pill {
      cursor: pointer;
      border: 0;
      font-family: inherit;
      padding: 3px var(--jd-space-2-5);
      border-radius: var(--jd-radius-full);
      font-size: 11px;
      font-weight: 500;
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
      color: var(--jd-color-muted);
    }
    .jd-mic__pill[data-active] {
      background: color-mix(in srgb, var(--jd-fin-accent) 14%, transparent);
      color: var(--jd-fin-accent-strong);
      font-weight: 700;
    }
    .jd-mic__pill:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-mic__legend {
      margin: 0 0 0 auto;
      padding: 0;
      list-style: none;
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: 11px;
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-mic__legend-item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-mic__swatch {
      width: 12px;
      height: 12px;
      border-radius: var(--jd-radius-sm);
    }

    .jd-mic__chart {
      display: block;
      width: 100%;
    }
  }

  @layer junds.components {
    jd-marquee {
      display: block;
      overflow: hidden;
    }

    .jd-marquee__track {
      display: flex;
      width: max-content;
      gap: var(--jd-marquee-gap, 48px);
      will-change: transform;
      animation: jd-marquee-scroll var(--jd-marquee-duration, 30s) linear infinite;
    }

    .jd-marquee__group {
      display: flex;
      flex-shrink: 0;
      align-items: center;
      gap: var(--jd-marquee-gap, 48px);
    }

    jd-marquee[direction="right"] > .jd-marquee__track {
      animation-direction: reverse;
    }

    /* v2는 마우스 호버만 알았다 — 키보드 포커스가 안으로 들어와도 멈춘다 */
    jd-marquee:not([no-pause]):hover > .jd-marquee__track,
    jd-marquee:not([no-pause]):focus-within > .jd-marquee__track,
    jd-marquee[paused] > .jd-marquee__track {
      animation-play-state: paused;
    }

    @keyframes jd-marquee-scroll {
      from {
        transform: translateX(0);
      }
      to {
        transform: translateX(
          calc((-100% - var(--jd-marquee-gap, 48px)) / var(--jd-marquee-copies, 2))
        );
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-marquee__track {
        animation: none;
        will-change: auto;
      }
    }
  }

  @layer junds.base {
    jd-masonry-grid:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    /* 기본 = columns 3 · base 1컬럼 */
    jd-masonry-grid {
      display: block;
      column-count: 1;
      column-gap: var(--jd-masonry-gap, var(--jd-space-4));
    }
    jd-masonry-grid > * {
      break-inside: avoid;
      margin-block-end: var(--jd-masonry-gap, var(--jd-space-4));
    }

    /* sm(640)+ : 2·3·4 전부 최소 2컬럼 (bare가 모두 커버) */
    @media (min-width: 640px) {
      jd-masonry-grid {
        column-count: 2;
      }
    }
    /* lg(1024)+ : 기본(3)·3·4는 3컬럼 · 2는 2 유지 */
    @media (min-width: 1024px) {
      jd-masonry-grid:not([columns="2"]) {
        column-count: 3;
      }
    }
    /* xl(1280)+ : 4만 4컬럼 */
    @media (min-width: 1280px) {
      jd-masonry-grid[columns="4"] {
        column-count: 4;
      }
    }
  }

  @layer junds.components {
    jd-mention {
      position: relative;
      display: block;
      font-family: var(--jd-font-sans);
    }

    /* ── 입력 ───────────────────────────────────────────────── */
    .jd-mention__input {
      display: block;
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      min-height: 80px;
      resize: vertical;
      font-family: inherit;
      color: var(--jd-color-foreground);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-mention__input::placeholder {
      color: var(--jd-color-neutral-400);
    }
    /* outline:none은 UA 기본 박스를 지우려는 것이고, 대체 표시(테두리 primary +
     글로우)를 같은 규칙 안에서 함께 준다(§1). :focus-visible이 아니라 :focus인
     이유는 타이핑하는 면이라 포인터로 들어와도 "여기 입력 중"이 보여야 하기 때문 —
     jd-textarea와 같은 어휘다. */
    .jd-mention__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-focus-ring), var(--jd-shadow-xs);
    }
    .jd-mention__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
      background: var(--jd-color-card-hover);
    }

    /* ── 팝업 ───────────────────────────────────────────────── */
    .jd-mention__popup {
      position: absolute;
      top: 100%;
      inset-inline-start: 0;
      min-width: 16rem;
      max-width: 100%;
      margin-block-start: var(--jd-space-1);
      z-index: var(--jd-z-dropdown);
      box-sizing: border-box;
      max-height: 12rem;
      overflow: auto;
      padding-block: var(--jd-space-1);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
      transform-origin: top center;
      animation: jd-mention-pop var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-mention__popup[hidden] {
      display: none;
    }
    @keyframes jd-mention-pop {
      from {
        opacity: 0;
        transform: scale(0.97);
      }
    }

    .jd-mention__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    .jd-mention__option {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      text-align: start;
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-mention__option:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
    }
    /* 키보드 포커스는 textarea에 남고 이 행은 aria-activedescendant로만 지시된다 —
     이 표시가 §1의 :focus-visible을 대신한다. hover 틴트(10%)와 primary-light는
     세기가 비슷해 커서가 지워지므로 포커스 링을 함께 그린다. 팝업이 overflow:auto라
     바깥 아웃라인은 잘린다 — 안쪽으로 눕힌다. */
    .jd-mention__option[data-active] {
      background: var(--jd-color-primary-light);
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    /* 눌린 행은 빛을 잃는다 — 포인터로 고르는 순간의 유일한 응답이다.
     활성 행과 특정도가 같아 순서로 이긴다: 위 규칙보다 뒤에 있어야 한다. */
    .jd-mention__option:active {
      background: color-mix(in srgb, var(--jd-color-primary) 20%, transparent);
    }

    .jd-mention__media {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      box-sizing: border-box;
      width: 1.5rem;
      height: 1.5rem;
      border-radius: var(--jd-radius-full);
      overflow: hidden;
    }
    .jd-mention__media[data-initial] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: var(--jd-color-primary-ink);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      user-select: none;
    }
    .jd-mention__avatar {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .jd-mention__body {
      display: flex;
      flex-direction: column;
      flex: 1;
      min-width: 0;
    }
    .jd-mention__label {
      font-weight: var(--jd-weight-medium);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-mention__desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-weight: var(--jd-weight-normal);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-mention__desc[hidden] {
      display: none;
    }

    /* 결과 수 공지 — 읽히기만 한다 (jd-trust-indicator __sr 관용구) */
    .jd-mention__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-mention__input,
      .jd-mention__option {
        transition: none;
      }
      .jd-mention__popup {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-mention-chip {
      display: inline;
    }

    .jd-mention-chip {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
      text-decoration: none;
      border-radius: var(--jd-radius-sm);
    }
    .jd-mention-chip:hover {
      text-decoration: underline;
    }
    .jd-mention-chip:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-mention-chip__verified {
      font-size: 11px;
    }
    .jd-mention-chip__verified[hidden] {
      display: none;
    }
  }

  @layer junds.base {
    jd-menubar:not(:defined) {
      display: flex;
    }
    jd-menubar:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-menubar {
      display: flex;
      align-items: center;
      padding: var(--jd-space-0-5) var(--jd-space-1);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      font-family: var(--jd-font-sans);
      user-select: none;
    }

    .jd-menubar__group {
      position: relative;
    }

    .jd-menubar__button {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border: 0;
      background: none;
      cursor: pointer;
      font-family: inherit;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
      /* 메뉴 라벨은 두 줄로 접히면 바 높이가 흔들린다(§5) */
      white-space: nowrap;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-menubar__button:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    .jd-menubar__button:active {
      scale: 0.97;
      color: var(--jd-color-foreground);
      background: var(--jd-color-border-light);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 바가 얕아 바깥 아웃라인이 이웃 버튼과 겹친다 — 링을 그림자로 준다(§1) */
    .jd-menubar__button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-menubar__group[data-open] > .jd-menubar__button {
      color: var(--jd-color-foreground);
      background: var(--jd-color-border-light);
    }

    .jd-menubar__menu {
      position: absolute;
      top: 100%;
      left: 0;
      z-index: var(--jd-z-popover);
      min-width: 12.5rem;
      margin-block-start: var(--jd-space-1);
      padding: var(--jd-space-1) 0;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      /* 떠 있는 면의 테두리는 눅인다 — 그림자가 이미 경계를 말하므로 실선이 세면 두 번 말한다(§2) */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
    }
    .jd-menubar__menu[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: no-preference) {
      .jd-menubar__group[data-open] > .jd-menubar__menu {
        animation: jd-menubar-in var(--jd-duration-fast) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-menubar-in {
      from {
        opacity: 0;
        scale: 0.98;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-menubar__button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-metric-card {
      padding: var(--jd-space-5);
    }

    /* 라벨 → 값 간격은 v2 mt-1 */
    jd-metric-card .jd-stat__text {
      gap: var(--jd-space-1);
    }
    jd-metric-card .jd-stat__main > [slot="icon"] {
      color: var(--jd-color-muted);
    }

    /* 변화량은 값 옆이 아니라 아래 줄이다 — 투명 래퍼를 실제 상자로 승격하고
     flex-basis 100%로 줄을 통째로 넘긴다(값·단위는 윗줄에 남는다). */
    jd-metric-card .jd-stat__delta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-basis: 100%;
      margin-block-start: var(--jd-space-1);
    }
    /* 칩 배경은 StatCard 고유 표현 — 여기서는 되돌린다 */
    jd-metric-card .jd-stat__change {
      padding: 0;
      background: none;
      border-radius: 0;
      margin-block-end: 0;
      font-weight: var(--jd-weight-semibold);
    }
    jd-metric-card .jd-stat__hint {
      margin-block-start: 0;
    }

    .jd-metric-card__spark {
      display: block;
      width: 100%;
      height: 48px;
      margin-block-start: var(--jd-space-3);
      color: var(--jd-color-primary-ink); /* stroke·gradient가 currentColor로 따라온다 */
      overflow: visible;
    }
  }

  @layer junds.components {
    jd-mini-candle {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --_up: var(--jd-fin-up);
      --_down: var(--jd-fin-down);
      display: inline-block;
      line-height: 0;
    }

    .jd-mini-candle__svg {
      display: block;
      overflow: visible;
    }

    .jd-mini-candle__candle[data-dir="up"] {
      --_c: var(--_up);
    }
    .jd-mini-candle__candle[data-dir="down"] {
      --_c: var(--_down);
    }
    jd-mini-candle[tone="up"] .jd-mini-candle__candle {
      --_c: var(--_up);
    }
    jd-mini-candle[tone="down"] .jd-mini-candle__candle {
      --_c: var(--_down);
    }

    .jd-mini-candle__wick {
      stroke: var(--_c);
      stroke-width: 1;
    }
    .jd-mini-candle__body {
      fill: var(--_c);
      stroke: none;
    }
  }

  @layer junds.base {
    jd-mini-chart:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-mini-chart {
      display: inline-block;
      line-height: 0; /* svg 아래 baseline 여백 제거 */
      color: var(--jd-mini-chart-color, var(--jd-color-primary));
    }

    .jd-mini-chart__svg {
      display: block;
      overflow: visible;
    }

    .jd-mini-chart__area {
      fill: currentColor;
      opacity: var(--jd-opacity-10);
    }
    .jd-mini-chart__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 1.5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .jd-mini-chart__head {
      fill: currentColor;
    }
    .jd-mini-chart__bar {
      fill: currentColor;
      opacity: var(--jd-opacity-80);
    }
  }

  @layer junds.components {
    jd-modal {
      display: none;
    }
    jd-modal[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-4);
    }

    .jd-modal__backdrop {
      position: absolute;
      inset: 0;
      background: color-mix(in srgb, #090811 46%, transparent);
      backdrop-filter: blur(3px) saturate(0.9);
    }

    .jd-modal__panel {
      position: relative;
      width: 100%;
      display: flex;
      flex-direction: column;
      max-height: 90vh;
      overflow: auto;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      border-radius: var(--jd-radius-2xl);
      box-shadow: 0 32px 80px rgba(0, 0, 0, 0.22), 0 12px 28px rgba(0, 0, 0, 0.1),
        inset 0 1px 0 var(--jd-color-highlight);
      /* size 기본 md(32rem) — 디폴트는 attribute 미반영(§1.3)이라 base가 담당 */
      max-width: min(32rem, calc(100vw - 2rem));
    }

    .jd-modal__header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-4);
      padding: var(--jd-space-5);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-modal__title {
      min-width: 0;
      margin: 0;
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      letter-spacing: -0.012em;
    }
    .jd-modal__close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex: none;
      width: 2rem;
      height: 2rem;
      padding: 0;
      margin: -0.25rem -0.25rem -0.25rem 0;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: transparent;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-modal__close:hover {
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-modal__close:active {
      scale: 0.94;
    }
    .jd-modal__close:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-modal__body {
      min-height: 0;
      padding: var(--jd-space-5);
      overflow: auto;
      line-height: var(--jd-leading-relaxed);
    }
    .jd-modal__footer {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      padding: var(--jd-space-4) var(--jd-space-5);
      border-top: var(--jd-border-thin) solid var(--jd-color-border-light);
      background: color-mix(in srgb, var(--jd-color-card-hover) 50%, transparent);
    }

    /* size — v2: sm 28rem / lg 42rem / xl 56rem / full 뷰포트 (md는 base) */
    jd-modal[size="sm"] > .jd-modal__panel {
      max-width: min(28rem, calc(100vw - 2rem));
    }
    jd-modal[size="lg"] > .jd-modal__panel {
      max-width: min(42rem, calc(100vw - 2rem));
    }
    jd-modal[size="xl"] > .jd-modal__panel {
      max-width: min(56rem, calc(100vw - 2rem));
    }
    jd-modal[size="full"] > .jd-modal__panel {
      max-width: calc(100vw - 2rem);
      max-height: calc(100vh - 2rem);
    }

    @media (max-width: 36rem) {
      jd-modal[open] {
        align-items: flex-end;
        padding: var(--jd-space-2);
      }
      .jd-modal__panel {
        max-width: none;
        max-height: calc(100dvh - var(--jd-space-4));
        border-radius: var(--jd-radius-2xl);
      }
      .jd-modal__header,
      .jd-modal__body {
        padding: var(--jd-space-4);
      }
      .jd-modal__footer {
        padding: var(--jd-space-3) var(--jd-space-4);
      }
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-modal[open] > .jd-modal__backdrop {
        animation: jd-modal-fade var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-modal[open] > .jd-modal__panel {
        animation: jd-modal-pop var(--jd-duration-normal) var(--jd-easing-default);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-modal__close {
        transition: none;
      }
    }
    @keyframes jd-modal-fade {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-modal-pop {
      from {
        opacity: 0;
        transform: scale(0.96);
      }
    }
  }

  @layer junds.components {
    
  [data-jd-grid-picker] {
    display: inline-block; box-sizing: border-box;
    padding: var(--jd-space-3);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg);
    user-select: none;
  }

  .jd-grid-picker__header {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: var(--jd-space-3);
  }
  .jd-grid-picker__label {
    font-size: var(--jd-text-md); font-weight: var(--jd-weight-semibold);
  }
  .jd-grid-picker__nav {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; padding: 0;
    color: inherit; background: none; border: 0;
    border-radius: var(--jd-radius-md); cursor: pointer;
    transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-grid-picker__nav:hover:not(:disabled) { background: var(--jd-color-card-hover); }
  .jd-grid-picker__nav:focus-visible { outline: none; box-shadow: var(--jd-shadow-focus-ring); }
  .jd-grid-picker__nav:disabled { opacity: var(--jd-opacity-40); cursor: not-allowed; }

  .jd-grid-picker__grid {
    display: grid; gap: var(--jd-space-1); width: 12.5rem;
  }
  .jd-grid-picker__cell {
    padding: var(--jd-space-2); margin: 0;
    font-family: inherit; font-size: var(--jd-text-md);
    color: var(--jd-color-foreground); background: none; border: 0;
    border-radius: var(--jd-radius-md); cursor: pointer;
    transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-grid-picker__cell:hover:not(:disabled) { background: var(--jd-color-card-hover); }
  .jd-grid-picker__cell:focus-visible { outline: none; box-shadow: var(--jd-shadow-focus-ring); }
  .jd-grid-picker__cell[aria-pressed="true"] {
    color: #fff; background: var(--jd-color-primary);
  }
  .jd-grid-picker__cell[aria-pressed="true"]:hover:not(:disabled) {
    background: var(--jd-color-primary-hover);
  }
  .jd-grid-picker__cell:disabled {
    opacity: var(--jd-opacity-30); cursor: not-allowed; background: none;
  }

  @media (prefers-reduced-motion: reduce) {
    .jd-grid-picker__nav, .jd-grid-picker__cell { transition: none; }
  }

  }

  @layer junds.components {
    jd-motion {
      display: block;
      animation: jd-m-fade 300ms var(--jd-easing-ease-out) both; /* preset 기본 fade */
    }
    jd-motion[preset="fade-up"] {
      animation: jd-m-fade-up 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="fade-down"] {
      animation: jd-m-fade-down 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="scale"] {
      animation: jd-m-scale 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="slide-up"] {
      animation: jd-m-slide-up 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="slide-down"] {
      animation: jd-m-slide-down 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="slide-left"] {
      animation: jd-m-slide-left 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    jd-motion[preset="slide-right"] {
      animation: jd-m-slide-right 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
    }

    @keyframes jd-m-fade {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
    @keyframes jd-m-fade-up {
      from {
        opacity: 0;
        transform: translateY(12px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-fade-down {
      from {
        opacity: 0;
        transform: translateY(-12px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-scale {
      from {
        opacity: 0;
        transform: scale(0.96);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-slide-up {
      from {
        opacity: 0;
        transform: translateY(24px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-slide-down {
      from {
        opacity: 0;
        transform: translateY(-24px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-slide-left {
      from {
        opacity: 0;
        transform: translateX(24px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
    @keyframes jd-m-slide-right {
      from {
        opacity: 0;
        transform: translateX(-24px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    /* 감속 선호 — 내용은 즉시 보이고 움직임만 사라진다. force-motion이 옵트아웃 */
    @media (prefers-reduced-motion: reduce) {
      jd-motion:not([force-motion]) {
        animation: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-multi-line-chart:not(:defined) {
      display: inline-block;
    }
    /* width/height 속성(기본 380×220)은 **의도한 비율**이지 최소 폭이 아니다.
     CHART_CSS의 inline-flex를 그대로 두면 좁은 칸에서 SVG가 자기 속성 폭을 우겨
     컨테이너 오른쪽으로 넘친다 — 넘치지 말고 접히고 줄어들어야 한다. */
    jd-multi-line-chart {
      max-width: 100%;
      flex-wrap: wrap;
    }
    jd-multi-line-chart .jd-chart__svg {
      /* viewBox가 비율을 지키므로 폭만 내주면 높이는 따라온다 */
      flex: 1 1 16rem;
      min-width: 0;
      max-width: 100%;
      height: auto;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
    }
    jd-multi-line-chart .jd-chart__legend:not([hidden]) {
      min-width: 0;
    }

    /* 0% 기준선 */
    .jd-mlc__zero {
      stroke: var(--jd-fin-muted, var(--jd-color-muted));
      stroke-dasharray: 3 3;
      stroke-opacity: 0.6;
    }

    /* 시리즈 끝점 헤드 */
    .jd-mlc__head {
      fill: var(--jd-series-color);
      stroke: var(--jd-color-card, #fff);
      stroke-width: 1.5;
    }

    /* hover */
    .jd-mlc__crosshair {
      stroke: var(--jd-color-muted);
      stroke-dasharray: 3 3;
      stroke-opacity: 0.5;
    }
    .jd-mlc__hoverdot {
      fill: var(--jd-series-color);
      stroke: var(--jd-color-card, #fff);
      stroke-width: 1.5;
    }

    /* 툴팁 — 색은 candle-chart와 공유하는 --jd-fin-tooltip-* 토큰 경유로, 소비자가 두
     차트의 툴팁을 한 번에 리브랜딩할 수 있게 한다.
     폴백은 surface 짝인 on-surface 계열이다: surface-overlay는 라이트에서도 어두운
     면이라, neutral-* 를 얹으면 다크 모드에서 어두운 글자가 어두운 툴팁에 묻힌다
     (실측: 다크에서 neutral-400 대 surface-overlay ≈ 1.9:1). 테두리도 잉크에서 뽑는다. */
    .jd-mlc__tip-bg {
      fill: var(--jd-fin-tooltip-bg, var(--jd-color-surface-overlay));
      stroke: var(
        --jd-fin-tooltip-border,
        color-mix(in srgb, var(--jd-color-on-surface) 20%, transparent)
      );
      stroke-width: 1;
    }
    /* 툴팁 안 글자는 11px 아래로 내려가지 않는다 — 위계는 크기가 아니라 굵기·색이
     맡는다(줄 높이 14px라 11px도 그대로 들어간다) */
    .jd-mlc__tip-label {
      fill: var(--jd-fin-tooltip-muted, var(--jd-color-on-surface-muted));
      font-size: 11px;
      font-weight: 700;
    }
    .jd-mlc__tip-dot {
      fill: var(--jd-series-color);
    }
    .jd-mlc__tip-name {
      fill: var(--jd-fin-tooltip-muted, var(--jd-color-on-surface-muted));
      font-size: 11px;
      font-weight: 600;
    }
    .jd-mlc__tip-val {
      fill: var(--jd-fin-tooltip-fg, var(--jd-color-on-surface));
      font-size: 11px;
      font-weight: 800;
      text-anchor: end;
    }
  }

  @layer junds.components {
    /* 호스트 셀렉터는 태그 단위라 jd-select 규칙이 파생에 닿지 않는다 —
     상속 대상 중 **호스트 스코프 규칙만** 다시 선언한다(drawer→modal 선례).
     .jd-select__* 클래스 규칙은 태그와 무관하게 그대로 적용된다. */
    jd-multi-select {
      position: relative;
      display: flex;
      flex-direction: column;
      width: 100%; /* v2 MultiSelect는 항상 w-full */
    }
    jd-multi-select[open] > .jd-select__trigger {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-multi-select[error] > .jd-select__trigger {
      border-color: var(--jd-color-danger);
    }
    jd-multi-select[error] > .jd-select__trigger:focus-visible,
    jd-multi-select[error][open] > .jd-select__trigger {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-multi-select[open] .jd-select__chevron {
      transform: rotate(180deg);
    }

    /* 칩이 줄바꿈하므로 고정 높이를 최소 높이로 바꾼다 */
    jd-multi-select > .jd-select__trigger {
      height: auto;
      min-height: 2.25rem;
      padding: var(--jd-space-1) var(--jd-space-2);
      align-items: center;
    }
    jd-multi-select[size="sm"] > .jd-select__trigger {
      height: auto;
      min-height: 2rem;
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-md);
    }
    jd-multi-select[size="lg"] > .jd-select__trigger {
      height: auto;
      min-height: 2.75rem;
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-xl);
    }

    jd-multi-select .jd-select__value {
      flex-wrap: wrap;
      gap: var(--jd-space-1);
      padding-inline-start: var(--jd-space-1);
    }
    jd-multi-select .jd-select__value[data-placeholder] {
      padding-inline-start: var(--jd-space-1);
    }

    .jd-multi-select__chip {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      max-width: 12rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }
    .jd-multi-select__chip[data-overflow] {
      background: color-mix(in srgb, var(--jd-color-muted) 14%, transparent);
      color: var(--jd-color-muted);
    }

    /* 선택 행 — v2는 bg-primary-light/50 (Select의 통짜 primary와 다르다) */
    jd-multi-select .jd-select__option[aria-selected="true"] {
      background: color-mix(in srgb, var(--jd-color-primary-light) 50%, transparent);
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-normal);
    }
    jd-multi-select .jd-select__option[aria-selected="true"][data-active],
    jd-multi-select .jd-select__option[aria-selected="true"]:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 12%, transparent);
      color: var(--jd-color-primary-ink);
    }

    /* 네이티브 checkbox 대신 표시 전용 상자 — 리스트박스 안 포커스 가능 요소를 만들지 않는다 */
    .jd-multi-select__box {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      box-sizing: border-box;
      width: 0.875rem;
      height: 0.875rem;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-sm);
      background: var(--jd-color-card);
      color: transparent;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-multi-select__box > svg {
      width: 0.75rem;
      height: 0.75rem;
    }
    .jd-select__option[aria-selected="true"] > .jd-multi-select__box {
      background: var(--jd-color-primary);
      border-color: var(--jd-color-primary);
      color: #fff;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-multi-select__box {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-my-position-panel {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면 한국 관례
       override가 이 컴포넌트만 비껴가 한 화면에서 등락색이 갈라진다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-up-soft: color-mix(in srgb, var(--jd-fin-up) 14%, transparent);
      --jd-fin-down-soft: color-mix(in srgb, var(--jd-fin-down) 14%, transparent);
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      /* 열 배분의 기준은 뷰포트가 아니라 이 패널이 실제로 받은 폭이다 */
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-mpp / inline-size;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-my-position-panel * {
      box-sizing: border-box;
    }
    .jd-my-position-panel__icon {
      flex-shrink: 0;
    }

    /* ── 포지션 카드 ── */
    .jd-my-position-panel__holding {
      display: block;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-my-position-panel__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-1) var(--jd-space-2);
      min-width: 0;
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-my-position-panel__titlewrap {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      color: var(--jd-fin-accent);
    }
    .jd-my-position-panel__heading {
      margin: 0;
      font-size: 14px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-text);
    }
    .jd-my-position-panel__tag {
      display: inline-flex;
      align-items: center;
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: 11px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-my-position-panel__tag[data-dir="up"] {
      background: var(--jd-fin-up-soft);
      color: var(--jd-fin-up);
    }
    .jd-my-position-panel__tag[data-dir="down"] {
      background: var(--jd-fin-down-soft);
      color: var(--jd-fin-down);
    }

    .jd-my-position-panel__grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--jd-space-3);
      padding: var(--jd-space-4);
    }
    /* 30rem = 네 칸 모두 "평균 단가 / 68,400원"을 한 줄로 담는 최소 패널 폭 */
    @container jd-mpp (min-width: 30rem) {
      .jd-my-position-panel__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }
    .jd-my-position-panel__cell {
      min-width: 0;
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-fin-soft);
    }
    /* 라벨은 두 줄로 접히면 안 된다 — "보유/수량"은 라벨이 아니라 파편이다 */
    .jd-my-position-panel__cell-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }
    /* 값 + 단위는 한 덩어리 — "42"와 "주"가 갈라지면 수가 아니라 낱말이 된다 */
    .jd-my-position-panel__cell-value {
      margin-block-start: 2px;
      font-size: 15px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-my-position-panel__cell-value[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    .jd-my-position-panel__cell-value[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    .jd-my-position-panel__cell-unit {
      margin-inline-start: 2px;
      font-size: var(--jd-text-2xs);
      font-weight: 600;
      opacity: 0.7;
    }

    .jd-my-position-panel__footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-fin-soft);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-my-position-panel__foot-right {
      text-align: end;
    }
    .jd-my-position-panel__foot-label {
      font-size: var(--jd-text-2xs);
      font-weight: 700;
      white-space: nowrap;
      color: var(--jd-fin-muted);
    }
    .jd-my-position-panel__profit-value {
      font-size: 20px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-my-position-panel__profit-value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-my-position-panel__profit-value[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-my-position-panel__cost-value {
      font-size: 16px;
      font-weight: 800;
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }

    /* ── 빈 상태 ── */
    .jd-my-position-panel__empty {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) dashed var(--jd-fin-border);
      color: var(--jd-fin-muted);
    }
    .jd-my-position-panel__empty-text {
      flex: 1;
      min-width: 0;
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
    }
    .jd-my-position-panel__empty-title {
      font-size: 12.5px;
      font-weight: 700;
      color: var(--jd-fin-text);
    }
    .jd-my-position-panel__empty-sub {
      font-size: 11.5px;
      color: var(--jd-fin-muted);
    }
    .jd-my-position-panel__register {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      height: 28px;
      padding: 0 var(--jd-space-2-5);
      border: none;
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      font-family: inherit;
      font-size: 12px;
      font-weight: 800;
      white-space: nowrap;
      background: var(--jd-fin-accent);
      /* 카드색은 다크에서 어두워져 accent 위에서 읽히지 않는다 — 흰 글자로 고정 */
      color: #fff;
      /* 채움만 있는 면은 색종이로 읽힌다 — 위에서 받는 빛을 얹는다 */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      /* all 금지 — 레이아웃 속성까지 대상이 되어 매 프레임 리플로우가 생긴다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* brightness는 글자·아이콘까지 밝혀 흰 글자가 배경에 녹는다 — 실색 전환으로 바꾼다 */
    .jd-my-position-panel__register:hover {
      background: var(--jd-color-primary-hover);
      box-shadow: 0 4px 12px var(--jd-color-primary-glow), var(--jd-shadow-xs),
        inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-my-position-panel__register:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-my-position-panel__register:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-my-position-panel__all {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-size: 12px;
      font-weight: 700;
      white-space: nowrap;
      border-radius: var(--jd-radius-sm);
      text-decoration: none;
      color: var(--jd-fin-accent);
    }
    .jd-my-position-panel__all:hover {
      text-decoration: underline;
    }
    .jd-my-position-panel__all:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-my-position-panel__tag,
      .jd-my-position-panel__cell-value,
      .jd-my-position-panel__profit-value,
      .jd-my-position-panel__register {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-nav-sidebar:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-nav-sidebar {
      display: flex;
      flex-direction: column;
      box-sizing: border-box; /* 명시 width + border-inline-end 병용 — 폭에 테두리 포함 */
      width: var(--jd-nav-sidebar-width, 248px);
      height: 100dvh;
      position: sticky;
      top: 0;
      background: var(--jd-color-card);
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      font-family: var(--jd-font-sans);
    }

    .jd-nav-sidebar__header {
      padding: var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-nav-sidebar__header[hidden] {
      display: none;
    }

    .jd-nav-sidebar__nav {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      padding-block: var(--jd-space-4);
    }
    .jd-nav-sidebar__top[hidden] {
      display: none;
    }

    .jd-nav-sidebar__section {
      padding: 0 var(--jd-space-3) var(--jd-space-4);
    }
    .jd-nav-sidebar__section-title {
      font-size: 0.65625rem; /* v2 10.5px */
      font-weight: 800;
      letter-spacing: 0.08em;
      padding: 0 var(--jd-space-3);
      margin-block-end: var(--jd-space-1-5);
      color: var(--jd-color-muted);
    }
    .jd-nav-sidebar__section-title[hidden] {
      display: none;
    }

    .jd-nav-sidebar__list {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
    }

    .jd-nav-sidebar__link {
      position: relative;
      display: flex;
      align-items: center;
      gap: var(--jd-space-2-5);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      font-size: 0.84375rem; /* v2 13.5px */
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      text-decoration: none;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-nav-sidebar__link:hover:not([data-active]) {
      background: var(--jd-color-border-light);
    }
    .jd-nav-sidebar__link:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-nav-sidebar__link[data-active] {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }

    .jd-nav-sidebar__rail {
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
      width: 2px;
      height: 16px;
      border-radius: 2px;
      background: var(--jd-color-primary);
      opacity: 0;
    }
    .jd-nav-sidebar__link[data-active] .jd-nav-sidebar__rail {
      opacity: 1;
    }

    .jd-nav-sidebar__icon {
      display: grid;
      place-items: center;
      width: 1.25rem;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }
    .jd-nav-sidebar__link[data-active] .jd-nav-sidebar__icon {
      color: var(--jd-color-primary-ink);
    }

    .jd-nav-sidebar__label {
      flex: 1;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-nav-sidebar__footer {
      padding: var(--jd-space-3) var(--jd-space-5);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      font-size: 0.6875rem; /* 11px */
      color: var(--jd-color-muted);
      display: flex;
      align-items: center;
      justify-content: flex-end;
    }
    .jd-nav-sidebar__footer[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-nav-sidebar__link {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-navigation-menu {
      display: inline-flex;
      position: relative;
      padding: var(--jd-space-1) var(--jd-space-2);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }

    .jd-navigation-menu__list {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-navigation-menu__item {
      position: relative;
      display: flex;
    }

    .jd-navigation-menu__link,
    .jd-navigation-menu__trigger {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-2) var(--jd-space-3);
      margin: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      border-radius: var(--jd-radius-lg);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      color: var(--jd-color-muted);
      text-decoration: none;
      white-space: nowrap;
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-navigation-menu__link:hover,
    .jd-navigation-menu__trigger:hover {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-foreground);
    }
    .jd-navigation-menu__link:focus-visible,
    .jd-navigation-menu__trigger:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-navigation-menu__item[data-open] > .jd-navigation-menu__trigger {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
      color: var(--jd-color-foreground);
    }

    .jd-navigation-menu__chevron {
      inline-size: 0.875rem;
      block-size: 0.875rem;
      flex-shrink: 0;
      transition: rotate var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-navigation-menu__item[data-open] .jd-navigation-menu__chevron {
      rotate: 180deg;
    }

    .jd-navigation-menu__panel {
      position: absolute;
      inset-block-start: 100%;
      inset-inline-start: 0;
      margin-block-start: var(--jd-space-1);
      min-inline-size: 17.5rem;
      z-index: var(--jd-z-dropdown);
      display: flex;
      flex-direction: column;
      padding: var(--jd-space-2);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-lg);
    }
    .jd-navigation-menu__panel[hidden] {
      display: none;
    }

    .jd-navigation-menu__child {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      text-decoration: none;
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-navigation-menu__child:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-navigation-menu__child:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-navigation-menu__child-icon {
      display: inline-flex;
      flex-shrink: 0;
      margin-block-start: var(--jd-space-0-5);
      color: var(--jd-color-muted);
    }
    .jd-navigation-menu__child-icon[hidden] {
      display: none;
    }
    .jd-navigation-menu__child-icon > svg {
      inline-size: 1rem;
      block-size: 1rem;
    }

    .jd-navigation-menu__child-body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      flex: 1 1 auto;
      min-inline-size: 0;
    }
    .jd-navigation-menu__child-label {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-navigation-menu__child-description {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-snug);
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
    .jd-navigation-menu__child-description[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-navigation-menu__link,
      .jd-navigation-menu__trigger,
      .jd-navigation-menu__child,
      .jd-navigation-menu__chevron {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-news-list {
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-sm);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-news-list * {
      box-sizing: border-box;
    }

    /* 스켈레톤 */
    .jd-news-list__skeleton {
      padding: var(--jd-space-3);
    }
    .jd-news-list__skeleton-row {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-news-list__skeleton-row + .jd-news-list__skeleton-row {
      margin-block-start: var(--jd-space-2);
    }
    .jd-news-list__bar {
      height: 12px;
      border-radius: var(--jd-radius-sm);
      background: linear-gradient(
        90deg,
        var(--jd-fin-soft) 25%,
        color-mix(in srgb, var(--jd-fin-muted) 14%, transparent) 37%,
        var(--jd-fin-soft) 63%
      );
      background-size: 400% 100%;
      animation: jd-news-shimmer 1.4s ease infinite;
    }
    @keyframes jd-news-shimmer {
      0% {
        background-position: 100% 0;
      }
      100% {
        background-position: 0 0;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-news-list__bar {
        animation: none;
      }
    }

    /* 에러/빈 결과 */
    .jd-news-list__message {
      padding: var(--jd-space-3);
      font-size: var(--jd-text-sm);
      color: var(--jd-fin-muted);
    }

    /* origin 배지 */
    .jd-news-list__badgewrap {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3) var(--jd-space-1);
    }
    .jd-news-list__badge {
      display: inline-flex;
      align-items: center;
      padding: 2px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: 11px;
      font-weight: 700;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
    }
    .jd-news-list__badge[data-origin="naver"] {
      background: #03c75a;
      color: #fff;
    }
    .jd-news-list__query {
      font-size: 11px;
      color: var(--jd-fin-muted);
    }

    /* 목록 */
    .jd-news-list__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-news-list__item + .jd-news-list__item {
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-news-list__link {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      text-decoration: none;
      color: inherit;
    }
    .jd-news-list__link:active {
      background: var(--jd-fin-soft);
    }
    .jd-news-list__text {
      flex: 1;
      min-width: 0;
      display: flex;
      flex-direction: column;
    }
    .jd-news-list__title {
      font-size: 13.5px;
      font-weight: 700;
      line-height: var(--jd-leading-snug);
      color: var(--jd-fin-text);
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .jd-news-list__desc {
      margin-block-start: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      color: var(--jd-fin-muted);
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .jd-news-list__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      margin-block-start: var(--jd-space-1-5);
      font-size: 11px;
      color: var(--jd-fin-muted);
    }
    .jd-news-list__source {
      font-weight: 600;
    }
    .jd-news-list__chevron {
      flex-shrink: 0;
      margin-block-start: 2px;
      color: var(--jd-fin-muted);
    }
  }

  @layer junds.base {
    jd-newsletter:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-newsletter {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-newsletter[variant="card"] {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-6);
    }

    .jd-newsletter__header {
      margin-bottom: var(--jd-space-4);
    }
    .jd-newsletter__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
    }
    .jd-newsletter__desc {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-newsletter__form {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    jd-newsletter[variant="inline"] .jd-newsletter__form {
      gap: var(--jd-space-2);
    }
    @media (min-width: 640px) {
      jd-newsletter[variant="inline"] .jd-newsletter__form {
        flex-direction: row;
        align-items: center;
      }
    }

    .jd-newsletter__field {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    @media (min-width: 640px) {
      jd-newsletter[variant="inline"] .jd-newsletter__field {
        flex-direction: row;
        flex: 1;
      }
    }

    .jd-newsletter__input {
      flex: 1;
      min-width: 0;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border-radius: var(--jd-radius-md);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-sm);
    }
    .jd-newsletter__input::placeholder {
      color: var(--jd-color-muted);
    }
    .jd-newsletter__input:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-newsletter__input[aria-invalid] {
      border-color: var(--jd-color-danger);
    }

    .jd-newsletter__submit {
      box-sizing: border-box;
      border: 0;
      margin: 0;
      padding: var(--jd-space-2-5) var(--jd-space-4);
      font-family: inherit;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      background: var(--jd-color-primary);
      color: #fff;
      white-space: nowrap;
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-newsletter__submit:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-newsletter__submit:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-newsletter__submit:disabled {
      opacity: var(--jd-opacity-50);
      cursor: default;
    }

    .jd-newsletter__consent {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      cursor: pointer;
    }
    .jd-newsletter__consent input {
      margin-top: 2px;
      accent-color: var(--jd-color-primary);
    }

    .jd-newsletter__message {
      font-size: var(--jd-text-xs);
    }
    .jd-newsletter__message[data-tone="danger"] {
      color: var(--jd-color-danger);
    }
    .jd-newsletter__message[data-tone="success"] {
      color: var(--jd-color-success);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-newsletter__submit {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-notification {
      display: flex;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      border: var(--jd-border-thin) solid color-mix(in srgb, var(--_jd-noti-color) 30%, transparent);
      border-radius: var(--jd-radius-xl);
      background: color-mix(in srgb, var(--_jd-noti-color) 5%, var(--jd-color-card));
      --_jd-noti-color: var(--jd-color-info);
    }
    jd-notification[hidden] {
      display: none;
    }
    jd-notification[variant="success"] {
      --_jd-noti-color: var(--jd-color-success);
    }
    jd-notification[variant="warning"] {
      --_jd-noti-color: var(--jd-color-warning);
    }
    jd-notification[variant="danger"] {
      --_jd-noti-color: var(--jd-color-danger);
    }

    jd-notification > [slot="icon"] {
      display: flex;
      flex-shrink: 0;
      margin-block-start: var(--jd-space-0-5);
      color: var(--_jd-noti-color);
    }
    .jd-notification__body {
      flex: 1;
      min-width: 0;
    }
    .jd-notification__title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-notification__title[hidden] {
      display: none;
    }
    .jd-notification__desc {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }
    .jd-notification__desc[hidden] {
      display: none;
    }
    .jd-notification__extra:not(:empty) {
      margin-block-start: var(--jd-space-2);
    }

    .jd-notification__close {
      display: flex;
      flex-shrink: 0;
      padding: var(--jd-space-1);
      border: 0;
      background: none;
      cursor: pointer;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
    }
    .jd-notification__close:hover {
      color: var(--jd-color-foreground);
    }
    .jd-notification__close[hidden] {
      display: none;
    }
    .jd-notification__close:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
  }

  @layer junds.base {
    jd-notification-center:not(:defined) {
      display: inline-block;
    }
    jd-notification-center:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    /* 호스트 박스 — popover.css는 파생 태그가 각자 선언하도록 요구한다 */
    jd-notification-center {
      position: relative;
      display: inline-block;
    }

    /* 패널 표면 오버라이드 (배치·애니메이션은 공유 시트) */
    jd-notification-center > .jd-popover__panel {
      width: 20rem;
      max-width: min(20rem, calc(100vw - 2rem));
      padding: 0;
      overflow: hidden;
      backdrop-filter: none;
      box-shadow: var(--jd-shadow-xl);
    }

    /* ── 벨 트리거 ── */
    .jd-notification-center__bell {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.25rem;
      height: 2.25rem;
      padding: 0;
      cursor: pointer;
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-lg);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-notification-center__bell:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-notification-center__bell:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-notification-center__badge {
      position: absolute;
      inset-block-start: -2px;
      inset-inline-end: -2px;
      box-sizing: border-box;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 18px;
      height: 18px;
      padding: 0 var(--jd-space-1);
      background: var(--jd-color-danger);
      color: #ffffff;
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      border-radius: var(--jd-radius-full);
    }
    .jd-notification-center__badge[hidden] {
      display: none;
    }

    /* ── 헤더 ── */
    .jd-notification-center__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-notification-center__heading {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-notification-center__header-actions {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-notification-center__mark-all,
    .jd-notification-center__clear {
      border: 0;
      background: none;
      cursor: pointer;
      padding: 0;
      font-family: inherit;
      font-size: 11px;
    }
    .jd-notification-center__mark-all {
      color: var(--jd-color-primary-ink);
    }
    .jd-notification-center__mark-all:hover {
      text-decoration: underline;
    }
    .jd-notification-center__clear {
      color: var(--jd-color-muted);
    }
    .jd-notification-center__clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-notification-center__mark-all[hidden],
    .jd-notification-center__clear[hidden] {
      display: none;
    }
    .jd-notification-center__mark-all:focus-visible,
    .jd-notification-center__clear:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }

    /* ── 목록 ── */
    .jd-notification-center__list {
      max-height: 20rem;
      overflow-y: auto;
    }
    .jd-notification-center__empty {
      padding: var(--jd-space-8) var(--jd-space-4);
      text-align: center;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-notification-center__item {
      display: flex;
      gap: var(--jd-space-3);
      width: 100%;
      box-sizing: border-box;
      padding: var(--jd-space-3) var(--jd-space-4);
      border: 0;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border-light);
      background: none;
      text-align: start;
      font-family: inherit;
      color: inherit;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-notification-center__list > .jd-notification-center__item:last-child {
      border-block-end: 0;
    }
    button.jd-notification-center__item {
      cursor: pointer;
    }
    button.jd-notification-center__item:hover {
      background: var(--jd-color-card-hover);
    }
    button.jd-notification-center__item:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: -2px;
    }
    .jd-notification-center__item[data-unread] {
      background: color-mix(in srgb, var(--jd-color-primary-light) 30%, transparent);
    }

    .jd-notification-center__icon {
      flex-shrink: 0;
      display: inline-flex;
      margin-block-start: 2px;
    }
    .jd-notification-center__icon > svg {
      width: 1.125rem;
      height: 1.125rem;
    }

    .jd-notification-center__body {
      flex: 1 1 auto;
      min-width: 0;
    }
    .jd-notification-center__title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-notification-center__item[data-unread] .jd-notification-center__title {
      font-weight: var(--jd-weight-medium);
    }
    .jd-notification-center__desc {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-notification-center__time {
      margin: 2px 0 0;
      font-size: 10px;
      color: var(--jd-color-muted-light);
    }

    .jd-notification-center__dot {
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      margin-block-start: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
    }
  }

  @layer junds.components {
    jd-number-input {
      display: inline-flex;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }
    /* 포커스를 받는 것은 안쪽 input이지만 그 input은 테두리가 없다 — 표시는 테두리를
     가진 호스트가 대신 낸다(§1 "대체 표시"). Tab이 닿는 것은 input 하나뿐이라
     focus-within은 곧 input의 포커스다. */
    jd-number-input:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-number-input[error] {
      border-color: var(--jd-color-danger);
    }
    jd-number-input[error]:focus-within {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-number-input[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-number-input__step {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 1.75rem;
      padding: 0;
      border: 0;
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-number-input__step[hidden] {
      display: none;
    }
    .jd-number-input__step:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
      color: var(--jd-color-foreground);
    }
    /* 눌린 면은 빛을 잃는다. 버튼이 컨트롤 테두리에 딱 맞물려 있어 scale은 틈을
     만든다 — 면을 눌러 넣는 인셋 그림자로 대신한다. */
    .jd-number-input__step:active:not(:disabled) {
      background: var(--jd-color-border-light);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* tabIndex=-1이라 Tab으로는 닿지 않지만 클릭·명령형 focus()로는 포커스를 받는다.
     호스트가 overflow:hidden이라 바깥 아웃라인도 바깥 그림자도 잘린다 — 안쪽 링. */
    .jd-number-input__step:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    .jd-number-input__step:disabled {
      opacity: var(--jd-opacity-30);
      cursor: not-allowed;
    }
    /* v2: 좌 버튼은 오른쪽 구분선, 우 버튼은 왼쪽 구분선 */
    .jd-number-input__step[data-dir="-1"] {
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-number-input__step[data-dir="1"] {
      border-inline-start: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-number-input__input {
      width: 4rem;
      min-width: 0;
      margin: 0;
      padding: 0;
      border: 0;
      outline: none;
      background: transparent;
      text-align: center;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
      /* 네이티브 스피너 제거 — 증감은 자체 버튼 (v2 [appearance:textfield]) */
      appearance: textfield;
      -moz-appearance: textfield;
      height: 2.25rem;
      font-size: var(--jd-text-sm);
    }
    .jd-number-input__input::-webkit-outer-spin-button,
    .jd-number-input__input::-webkit-inner-spin-button {
      appearance: none;
      margin: 0;
    }
    .jd-number-input__input:disabled {
      cursor: not-allowed;
    }

    jd-number-input[size="sm"] .jd-number-input__input {
      height: 2rem;
      font-size: var(--jd-text-xs);
    }
    jd-number-input[size="lg"] .jd-number-input__input {
      height: 2.75rem;
      font-size: var(--jd-text-md);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-number-input__step {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-offline-indicator {
      display: none;
      box-sizing: border-box;
      position: fixed;
      inset-inline: 0;
      z-index: var(--jd-z-modal);
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2-5);
      padding: var(--jd-space-3) var(--jd-space-5);
      min-height: 2.75rem;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      text-wrap: balance; /* 좁은 폭에서 접힐 때 한 단어만 남는 둘째 줄을 막는다 */
      color: #fff;
      background: color-mix(in srgb, var(--_jd-offline-color) 80%, var(--jd-color-foreground));
      /* 문서 위에 떠 있는 띠다 — 경계선 대신 그림자로 본문과 분리한다(§2) */
      box-shadow: var(--jd-shadow-lg);
      /* 끊김 → 복구는 같은 띠가 색만 바꾸는 사건이다. 즉시 갈아치우면 무엇이 바뀐 건지
       보이지 않는다 — 색만 전이한다(레이아웃 속성은 대상 밖, §3). */
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
      --_jd-offline-color: var(--jd-color-danger);
      inset-block-start: 0; /* position 기본 top */
    }
    jd-offline-indicator[visible] {
      display: flex;
    }
    jd-offline-indicator[position="bottom"] {
      inset-block-start: auto;
      inset-block-end: 0;
    }
    jd-offline-indicator[online] {
      --_jd-offline-color: var(--jd-color-success);
    }

    .jd-offline-indicator__dot {
      width: 0.5rem;
      height: 0.5rem;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      background: currentColor;
      opacity: var(--jd-opacity-80);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-offline-indicator {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-onboarding {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      padding: var(--jd-space-5);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }

    /* ── 헤더 ───────────────────────────────────────────────── */
    .jd-onboarding__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-4);
    }
    .jd-onboarding__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
    }
    .jd-onboarding__title[hidden] {
      display: none;
    }
    .jd-onboarding__count {
      flex-shrink: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    /* ── 진행바 ─────────────────────────────────────────────── */
    .jd-onboarding__track {
      height: 6px;
      overflow: hidden;
      margin-block-end: var(--jd-space-4);
      background: var(--jd-color-border-light);
      border-radius: var(--jd-radius-full);
    }
    .jd-onboarding__fill {
      height: 100%;
      width: 0;
      background: var(--jd-color-primary);
      border-radius: var(--jd-radius-full);
      transition: width var(--jd-duration-slower) var(--jd-easing-ease-out);
    }

    /* ── 단계 목록 ──────────────────────────────────────────── */
    .jd-onboarding__list {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    .jd-onboarding__button {
      position: relative; /* 숨김 상태 텍스트(absolute)의 기준 — 문서 끝으로 새지 않게 */
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      padding: var(--jd-space-3);
      border: 0;
      background: transparent;
      border-radius: var(--jd-radius-lg);
      font-family: inherit;
      text-align: start;
      cursor: pointer;
      color: var(--jd-color-foreground);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding__button:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-onboarding__button:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    /* 완료 행 — 눌러도 아무 일이 없다(aria-disabled) */
    .jd-onboarding__step[data-completed] > .jd-onboarding__button {
      background: color-mix(in srgb, var(--jd-color-success) 5%, transparent);
      cursor: default;
    }
    .jd-onboarding__step[data-completed] > .jd-onboarding__button:hover {
      background: color-mix(in srgb, var(--jd-color-success) 5%, transparent);
    }

    .jd-onboarding__marker {
      flex-shrink: 0;
      box-sizing: border-box;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 1.25rem;
      height: 1.25rem;
      margin-block-start: 0.125rem; /* v2 mt-0.5 — 첫 줄 글자와 광학 정렬 */
      border: var(--jd-border-medium) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      color: transparent; /* 체크는 항상 있고 완료일 때만 보인다 */
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding__marker > svg {
      width: 10px;
      height: 10px;
      display: block;
    }
    .jd-onboarding__step[data-completed] .jd-onboarding__marker {
      background: var(--jd-color-success);
      border-color: var(--jd-color-success);
      color: #fff; /* 성공색 위 체크 — 대비 고정값(v2 stroke="white") */
    }

    .jd-onboarding__body {
      display: flex;
      flex-direction: column;
      gap: 0.125rem;
      min-width: 0;
    }
    .jd-onboarding__step-title {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
    }
    .jd-onboarding__step[data-completed] .jd-onboarding__step-title {
      text-decoration: line-through;
      color: var(--jd-color-muted);
    }
    .jd-onboarding__desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-normal);
    }
    .jd-onboarding__desc[hidden] {
      display: none;
    }

    /* 상태 텍스트는 읽히기만 한다 (jd-progress-steps __status 관용구) */
    .jd-onboarding__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    /* ── 마무리 버튼 ────────────────────────────────────────── */
    .jd-onboarding__finish {
      display: block;
      width: 100%;
      box-sizing: border-box;
      height: 2.25rem;
      margin-block-start: var(--jd-space-4);
      border: 0;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-primary);
      color: #fff;
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding__finish:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-onboarding__finish:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-onboarding__finish[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-onboarding__fill,
      .jd-onboarding__button,
      .jd-onboarding__marker,
      .jd-onboarding__finish {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-onboarding-tour:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-onboarding-tour {
      display: none;
    }
    jd-onboarding-tour[open] {
      display: block;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-max);
    }

    .jd-onboarding-tour__backdrop {
      position: absolute;
      inset: 0;
      background: rgba(0, 0, 0, 0.55);
    }

    /* 스팟 = 대상 위 링 + 9999px 딤. pointer-events 없음 → 클릭은 아래 백드롭이 받는다 */
    .jd-onboarding-tour__spot {
      position: absolute;
      top: 0;
      left: 0;
      width: 0;
      height: 0;
      pointer-events: none;
      border-radius: var(--jd-radius-lg);
      box-shadow: 0 0 0 var(--jd-border-heavy)
          color-mix(in srgb, var(--jd-color-primary) 70%, transparent),
        0 0 0 9999px rgba(0, 0, 0, 0.55);
    }
    .jd-onboarding-tour__spot[hidden] {
      display: none;
    }

    .jd-onboarding-tour__tooltip {
      position: absolute;
      top: 24px;
      left: 24px;
      z-index: 1;
      box-sizing: border-box;
      width: 20rem;
      max-width: calc(100vw - 2rem);
      padding: var(--jd-space-4);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-xl);
      font-family: var(--jd-font-sans);
    }
    .jd-onboarding-tour__tooltip[hidden] {
      display: none;
    }

    .jd-onboarding-tour__counter {
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-normal);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }

    .jd-onboarding-tour__title {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
    }
    .jd-onboarding-tour__title[hidden] {
      display: none;
    }

    .jd-onboarding-tour__desc {
      margin-top: var(--jd-space-1);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-muted);
    }
    .jd-onboarding-tour__desc[hidden] {
      display: none;
    }

    .jd-onboarding-tour__actions {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-top: var(--jd-space-3);
      gap: var(--jd-space-3);
    }
    .jd-onboarding-tour__nav {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-onboarding-tour__skip,
    .jd-onboarding-tour__prev,
    .jd-onboarding-tour__next {
      font-family: inherit;
      cursor: pointer;
    }

    .jd-onboarding-tour__skip:focus-visible,
    .jd-onboarding-tour__prev:focus-visible,
    .jd-onboarding-tour__next:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-onboarding-tour__skip {
      padding: 0;
      border: 0;
      background: none;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding-tour__skip:hover {
      color: var(--jd-color-foreground);
    }

    .jd-onboarding-tour__prev {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-foreground);
      background: transparent;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding-tour__prev:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-onboarding-tour__prev[hidden] {
      display: none;
    }

    .jd-onboarding-tour__next {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      color: #fff;
      background: var(--jd-color-primary);
      border: 0;
      border-radius: var(--jd-radius-md);
      transition: filter var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-onboarding-tour__next:hover {
      filter: brightness(1.1);
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-onboarding-tour[open] > .jd-onboarding-tour__backdrop {
        animation: jd-onboarding-tour-fade var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-onboarding-tour[open] > .jd-onboarding-tour__tooltip {
        animation: jd-onboarding-tour-pop var(--jd-duration-normal) var(--jd-easing-default);
      }
      .jd-onboarding-tour__spot {
        transition: top var(--jd-duration-normal) var(--jd-easing-ease-out),
          left var(--jd-duration-normal) var(--jd-easing-ease-out),
          width var(--jd-duration-normal) var(--jd-easing-ease-out),
          height var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-onboarding-tour-fade {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-onboarding-tour-pop {
      from {
        opacity: 0;
        transform: scale(0.96);
      }
    }
  }

  @layer junds.components {
    jd-online-status {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      /* sm 기본 */
      --_jd-online-size: 8px;
      --_jd-online-ping: 5px;
      /* offline 기본 — 자리는 지키되 말은 하지 않는 중립색 */
      --_jd-online-color: var(--jd-color-muted-light);
    }
    jd-online-status[size="xs"] {
      --_jd-online-size: 6px;
      --_jd-online-ping: 4px;
    }
    jd-online-status[size="md"] {
      --_jd-online-size: 10px;
      --_jd-online-ping: 6px;
    }
    jd-online-status[size="lg"] {
      --_jd-online-size: 12px;
      --_jd-online-ping: 7px;
    }

    jd-online-status[status="online"] {
      --_jd-online-color: var(--jd-color-success);
    }
    jd-online-status[status="away"] {
      --_jd-online-color: var(--jd-color-warning);
    }
    jd-online-status[status="busy"] {
      --_jd-online-color: var(--jd-color-danger);
    }

    jd-online-status::before {
      content: "";
      display: block;
      flex-shrink: 0;
      box-sizing: border-box;
      width: var(--_jd-online-size);
      height: var(--_jd-online-size);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-medium) solid var(--jd-color-background);
      background: var(--_jd-online-color);
    }

    /* v2와 같이 펄스는 online에서만 보인다 */
    jd-online-status[pulse][status="online"]::before {
      animation: jd-online-ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
    }
    @keyframes jd-online-ping {
      0% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--_jd-online-color) 50%, transparent);
      }
      70% {
        box-shadow: 0 0 0 var(--_jd-online-ping) transparent;
      }
      100% {
        box-shadow: 0 0 0 0 transparent;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-online-status[pulse][status="online"]::before {
        animation: none;
      }
    }

    .jd-online-status__label {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-online-status__label[hidden] {
      display: none;
    }
    .jd-online-status__seen[hidden],
    .jd-online-status__sep[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-open-picks-card {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-warning: var(--jd-color-warning);
      --jd-fin-muted: var(--jd-color-muted);
      --jd-fin-text: var(--jd-color-foreground);
      --jd-fin-border: var(--jd-color-border);
      --jd-fin-card: var(--jd-color-card);
      --jd-fin-soft: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
      --jd-fin-soft-200: color-mix(in srgb, var(--jd-color-foreground) 10%, transparent);

      display: block;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-sm);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-open-picks-card * {
      box-sizing: border-box;
    }

    /* 헤더 */
    .jd-open-picks-card__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-open-picks-card__titlewrap {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-open-picks-card__emoji {
      font-size: 14px;
      line-height: 1;
      flex-shrink: 0;
    }
    .jd-open-picks-card__title {
      margin: 0;
      font-size: 13.5px;
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-open-picks-card__summary {
      flex-shrink: 0;
      font-size: 11px;
      font-weight: 700;
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }

    /* 목록 */
    .jd-open-picks-card__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-open-picks-card__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-4);
    }
    .jd-open-picks-card__item + .jd-open-picks-card__item {
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }

    /* 강도 배지 */
    .jd-open-picks-card__badge {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 22px;
      height: 22px;
      border-radius: var(--jd-radius-md);
      font-size: 10.5px;
      font-weight: 800;
      background: var(--jd-fin-soft-200);
      color: var(--jd-fin-muted);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-open-picks-card__badge[data-strength="high"] {
      background: var(--jd-fin-up);
      color: #fff;
      border-color: transparent;
    }
    .jd-open-picks-card__badge[data-strength="medium"] {
      background: var(--jd-fin-warning);
      color: #17141f;
      border-color: transparent; /* 원색 채움 위 잉크 — 모드 무관 */
    }

    /* 본문 */
    .jd-open-picks-card__body {
      min-width: 0;
      flex: 1;
      display: flex;
      flex-direction: column;
    }
    .jd-open-picks-card__name {
      font-size: 13.5px;
      font-weight: 800;
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-decoration: none;
    }
    a.jd-open-picks-card__name {
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    a.jd-open-picks-card__name:hover {
      color: var(--jd-color-primary-ink);
      text-decoration: underline;
    }
    /* 눌린 순간을 색으로 답한다 — 행에서 키보드로 닿는 것은 이 링크뿐이다 */
    a.jd-open-picks-card__name:active {
      color: var(--jd-color-primary-hover);
    }
    a.jd-open-picks-card__name:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }
    .jd-open-picks-card__reason {
      margin-block-start: 2px;
      font-size: 11px;
      color: var(--jd-fin-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-open-picks-card__pct {
      flex-shrink: 0;
      font-size: 13.5px;
      font-weight: 800;
      color: var(--jd-fin-up);
      font-variant-numeric: tabular-nums;
    }

    /* footer */
    .jd-open-picks-card__footer {
      padding: var(--jd-space-2) var(--jd-space-4);
      font-size: 10.5px;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }

    @media (prefers-reduced-motion: reduce) {
      a.jd-open-picks-card__name {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-otp-input {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }

    .jd-otp-input__separator {
      width: 0.75rem;
      height: 2px;
      margin-inline: var(--jd-space-1);
      background: var(--jd-color-border);
      border-radius: var(--jd-radius-full);
    }

    .jd-otp-input__cell {
      box-sizing: border-box;
      width: 2.75rem;
      height: 3.25rem;
      margin: 0;
      padding: 0;
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-medium) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      outline: none;
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-otp-input__cell[data-filled] {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    .jd-otp-input__cell:focus {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
      transform: scale(1.05);
    }
    .jd-otp-input__cell:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-otp-input[error] .jd-otp-input__cell {
      border-color: var(--jd-color-danger);
      animation: jd-otp-shake var(--jd-duration-slow) var(--jd-easing-ease-in-out);
    }
    jd-otp-input[error] .jd-otp-input__cell:focus {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    @keyframes jd-otp-shake {
      0%,
      100% {
        transform: translateX(0);
      }
      25% {
        transform: translateX(-3px);
      }
      75% {
        transform: translateX(3px);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-otp-input__cell {
        transition: none;
      }
      .jd-otp-input__cell:focus {
        transform: none;
      }
      jd-otp-input[error] .jd-otp-input__cell {
        animation: none;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: inset 0 절대 배치 + 양축 중앙(center=true), blur는 backdrop 4px */
    jd-overlay {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    jd-overlay[no-center] {
      display: block;
    }
    jd-overlay[blur] {
      backdrop-filter: blur(4px);
    }
  }

  @layer junds.components {
    jd-page {
      display: block;
      box-sizing: border-box; /* width:100%+padding 병용 — 전역 리셋 비의존 (DEC-014-9) */
      width: 100%;
      margin-inline: auto;
      max-width: 1280px;
      padding: var(--jd-space-4);
    }
    jd-page[max-width="sm"] {
      max-width: 640px;
    }
    jd-page[max-width="md"] {
      max-width: 768px;
    }
    jd-page[max-width="lg"] {
      max-width: 1024px;
    }
    jd-page[max-width="2xl"] {
      max-width: 1536px;
    }
    jd-page[max-width="full"] {
      max-width: 100%;
    }

    jd-page-header {
      display: block;
      margin-bottom: var(--jd-space-6);
    }
    .jd-page-header__breadcrumb {
      margin-bottom: var(--jd-space-3);
    }
    .jd-page-header__row {
      display: block;
    }
    .jd-page-header__title {
      margin: 0;
      font-size: 1.5rem;
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
      color: var(--jd-color-foreground);
    }
    .jd-page-header__desc {
      margin: var(--jd-space-1) 0 0;
      font-size: 0.875rem;
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }
    .jd-page-header__actions {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-shrink: 0;
      margin-top: var(--jd-space-3);
    }
    .jd-page-header__actions[hidden] {
      display: none;
    }

    jd-page-body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }

    @media (min-width: 768px) {
      jd-page {
        padding: var(--jd-space-6);
      }
      .jd-page-header__row {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--jd-space-4);
      }
      .jd-page-header__title {
        font-size: 1.875rem;
      }
      .jd-page-header__actions {
        margin-top: 0;
      }
      jd-page-body {
        gap: var(--jd-space-6);
      }
    }
  }

  @layer junds.components {
    jd-page-empty-state {
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));

      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      text-align: center;
      font-family: var(--jd-font-sans);
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      /* 기본 md */
      padding: var(--jd-space-12) var(--jd-space-6);
    }
    jd-page-empty-state[size="sm"] {
      padding: var(--jd-space-8) var(--jd-space-6);
    }
    jd-page-empty-state[size="lg"] {
      padding: var(--jd-space-16) var(--jd-space-6);
    }

    /* 아이콘 칩 해제 — 이모지/도형을 그대로 크게 */
    jd-page-empty-state .jd-empty-state__icon {
      width: auto;
      height: auto;
      background: none;
      margin-block-end: var(--jd-space-4);
      color: var(--jd-color-muted);
    }
    jd-page-empty-state .jd-page-empty-state__emoji {
      font-size: 40px;
      line-height: 1;
      display: block;
    }
    jd-page-empty-state > [slot="action"] {
      margin-block-start: var(--jd-space-5);
    }
  }

  @layer junds.components {
    jd-page-header-bar {
      display: block;
    }

    .jd-page-header-bar {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
      padding: var(--jd-space-4);
    }
    .jd-page-header-bar[data-divider] {
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
    }

    /* breadcrumb */
    .jd-page-header-bar__breadcrumb[hidden] {
      display: none;
    }
    .jd-page-header-bar__crumbs {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      padding: 0;
      list-style: none;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-page-header-bar__crumb {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      min-width: 0;
    }
    .jd-page-header-bar__crumb-content {
      color: var(--jd-color-muted);
      text-decoration: none;
      transition: color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    a.jd-page-header-bar__crumb-content:hover {
      color: var(--jd-color-foreground);
    }
    a.jd-page-header-bar__crumb-content:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }
    .jd-page-header-bar__crumb-content[aria-current="page"] {
      color: var(--jd-color-foreground);
    }
    .jd-page-header-bar__sep {
      flex-shrink: 0;
      opacity: 0.5;
    }

    /* 본문 행 */
    .jd-page-header-bar__main {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
    }

    .jd-page-header-bar__back {
      flex-shrink: 0;
      margin-top: var(--jd-space-1);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: var(--jd-space-8);
      height: var(--jd-space-8);
      padding: 0;
      border: 0;
      background: transparent;
      border-radius: var(--jd-radius-md);
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-page-header-bar__back:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
      color: var(--jd-color-foreground);
    }
    .jd-page-header-bar__back:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-page-header-bar__back[hidden] {
      display: none;
    }

    .jd-page-header-bar__avatar {
      flex-shrink: 0;
    }
    .jd-page-header-bar__avatar[hidden] {
      display: none;
    }

    .jd-page-header-bar__heading {
      flex: 1;
      min-width: 0;
    }
    .jd-page-header-bar__title {
      margin: 0;
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-tight);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-page-header-bar__title[hidden] {
      display: none;
    }
    .jd-page-header-bar__description {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      overflow: hidden;
    }
    .jd-page-header-bar__description[hidden] {
      display: none;
    }

    .jd-page-header-bar__actions {
      flex-shrink: 0;
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-page-header-bar__actions[hidden] {
      display: none;
    }

    .jd-page-header-bar__footer {
      padding-top: var(--jd-space-1);
    }
    .jd-page-header-bar__footer[hidden] {
      display: none;
    }

    /* sm 이상 — 좌우 여백·타이틀·간격 확대 (v2 sm:px-6 sm:text-2xl sm:gap-4) */
    @media (min-width: 640px) {
      .jd-page-header-bar {
        padding-inline: var(--jd-space-6);
      }
      .jd-page-header-bar__main {
        gap: var(--jd-space-4);
      }
      .jd-page-header-bar__title {
        font-size: var(--jd-text-2xl);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-page-header-bar__crumb-content,
      .jd-page-header-bar__back {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-page-shell {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      padding-block: var(--jd-space-5);
      padding-inline: var(--jd-space-4);
    }
    @media (min-width: 1024px) {
      jd-page-shell {
        padding-block: 1.75rem; /* py-7 */
        padding-inline: var(--jd-space-6);
      }
    }

    .jd-page-shell__inner {
      margin-inline: auto;
      width: 100%;
    }

    .jd-page-shell__header:not([hidden]) {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-5);
    }
    @media (min-width: 640px) {
      .jd-page-shell__header:not([hidden]) {
        flex-direction: row;
        align-items: flex-end;
        justify-content: space-between;
      }
    }

    .jd-page-shell__titles {
      min-width: 0;
      flex: 1 1 auto;
    }
    .jd-page-shell__title:not([hidden]) {
      display: block;
      margin: 0;
      font-size: 20px;
      font-weight: 800;
      line-height: var(--jd-leading-tight);
      letter-spacing: var(--jd-tracking-tight);
    }
    @media (min-width: 1024px) {
      .jd-page-shell__title:not([hidden]) {
        font-size: 24px;
      }
    }
    .jd-page-shell__desc:not([hidden]) {
      display: block;
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    @media (min-width: 640px) {
      .jd-page-shell__actions {
        flex-shrink: 0;
      }
    }
  }

  @layer junds.components {
    jd-pagination {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    jd-pagination[hidden] {
      display: none;
    }

    .jd-pagination__list {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-pagination__item {
      display: inline-flex;
    }

    .jd-pagination__arrow,
    .jd-pagination__page,
    .jd-pagination__ellipsis {
      /* v2: w-8 h-8 */
      inline-size: 2rem;
      block-size: 2rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: transparent;
      border-radius: var(--jd-radius-lg);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      color: var(--jd-color-muted);
    }

    .jd-pagination__arrow,
    .jd-pagination__page {
      cursor: pointer;
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-pagination__arrow:hover:not(:disabled),
    .jd-pagination__page:hover:not([aria-current="page"]) {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
      color: var(--jd-color-foreground);
    }
    .jd-pagination__arrow:focus-visible,
    .jd-pagination__page:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-pagination__arrow:disabled {
      opacity: var(--jd-opacity-30);
      pointer-events: none;
    }
    .jd-pagination__arrow > svg {
      inline-size: 16px;
      block-size: 16px;
    }

    .jd-pagination__page[aria-current="page"] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-sm);
    }

    .jd-pagination__ellipsis {
      cursor: default;
      user-select: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pagination__arrow,
      .jd-pagination__page {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-password-input {
      display: block;
      width: 100%;
    }

    .jd-password-input__field {
      position: relative;
      display: block;
    }

    .jd-password-input__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
      height: 2.25rem;
      font-size: var(--jd-text-sm);
      border-radius: var(--jd-radius-lg);
      padding-inline: var(--jd-space-3) 2.5rem; /* 우측은 토글 버튼 자리 */
    }
    .jd-password-input__input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-password-input__input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-password-input__input:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    jd-password-input[error] .jd-password-input__input {
      border-color: var(--jd-color-danger);
    }
    jd-password-input[error] .jd-password-input__input:focus {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    jd-password-input[size="sm"] .jd-password-input__input {
      height: 2rem;
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-md);
      padding-inline: var(--jd-space-2-5) 2.25rem;
    }
    jd-password-input[size="lg"] .jd-password-input__input {
      height: 2.75rem;
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-xl);
      padding-inline: var(--jd-space-4) 2.75rem;
    }

    .jd-password-input__toggle {
      position: absolute;
      inset-inline-end: var(--jd-space-2-5);
      top: 50%;
      transform: translateY(-50%);
      display: flex;
      align-items: center;
      justify-content: center;
      /* 아이콘(16px)에 2px 패딩만 두면 hover 면이 아이콘에 달라붙어 실수처럼 보이고
       히트 영역도 20px에 그쳤다 — 정사각 버튼으로 잡아 준다. 입력 우측에 비워 둔
       자리(sm 2.25rem)보다 작아 어느 size에서도 글자를 침범하지 않는다. */
      width: 1.5rem;
      height: 1.5rem;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-md);
      background: none;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-password-input__toggle:hover {
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    /* 눌린 면은 빛을 잃는다. transform은 세로 중앙 정렬(translateY)에 이미 쓰이고
     있으므로 scale 속성으로 따로 누른다 — 둘은 서로를 덮지 않는다. */
    .jd-password-input__toggle:active {
      scale: 0.92;
      color: var(--jd-color-foreground);
    }
    /* 눈 아이콘은 입력창 안쪽에 겹쳐 있어 포커스가 오면 배경과 구분이 안 된다.
     __field는 overflow를 자르지 않으므로 아웃라인이 그대로 보인다. */
    .jd-password-input__toggle:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* ─── 강도 게이지 ─── */
    .jd-password-input__strength {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin-block-start: var(--jd-space-2);
    }
    .jd-password-input__strength[hidden] {
      display: none;
    }
    .jd-password-input__bar {
      flex: 1;
      height: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border);
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-password-input__level {
      min-width: 1.75rem;
      margin-inline-start: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      font-family: var(--jd-font-sans);
    }
    /* 막대는 그래픽(3:1)이라 원색 그대로, 글자는 텍스트(4.5:1)라 foreground와 섞는다 —
     원색을 그대로 쓰면 warning 3.3:1 · success 3.6:1로 AA 미달(B6 axe 실측 후 소급 교정) */
    .jd-password-input__strength[data-level="weak"] .jd-password-input__bar[data-on] {
      background: var(--jd-color-danger);
    }
    .jd-password-input__strength[data-level="weak"] .jd-password-input__level {
      color: color-mix(in srgb, var(--jd-color-danger) 65%, var(--jd-color-foreground));
    }
    .jd-password-input__strength[data-level="fair"] .jd-password-input__bar[data-on] {
      background: var(--jd-color-warning);
    }
    .jd-password-input__strength[data-level="fair"] .jd-password-input__level {
      color: color-mix(in srgb, var(--jd-color-warning) 65%, var(--jd-color-foreground));
    }
    .jd-password-input__strength[data-level="good"] .jd-password-input__bar[data-on] {
      background: var(--jd-color-info);
    }
    .jd-password-input__strength[data-level="good"] .jd-password-input__level {
      color: color-mix(in srgb, var(--jd-color-info) 65%, var(--jd-color-foreground));
    }
    .jd-password-input__strength[data-level="strong"] .jd-password-input__bar[data-on] {
      background: var(--jd-color-success);
    }
    .jd-password-input__strength[data-level="strong"] .jd-password-input__level {
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
    }

    /* ─── 규칙 체크리스트 ─── */
    .jd-password-input__rules {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      margin: var(--jd-space-2) 0 0;
      padding: 0;
      list-style: none;
    }
    .jd-password-input__rules[hidden] {
      display: none;
    }
    .jd-password-input__rule {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-muted);
    }
    .jd-password-input__rule[data-passed] {
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
    }
    .jd-password-input__rule-icon {
      display: flex;
      flex-shrink: 0;
      color: var(--jd-color-muted-light);
    }
    /* 아이콘은 그래픽이라 원색 유지 — 글자만 섞은 값 */
    .jd-password-input__rule[data-passed] .jd-password-input__rule-icon {
      color: var(--jd-color-success);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-password-input__input,
      .jd-password-input__toggle,
      .jd-password-input__bar {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-password-strength {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      width: 100%;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    .jd-password-strength__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-password-strength__meter {
      flex: 1;
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: var(--jd-space-1);
    }
    .jd-password-strength__bar {
      height: 0.375rem;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border-light); /* v2 bg-surface-soft */
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 채워진 막대는 전부 현재 등급 색 (v2 LEVEL_COLOR[level]) */
    jd-password-strength[data-level="0"] .jd-password-strength__bar[data-on] {
      background: var(--jd-color-danger);
    }
    jd-password-strength[data-level="1"] .jd-password-strength__bar[data-on],
    jd-password-strength[data-level="2"] .jd-password-strength__bar[data-on] {
      background: var(--jd-color-warning);
    }
    jd-password-strength[data-level="3"] .jd-password-strength__bar[data-on],
    jd-password-strength[data-level="4"] .jd-password-strength__bar[data-on] {
      background: var(--jd-color-success);
    }

    .jd-password-strength__label {
      flex-shrink: 0;
      width: 4rem;
      text-align: end;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-password-strength__label[hidden] {
      display: none;
    }

    .jd-password-strength__rules {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      margin: 0;
      padding: 0;
      list-style: none;
      font-size: var(--jd-text-xs);
    }
    .jd-password-strength__rules[hidden] {
      display: none;
    }

    .jd-password-strength__rule {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      color: var(--jd-color-muted);
    }
    .jd-password-strength__rule[data-ok] {
      color: color-mix(
        in srgb,
        var(--jd-color-success) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    .jd-password-strength__mark {
      flex-shrink: 0;
    }

    /* 규칙 통과 여부의 비시각 경로 — 색·글리프만으로 전달하지 않는다(WCAG 1.4.1) */
    .jd-password-strength__state {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-password-strength__bar {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-phone-input {
      display: inline-flex;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }
    /* 포커스를 받는 것은 안쪽 select/input이지만 둘 다 테두리가 없다 — 표시는
     테두리를 가진 호스트가 대신 낸다(§1 "대체 표시"). 단 호스트 링만으로는 Tab이
     국가와 번호 중 어디에 있는지 말하지 못한다 — 아래에서 칸별 링을 덧댄다. */
    jd-phone-input:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-phone-input[error] {
      border-color: var(--jd-color-danger);
    }
    jd-phone-input[error]:focus-within {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-phone-input[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-phone-input__country {
      position: relative;
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      border-inline-end: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 비활성일 때는 누를 수 없으므로 hover도 응답하지 않는다 — 호스트의 흐림만으로는
     "눌리는 것처럼 보이는데 안 눌린다"가 남는다 */
    jd-phone-input:not([disabled]) > .jd-phone-input__country:hover {
      background: var(--jd-color-card-hover);
    }
    /* 눌린 면은 빛을 잃는다. 칸이 컨트롤 테두리에 물려 있어 scale은 틈을 만든다 —
     인셋 그림자로 눌러 넣는다. */
    jd-phone-input:not([disabled]) > .jd-phone-input__country:active {
      background: var(--jd-color-border-light);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }

    .jd-phone-input__select {
      appearance: none;
      -webkit-appearance: none;
      height: 2.25rem;
      margin: 0;
      padding-inline: var(--jd-space-3) var(--jd-space-6);
      border: 0;
      outline: none;
      background: transparent;
      cursor: pointer;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    /* 국가 select는 번호 input과 별개의 Tab 정거장이다. outline:none만 두고 호스트
     링에 맡기면 두 정거장이 똑같이 보여 지금 어느 칸을 조작하는지 알 수 없다 —
     칸 자체에 링을 돌려준다. 호스트가 overflow:hidden이라 바깥으로 나가는 아웃라인·
     그림자는 잘리므로 안쪽으로 눕힌다. */
    .jd-phone-input__select:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }
    .jd-phone-input__select:disabled {
      cursor: not-allowed;
    }
    /* 열린 목록은 플랫폼 렌더 — 다크에서 흰 배경으로 뭉개지지 않도록 옵션 색 지정 */
    .jd-phone-input__select option {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
    }

    .jd-phone-input__caret {
      position: absolute;
      inset-inline-end: var(--jd-space-2);
      top: 50%;
      transform: translateY(-50%);
      display: flex;
      pointer-events: none;
      color: var(--jd-color-muted);
    }

    .jd-phone-input__input {
      flex: 1;
      min-width: 0;
      margin: 0;
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      border: 0;
      outline: none;
      background: transparent;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-phone-input__input:disabled {
      cursor: not-allowed;
    }

    jd-phone-input[size="sm"] .jd-phone-input__select,
    jd-phone-input[size="sm"] .jd-phone-input__input {
      height: 2rem;
      font-size: var(--jd-text-xs);
    }
    jd-phone-input[size="lg"] .jd-phone-input__select,
    jd-phone-input[size="lg"] .jd-phone-input__input {
      height: 2.75rem;
    }
    jd-phone-input[size="lg"] .jd-phone-input__input {
      font-size: var(--jd-text-md);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-phone-input__country {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-photo-album {
      display: block;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-photo-album__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-bottom: var(--jd-space-4);
    }
    .jd-photo-album__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-photo-album__count {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-photo-album__filters {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      margin-bottom: var(--jd-space-4);
    }
    /* 칩은 '앱의 본문' 위에 놓인 컨트롤이다 — surface 3단(라이트에서도 어두운 크롬)에
     foreground를 얹으면 라이트 모드에서 검은 글자가 검은 칩에 묻힌다. 면은 card,
     테두리는 border — 채움만 있는 칩은 색종이로 읽히므로 위에서 받는 빛도 함께. */
    .jd-photo-album__chip {
      display: inline-flex;
      align-items: center;
      padding: var(--jd-space-1) var(--jd-space-3);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-xs);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-photo-album__chip:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-photo-album__chip:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-photo-album__chip[aria-checked="true"] {
      background: var(--jd-color-primary);
      border-color: transparent;
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-photo-album__chip[aria-checked="true"]:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-photo-album__chip:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    /* 열 수: 모바일 2, 640+에서 인라인 --cols-desktop 채택 */
    .jd-photo-album__grid {
      --cols: 2;
    }
    @media (min-width: 640px) {
      .jd-photo-album__grid {
        --cols: var(--cols-desktop, 4);
      }
    }

    /* grid 레이아웃(기본 아님 — 호스트 attr로 승격) */
    .jd-photo-album__grid {
      display: grid;
      grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
      gap: var(--jd-space-2);
    }
    /* masonry — 호스트 속성 셀렉터가 특이도 우위(§4.3) */
    jd-photo-album[layout="masonry"] .jd-photo-album__grid {
      display: block;
      column-count: var(--cols);
      column-gap: var(--jd-space-2);
    }
    jd-photo-album[layout="masonry"] .jd-photo-album__cell {
      break-inside: avoid;
      margin-bottom: var(--jd-space-2);
      width: 100%;
    }

    .jd-photo-album__cell {
      display: block;
      padding: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      text-align: left;
    }
    .jd-photo-album__cell:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-photo-album__cell:active {
      scale: 0.99;
    }
    .jd-photo-album__figure {
      margin: 0;
      position: relative;
    }
    .jd-photo-album__img {
      display: block;
      width: 100%;
      height: auto;
      object-fit: cover;
      /* 로딩 전 빈 칸 — surface(라이트에서도 어두운 크롬)를 쓰면 밝은 앨범에 검은
       구멍이 뚫린다. 은은하게 꺼진 중립면이면 충분하다. */
      background: var(--jd-color-neutral-100);
      transition: transform var(--jd-duration-normal) var(--jd-easing-default);
    }
    .jd-photo-album__cell:hover .jd-photo-album__img {
      transform: scale(1.03);
    }
    .jd-photo-album__caption {
      position: absolute;
      inset-inline: 0;
      inset-block-end: 0;
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-6) var(--jd-space-3) var(--jd-space-2);
      background: linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent);
      color: #fff;
      font-size: var(--jd-text-xs);
      opacity: 0;
      transition: opacity var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-photo-album__cell:hover .jd-photo-album__caption,
    .jd-photo-album__cell:focus-visible .jd-photo-album__caption {
      opacity: 1;
    }
    .jd-photo-album__caption-title {
      font-weight: var(--jd-weight-medium);
    }
    .jd-photo-album__caption-meta {
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    .jd-photo-album__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-16) var(--jd-space-4);
    }
    .jd-photo-album__empty-icon {
      font-size: var(--jd-text-4xl);
    }
    .jd-photo-album__empty-title {
      margin: 0;
      font-weight: var(--jd-weight-semibold);
    }

    /* 라이트박스 */
    .jd-photo-album__lightbox {
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .jd-photo-album__lightbox[hidden] {
      display: none;
    }
    .jd-photo-album__lb-backdrop {
      position: absolute;
      inset: 0;
      background: rgba(0, 0, 0, 0.85);
    }
    .jd-photo-album__lb-panel {
      position: relative;
      z-index: 1;
      width: min(92vw, 72rem);
      max-height: 92vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .jd-photo-album__lb-figure {
      margin: 0;
      max-height: 92vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-photo-album__lb-img {
      max-width: 100%;
      max-height: 82vh;
      object-fit: contain;
      border-radius: var(--jd-radius-md);
    }
    .jd-photo-album__lb-cap {
      margin: 0;
      color: rgba(255, 255, 255, 0.85);
      font-size: var(--jd-text-sm);
      text-align: center;
    }
    .jd-photo-album__lb-close {
      position: absolute;
      inset-block-start: calc(-1 * var(--jd-space-10));
      inset-inline-end: 0;
      width: 2.5rem;
      height: 2.5rem;
      border: 0;
      cursor: pointer;
      border-radius: var(--jd-radius-full);
      background: rgba(255, 255, 255, 0.12);
      color: #fff;
      font-size: var(--jd-text-lg);
    }
    .jd-photo-album__lb-nav {
      position: absolute;
      inset-block-start: 50%;
      transform: translateY(-50%);
      width: 2.75rem;
      height: 2.75rem;
      border: 0;
      cursor: pointer;
      border-radius: var(--jd-radius-full);
      background: rgba(255, 255, 255, 0.12);
      color: #fff;
      font-size: var(--jd-text-2xl);
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }
    .jd-photo-album__lb-prev {
      inset-inline-start: calc(-1 * var(--jd-space-12));
    }
    .jd-photo-album__lb-next {
      inset-inline-end: calc(-1 * var(--jd-space-12));
    }
    .jd-photo-album__lb-close:hover,
    .jd-photo-album__lb-nav:hover {
      background: rgba(255, 255, 255, 0.24);
    }
    /* 누를 수 있는 것은 눌린 상태를 갖는다 — 백드롭 위 반투명 원반이라 그림자 대신
     면이 한 번 더 밝아지고 살짝 들어간다 */
    .jd-photo-album__lb-close:active,
    .jd-photo-album__lb-nav:active {
      background: rgba(255, 255, 255, 0.32);
    }
    .jd-photo-album__lb-close:active {
      scale: 0.94;
    }
    /* nav는 세로 중앙을 transform으로 잡고 있다 — scale 프로퍼티를 따로 걸면 그 translate가
     함께 축소돼 눌릴 때 버튼이 아래로 밀린다. 한 transform 안에서 같이 말한다. */
    .jd-photo-album__lb-nav:active {
      transform: translateY(-50%) scale(0.94);
    }
    /* 라이트박스는 거의 검은 백드롭 위라 primary 링이 묻힌다 — 여기서만 흰 링을 쓰되
     두께·간격은 포커스 링 레시피의 토큰을 따른다 */
    .jd-photo-album__lb-close:focus-visible,
    .jd-photo-album__lb-nav:focus-visible {
      outline: var(--jd-border-medium) solid #fff;
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-photo-album__lb-counter {
      position: absolute;
      inset-block-end: calc(-1 * var(--jd-space-8));
      inset-inline: 0;
      margin: 0;
      text-align: center;
      color: rgba(255, 255, 255, 0.7);
      font-size: var(--jd-text-xs);
      font-variant-numeric: tabular-nums;
    }
    @media (max-width: 640px) {
      .jd-photo-album__lb-prev {
        inset-inline-start: var(--jd-space-1);
      }
      .jd-photo-album__lb-next {
        inset-inline-end: var(--jd-space-1);
      }
      .jd-photo-album__lb-close {
        inset-block-start: var(--jd-space-1);
        inset-inline-end: var(--jd-space-1);
        background: rgba(0, 0, 0, 0.4);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-photo-album__img,
      .jd-photo-album__caption,
      .jd-photo-album__chip {
        transition: none;
      }
      .jd-photo-album__cell:hover .jd-photo-album__img {
        transform: none;
      }
      .jd-photo-album__cell:active,
      .jd-photo-album__chip:active,
      .jd-photo-album__lb-close:active {
        scale: none;
      }
      .jd-photo-album__lb-nav:active {
        transform: translateY(-50%);
      }
    }
  }

  @layer junds.base {
    jd-photo-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-photo-card {
      display: block;
    }

    .jd-photo-card__figure {
      margin: 0;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
    }

    jd-photo-card[interactive] > .jd-photo-card__figure {
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-photo-card[interactive]:hover > .jd-photo-card__figure,
    jd-photo-card[interactive]:focus-within > .jd-photo-card__figure {
      transform: translateY(-2px); /* v2 -translate-y-0.5 */
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    }

    .jd-photo-card__frame {
      position: relative;
      aspect-ratio: var(--jd-photo-card-ratio, 4 / 5);
      background: var(--jd-color-card-hover); /* 로드 전 빈 프레임이 흰 구멍이 되지 않게 */
    }

    .jd-photo-card__img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .jd-photo-card__badge {
      position: absolute;
      inset-block-start: var(--jd-space-2);
      inset-inline-end: var(--jd-space-2);
      display: inline-flex;
      align-items: center;
      padding: 0.125rem var(--jd-space-2); /* v2 px-2 py-0.5 */
      color: #fff;
      background: rgba(0, 0, 0, 0.6);
      border-radius: var(--jd-radius-full);
      font-size: 10px; /* v2 text-[10px] — 대응 토큰 없음(jd-badge 선례) */
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      backdrop-filter: blur(4px);
    }
    .jd-photo-card__badge[hidden] {
      display: none;
    }

    .jd-photo-card__caption {
      padding: var(--jd-space-3);
    }
    .jd-photo-card__caption[hidden] {
      display: none;
    }

    .jd-photo-card__text {
      margin: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-photo-card__text[hidden] {
      display: none;
    }

    .jd-photo-card__meta {
      margin: var(--jd-space-0-5) 0 0;
      font-size: 11px; /* v2 text-[11px] */
      color: var(--jd-color-muted);
    }
    .jd-photo-card__meta[hidden] {
      display: none;
    }

    .jd-photo-card__stats {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      margin-block-start: var(--jd-space-2);
      font-size: 11px;
      color: var(--jd-color-muted);
    }
    .jd-photo-card__stats[hidden] {
      display: none;
    }

    .jd-photo-card__stat {
      display: inline-flex;
      align-items: center;
      gap: 0.25em;
      font-variant-numeric: tabular-nums;
    }
    .jd-photo-card__stat[hidden] {
      display: none;
    }

    /* 이름은 화면에서만 감춘다 — AT는 "좋아요 142"로 읽는다 */
    .jd-photo-card__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-photo-card[interactive] > .jd-photo-card__figure {
        transition: none;
      }
      jd-photo-card[interactive]:hover > .jd-photo-card__figure,
      jd-photo-card[interactive]:focus-within > .jd-photo-card__figure {
        transform: none;
      }
    }
  }

  @layer junds.base {
    jd-photo-carousel:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-photo-carousel {
      display: block;
      position: relative;
      overflow: hidden;
      background: #000;
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
    }
    /* v2는 photos가 비면 아무것도 렌더하지 않았다 */
    jd-photo-carousel[data-empty] {
      display: none;
    }

    jd-photo-carousel > .jd-carousel__track {
      aspect-ratio: var(--jd-photo-carousel-ratio, 16 / 9);
    }
    jd-photo-carousel .jd-carousel__track:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: -2px;
    }

    .jd-photo-carousel__figure {
      position: relative;
      width: 100%;
      height: 100%;
      margin: 0;
    }
    .jd-photo-carousel__img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    .jd-photo-carousel__caption {
      position: absolute;
      inset-block-end: 0;
      inset-inline: 0;
      margin: 0;
      padding: var(--jd-space-4);
      color: #fff;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
      background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
    }
    .jd-photo-carousel__caption[hidden] {
      display: none;
    }

    /* ── 컨트롤 스킨 ─────────────────────────────────────────── */
    jd-photo-carousel .jd-carousel__arrow {
      width: 2.25rem;
      height: 2.25rem;
      color: #fff;
      background: rgba(255, 255, 255, 0.2);
      border: 0;
      box-shadow: none;
      backdrop-filter: blur(4px);
      opacity: var(--jd-opacity-100);
    }
    jd-photo-carousel .jd-carousel__arrow:hover {
      background: rgba(255, 255, 255, 0.3);
    }
    jd-photo-carousel .jd-carousel__arrow:focus-visible {
      outline-color: #fff;
    }
    jd-photo-carousel .jd-carousel__arrow > svg {
      width: 1.125rem;
      height: 1.125rem;
    }
    jd-photo-carousel .jd-carousel__arrow[data-dir="prev"] {
      inset-inline-start: var(--jd-space-3);
    }
    jd-photo-carousel .jd-carousel__arrow[data-dir="next"] {
      inset-inline-end: var(--jd-space-3);
    }

    jd-photo-carousel .jd-carousel__dots {
      position: absolute;
      inset-inline: 0;
      inset-block-end: var(--jd-space-3);
      margin-block-start: 0;
    }
    jd-photo-carousel .jd-carousel__dot {
      width: 0.375rem; /* v2 w-1.5 */
      height: 0.375rem;
      background: rgba(255, 255, 255, 0.5);
    }
    jd-photo-carousel .jd-carousel__dot:hover {
      background: rgba(255, 255, 255, 0.8);
    }
    jd-photo-carousel .jd-carousel__dot[data-active] {
      width: 1.25rem; /* v2 w-5 */
      background: #fff;
    }
    jd-photo-carousel .jd-carousel__dot:focus-visible {
      outline-color: #fff;
    }
  }

  @layer junds.base {
    jd-photo-filters:not(:defined) {
      display: flex;
    }
    jd-photo-filters:not(:defined) > script {
      display: none;
    }
  }
  @layer junds.components {
    jd-photo-filters {
      display: flex;
      gap: var(--jd-space-2);
      overflow-x: auto;
      padding-block: var(--jd-space-2);
      padding-inline: var(--jd-space-2);
      margin-inline: calc(var(--jd-space-2) * -1); /* v2 -mx-2 px-2: 스크롤 여백을 밖으로 뺀다 */
      scroll-snap-type: x proximity;
      font-family: var(--jd-font-sans);
    }

    .jd-photo-filters__item {
      display: flex;
      flex: 0 0 auto;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1-5);
      color: var(--jd-color-foreground);
      border-radius: var(--jd-radius-lg);
      scroll-snap-align: start;
      cursor: pointer;
      user-select: none;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-photo-filters__item:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-photo-filters__item[data-active] {
      color: var(--jd-color-primary-ink);
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
    }
    .jd-photo-filters__item[data-disabled] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    /* 라디오는 시각적으로만 감춘다 (jd-filter-button-group 관용구) */
    .jd-photo-filters__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-photo-filters__item:has(.jd-photo-filters__input:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-photo-filters__thumb {
      display: block;
      box-sizing: border-box;
      width: 3.5rem; /* v2 w-14 */
      height: 3.5rem;
      overflow: hidden;
      background: var(--jd-color-card-hover);
      border: var(--jd-border-medium) solid transparent;
      border-radius: var(--jd-radius-md);
    }
    .jd-photo-filters__item[data-active] .jd-photo-filters__thumb {
      border-color: var(--jd-color-primary);
    }
    .jd-photo-filters__img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .jd-photo-filters__label {
      font-size: 11px; /* v2 text-[11px] — 대응 토큰 없음 */
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-normal);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-photo-filters__item {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-photo-grid:not(:defined) {
      display: grid;
    }
  }
  @layer junds.components {
    /* ── 기본 = uniform · columns 3 ─────────────────────────────── */
    jd-photo-grid {
      display: grid;
      gap: var(--jd-space-2);
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    jd-photo-grid[columns="2"] {
      grid-template-columns: repeat(1, minmax(0, 1fr));
    }

    @media (min-width: 640px) {
      jd-photo-grid,
      jd-photo-grid[columns="3"],
      jd-photo-grid[columns="4"],
      jd-photo-grid[columns="5"] {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }
      jd-photo-grid[columns="2"] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
    }
    @media (min-width: 1024px) {
      jd-photo-grid[columns="4"] {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
      jd-photo-grid[columns="5"] {
        grid-template-columns: repeat(5, minmax(0, 1fr));
      }
    }

    /* ── masonry — 폭만 같고 높이는 자유(multicol) ────────────────── */
    jd-photo-grid[layout="masonry"] {
      display: block;
      column-count: 2;
    }
    jd-photo-grid[layout="masonry"][columns="2"] {
      column-count: 1;
    }
    jd-photo-grid[layout="masonry"] > * {
      break-inside: avoid;
      margin-block-end: var(--jd-photo-grid-masonry-gap, var(--jd-space-2));
    }
    @media (min-width: 640px) {
      jd-photo-grid[layout="masonry"],
      jd-photo-grid[layout="masonry"][columns="3"],
      jd-photo-grid[layout="masonry"][columns="4"],
      jd-photo-grid[layout="masonry"][columns="5"] {
        column-count: 3;
      }
      jd-photo-grid[layout="masonry"][columns="2"] {
        column-count: 2;
      }
    }
    @media (min-width: 1024px) {
      jd-photo-grid[layout="masonry"][columns="4"] {
        column-count: 4;
      }
      jd-photo-grid[layout="masonry"][columns="5"] {
        column-count: 5;
      }
    }

    /* ── mosaic — 첫 항목이 2×2, 나머지는 자동 배치 (columns 무시, v2 동형) ── */
    jd-photo-grid[layout="mosaic"] {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      grid-template-rows: repeat(2, minmax(0, 1fr));
    }
    jd-photo-grid[layout="mosaic"] > :first-child {
      grid-column: span 2;
      grid-row: span 2;
    }
  }

  @layer junds.base {
    jd-photo-lightbox:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-photo-lightbox > .jd-modal__backdrop {
      background: rgba(0, 0, 0, 0.95);
      backdrop-filter: none;
    }

    .jd-photo-lightbox__panel {
      width: 100%;
      height: 100%;
      max-width: none;
      max-height: none;
      align-items: center;
      justify-content: center;
      overflow: visible;
      color: #fff;
      background: none;
      border-radius: var(--jd-radius-none);
      box-shadow: none;
      pointer-events: none;
    }
    .jd-photo-lightbox__close,
    .jd-photo-lightbox__nav,
    .jd-photo-lightbox__figure {
      pointer-events: auto;
    }

    /* ── 컨트롤 ─────────────────────────────────────────────── */
    .jd-photo-lightbox__close,
    .jd-photo-lightbox__nav {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 2.5rem;
      height: 2.5rem;
      padding: 0;
      color: #fff;
      background: rgba(255, 255, 255, 0.1);
      border: 0;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      /* 검은 화면 위 반투명 원은 위에서 빛을 받는 면으로 그려야 단추로 읽힌다 */
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-photo-lightbox__close:hover,
    .jd-photo-lightbox__nav:hover {
      background: rgba(255, 255, 255, 0.2);
    }
    .jd-photo-lightbox__close:active,
    .jd-photo-lightbox__nav:active {
      scale: 0.94;
      box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.38);
    }
    .jd-photo-lightbox__close:focus-visible,
    .jd-photo-lightbox__nav:focus-visible {
      outline: var(--jd-border-medium) solid #fff;
      outline-offset: 2px;
    }
    .jd-photo-lightbox__close[hidden],
    .jd-photo-lightbox__nav[hidden] {
      display: none;
    }
    .jd-photo-lightbox__close > svg {
      width: 1.25rem;
      height: 1.25rem;
    }
    .jd-photo-lightbox__nav > svg {
      width: 1.25rem;
      height: 1.25rem;
    }

    .jd-photo-lightbox__close {
      position: absolute;
      inset-block-start: var(--jd-space-4);
      inset-inline-end: var(--jd-space-4);
    }

    /* ── 무대 ───────────────────────────────────────────────── */
    /* 치수를 vw/vh가 아니라 **패널 비율**로 잡는다: 라이트박스는 fixed지만 컨테이닝
     블록이 항상 뷰포트인 것은 아니다(transform·contain: paint 조상이 있으면 그 상자다).
     vh로 재면 무대가 덮개보다 커져 넘치고, 그 상태에서 좌우 버튼이 캡션·순번 위로
     내려앉는다. 또 사진이 없을 때 폭이 0으로 접히면 두 버튼이 한 점에 겹친다(실측) —
     figure에 폭을 확정해 두면 두 증상이 함께 사라진다. */
    .jd-photo-lightbox__figure {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-4);
      margin: 0;
      width: min(90%, 64rem);
      min-width: 0;
      min-height: 0;
      max-height: 100%;
      font-family: var(--jd-font-sans);
    }

    .jd-photo-lightbox__stage {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      flex: 1 1 auto;
      width: 100%;
      min-width: 0;
      /* 좌우 버튼(2.5rem)이 앉을 자리 — 사진이 오기 전에도 무대가 접히지 않는다 */
      min-height: 4rem;
    }
    .jd-photo-lightbox__nav {
      position: absolute;
      inset-block-start: 50%;
      transform: translateY(-50%);
      z-index: 1;
    }
    .jd-photo-lightbox__nav[data-dir="prev"] {
      inset-inline-start: var(--jd-space-2);
    }
    .jd-photo-lightbox__nav[data-dir="next"] {
      inset-inline-end: var(--jd-space-2);
    }

    .jd-photo-lightbox__img {
      display: block;
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
      border-radius: var(--jd-radius-lg);
    }
    .jd-photo-lightbox__img[hidden] {
      display: none;
    }

    /* ── 캡션·순번 ──────────────────────────────────────────── */
    .jd-photo-lightbox__info {
      flex: none;
      width: 100%;
      max-width: 42rem; /* v2 max-w-2xl */
      margin-inline: auto;
      text-align: center;
    }
    .jd-photo-lightbox__caption {
      margin: 0;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
    }
    .jd-photo-lightbox__caption[hidden] {
      display: none;
    }
    .jd-photo-lightbox__counter {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-2xs); /* v2 text-[11px] = 토큰 하한 */
      color: rgba(255, 255, 255, 0.7);
      font-variant-numeric: tabular-nums;
    }
    .jd-photo-lightbox__counter[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-photo-lightbox__close,
      .jd-photo-lightbox__nav {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-photo-uploader:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-photo-uploader {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2); /* v2 space-y-2 */
      font-family: var(--jd-font-sans);
    }

    /* 네이티브 피커는 시각적으로만 숨긴다 (jd-file-upload 관용구) */
    .jd-photo-uploader__input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-photo-uploader__zone {
      display: block;
      box-sizing: border-box;
      width: 100%;
      padding: var(--jd-space-6);
      text-align: center;
      color: var(--jd-color-foreground);
      background: transparent;
      border: var(--jd-border-medium) dashed var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      cursor: pointer;
      transition: border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-photo-uploader__zone:hover {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      background: color-mix(in srgb, var(--jd-color-primary-light) 10%, transparent);
    }
    .jd-photo-uploader__zone[data-drag] {
      border-color: var(--jd-color-primary);
      background: color-mix(in srgb, var(--jd-color-primary-light) 30%, transparent);
    }
    .jd-photo-uploader__zone:focus-visible {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-photo-uploader__zone:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    jd-photo-uploader[error]:not([error=""]) .jd-photo-uploader__zone {
      border-color: color-mix(in srgb, var(--jd-color-danger) 40%, transparent);
    }

    .jd-photo-uploader__desc {
      display: block;
      font-size: var(--jd-text-md); /* v2 text-sm */
    }
    .jd-photo-uploader__count {
      display: block;
      margin-block-start: var(--jd-space-1);
      font-size: 11px; /* v2 text-[11px] */
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }

    .jd-photo-uploader__error {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-danger);
    }
    .jd-photo-uploader__error[hidden] {
      display: none;
    }

    /* ── 미리보기 ───────────────────────────────────────────── */
    .jd-photo-uploader__grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: var(--jd-space-2);
    }
    .jd-photo-uploader__grid[hidden] {
      display: none;
    }
    @media (min-width: 640px) {
      .jd-photo-uploader__grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
      }
    }

    .jd-photo-uploader__item {
      position: relative;
      aspect-ratio: 1;
      overflow: hidden;
      background: var(--jd-color-card-hover);
      border-radius: var(--jd-radius-lg);
    }
    .jd-photo-uploader__thumb {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .jd-photo-uploader__remove {
      position: absolute;
      inset-block-start: var(--jd-space-1);
      inset-inline-end: var(--jd-space-1);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.5rem;
      height: 1.5rem;
      padding: 0;
      color: #fff;
      background: rgba(0, 0, 0, 0.6);
      border: 0;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-photo-uploader__remove:hover {
      background: rgba(0, 0, 0, 0.8);
    }
    .jd-photo-uploader__remove:focus-visible {
      outline: var(--jd-border-medium) solid #fff;
      outline-offset: 1px;
    }
    .jd-photo-uploader__remove:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-photo-uploader__remove > svg {
      width: 0.75rem;
      height: 0.75rem;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-photo-uploader__zone,
      .jd-photo-uploader__remove {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-pie-chart {
      /* 계열색은 hue 팔레트에서만(§8). 공용 기본값은 success/warning/danger를 조각색으로
       써서 "4번 조각"과 "위험"이 한 화면에서 같은 색이 된다 — 구성비는 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 원 200px + 범례가 카드보다 넓으면 범례가 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 정사각
     비율을 대신 말하므로 폭만 줄여도 원이 타원이 되지 않는다. */
    jd-pie-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 9rem);
    }

    .jd-pie-chart__slice {
      fill: var(--jd-series-color);
      fill-rule: evenodd;
      /* 인접한 두 조각의 명도가 비슷하면 경계가 사라진다 — 카드색 실선이 조각을
       떼어 놓는다(면과 면 사이를 색으로만 구분하지 않는다). */
      stroke: var(--jd-color-card);
      stroke-width: 1;
      stroke-linejoin: round;
    }
    .jd-pie-chart__center {
      fill: var(--jd-color-foreground);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
    }

    jd-pie-chart:not(:defined) {
      display: inline-flex;
    }
  }

  @layer junds.components {
    jd-pin-input {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-pin-input__cell {
      box-sizing: border-box;
      width: 2.5rem;
      height: 3rem;
      margin: 0;
      padding: 0;
      text-align: center;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      outline: none;
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-pin-input__cell[data-filled] {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    .jd-pin-input__cell:focus {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-pin-input__cell:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-pin-input[error] .jd-pin-input__cell {
      border-color: var(--jd-color-danger);
      animation: jd-pin-shake var(--jd-duration-slow) var(--jd-easing-ease-in-out);
    }
    jd-pin-input[error] .jd-pin-input__cell:focus {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    @keyframes jd-pin-shake {
      0%,
      100% {
        transform: translateX(0);
      }
      25% {
        transform: translateX(-3px);
      }
      75% {
        transform: translateX(3px);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pin-input__cell {
        transition: none;
      }
      jd-pin-input[error] .jd-pin-input__cell {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-poll-card {
      display: block;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
    }

    .jd-poll-card__question {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }

    .jd-poll-card__options {
      list-style: none;
      margin: var(--jd-space-3) 0 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    .jd-poll-card__option {
      position: relative;
      width: 100%;
      overflow: hidden;
      box-sizing: border-box;
      text-align: left;
      cursor: pointer;
      padding: var(--jd-space-2) var(--jd-space-3);
      font-family: inherit;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: transparent;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      transition: border-color var(--jd-duration-normal) var(--jd-easing-default),
        background-color var(--jd-duration-normal) var(--jd-easing-default);
    }
    .jd-poll-card__option:hover:not(:disabled) {
      border-color: color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }
    .jd-poll-card__option:disabled {
      cursor: default;
    }
    .jd-poll-card__option[aria-pressed="true"] {
      border-color: var(--jd-color-primary);
      background: color-mix(in srgb, var(--jd-color-primary) 5%, transparent);
    }
    .jd-poll-card__option:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-poll-card__bar {
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      background: color-mix(in srgb, var(--jd-color-border) 60%, transparent);
      transition: width var(--jd-duration-slower) var(--jd-easing-default);
    }
    .jd-poll-card__bar[hidden] {
      display: none;
    }
    .jd-poll-card__option[data-top] .jd-poll-card__bar {
      background: color-mix(in srgb, var(--jd-color-warning) 25%, transparent);
    }
    .jd-poll-card__option[aria-pressed="true"] .jd-poll-card__bar {
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
    }

    .jd-poll-card__row {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-poll-card__label {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-poll-card__label-text {
      min-width: 0;
    }
    .jd-poll-card__check {
      flex-shrink: 0;
      color: var(--jd-color-primary-ink);
    }
    .jd-poll-card__check[hidden] {
      display: none;
    }
    .jd-poll-card__pct {
      flex-shrink: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-poll-card__pct[hidden] {
      display: none;
    }

    .jd-poll-card__footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-block-start: var(--jd-space-3);
      font-size: 11px;
      color: var(--jd-color-muted);
    }
    .jd-poll-card__closes[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-poll-card__option,
      .jd-poll-card__bar {
        transition: none;
      }
    }
  }

  @layer junds.base {
    /* 업그레이드 전(§3.2): 트리거만 보이고 패널이 될 children은 감춘다 */
    jd-popover:not(:defined) {
      display: inline-block;
    }
    jd-popover:not(:defined) > :not([slot="trigger"]) {
      display: none;
    }
  }
  @layer junds.components {
    jd-popover {
      position: relative;
      display: inline-block;
    }

    .jd-popover__trigger {
      display: contents;
    }
    /* 합성 트리거(포커스 가능한 자식이 없어 래퍼가 승격된 경우)만 실체를 가진다 */
    .jd-popover__trigger[tabindex] {
      display: inline-flex;
      align-items: center;
    }
    .jd-popover__trigger[role="button"] {
      cursor: pointer;
    }
    .jd-popover__trigger[tabindex]:focus-visible {
      outline: none;
      border-radius: var(--jd-radius-md);
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-popover__panel {
      --jd-popover-offset: var(--jd-space-1);
      --jd-popover-tx: 0;
      --jd-popover-ty: 0;
      /* 꼬리 반폭. 0이면 ::after가 0×0이라 그려지지 않는다 — 파생(Dropdown·ContextMenu처럼
       메뉴 표면인 것들)은 아무것도 하지 않으면 꼬리가 없다. 켤 파생만 값을 준다. */
      --jd-popover-arrow: 0px;
      --jd-popover-arrow-face: var(--jd-color-card);
      position: absolute;
      z-index: var(--jd-z-popover);
      translate: var(--jd-popover-tx) var(--jd-popover-ty);
      /* 기본 side=bottom · align=left */
      top: 100%;
      bottom: auto;
      left: 0;
      right: auto;
      margin-block-start: var(--jd-popover-offset);
      box-sizing: border-box;
      /* 절대 배치 상자는 shrink-to-fit이라 컨테이닝 블록(=트리거 폭)에 갇힌다 —
       버튼 하나짜리 앵커에서 패널이 세로로 찌그러지는 실측 문제. max-content로
       내용 폭을 쓰되 뷰포트를 넘지 않게 상한을 둔다. */
      width: max-content;
      max-width: min(24rem, calc(100vw - 2rem));
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      /* 떠 있는 것의 테두리는 눅인다 — 실선 border는 그림자 위에서 두 번 그은 선이 된다 */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      border-radius: var(--jd-radius-xl);
      box-shadow: var(--jd-shadow-xl);
      backdrop-filter: blur(2px);
      padding: var(--jd-space-4);
    }
    .jd-popover__panel[hidden] {
      display: none;
    }
    /* 원형(jd-popover) 자신은 꼬리를 켠다. 꼬리(6px)가 간격(4px)보다 크면 트리거를
     파고들므로 오프셋도 함께 올린다. 파생은 각자 시트에서 켜고 끈다. */
    jd-popover > .jd-popover__panel {
      --jd-popover-arrow: 6px;
      --jd-popover-offset: var(--jd-space-2);
    }

    /* ── 꼬리 ──
     앵커를 가리키지 않는 패널은 "어디서 나온 상자인지"를 말하지 않는다(§7 어포던스).
     테두리 삼각형이라 패널 면색 하나만 물려받으면 되고, 스킨을 바꾸는 파생은
     --jd-popover-arrow-face 한 줄만 갈아 끼운다. 기본 side=bottom · align=left는
     attribute로 반영되지 않으므로(§1.3) base 규칙이 담당한다. */
    .jd-popover__panel::after {
      content: "";
      position: absolute;
      border: var(--jd-popover-arrow) solid transparent;
      pointer-events: none;
      /* side=bottom — 꼬리는 패널 위쪽 모서리에서 트리거를 향해 선다 */
      bottom: 100%;
      border-top-width: 0;
      border-bottom-color: var(--jd-popover-arrow-face);
      left: var(--jd-space-4);
    }
    /* align이 먼저, side가 뒤 — 기하 규칙과 같은 서열이다(side=left/right는 정렬을
     수직 중앙으로 고정하므로 align이 쓴 가로 좌표를 되돌려야 한다). */
    [align="left"] > .jd-popover__panel::after {
      left: var(--jd-space-4);
      right: auto;
      margin-inline-start: 0;
    }
    [align="center"] > .jd-popover__panel::after {
      left: 50%;
      right: auto;
      margin-inline-start: calc(-1 * var(--jd-popover-arrow));
    }
    [align="right"] > .jd-popover__panel::after {
      left: auto;
      right: var(--jd-space-4);
      margin-inline-start: 0;
    }
    [side="bottom"] > .jd-popover__panel::after {
      top: auto;
      bottom: 100%;
      margin-block-start: 0;
      border-width: var(--jd-popover-arrow);
      border-top-width: 0;
      border-top-color: transparent;
      border-bottom-color: var(--jd-popover-arrow-face);
    }
    [side="top"] > .jd-popover__panel::after {
      bottom: auto;
      top: 100%;
      margin-block-start: 0;
      border-width: var(--jd-popover-arrow);
      border-bottom-width: 0;
      border-bottom-color: transparent;
      border-top-color: var(--jd-popover-arrow-face);
    }
    [side="left"] > .jd-popover__panel::after,
    [side="right"] > .jd-popover__panel::after {
      bottom: auto;
      top: 50%;
      margin-block-start: calc(-1 * var(--jd-popover-arrow));
      margin-inline-start: 0;
      border-width: var(--jd-popover-arrow);
      border-bottom-color: transparent;
      border-top-color: transparent;
    }
    [side="left"] > .jd-popover__panel::after {
      left: 100%;
      right: auto;
      border-right-width: 0;
      border-left-color: var(--jd-popover-arrow-face);
    }
    [side="right"] > .jd-popover__panel::after {
      left: auto;
      right: 100%;
      border-left-width: 0;
      border-right-color: var(--jd-popover-arrow-face);
    }

    /* ── align (side=top/bottom에서 유효) ──
     파생이 자기 기본값을 낮은 특이도(0,1,1)로 선언하므로, **명시 attribute 규칙은
     축을 완전히 리셋**해야 파생 기본값을 확실히 이긴다(0,2,0). */
    [align="left"] > .jd-popover__panel {
      left: 0;
      right: auto;
      --jd-popover-tx: 0;
    }
    [align="right"] > .jd-popover__panel {
      left: auto;
      right: 0;
      --jd-popover-tx: 0;
    }
    [align="center"] > .jd-popover__panel {
      left: 50%;
      right: auto;
      --jd-popover-tx: -50%;
    }

    /* ── side ── (align 뒤에 온다 — left/right는 정렬을 수직 중앙으로 고정한다) */
    [side="bottom"] > .jd-popover__panel {
      top: 100%;
      bottom: auto;
      margin-block: var(--jd-popover-offset) 0;
      --jd-popover-ty: 0;
    }
    [side="top"] > .jd-popover__panel {
      top: auto;
      bottom: 100%;
      margin-block: 0 var(--jd-popover-offset);
      --jd-popover-ty: 0;
    }
    [side="left"] > .jd-popover__panel,
    [side="right"] > .jd-popover__panel {
      top: 50%;
      bottom: auto;
      margin-block: 0;
      --jd-popover-tx: 0;
      --jd-popover-ty: -50%;
    }
    [side="left"] > .jd-popover__panel {
      left: auto;
      right: 100%;
      margin-inline: 0 var(--jd-popover-offset);
    }
    [side="right"] > .jd-popover__panel {
      left: 100%;
      right: auto;
      margin-inline: var(--jd-popover-offset) 0;
    }

    .jd-popover__label {
      display: block;
    }

    @media (prefers-reduced-motion: no-preference) {
      [open] > .jd-popover__panel {
        animation: jd-popover-in var(--jd-duration-fast) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-popover-in {
      from {
        opacity: 0;
        scale: 0.96;
      }
    }
  }

  @layer junds.components {
    jd-portfolio-council {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-warning: var(--bm-warning, var(--jd-color-warning));

      display: block;
      box-sizing: border-box;
      /* 셀 여백 계단의 기준은 뷰포트가 아니라 이 카드가 실제로 받은 폭이다.
       inline-size 컨테이너는 내용이 폭을 정하지 못해, 폭을 명시하지 않으면 flex 문맥에서
       호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-pc / inline-size;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
      box-shadow: var(--jd-shadow-sm);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-portfolio-council * {
      box-sizing: border-box;
    }

    /* 스켈레톤 */
    jd-portfolio-council .jd-portfolio-council__skeleton {
      height: 128px;
      margin: var(--jd-space-5);
      border-radius: var(--jd-radius-lg);
      background: linear-gradient(
        90deg,
        var(--jd-fin-soft) 25%,
        color-mix(in srgb, var(--jd-fin-muted) 14%, transparent) 37%,
        var(--jd-fin-soft) 63%
      );
      background-size: 400% 100%;
      animation: jd-pc-shimmer 1.4s ease infinite;
    }
    @keyframes jd-pc-shimmer {
      0% {
        background-position: 100% 0;
      }
      100% {
        background-position: 0 0;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-portfolio-council .jd-portfolio-council__skeleton {
        animation: none;
      }
    }

    /* 빈 상태 */
    jd-portfolio-council .jd-portfolio-council__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-12) var(--jd-space-6);
    }
    jd-portfolio-council .jd-portfolio-council__empty-icon {
      color: var(--jd-fin-muted);
      margin-block-end: var(--jd-space-1);
    }
    jd-portfolio-council .jd-portfolio-council__empty-title {
      font-size: var(--jd-text-md);
      font-weight: 800;
      color: var(--jd-fin-text);
    }
    jd-portfolio-council .jd-portfolio-council__empty-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-fin-muted);
      max-width: 30ch;
    }

    /* 헤더 */
    jd-portfolio-council .jd-portfolio-council__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3-5) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-portfolio-council .jd-portfolio-council__title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
    }
    jd-portfolio-council .jd-portfolio-council__icon {
      color: var(--jd-fin-accent);
    }
    jd-portfolio-council .jd-portfolio-council__count {
      font-size: 11px;
      font-weight: 700;
      color: var(--jd-fin-muted);
    }

    /* 표 — 7열 nowrap은 좁은 카드 폭을 넘는다. 잘린 채 끝나는 것과 굴릴 수 있는 것은
     다르다(§6, 형제 jd-live-stock-table과 동일 관용구). 스크롤 끝에서 페이지가 이어
     밀리지 않게 막고, 스크롤바는 표를 가리지 않도록 가늘게. */
    jd-portfolio-council .jd-portfolio-council__scroll {
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      -webkit-overflow-scrolling: touch;
    }
    jd-portfolio-council .jd-portfolio-council__caption {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0 0 0 0);
      white-space: nowrap;
      border: 0;
    }
    jd-portfolio-council .jd-portfolio-council__table {
      width: 100%;
      /* 일곱 열이 다 읽히는 최소 폭 — 이보다 좁으면 셀을 구기지 말고 굴린다.
       이 바닥이 없으면 표가 컨테이너에 맞춰 줄다가 "현재가" 열이 잘려 나간다(실측). */
      min-width: 40rem;
      border-collapse: collapse;
      font-size: var(--jd-text-sm);
    }
    jd-portfolio-council .jd-portfolio-council__table th {
      text-align: start;
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
      white-space: nowrap;
    }
    jd-portfolio-council .jd-portfolio-council__table td {
      padding: var(--jd-space-3) var(--jd-space-4);
      vertical-align: middle;
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
      white-space: nowrap;
    }
    /* 셀 좌우 여백은 열이 일곱이면 그 자체로 7rem을 먹는다 — 카드가 좁을 때만 좁혀
     스크롤 거리를 줄인다. 기준은 뷰포트가 아니라 카드가 실제로 받은 폭이다. */
    @container jd-pc (max-width: 34rem) {
      jd-portfolio-council .jd-portfolio-council__table th,
      jd-portfolio-council .jd-portfolio-council__table td {
        padding-inline: var(--jd-space-3);
      }
    }
    jd-portfolio-council .jd-portfolio-council__table tbody tr:last-child td {
      border-block-end: none;
    }
    jd-portfolio-council .jd-portfolio-council__table tr[data-divergence] td {
      background: color-mix(in srgb, var(--jd-fin-warning) 8%, transparent);
    }

    jd-portfolio-council .jd-portfolio-council__num {
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-portfolio-council .jd-portfolio-council__num[data-tone="muted"] {
      color: var(--jd-fin-muted);
    }
    jd-portfolio-council .jd-portfolio-council__num[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-portfolio-council .jd-portfolio-council__num[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-portfolio-council .jd-portfolio-council__strong {
      font-weight: 800;
    }

    /* 종목명 */
    jd-portfolio-council .jd-portfolio-council__name {
      font: inherit;
      font-weight: 800;
      color: var(--jd-fin-text);
      background: none;
      border: 0;
      padding: 0;
      cursor: pointer;
      text-decoration: none;
    }
    jd-portfolio-council a.jd-portfolio-council__name:hover,
    jd-portfolio-council button.jd-portfolio-council__name:hover {
      text-decoration: underline;
    }
    jd-portfolio-council .jd-portfolio-council__name:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }
    jd-portfolio-council .jd-portfolio-council__warn {
      margin-inline-start: var(--jd-space-1-5);
      font-size: 10px;
      font-weight: 800;
      padding: 1px var(--jd-space-1-5);
      border-radius: var(--jd-radius-sm);
      background: color-mix(in srgb, var(--jd-fin-warning) 18%, transparent);
      color: color-mix(in srgb, var(--jd-fin-warning) 65%, var(--jd-color-foreground));
    }

    /* 위원회 이모지 */
    jd-portfolio-council .jd-portfolio-council__emojis {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: 2px;
      font-size: 14px;
      line-height: var(--jd-leading-none);
    }

    /* 의견 */
    jd-portfolio-council .jd-portfolio-council__verdict {
      font-weight: 800;
    }
    jd-portfolio-council .jd-portfolio-council__verdict[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-portfolio-council .jd-portfolio-council__verdict[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-portfolio-council .jd-portfolio-council__verdict[data-tone="flat"] {
      color: var(--jd-fin-muted);
    }
    jd-portfolio-council .jd-portfolio-council__ratio {
      margin-inline-start: var(--jd-space-1-5);
      font-size: 10.5px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
    }
  }

  @layer junds.components {
    /* 호스트 오버레이 규칙은 jd-modal 태그 셀렉터라 파생 태그로 캐스케이드되지 않는다
     — 다시 선언한다(jd-holding-form-modal 선례). 패널 폭은 v2 size="lg"(42rem). */
    jd-portfolio-day-detail-modal:not(:defined) {
      display: none;
    }
    jd-portfolio-day-detail-modal {
      display: none;
    }
    jd-portfolio-day-detail-modal[open] {
      display: flex;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-modal);
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-4);
    }
    jd-portfolio-day-detail-modal > .jd-modal__panel {
      max-width: min(42rem, calc(100vw - 2rem));
    }

    jd-portfolio-day-detail-modal {
      --jd-pddm-soft: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }

    .jd-pddm__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-4) var(--jd-space-5) var(--jd-space-2);
      font-weight: 800;
    }
    .jd-pddm__title {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: 800;
    }
    .jd-pddm__close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 1.75rem;
      height: 1.75rem;
      border: 0;
      border-radius: var(--jd-radius-lg);
      background: transparent;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-pddm__close:hover {
      background: var(--jd-pddm-soft);
      color: var(--jd-color-foreground);
    }
    .jd-pddm__close:active {
      scale: 0.94;
    }
    /* 이 버튼은 data-autofocus 대상이라 다이얼로그가 열리는 순간 포커스를 받는다 —
     표시가 없으면 키보드 사용자는 열린 직후 자기 커서가 어디 있는지 알 수 없다.
     패널은 overflow:auto지만 헤더 패딩(space-4/5)이 링보다 넓어 잘리지 않는다. */
    .jd-pddm__close:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-pddm__close svg {
      width: 16px;
      height: 16px;
    }

    .jd-pddm__empty {
      padding: var(--jd-space-2) var(--jd-space-5) var(--jd-space-6);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-pddm__content {
      padding: var(--jd-space-1) var(--jd-space-5) var(--jd-space-5);
      max-height: 75vh;
      overflow-y: auto;
    }

    .jd-pddm__grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--jd-space-3);
    }
    @media (min-width: 640px) {
      .jd-pddm__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }

    /* 채움만 있는 타일은 색종이로 읽힌다 — 위에서 받는 빛을 함께 준다(§2) */
    .jd-pddm__stat {
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      background: var(--jd-pddm-soft);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 10.5px는 §9 하한(2xs=11px) 미달이었다 — 지표 이름은 값과 짝이라 읽혀야 한다 */
    .jd-pddm__stat-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }
    .jd-pddm__stat-value {
      margin-block-start: var(--jd-space-0-5);
      font-size: 15px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-pddm__stat-unit {
      margin-inline-start: var(--jd-space-0-5);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      opacity: var(--jd-opacity-70);
    }

    .jd-pddm__section {
      margin: var(--jd-space-5) 0 var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: 800;
    }

    .jd-pddm__table-wrap {
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-pddm__table {
      width: 100%;
      border-collapse: collapse;
      font-size: 12.5px;
      font-variant-numeric: tabular-nums;
    }
    .jd-pddm__table thead {
      background: var(--jd-pddm-soft);
      color: var(--jd-color-muted);
      font-size: 11px;
      font-weight: var(--jd-weight-bold);
    }
    .jd-pddm__table th,
    .jd-pddm__table td {
      padding: var(--jd-space-2) var(--jd-space-3);
      text-align: left;
      font-weight: var(--jd-weight-normal);
    }
    .jd-pddm__table th[data-align="right"],
    .jd-pddm__table td[data-align="right"] {
      text-align: right;
    }
    .jd-pddm__table tbody tr {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-pddm__td-name {
      font-weight: var(--jd-weight-bold);
    }
    .jd-pddm__td-amount {
      font-weight: var(--jd-weight-semibold);
    }
    .jd-pddm__td-fee {
      color: var(--jd-color-muted);
    }
    .jd-pddm__td-pl {
      font-weight: 800;
    }

    /* 10.5px는 §9 하한 미달이었다 — 매수/매도는 이 표에서 가장 먼저 읽는 글자다 */
    .jd-pddm__side {
      display: inline-block;
      padding: var(--jd-space-px) var(--jd-space-1-5);
      border-radius: var(--jd-radius-sm);
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-pddm__side[data-side="sell"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 12%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 65%,
        var(--jd-color-foreground)
      );
    }
    .jd-pddm__side[data-side="buy"] {
      background: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 12%,
        transparent
      );
      color: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 65%,
        var(--jd-color-foreground)
      );
    }

    .jd-pddm__note {
      margin: var(--jd-space-4) 0 0;
      font-size: 11.5px;
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pddm__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-portfolio-heatmap {
      display: block;
      box-sizing: border-box; /* 스타일 프롭 w/maxW + border 병용 (DEC-014-9, jd-card 선례) */
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
      padding: var(--jd-space-4);
      overflow: hidden;
    }

    .jd-ph__header {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      flex-wrap: wrap;
      margin-block-end: var(--jd-space-3);
    }
    .jd-ph__title {
      margin: 0;
      font-size: 15px;
      font-weight: 800;
    }
    .jd-ph__sub {
      font-size: 11px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }

    .jd-ph__stats {
      margin-inline-start: auto;
      display: grid;
      grid-template-columns: repeat(3, auto);
      gap: var(--jd-space-3);
    }
    .jd-ph__stat {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      line-height: var(--jd-leading-tight);
      font-variant-numeric: tabular-nums;
    }
    .jd-ph__stat-label {
      font-size: 10px;
      font-weight: 800;
      color: var(--jd-color-muted);
    }
    .jd-ph__stat-value {
      font-size: 13px;
      font-weight: 800;
    }
    .jd-ph__stat-sub {
      font-size: 10.5px;
      font-weight: var(--jd-weight-bold);
    }
    .jd-ph__stat-sub:empty {
      display: none;
    }

    .jd-ph__map {
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
    }
    .jd-ph__svg {
      display: block;
      max-width: 100%;
      height: auto;
    }
    .jd-ph__bg {
      fill: var(--jd-color-card);
    }

    /* 칸 색(fill)은 데이터라 element가 인라인 style로 싣는다 — 표시 속성이 아니라 style인
     이유는 그 값이 --jd-finance-* 훅을 경유하는 color-mix라서다(표시 속성은 var()를 풀지
     못한다). 세기 램프는 element의 heatmapColor 주석 참조. */
    .jd-ph__cell rect {
      stroke: color-mix(in srgb, var(--jd-color-card) 85%, transparent);
      stroke-width: 1;
    }
    .jd-ph__cell text {
      fill: #fff;
      text-anchor: middle;
      dominant-baseline: middle;
      pointer-events: none;
      filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55));
    }
    .jd-ph__cell-name {
      font-weight: 800;
    }
    .jd-ph__cell-sub {
      font-weight: var(--jd-weight-bold);
      fill: rgba(255, 255, 255, 0.95);
    }
    .jd-ph__cell-price {
      fill: rgba(255, 255, 255, 0.78);
      filter: none;
    }

    /* 시각적으로 숨긴 대체 목록 (jd-treemap-chart sr 규칙과 동형) */
    .jd-ph__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      border: 0;
      overflow: hidden;
      clip: rect(0 0 0 0);
      clip-path: inset(50%);
      white-space: nowrap;
      list-style: none;
    }
  }

  @layer junds.components {
    jd-position-bar {
      --jd-position-bar-color: var(--jd-finance-up, var(--jd-color-success));
      position: relative;
      display: block;
      /* 자식이 전부 절대배치라 내용 폭이 0이다 — flex/inline 문맥에서 호스트가 접히면
       정중앙 마커 2px 한 줄만 남아 "고장난 것"으로 읽힌다(실측). 바닥을 깔아 둔다. */
      min-width: 4rem;
      height: 0.5rem;
      border-radius: var(--jd-radius-full);
      /* 빈 데이터(low=high=cur=0)일 때 남는 것은 트랙뿐이다. 홈이 파인 면으로 그려 두면
       그 상태가 "구간 없음"으로 읽힌다 — 옅은 실선 한 줄은 결함으로 읽힌다. */
      background: var(--jd-color-control-track);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
      overflow: visible;
    }
    jd-position-bar[tone="down"] {
      --jd-position-bar-color: var(--jd-finance-down, var(--jd-color-danger));
    }

    .jd-position-bar__band {
      position: absolute;
      inset-block-start: 0;
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-position-bar-color) 22%, transparent);
    }
    .jd-position-bar__fill {
      position: absolute;
      inset-block-start: 0;
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: var(--jd-position-bar-color);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 마커는 채움 위에도 올라간다 — 같은 명도끼리 닿으면 사라지므로 면 색 테두리로 뗀다 */
    .jd-position-bar__marker {
      position: absolute;
      inset-block-start: 50%;
      inset-inline-start: 50%;
      transform: translate(-50%, -50%);
      width: 2px;
      height: 0.75rem;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-foreground);
      box-shadow: 0 0 0 var(--jd-border-thin) var(--jd-color-card), var(--jd-shadow-xs);
    }
  }

  @layer junds.components {
    jd-post-card {
      display: block;
    }

    .jd-post-card {
      border-radius: var(--jd-radius-xl);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      padding: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-post-card[clickable] .jd-post-card {
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-post-card[clickable] .jd-post-card:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-post-card[role="button"]:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }

    .jd-post-card__header {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-post-card__avatar-img,
    .jd-post-card__avatar-fallback {
      width: 2.5rem;
      height: 2.5rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      flex-shrink: 0;
    }
    .jd-post-card__avatar-fallback {
      display: flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      /* 틴트 위 이니셜: 원색 대신 foreground 혼합으로 대비 확보(emoji-picker 선례·§4). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-weight: var(--jd-weight-semibold);
      user-select: none;
    }
    .jd-post-card__avatar-img[hidden],
    .jd-post-card__avatar-fallback[hidden] {
      display: none;
    }

    .jd-post-card__meta {
      min-width: 0;
      flex: 1;
    }
    .jd-post-card__name-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-post-card__name {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-post-card__verified {
      color: var(--jd-color-primary-ink);
      font-size: var(--jd-text-xs);
    }
    .jd-post-card__verified[hidden] {
      display: none;
    }

    .jd-post-card__sub {
      margin: 0;
      font-size: 11px;
      color: var(--jd-color-muted);
      display: flex;
      align-items: center;
    }
    .jd-post-card__dot {
      margin: 0 var(--jd-space-1);
    }
    .jd-post-card__handle[hidden],
    .jd-post-card__dot[hidden],
    .jd-post-card__time[hidden] {
      display: none;
    }

    .jd-post-card__content {
      margin-top: var(--jd-space-3);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
      white-space: pre-wrap;
    }

    .jd-post-card__media {
      margin-top: var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-post-card__media:empty {
      display: none;
    }
    .jd-post-card__media img,
    .jd-post-card__media video {
      display: block;
      width: 100%;
      max-width: 100%;
    }

    .jd-post-card__footer {
      margin-top: var(--jd-space-3);
      margin-inline: calc(-1 * var(--jd-space-2));
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    .jd-post-card__footer[hidden] {
      display: none;
    }

    .jd-post-card__action {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      border: 0;
      border-radius: var(--jd-radius-full);
      background: transparent;
      color: var(--jd-color-muted);
      font-size: var(--jd-text-xs);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-post-card__action:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-post-card__action:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-post-card__action[hidden] {
      display: none;
    }
    .jd-post-card__like[aria-pressed="true"] {
      color: #f43f5e;
    }
    .jd-post-card__count {
      font-variant-numeric: tabular-nums;
    }
    .jd-post-card__count[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-price-badge {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-family: var(--jd-font-sans);
      font-variant-numeric: tabular-nums;
      font-size: 14px;
      font-weight: var(--jd-weight-bold);
      line-height: 1;
      color: var(--jd-color-muted);
    }
    jd-price-badge[size="sm"] {
      font-size: 12px;
    }
    jd-price-badge[no-bold] {
      font-weight: var(--jd-weight-medium);
    }

    jd-price-badge[data-trend="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    jd-price-badge[data-trend="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
    jd-price-badge[data-trend="flat"] {
      color: var(--jd-color-muted);
    }

    .jd-price-badge__arrow {
      display: inline-block;
      width: 11px;
      height: 11px;
      flex-shrink: 0;
    }
    .jd-price-badge__arrow--hidden {
      display: none;
    }
    .jd-price-badge__value {
      display: inline;
    }
  }

  @layer junds.base {
    jd-price-display:not(:defined) {
      display: inline-flex;
    }
  }
  @layer junds.components {
    jd-price-display {
      display: inline-flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    jd-price-display[layout="stacked"] {
      flex-direction: column;
      align-items: flex-start;
      gap: var(--jd-space-0-5);
    }

    .jd-price-display__current {
      display: inline-flex;
      align-items: baseline;
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }
    .jd-price-display__suffix {
      margin-inline-start: var(--jd-space-0-5);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }
    .jd-price-display__discount {
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-danger);
    }
    .jd-price-display__original {
      color: var(--jd-color-muted);
      text-decoration: line-through;
      font-variant-numeric: tabular-nums;
    }

    /* size md (기본) */
    .jd-price-display__current,
    .jd-price-display__discount {
      font-size: var(--jd-text-lg);
    }
    .jd-price-display__original {
      font-size: var(--jd-text-xs);
    }

    jd-price-display[size="sm"] .jd-price-display__current,
    jd-price-display[size="sm"] .jd-price-display__discount {
      font-size: var(--jd-text-md);
    }
    jd-price-display[size="sm"] .jd-price-display__original {
      font-size: var(--jd-text-xs);
    }

    jd-price-display[size="lg"] .jd-price-display__current,
    jd-price-display[size="lg"] .jd-price-display__discount {
      font-size: var(--jd-text-2xl);
    }
    jd-price-display[size="lg"] .jd-price-display__original {
      font-size: var(--jd-text-md);
    }

    jd-price-display[size="xl"] .jd-price-display__current {
      font-size: var(--jd-text-4xl);
    }
    jd-price-display[size="xl"] .jd-price-display__discount {
      font-size: var(--jd-text-3xl);
    }
    jd-price-display[size="xl"] .jd-price-display__original {
      font-size: var(--jd-text-lg);
    }
  }

  @layer junds.base {
    jd-pricing-page:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-pricing-page {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      max-width: 72rem;
      margin-inline: auto;
      padding-inline: var(--jd-space-4);
      padding-block: var(--jd-space-10);
    }
    @media (min-width: 640px) {
      jd-pricing-page {
        padding-block: var(--jd-space-16);
      }
    }

    .jd-pricing-page__head {
      text-align: center;
      margin-block-end: var(--jd-space-10);
    }
    .jd-pricing-page__title {
      margin: 0;
      font-size: var(--jd-text-3xl);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
    }
    @media (min-width: 640px) {
      .jd-pricing-page__title {
        font-size: var(--jd-text-4xl);
      }
    }
    .jd-pricing-page__title[hidden] {
      display: none;
    }

    .jd-pricing-page__desc {
      margin: var(--jd-space-3) auto 0;
      max-width: 42rem;
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
    }
    .jd-pricing-page__desc[hidden] {
      display: none;
    }

    /* 토글 — v2 bg-surface는 Tailwind의 밝은 패널색이었다. --jd-color-surface는
     라이트에서도 어두운 크롬이라, 그 위에 foreground 글자를 얹으면 라이트 모드에서
     검은 글자가 검은 트랙에 묻힌다. 트랙은 '앱의 본문' 쪽이므로 card가 맞다. */
    .jd-pricing-page__toggle {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin-block-start: var(--jd-space-6);
      padding: var(--jd-space-1);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-pricing-page__toggle[hidden] {
      display: none;
    }
    .jd-pricing-page__period {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-4);
      font-size: var(--jd-text-sm);
      font-family: inherit;
      white-space: nowrap;
      color: var(--jd-color-foreground);
      background: transparent;
      border: 0;
      border-radius: var(--jd-radius-full);
      cursor: pointer;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-pricing-page__period:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-pricing-page__period:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-pricing-page__period[data-active] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-pricing-page__period[data-active]:hover {
      background: var(--jd-color-primary-hover);
    }
    .jd-pricing-page__period:focus-visible {
      /* 알약이 토글 트랙 안에 갇혀 outline이 잘린다 — 링을 그림자로 그린다 */
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-pricing-page__save {
      /* 11px 아래로는 내려가지 않는다 — 절약 배지는 장식이 아니라 값이다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-success) 10%, transparent);
      color: color-mix(in srgb, var(--jd-color-success) 65%, var(--jd-color-foreground));
    }
    .jd-pricing-page__period[data-active] .jd-pricing-page__save {
      background: rgba(255, 255, 255, 0.2);
      color: inherit;
    }

    .jd-pricing-page__table {
      display: block;
    }

    /* FAQ */
    .jd-pricing-page__faq {
      margin-block-start: var(--jd-space-16);
    }
    .jd-pricing-page__faq[hidden] {
      display: none;
    }
    .jd-pricing-page__faq-title {
      margin: 0 0 var(--jd-space-6);
      text-align: center;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
    }
    .jd-pricing-page__faq-list {
      max-width: 42rem;
      margin-inline: auto;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    /* FAQ 카드도 같은 이유로 surface가 아니라 card — 답변 본문이 muted라 어두운 면
     위에서는 라이트 모드 대비가 그대로 무너진다 */
    .jd-pricing-page__faq-item {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-xs);
      padding: var(--jd-space-4);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-pricing-page__faq-item:hover {
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-pricing-page__faq-q {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      font-weight: var(--jd-weight-medium);
      cursor: pointer;
      list-style: none;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-pricing-page__faq-q::-webkit-details-marker {
      display: none;
    }
    /* 맨 텍스트는 트리거가 아니다 — 질문 줄에 손을 얹으면 열 수 있는 줄임이 보여야 한다 */
    .jd-pricing-page__faq-q:hover {
      color: var(--jd-color-primary-ink);
    }
    .jd-pricing-page__faq-q:hover .jd-pricing-page__faq-caret {
      color: var(--jd-color-primary-ink);
    }
    .jd-pricing-page__faq-q:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      border-radius: var(--jd-radius-sm);
    }
    .jd-pricing-page__faq-caret {
      flex-shrink: 0;
      color: var(--jd-color-muted);
      transition: transform var(--jd-duration-normal) var(--jd-easing-default),
        color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-pricing-page__faq-item[open] .jd-pricing-page__faq-caret {
      transform: rotate(180deg);
    }
    .jd-pricing-page__faq-a {
      margin-block-start: var(--jd-space-3);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    /* 푸터 CTA */
    .jd-pricing-page__footer {
      margin-block-start: var(--jd-space-16);
      text-align: center;
    }
    .jd-pricing-page__footer:empty {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pricing-page__period,
      .jd-pricing-page__faq-item,
      .jd-pricing-page__faq-q,
      .jd-pricing-page__faq-caret {
        transition: none;
      }
      .jd-pricing-page__period:active {
        scale: none;
      }
    }
  }

  @layer junds.base {
    jd-pricing-table:not(:defined) {
      display: grid;
    }
  }
  @layer junds.components {
    jd-pricing-table {
      display: grid;
      box-sizing: border-box;
      gap: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      grid-template-columns: minmax(0, 1fr);
    }
    @media (min-width: 768px) {
      jd-pricing-table {
        grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
      }
    }

    .jd-pricing-table__plan {
      position: relative;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-6);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-pricing-table__plan:hover {
      box-shadow: var(--jd-shadow-md);
    }
    .jd-pricing-table__plan[data-highlighted] {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-lg),
        0 0 0 1px color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-pricing-table__plan[data-disabled] {
      opacity: var(--jd-opacity-60);
    }

    .jd-pricing-table__badge {
      position: absolute;
      top: calc(-1 * var(--jd-space-2));
      inset-inline-end: var(--jd-space-4);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
      color: #fff;
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    .jd-pricing-table__header {
      margin-bottom: var(--jd-space-4);
    }
    .jd-pricing-table__name {
      margin: 0;
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
    }
    .jd-pricing-table__desc {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-pricing-table__price {
      margin-bottom: var(--jd-space-5);
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-1);
    }
    .jd-pricing-table__amount {
      font-size: var(--jd-text-3xl);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-tight);
    }
    .jd-pricing-table__suffix {
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-pricing-table__features {
      flex: 1;
      list-style: none;
      margin: 0 0 var(--jd-space-6);
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    .jd-pricing-table__feature {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-normal);
    }
    .jd-pricing-table__check {
      flex-shrink: 0;
      margin-top: 2px;
      color: var(--jd-color-success);
    }

    .jd-pricing-table__cta {
      width: 100%;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid transparent;
      margin: 0;
      padding: var(--jd-space-2-5) var(--jd-space-4);
      font-family: inherit;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border-color: var(--jd-color-border);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-pricing-table__cta:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-pricing-table__cta:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-pricing-table__cta:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-pricing-table__plan[data-highlighted] .jd-pricing-table__cta {
      background: var(--jd-color-primary);
      color: #fff;
      border-color: transparent;
    }
    .jd-pricing-table__plan[data-highlighted] .jd-pricing-table__cta:hover {
      background: var(--jd-color-primary-hover);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pricing-table__plan,
      .jd-pricing-table__cta {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-product-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-product-card {
      position: relative;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      overflow: hidden;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      /* 테두리만 있는 카드는 종이에 그린 사각형으로 읽힌다 — 평상시에도 얕은 그림자를
       깔아 두어야 호버의 shadow-md가 '떠오름'으로 읽힌다 */
      box-shadow: var(--jd-shadow-xs);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-product-card[disabled] {
      opacity: 0.6;
    }
    /* display를 지정한 요소는 [hidden]이 안 먹는다(작성자 규칙이 UA를 이김) — 명시 가드 */
    .jd-product-card__wishlist[hidden],
    .jd-product-card__placeholder[hidden],
    .jd-product-card__stock[hidden],
    .jd-product-card__rating[hidden] {
      display: none;
    }
    jd-product-card[data-clickable] {
      cursor: pointer;
    }
    jd-product-card[data-clickable]:hover {
      box-shadow: var(--jd-shadow-md);
    }
    jd-product-card:has(.jd-product-card__link:focus-visible) {
      box-shadow: var(--jd-shadow-md), var(--jd-shadow-focus-ring);
    }

    /* 전면 오버레이 링크 — 카드 본문을 덮어 하나의 큰 히트 영역이 된다(중첩 인터랙티브 제거) */
    .jd-product-card__link {
      position: absolute;
      inset: 0;
      z-index: 1;
      margin: 0;
      padding: 0;
      border: none;
      background: transparent;
      color: transparent;
      font: inherit;
      cursor: inherit;
    }
    .jd-product-card__link:focus-visible {
      outline: none;
    }

    /* 배지 */
    .jd-product-card__badge {
      position: absolute;
      top: var(--jd-space-2);
      left: var(--jd-space-2);
      z-index: 3;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-danger);
      color: #fff;
      /* 11px 아래로 내려가지 않는다 — 대문자 + wider 자간이라 더 그렇다 */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-normal);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    /* 위시리스트 */
    .jd-product-card__wishlist {
      position: absolute;
      top: var(--jd-space-2);
      right: var(--jd-space-2);
      z-index: 4;
      width: 2rem;
      height: 2rem;
      padding: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: none;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-card) 90%, transparent);
      -webkit-backdrop-filter: blur(4px);
      backdrop-filter: blur(4px);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-xs);
      cursor: pointer;
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 확대만으로는 사진 위에서 커졌는지 알기 어렵다 — 면이 함께 또렷해져야 한다 */
    .jd-product-card__wishlist:hover {
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-product-card__wishlist:active {
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-product-card__wishlist:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-product-card__wishlist-icon {
      width: 16px;
      height: 16px;
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
    }
    .jd-product-card__wishlist[data-on] .jd-product-card__wishlist-icon {
      fill: var(--jd-color-danger);
      stroke: var(--jd-color-danger);
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-product-card__wishlist:hover {
        scale: 1.1;
      }
      /* 호버 뒤에 와야 한다 — 누르는 동안에도 :hover가 참이라, 앞에 두면 확대가 이긴다 */
      .jd-product-card__wishlist:active {
        scale: 0.94;
      }
    }

    /* 미디어 */
    .jd-product-card__main {
      display: block;
    }
    .jd-product-card__media {
      position: relative;
      display: block;
      width: 100%;
      overflow: hidden;
      background: var(--jd-color-background);
    }
    .jd-product-card__image {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: scale var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    @media (prefers-reduced-motion: no-preference) {
      jd-product-card[data-clickable]:hover .jd-product-card__image {
        scale: 1.05;
      }
    }
    /* '이미지 없음'은 빈 자리이지 고장난 자리가 아니다 — 균일한 회색 판은 로딩 실패와
     구분되지 않는다. 대각 줄무늬가 '아직 비어 있는 칸'이라고 말하고, 액자 아이콘이
     그 칸이 사진 자리임을 말한다. 색은 전부 border/muted에서 뽑아 테마를 따라간다. */
    .jd-product-card__placeholder {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-2);
      color: var(--jd-color-muted);
      font-size: var(--jd-text-xs);
      --jd-product-card-ph-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='15' rx='2.5'/%3E%3Ccircle cx='8.5' cy='10' r='1.6'/%3E%3Cpath d='M21 15.5 16 10.5 5 21'/%3E%3C/svg%3E");
      background-image: repeating-linear-gradient(
        135deg,
        color-mix(in srgb, var(--jd-color-border) 65%, transparent) 0 var(--jd-space-0-5),
        transparent var(--jd-space-0-5) var(--jd-space-2-5)
      );
    }
    .jd-product-card__placeholder::before {
      content: "";
      width: 1.75rem;
      height: 1.75rem;
      /* 아이콘은 마스크로 그린다 — 칠은 currentColor라 muted 토큰을 그대로 따라가고,
       색을 나르는 SVG 자산을 따로 둘 필요가 없다 */
      background: currentColor;
      opacity: var(--jd-opacity-60);
      -webkit-mask: var(--jd-product-card-ph-icon) center / contain no-repeat;
      mask: var(--jd-product-card-ph-icon) center / contain no-repeat;
    }
    .jd-product-card__stock {
      position: absolute;
      inset: 0;
      z-index: 2;
      display: flex;
      align-items: center;
      justify-content: center;
      /* 품절 베일은 토큰 스크림으로 — 리터럴이면 다크에서 사진이 두 번 어두워진다 */
      background: var(--jd-color-overlay-scrim);
    }
    .jd-product-card__stock-label {
      color: #fff;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    /* 본문 */
    .jd-product-card__body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      padding: var(--jd-space-4);
    }
    .jd-product-card__brand {
      font-size: var(--jd-text-2xs);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }
    .jd-product-card__title {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .jd-product-card__rating {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-product-card__star {
      color: var(--jd-color-warning);
    }
    .jd-product-card__rating-value {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-product-card__rating-count {
      font-variant-numeric: tabular-nums;
    }
    .jd-product-card__price {
      margin-top: var(--jd-space-1);
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }

    /* 장바구니 — 오버레이 링크 위로 올린다(형제, z-index 2) */
    .jd-product-card__cart {
      position: relative;
      z-index: 2;
      margin: 0 var(--jd-space-4) var(--jd-space-4);
      padding: var(--jd-space-2) var(--jd-space-3);
      border: none;
      border-radius: var(--jd-radius-md);
      background: var(--jd-color-foreground);
      color: var(--jd-color-background);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      cursor: pointer;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 호버는 opacity가 아니라 실색 전환 — 반투명해지면 글자까지 함께 흐려져
     '비활성'처럼 읽히고, 카드 배경이 버튼 안으로 비친다 */
    .jd-product-card__cart:hover {
      background: color-mix(in srgb, var(--jd-color-foreground) 88%, var(--jd-color-muted));
    }
    .jd-product-card__cart:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-product-card__cart:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-product-card,
      .jd-product-card__image,
      .jd-product-card__wishlist,
      .jd-product-card__cart {
        transition: none;
      }
      .jd-product-card__cart:active {
        scale: none;
      }
    }
  }

  @layer junds.components {
    jd-profile-header {
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-profile-header {
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
    }

    .jd-profile-header__banner {
      position: relative;
      height: 8rem;
      background: linear-gradient(
        to right,
        color-mix(in srgb, var(--jd-color-primary) 20%, transparent),
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent)
      );
    }
    .jd-profile-header__banner-img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .jd-profile-header__banner-img[hidden] {
      display: none;
    }

    .jd-profile-header__body {
      position: relative;
      padding: 0 var(--jd-space-5) var(--jd-space-5);
    }

    .jd-profile-header__top {
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      margin-top: -2.5rem;
    }
    .jd-profile-header__avatar {
      width: 5rem;
      height: 5rem;
      border-radius: var(--jd-radius-full);
      box-shadow: 0 0 0 4px var(--jd-color-card);
      background: var(--jd-color-card-hover);
      overflow: hidden;
      flex-shrink: 0;
    }
    .jd-profile-header__avatar-img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }
    .jd-profile-header__avatar-img[hidden] {
      display: none;
    }
    .jd-profile-header__avatar-fallback {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-primary) 20%, transparent);
      /* 틴트 위 이니셜: 원색 대신 foreground 혼합으로 대비 확보(emoji-picker 선례·§4). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      user-select: none;
    }
    .jd-profile-header__avatar-fallback[hidden] {
      display: none;
    }
    .jd-profile-header__actions {
      margin-bottom: var(--jd-space-1);
    }

    .jd-profile-header__identity {
      margin-top: var(--jd-space-3);
    }
    .jd-profile-header__name-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }
    .jd-profile-header__name {
      margin: 0;
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-profile-header__verified {
      color: var(--jd-color-primary-ink);
    }
    .jd-profile-header__verified[hidden] {
      display: none;
    }
    .jd-profile-header__handle {
      margin: 0;
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted);
    }
    .jd-profile-header__handle[hidden] {
      display: none;
    }

    .jd-profile-header__bio {
      margin-top: var(--jd-space-2);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
    }
    .jd-profile-header__bio[hidden] {
      display: none;
    }

    .jd-profile-header__location {
      margin: var(--jd-space-2) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-1) var(--jd-space-3);
    }
    .jd-profile-header__location[hidden] {
      display: none;
    }
    .jd-profile-header__loc[hidden],
    .jd-profile-header__joined[hidden] {
      display: none;
    }

    .jd-profile-header__stats {
      list-style: none;
      margin: var(--jd-space-3) 0 0;
      padding: 0;
      display: flex;
      align-items: center;
      gap: var(--jd-space-4);
      font-size: var(--jd-text-md);
    }
    .jd-profile-header__stats[hidden] {
      display: none;
    }
    .jd-profile-header__stat-link {
      color: inherit;
      text-decoration: none;
      border-radius: var(--jd-radius-sm);
    }
    a.jd-profile-header__stat-link:hover {
      text-decoration: underline;
    }
    a.jd-profile-header__stat-link:focus-visible {
      outline: 2px solid var(--jd-color-primary);
      outline-offset: 2px;
    }
    .jd-profile-header__stat-value {
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-profile-header__stat-label {
      margin-inline-start: var(--jd-space-1);
      color: var(--jd-color-muted);
    }
  }

  @layer junds.components {
    jd-progress-bar {
      display: block;
      width: 100%;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    .jd-progress-bar__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-block-end: var(--jd-space-1);
      font-size: var(--jd-text-xs);
    }
    /* 저작 display가 UA의 [hidden] 규칙을 이긴다 — 명시 규칙 필수(레포 관용구) */
    .jd-progress-bar__header[hidden] {
      display: none;
    }
    .jd-progress-bar__label {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-progress-bar__label[hidden] {
      display: none;
    }
    .jd-progress-bar__value {
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-progress-bar__value[hidden] {
      display: none;
    }

    .jd-progress-bar__track {
      width: 100%;
      overflow: hidden;
      height: var(--jd-progress-bar-height, 0.625rem); /* md */
      /* 트랙은 "컨트롤의 홈"이다 — control-track이 이미 모드별 값을 갖는다.
       다크에서만 색을 갈아끼우던 규칙은 --jd-progress-bar-track을 호스트에 **정의**해
       바깥(jd-loading-screen 등)의 합성을 막고 있었다(높이 변수와 같은 함정). */
      background: var(--jd-progress-bar-track, var(--jd-color-control-track));
      border-radius: var(--jd-radius-full);
    }
    jd-progress-bar[size="sm"] .jd-progress-bar__track {
      height: var(--jd-progress-bar-height, 0.375rem);
    }
    jd-progress-bar[size="lg"] .jd-progress-bar__track {
      height: var(--jd-progress-bar-height, 1rem);
    }

    /* 진행은 의미가 아니라 강조다 — 기본은 primary, 의미색은 variant가 받는다.
     인셋 하이라이트로 채움이 트랙 홈 위에 얹힌 면으로 읽히게 한다. */
    .jd-progress-bar__fill {
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
      transition: width var(--jd-duration-slower) var(--jd-easing-default);
    }
    jd-progress-bar[variant="success"] .jd-progress-bar__fill {
      background: var(--jd-color-success);
    }
    jd-progress-bar[variant="warning"] .jd-progress-bar__fill {
      background: var(--jd-color-warning);
    }
    jd-progress-bar[variant="danger"] .jd-progress-bar__fill {
      background: var(--jd-color-danger);
    }

    /* v2 animate-progress — 마운트 시 0에서 차오른다 */
    jd-progress-bar[animated] .jd-progress-bar__fill {
      animation: jd-progress-fill 1s var(--jd-easing-default) forwards;
    }

    @keyframes jd-progress-fill {
      from {
        width: 0;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-progress-bar__fill {
        transition: none;
      }
      jd-progress-bar[animated] .jd-progress-bar__fill {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-progress-ring {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-family: var(--jd-font-sans);
    }

    .jd-progress-ring__svg {
      display: block;
      transform: rotate(-90deg); /* 12시에서 시작 */
    }
    .jd-progress-ring__track {
      stroke: var(--jd-progress-ring-track, var(--jd-color-border));
    }
    .jd-progress-ring__fill {
      stroke: var(--jd-progress-ring-color, var(--jd-color-primary));
      stroke-linecap: round;
      transition: stroke-dashoffset var(--jd-duration-slower) var(--jd-easing-default);
    }

    .jd-progress-ring__center {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--jd-color-foreground);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-progress-ring__fill {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-progress-steps {
      display: block;
      font-family: var(--jd-font-sans);
    }

    .jd-progress-steps__list {
      display: flex;
      align-items: flex-start;
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-progress-steps__step {
      display: flex;
      align-items: center;
      flex: 1 1 0%;
      min-width: 0;
    }
    .jd-progress-steps__step[data-last] {
      flex: 0 0 auto;
    }

    .jd-progress-steps__marker {
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .jd-progress-steps__circle {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 1.75rem;
      height: 1.75rem;
      flex-shrink: 0;
      box-sizing: border-box;
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      font-variant-numeric: tabular-nums;
      /* 예정 기본 */
      background: var(--jd-progress-steps-track, var(--jd-color-neutral-100));
      color: var(--jd-color-muted);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-default),
        color var(--jd-duration-normal) var(--jd-easing-default);
    }
    .jd-progress-steps__step[data-status="done"] .jd-progress-steps__circle,
    .jd-progress-steps__step[data-status="current"] .jd-progress-steps__circle {
      background: var(--jd-color-primary);
      color: #fff;
      border-color: transparent;
    }
    /* v2 ring-2 ring-primary/30 ring-offset-1 — 바깥 흰 링 1px + 색 링 2px */
    .jd-progress-steps__step[data-status="current"] .jd-progress-steps__circle {
      box-shadow: 0 0 0 1px var(--jd-color-background),
        0 0 0 3px color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-progress-steps__circle svg {
      width: 14px;
      height: 14px;
    }

    .jd-progress-steps__label {
      margin-block-start: var(--jd-space-1);
      font-size: 10px;
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    .jd-progress-steps__label[hidden] {
      display: none;
    }
    .jd-progress-steps__step[data-status="done"] .jd-progress-steps__label,
    .jd-progress-steps__step[data-status="current"] .jd-progress-steps__label {
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
    }

    .jd-progress-steps__line {
      flex: 1 1 0%;
      height: 2px;
      min-width: var(--jd-space-2);
      margin-inline: var(--jd-space-1);
      background: var(--jd-progress-steps-line, var(--jd-color-neutral-200));
      /* 원(1.75rem)의 중심에 맞춘다 — v2는 items-center로 라벨까지 포함한 높이의
       한가운데에 선이 걸려 라벨이 길어지면 선이 내려앉았다 */
      align-self: flex-start;
      margin-block-start: calc(1.75rem / 2 - 1px);
    }
    .jd-progress-steps__line[hidden] {
      display: none;
    }
    .jd-progress-steps__step[data-status="done"] .jd-progress-steps__line {
      background: var(--jd-color-primary);
    }

    /* 상태의 비시각 경로 — 색만으로 전달하지 않는다(WCAG 1.4.1) */
    .jd-progress-steps__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    [data-jd-theme="dark"] jd-progress-steps,
    [data-theme="dark"] jd-progress-steps {
      --jd-progress-steps-track: var(--jd-color-border-light);
      --jd-progress-steps-line: var(--jd-color-border);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-progress-steps__circle {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-pull-to-refresh {
      display: block;
      overflow: auto;
      /* 당김이 페이지 전체 고무줄로 번지지 않게 */
      overscroll-behavior-y: contain;
      scrollbar-width: thin;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* 당겨서 새로고침이 붙는 자리는 사실상 언제나 **목록**이다. v2는 본문에 아무
     규약을 두지 않아 항목 사이에 여백만 벌어지고 어디서 한 행이 끝나는지 보이지
     않았다 — 직계 자식에 행 리듬을 준다(인디케이터는 본문이 아니므로 제외).
     자기 표면을 가진 본문은 --jd-pull-to-refresh-row-padding: 0 ·
     --jd-pull-to-refresh-rule: transparent 로 끈다. */
    jd-pull-to-refresh > :not(.jd-pull-to-refresh__indicator) {
      padding-block: var(--jd-pull-to-refresh-row-padding, var(--jd-space-3));
    }
    /* 첫 행 위에는 선을 긋지 않는다 — 인디케이터와 본문 사이는 경계가 아니다 */
    jd-pull-to-refresh
      > :not(.jd-pull-to-refresh__indicator)
      ~ :not(.jd-pull-to-refresh__indicator) {
      border-block-start: var(--jd-border-thin) solid
        var(--jd-pull-to-refresh-rule, var(--jd-color-border-light));
    }

    .jd-pull-to-refresh__indicator {
      display: flex;
      align-items: flex-start;
      justify-content: center;
      overflow: hidden;
      height: var(--_jd-ptr-pull, 0px);
      opacity: var(--_jd-ptr-progress, 0);
      transition: height var(--jd-duration-fast) var(--jd-easing-ease-out),
        opacity var(--jd-duration-fast) var(--jd-easing-ease-out);
    }

    .jd-pull-to-refresh__spinner {
      width: 1.25rem;
      height: 1.25rem;
      margin-block-start: var(--jd-space-2);
      color: var(--jd-color-primary-ink);
    }
    jd-pull-to-refresh[refreshing] .jd-pull-to-refresh__spinner {
      animation: jd-ptr-spin 1s linear infinite;
    }

    /* 상태 문구는 접근성 트리 전용 — 화면에는 스피너만 있다(v2 시각 동형) */
    .jd-pull-to-refresh__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @keyframes jd-ptr-spin {
      to {
        transform: rotate(360deg);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-pull-to-refresh__indicator {
        transition: none;
      }
      /* 진행 표시는 남기되 회전을 늦춘다 — 완전 정지는 "멈춘 것"으로 읽힌다 */
      jd-pull-to-refresh[refreshing] .jd-pull-to-refresh__spinner {
        animation-duration: 3s;
      }
    }
  }

  @layer junds.components {
    jd-qr-code {
      display: inline-block;
      line-height: 0;
    }

    .jd-qr-code__canvas {
      display: block;
      max-width: 100%;
      aspect-ratio: 1 / 1;
      shape-rendering: crispEdges;
    }
  }

  @layer junds.components {
    jd-quantity-selector {
      display: inline-flex;
      align-items: center;
      box-sizing: border-box;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md); /* v2 rounded-md */
    }
    jd-quantity-selector:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-quantity-selector[error] {
      border-color: var(--jd-color-danger);
    }
    jd-quantity-selector[error]:focus-within {
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-quantity-selector[disabled] {
      opacity: var(--jd-opacity-50);
    }

    /* size 기본 md — 버튼 36px 정사각 · 입력 48px 폭 */
    jd-quantity-selector .jd-number-input__step {
      width: 2.25rem;
      height: 2.25rem;
    }
    jd-quantity-selector .jd-number-input__input {
      width: 3rem;
      height: 2.25rem;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
    }
    jd-quantity-selector[size="sm"] .jd-number-input__step {
      width: 1.75rem;
      height: 1.75rem;
    }
    jd-quantity-selector[size="sm"] .jd-number-input__input {
      width: 2.25rem;
      height: 1.75rem;
      font-size: var(--jd-text-xs);
    }
    jd-quantity-selector[size="lg"] .jd-number-input__step {
      width: 2.75rem;
      height: 2.75rem;
    }
    jd-quantity-selector[size="lg"] .jd-number-input__input {
      width: 3.5rem;
      height: 2.75rem;
      font-size: var(--jd-text-md);
    }

    /* readonly 모드에서는 스텝 버튼이 유일한 키보드 경로 — 포커스 링이 반드시 보여야 한다.
     호스트가 overflow:hidden이라 바깥쪽 아웃라인은 잘린다 → 안쪽으로 그린다. */
    jd-quantity-selector .jd-number-input__step:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: -2px;
    }
    jd-quantity-selector .jd-number-input__input:read-only {
      cursor: default;
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-quarter-bar-chart {
      /* v2 승계 리터럴은 민트(#5cdcd0)·형광 보라(#a855f7)라 팔레트 밖이었다(§8).
       계열색은 hue 토큰에서만 뽑는다 — 매출/이익은 등락이 아니라 **범주**이므로
       success·danger 같은 의미색을 빌려 쓰지 않는다. */
      --jd-qbar-revenue: var(--jd-color-hue-violet);
      --jd-qbar-op: var(--jd-color-hue-teal);
      --jd-qbar-net: var(--jd-color-hue-blue);
      /* 380px 뷰박스가 카드보다 넓으면 오른쪽 끝 분기 라벨이 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 비율을
     대신 말한다. min-width는 플렉스 자식의 min-width:auto(=내용 폭) 바닥을 풀되,
     범례 옆에서 뭉개지지 않게 컨테이너가 더 좁을 때만 양보하도록 잡는다. */
    jd-quarter-bar-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 15rem);
    }
    /* rx는 SVG2에서 CSS 기하 속성이다 — 표시 속성 rx="2"를 이겨 값을 토큰으로 말한다.
     CSS rx를 모르는 브라우저에선 그 속성이 그대로 폴백이 된다. */
    jd-quarter-bar-chart .jd-chart__bar {
      rx: var(--jd-radius-sm);
    }
    jd-quarter-bar-chart:not(:defined) {
      display: inline-block;
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-radar-chart {
      --jd-chart-fill-opacity: 0.2;
      /* 계열색은 hue 팔레트에서만(§8). 공용 기본값은 success/warning/danger를 계열색으로
       써서 "2번 시리즈"와 "성공"이 한 화면에서 같은 색이 된다 — 계열은 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 정사각 280px + 범례가 카드보다 넓으면 축 라벨이 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 정사각
     비율을 대신 말한다. min-width는 플렉스 자식의 min-width:auto 바닥을 풀되,
     축 라벨이 겹쳐 읽히지 않을 만큼은 남긴다. */
    jd-radar-chart > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 10rem);
    }

    .jd-radar-chart__grid-ring {
      fill: none;
      stroke: var(--jd-color-border);
      stroke-opacity: 0.4;
      stroke-width: 1;
    }
    .jd-radar-chart__spoke {
      stroke: var(--jd-color-border);
      stroke-opacity: 0.3;
      stroke-width: 1;
    }
    .jd-radar-chart__shape {
      fill: var(--jd-series-color);
      fill-opacity: var(--jd-chart-fill-opacity, 0.2);
      stroke: var(--jd-series-color);
      stroke-width: 1.5;
      stroke-linejoin: round;
    }

    jd-radar-chart:not(:defined) {
      display: inline-flex;
    }
  }

  @layer junds.components {
    /* 기본 1컬럼 — columns>1일 때만 update()가 인라인으로 덮는다 */
    jd-radio-card-group {
      display: grid;
      grid-template-columns: repeat(1, minmax(0, 1fr));
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
    }

    .jd-radio-card-group__item {
      position: relative;
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      padding: var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      user-select: none;
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-radio-card-group__item:hover {
      background: var(--jd-color-card-hover);
    }

    /* v2: border-primary + bg-primary-soft + ring-1 ring-primary/30 */
    .jd-radio-card-group__item[data-selected] {
      border-color: var(--jd-color-primary);
      background: var(--jd-color-primary-light);
      box-shadow: 0 0 0 var(--jd-border-thin)
        color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-radio-card-group__item[data-selected]:hover {
      background: var(--jd-color-primary-light);
    }

    .jd-radio-card-group__item[data-disabled] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-radio-card-group__item[data-disabled]:hover {
      background: var(--jd-color-card);
    }
    .jd-radio-card-group__item[data-disabled][data-selected]:hover {
      background: var(--jd-color-primary-light);
    }

    /* 키보드 초점은 카드 전체에 — 내부 input에만 걸리면 카드 경계가 보이지 않는다 */
    .jd-radio-card-group__item:has(.jd-radio-card-group__input:focus-visible) {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }

    .jd-radio-card-group__input {
      appearance: auto;
      flex-shrink: 0;
      margin: var(--jd-space-1) 0 0;
      width: 1rem;
      height: 1rem;
      accent-color: var(--jd-color-primary);
      cursor: inherit;
    }

    .jd-radio-card-group__icon {
      flex-shrink: 0;
      margin-block-start: var(--jd-space-0-5);
      font-size: var(--jd-text-xl);
      line-height: var(--jd-leading-none);
    }

    .jd-radio-card-group__body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      flex: 1 1 0;
      min-width: 0;
    }

    .jd-radio-card-group__title {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-radio-card-group__description {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-radio-card-group__badge {
      flex-shrink: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-radio-card-group__icon[hidden],
    .jd-radio-card-group__description[hidden],
    .jd-radio-card-group__badge[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-radio-card-group__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-radio-group {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    jd-radio-group[direction="horizontal"] {
      flex-direction: row;
      flex-wrap: wrap;
      gap: var(--jd-space-4);
    }

    .jd-radio-group__item {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
    }
    .jd-radio-group__item[data-disabled] {
      cursor: not-allowed;
    }

    .jd-radio-group__input {
      appearance: none;
      -webkit-appearance: none;
      flex: none;
      margin: 0;
      padding: 0;
      cursor: inherit;
      width: 1.125rem;
      height: 1.125rem;
      border: 1.5px solid var(--jd-color-neutral-300);
      border-radius: var(--jd-radius-full);
      background-color: var(--jd-color-control-surface);
      box-shadow: var(--jd-shadow-xs);
      /* closest-side + 100% — 기본 farthest-corner를 쓰면 원 반지름이 배경 상자의
       0.707배가 되어 점이 지정 크기의 70%로 작아진다. closest-side로 고정하면
       background-size가 곧 점의 지름이다. */
      background-image: radial-gradient(circle closest-side, #fff 100%, transparent 100%);
      background-repeat: no-repeat;
      background-position: center;
      background-size: 0% 0%;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-size var(--jd-duration-snap) var(--jd-easing-overshoot),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-radio-group__input:hover:not(:disabled) {
      border-color: var(--jd-color-neutral-400);
      background-color: var(--jd-color-control-surface-hover);
    }
    .jd-radio-group__input:active:not(:disabled) {
      scale: 0.92;
    }

    .jd-radio-group__input:checked {
      background-color: var(--jd-color-primary);
      border-color: var(--jd-color-primary);
      background-size: 44% 44%;
      box-shadow: 0 1px 3px -1px color-mix(in srgb, var(--jd-color-primary) 55%, transparent);
    }

    .jd-radio-group__input:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-radio-group__input:disabled {
      background-color: var(--jd-color-control-surface-muted);
      border-color: var(--jd-color-border);
    }
    .jd-radio-group__input:disabled:checked {
      background-color: var(--jd-color-neutral-400);
      border-color: var(--jd-color-neutral-400);
      box-shadow: none;
    }

    jd-radio-group[size="sm"] .jd-radio-group__input {
      width: 1rem;
      height: 1rem;
    }

    .jd-radio-group__label {
      color: var(--jd-color-foreground);
      font-size: var(--jd-text-md);
    }
    jd-radio-group[size="sm"] .jd-radio-group__label {
      font-size: var(--jd-text-xs);
    }
    .jd-radio-group__item[data-disabled] .jd-radio-group__label {
      color: var(--jd-color-muted);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-radio-group__input {
        transition: none;
      }
      .jd-radio-group__input:active:not(:disabled) {
        scale: 1;
      }
    }
  }

  @layer junds.components {
    jd-range-slider {
      display: block;
      width: 100%;
    }
    jd-range-slider[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-range-slider__values {
      display: flex;
      justify-content: space-between;
      margin-bottom: var(--jd-space-1);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-range-slider__values[hidden] {
      display: none;
    }

    .jd-range-slider__track {
      position: relative;
      height: 1.25rem;
      display: flex;
      align-items: center;
      cursor: pointer;
      touch-action: none;
    }
    jd-range-slider[disabled] .jd-range-slider__track {
      cursor: not-allowed;
    }

    .jd-range-slider__rail {
      position: absolute;
      inset-inline: 0;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-neutral-200);
    }
    .jd-range-slider__fill {
      position: absolute;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
    }

    .jd-range-slider__thumb {
      position: absolute;
      width: 1.25rem;
      height: 1.25rem;
      transform: translateX(-50%);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      border: 2px solid var(--jd-color-primary);
      box-sizing: border-box;
      box-shadow: var(--jd-shadow-sm);
      cursor: grab;
      transition: scale var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-range-slider__thumb:hover {
      scale: 1.1;
    }
    jd-range-slider[data-dragging] .jd-range-slider__thumb {
      cursor: grabbing;
    }
    .jd-range-slider__thumb:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-range-slider__thumb {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-rating {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5); /* v2 gap-0.5 */
    }
    jd-rating[disabled] {
      opacity: var(--jd-opacity-50);
    }

    /* size 기본 md(20px) — 디폴트는 attribute 미반영(§1.3)이라 base가 담당 */
    .jd-rating__star {
      position: relative;
      display: inline-block;
      flex-shrink: 0;
      width: 1.25rem;
      height: 1.25rem;
    }
    jd-rating[size="sm"] .jd-rating__star {
      width: 1rem;
      height: 1rem;
    }
    jd-rating[size="lg"] .jd-rating__star {
      width: 1.75rem;
      height: 1.75rem;
    }

    .jd-rating__icon {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      fill: none;
      stroke: var(--jd-color-border);
      stroke-width: 1.5;
      stroke-linejoin: round;
    }
    .jd-rating__icon--fill {
      fill: var(--jd-color-warning);
      stroke: var(--jd-color-warning);
      clip-path: inset(0 100% 0 0); /* data-fill="none" */
    }
    .jd-rating__star[data-fill="half"] .jd-rating__icon--fill {
      clip-path: inset(0 50% 0 0);
    }
    .jd-rating__star[data-fill="full"] .jd-rating__icon--fill {
      clip-path: inset(0);
    }
    /* v2: 반쯤 찬 별도 외곽선 전체가 warning이다 */
    .jd-rating__star[data-fill="half"] .jd-rating__icon--empty,
    .jd-rating__star[data-fill="full"] .jd-rating__icon--empty {
      stroke: var(--jd-color-warning);
    }

    /* 히트 영역 — 아이콘 위에 깔린다(뒤 형제라 z-index 불필요) */
    .jd-rating__hit {
      position: absolute;
      inset-block: 0;
      width: 50%;
      cursor: pointer;
    }
    .jd-rating__hit[data-side="half"] {
      inset-inline-start: 0;
    }
    .jd-rating__hit[data-side="full"] {
      inset-inline-end: 0;
    }
    /* 반칸이 아니면 한 칸이 별 전체를 덮는다 */
    jd-rating:not([half]) .jd-rating__hit[data-side="full"] {
      inset-inline: 0;
      width: 100%;
    }
    jd-rating[readonly] .jd-rating__hit,
    jd-rating[disabled] .jd-rating__hit {
      cursor: default;
    }

    /* 라디오는 시각적으로만 감춘다 — 포커스 링은 :has로 히트 영역에 그린다 */
    .jd-rating__radio {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-rating__hit:has(.jd-rating__radio:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 1px;
      border-radius: var(--jd-radius-sm);
    }
  }

  @layer junds.components {
    jd-reaction-picker {
      position: relative;
      display: inline-block;
      font-family: var(--jd-font-sans);
    }

    .jd-reaction-picker__trigger {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-1) var(--jd-space-2-5);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: inherit;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      user-select: none;
      /* 눌리는 알약은 면 + 위에서 받는 빛을 함께 가진다 — 채움만 있으면 색종이로 읽힌다 */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      /* all 금지 — padding·font-size까지 대상이 되어 레이아웃이 매 프레임 리플로우된다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-reaction-picker__trigger:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    .jd-reaction-picker__trigger:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-reaction-picker__trigger:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-reaction-picker__trigger[data-selected] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, var(--jd-color-card));
      border-color: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    /* 이모지와 plus 글리프의 높이가 달라 알약이 들썩이지 않게 자리를 고정한다 */
    .jd-reaction-picker__value {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 1.125rem;
      font-size: var(--jd-text-lg);
      line-height: var(--jd-leading-none);
    }
    .jd-reaction-picker__trigger-label {
      font-size: var(--jd-text-xs);
      white-space: nowrap;
    }
    .jd-reaction-picker__trigger-label[hidden] {
      display: none;
    }

    /* 기본 placement=top은 **base 규칙이** 담당한다 — 디폴트는 attribute로 반영되지
     않으므로(§1.3 reflect는 set 시점) [placement="top"]은 매치되지 않는다. 그러면
     top/bottom이 둘 다 auto가 되어 팝업이 정적 위치(= 트리거 바로 뒤)에 얹히고,
     이모지 하나만 트리거 옆에 뜬 채 나머지가 좌상단에 압착되어 보인다(실측). */
    .jd-reaction-picker__menu {
      position: absolute;
      left: 0;
      bottom: 100%;
      top: auto;
      margin-block: 0 var(--jd-space-1-5);
      z-index: var(--jd-z-dropdown);
      display: flex;
      align-items: center;
      flex-wrap: nowrap;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card);
      /* 떠 있는 것은 lg 이상 + 눅인 테두리 */
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-border) 76%, transparent);
      box-shadow: var(--jd-shadow-lg), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-reaction-picker__menu[hidden] {
      display: none;
    }
    jd-reaction-picker[placement="top"] .jd-reaction-picker__menu {
      top: auto;
      bottom: 100%;
      margin-block: 0 var(--jd-space-1-5);
    }
    jd-reaction-picker[placement="bottom"] .jd-reaction-picker__menu {
      top: 100%;
      bottom: auto;
      margin-block: var(--jd-space-1-5) 0;
    }

    .jd-reaction-picker__option {
      appearance: none;
      -webkit-appearance: none;
      margin: 0;
      padding: 0;
      flex: none;
      width: 2rem;
      height: 2rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: transparent;
      font-family: inherit;
      font-size: var(--jd-text-xl);
      line-height: var(--jd-leading-none);
      cursor: pointer;
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out),
        background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-reaction-picker__option:hover {
      transform: scale(1.25);
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-reaction-picker__option:active {
      transform: scale(0.94);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-reaction-picker__option:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: 1px;
    }
    .jd-reaction-picker__option[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-reaction-picker__trigger,
      .jd-reaction-picker__option {
        transition: none;
      }
      .jd-reaction-picker__option:hover {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-reading-goal {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    .jd-reading-goal__center {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      line-height: var(--jd-leading-tight);
    }
    .jd-reading-goal__value {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
    }
    .jd-reading-goal__slash {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }
    .jd-reading-goal__unit {
      font-size: 11px;
      color: var(--jd-color-muted);
    }

    .jd-reading-goal__label {
      margin: var(--jd-space-2) 0 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
  }

  @layer junds.components {
    jd-reading-progress {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }
    jd-reading-progress[compact] {
      flex-direction: row;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-reading-progress__head {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: var(--jd-space-3);
    }
    .jd-reading-progress__chapter {
      margin: 0;
      min-width: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-reading-progress__count {
      margin: 0;
      flex-shrink: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-reading-progress__cur {
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-reading-progress__sep {
      margin-inline: var(--jd-space-1);
    }

    .jd-reading-progress__track {
      position: relative;
      overflow: hidden;
      height: 0.5rem;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border);
    }
    jd-reading-progress[compact] .jd-reading-progress__track {
      flex: 1;
      height: 0.25rem;
    }
    .jd-reading-progress__fill {
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      border-radius: var(--jd-radius-full);
      background: linear-gradient(90deg, var(--jd-color-primary), var(--jd-color-primary-hover));
      transition: width var(--jd-duration-slow) var(--jd-easing-default);
    }
    jd-reading-progress[compact] .jd-reading-progress__fill {
      background: var(--jd-color-primary);
    }

    .jd-reading-progress__compact-pct {
      flex-shrink: 0;
      font-variant-numeric: tabular-nums;
    }

    .jd-reading-progress__foot {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 11px;
      color: var(--jd-color-muted);
    }
    .jd-reading-progress__remain[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-reading-progress__fill {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* 열 수는 v2 지도(2 → md 4)를 따르되 열 폭은 칸이 정한다. 고정 repeat(4)는 넓은
     화면의 좁은 칼럼 안에서 타일을 100px대로 눌러 12h 34m 이 두 줄로 갈라졌다(§5·§6).
     auto-fit + "요청 열 수로 나눈 폭" 하한이면 넓을 때만 4열이다(jd-descriptions 선례). */
    jd-reading-stats {
      --jd-reading-stats-gap: var(--jd-space-3);
      /* 2xl 수치 + 단위가 한 줄에 서는 최소 타일 폭(패딩 2rem 포함) */
      --jd-reading-stats-col-min: 9rem;
      --_jd-rs-n: 2;
      display: grid;
      box-sizing: border-box;
      gap: var(--jd-reading-stats-gap);
      grid-template-columns: repeat(
        auto-fit,
        minmax(
          min(
            100%,
            max(
              var(--jd-reading-stats-col-min),
              (100% - (var(--_jd-rs-n) - 1) * var(--jd-reading-stats-gap)) / var(--_jd-rs-n)
            )
          ),
          1fr
        )
      );
      font-family: var(--jd-font-sans);
    }
    @media (min-width: 768px) {
      jd-reading-stats {
        --_jd-rs-n: 4;
      }
    }

    .jd-reading-stats__tile {
      box-sizing: border-box;
      min-width: 0; /* 긴 값이 트랙을 밀어 격자를 넘기지 않게(§6) */
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      padding: var(--jd-space-4);
    }

    /* 라벨은 두 글자 남기고 접히면 뜻을 잃는다 — 한 줄로 두고 넘치면 말줄임(§5) */
    .jd-reading-stats__label {
      margin: 0;
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* 숫자와 단위는 한 덩어리다 — 누적 시간은 12h 34m 처럼 사이에 공백이 있어
     좁은 타일에서 12h / 34m 으로 갈라졌다(§5) */
    .jd-reading-stats__value {
      margin: var(--jd-space-1) 0 0;
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
      line-height: var(--jd-leading-tight);
      white-space: nowrap;
    }
    .jd-reading-stats__unit {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-normal);
      color: var(--jd-color-muted);
    }

    .jd-reading-stats__track {
      margin-block-start: var(--jd-space-2);
      height: 0.25rem;
      overflow: hidden;
      background: var(--jd-color-border);
      border-radius: var(--jd-radius-full);
    }
    .jd-reading-stats__track[hidden] {
      display: none;
    }
    .jd-reading-stats__bar {
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-primary);
      transition: width var(--jd-duration-slow) var(--jd-easing-default);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-reading-stats__bar {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-reading-time {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-reading-time__sep {
      color: var(--jd-color-muted-light);
    }
    .jd-reading-time__sep[hidden],
    .jd-reading-time__level[hidden] {
      display: none;
    }

    .jd-reading-time__level {
      font-weight: var(--jd-weight-medium);
    }
    .jd-reading-time__level[data-level="basic"] {
      color: color-mix(
        in srgb,
        var(--jd-color-success) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    .jd-reading-time__level[data-level="intermediate"] {
      color: color-mix(
        in srgb,
        var(--jd-color-warning) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    .jd-reading-time__level[data-level="advanced"] {
      color: color-mix(
        in srgb,
        var(--jd-color-danger) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    /* 스크린리더 전용 접두("난이도 ") — visually-hidden과 같은 clip-path 관용구 */
    .jd-reading-time__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-real-candle-chart {
      display: block;
      min-width: 0;
      font-family: var(--jd-font-sans);
      --_success: var(--jd-fin-success, var(--jd-color-success));
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_bright: var(--jd-fin-live-bright, var(--jd-fin-accent, var(--jd-color-primary)));
    }
    jd-real-candle-chart:not(:defined) {
      display: block;
    }

    .jd-real-candle-chart__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      margin-block-end: var(--jd-space-2);
      padding-inline: var(--jd-space-1);
    }
    .jd-real-candle-chart__meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-2xs);
      min-width: 0;
      flex-wrap: wrap;
    }

    .jd-real-candle-chart__badge {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-1) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      /* 톤 레시피: 앵커 하나에서 면(승강)·테두리·글자를 파생한다 */
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-border-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }
    .jd-real-candle-chart__badge[data-source="yahoo"] {
      --jd-tone: var(--_success);
    }
    .jd-real-candle-chart__badge[data-source="mock"] {
      --jd-tone: var(--jd-color-hue-gray);
    }
    .jd-real-candle-chart__dot {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: currentColor;
      flex-shrink: 0;
    }

    .jd-real-candle-chart__count {
      font-size: var(--jd-text-2xs);
      color: var(--_muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-real-candle-chart__count[hidden] {
      display: none;
    }

    .jd-real-candle-chart__freshness {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--_muted);
      white-space: nowrap;
    }
    .jd-real-candle-chart__freshness[hidden] {
      display: none;
    }
    .jd-real-candle-chart__fresh-dot {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--_muted);
      flex-shrink: 0;
    }
    .jd-real-candle-chart__fresh-dot[data-live="true"] {
      background: var(--_bright);
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--_bright) 22%, transparent);
    }

    .jd-real-candle-chart__yahoo {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      flex-shrink: 0;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--_muted);
      text-decoration: none;
      text-underline-offset: 2px;
      white-space: nowrap;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-real-candle-chart__yahoo[hidden] {
      display: none;
    }
    .jd-real-candle-chart__yahoo:hover {
      color: var(--jd-color-foreground);
      text-decoration-line: underline;
    }
    /* 없는 변수(--jd-color-focus)를 참조하던 자리 — 폴백이 없어 outline 선언 자체가
     무효가 되고 링이 아예 그려지지 않았다. 포커스 링은 단일 레시피를 쓴다(DEC-039). */
    .jd-real-candle-chart__yahoo:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }
    .jd-real-candle-chart__ext {
      flex-shrink: 0;
    }

    /* 캔들이 하나도 없으면 SVG는 빈 투명 상자다 — 헤더의 흐린 점만 남아 "고장"으로
     읽힌다. 플롯 영역에 자리(면 + 안쪽 실선)를 깔아 두면 같은 상태가 "데이터 없는
     차트"로 읽히고, 데이터가 있을 때는 캔들 뒤에 눕는 옅은 판이 된다. */
    .jd-real-candle-chart__chart {
      display: block;
      box-sizing: border-box;
      width: 100%;
      max-width: 100%;
      min-height: 7rem;
      border-radius: var(--jd-radius-lg);
      background: color-mix(in srgb, var(--jd-color-card-hover) 70%, transparent);
      box-shadow: inset 0 0 0 var(--jd-border-thin) var(--jd-color-border-light);
    }
    /* 불러오는 중임을 판 자체가 말한다 — 빈 판과 구분되지 않으면 로딩이 정지로 읽힌다 */
    jd-real-candle-chart[loading] .jd-real-candle-chart__chart {
      background-image: var(--jd-gradient-shimmer);
      background-size: 200% 100%;
      background-repeat: no-repeat;
      animation: jd-real-candle-chart-shimmer calc(var(--jd-duration-slower) * 3) linear infinite;
    }
    @keyframes jd-real-candle-chart-shimmer {
      from {
        background-position: -60% 0;
      }
      to {
        background-position: 160% 0;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-real-candle-chart__yahoo {
        transition: none;
      }
      jd-real-candle-chart[loading] .jd-real-candle-chart__chart {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-real-quote-header {
      display: block;
      box-sizing: border-box;
      /* 열 계단의 기준은 뷰포트가 아니라 이 카드가 실제로 받은 폭이다 — 화면이 넓다는
       이유로 좁은 칼럼 안에서 6열을 그리면 "거래량"과 값이 갈라진다(§5).
       inline-size 컨테이너는 내용이 폭을 정하지 못하므로 폭을 명시적으로 받는다. */
      width: 100%;
      container: jd-rqh / inline-size;
      overflow: hidden;
      border: 1px solid var(--jd-fin-border, var(--jd-color-border));
      border-radius: var(--jd-radius-lg);
      background: var(--jd-fin-card, var(--jd-color-card));
      color: var(--jd-fin-text, var(--jd-color-foreground));
      font-family: var(--jd-font-sans);
      --_up: var(--jd-fin-up, var(--jd-finance-up, var(--jd-color-success)));
      --_down: var(--jd-fin-down, var(--jd-finance-down, var(--jd-color-danger)));
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_border: var(--jd-fin-border, var(--jd-color-border));
      --_soft: var(--jd-fin-soft-100, var(--jd-color-card-hover));
      --_accent: var(--jd-fin-accent, var(--jd-color-hue-teal));
      /* 배지 글자는 틴트 위에 얹히므로 원색보다 한 계단 진해야 읽힌다 — 전경색과 섞으면
       라이트에선 어두워지고 다크에선 밝아져 두 모드가 같은 규칙으로 성립한다 */
      --_accent-strong: var(
        --jd-fin-accent-strong,
        color-mix(in srgb, var(--jd-color-hue-teal) 72%, var(--jd-color-foreground))
      );
    }
    jd-real-quote-header[hidden],
    jd-real-quote-header:not(:defined) {
      display: none;
    }

    .jd-real-quote-header__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: 1px solid var(--_border);
    }
    .jd-real-quote-header__titlebar {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-real-quote-header__icon {
      flex-shrink: 0;
      color: var(--_accent-strong);
    }
    .jd-real-quote-header__heading {
      margin: 0;
      font-size: 14px;
      font-weight: 800;
    }

    .jd-real-quote-header__source {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      border-radius: var(--jd-radius-full);
      white-space: nowrap;
    }
    .jd-real-quote-header__source::before {
      content: "";
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
    }
    .jd-real-quote-header__source[data-source="kis"] {
      padding: 4px 10px;
      font-size: 12px;
      font-weight: 800;
      letter-spacing: 0.02em;
      color: var(--_accent-strong);
      background: color-mix(in srgb, var(--_accent) 14%, transparent);
      border: 1.5px solid color-mix(in srgb, var(--_accent) 45%, transparent);
    }
    .jd-real-quote-header__source[data-source="kis"]::before {
      width: 8px;
      height: 8px;
      background: var(--_accent);
      box-shadow: 0 0 0 4px color-mix(in srgb, var(--_accent) 18%, transparent);
    }
    .jd-real-quote-header__source[data-source="yahoo"] {
      padding: 2px 6px;
      font-size: 10px;
      font-weight: 700;
      opacity: 0.8;
      color: var(--_muted);
      background: var(--_soft);
      border: 1px solid var(--_border);
    }
    .jd-real-quote-header__source[data-source="yahoo"]::before {
      width: 4px;
      height: 4px;
      background: var(--_muted);
    }

    .jd-real-quote-header__delay {
      flex-shrink: 0;
      font-size: 11px;
      font-weight: 600;
      color: var(--_muted);
    }

    .jd-real-quote-header__kv {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      font-variant-numeric: tabular-nums;
    }
    .jd-real-quote-header__kv-label {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--_muted);
    }
    /* 수치와 단위는 한 덩어리다 — "71,200"과 "원"이 갈라지면 다른 수로 읽힌다(§5) */
    .jd-real-quote-header__kv-value {
      margin-block-start: 2px;
      font-size: 14px;
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-text, var(--jd-color-foreground));
    }
    .jd-real-quote-header__kv-value[data-large] {
      font-size: 18px;
    }
    .jd-real-quote-header__kv-value[data-tone="up"] {
      color: var(--_up);
    }
    .jd-real-quote-header__kv-value[data-tone="down"] {
      color: var(--_down);
    }
    .jd-real-quote-header__kv-unit {
      margin-inline-start: 4px;
      font-size: 10.5px;
      font-weight: 600;
      opacity: 0.8;
    }
    .jd-real-quote-header__kv-unit[hidden] {
      display: none;
    }

    .jd-real-quote-header__mini,
    .jd-real-quote-header__ratio {
      display: grid;
      gap: var(--jd-space-3);
      font-size: 11.5px;
      font-variant-numeric: tabular-nums;
      border-block-start: 1px solid var(--_border);
    }
    .jd-real-quote-header__mini {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      padding: 10px var(--jd-space-4);
      background: var(--_soft);
    }
    .jd-real-quote-header__ratio {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      padding: var(--jd-space-2) var(--jd-space-4);
    }
    .jd-real-quote-header__ratio[hidden] {
      display: none;
    }

    .jd-real-quote-header__mini-cell {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-real-quote-header__mini-label {
      font-size: 10.5px;
      font-weight: 700;
      color: var(--_muted);
    }
    .jd-real-quote-header__mini-value {
      font-weight: 800;
      white-space: nowrap;
      color: var(--jd-fin-text, var(--jd-color-foreground));
    }
    .jd-real-quote-header__mini-value[data-tone="up"] {
      color: var(--_up);
    }
    .jd-real-quote-header__mini-value[data-tone="down"] {
      color: var(--_down);
    }

    @container jd-rqh (min-width: 44rem) {
      .jd-real-quote-header__kv {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
      .jd-real-quote-header__mini {
        grid-template-columns: repeat(6, minmax(0, 1fr));
      }
    }
  }

  @layer junds.components {
    jd-recent-visit-tracker,
    jd-recent-visit-tracker:not(:defined) {
      display: none;
    }
  }

  @layer junds.components {
    jd-recently-viewed {
      display: block;
      padding-inline: var(--jd-space-3);
      padding-block-end: var(--jd-space-4);
      font-family: var(--jd-font-sans);
      --_up: var(--jd-fin-up, var(--jd-finance-up, var(--jd-color-success)));
      --_down: var(--jd-fin-down, var(--jd-finance-down, var(--jd-color-danger)));
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_hover: var(--jd-fin-soft-100, var(--jd-color-card-hover));
    }
    jd-recently-viewed[hidden],
    jd-recently-viewed:not(:defined) {
      display: none;
    }

    .jd-recently-viewed__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding-inline: var(--jd-space-3);
      margin-block-end: var(--jd-space-1);
    }
    .jd-recently-viewed__title {
      font-size: 10.5px;
      font-weight: 800;
      letter-spacing: 0.08em;
      color: var(--_muted);
    }
    .jd-recently-viewed__clear {
      appearance: none;
      margin: 0;
      padding: 0;
      border: 0;
      background: none;
      font-family: inherit;
      font-size: 10px;
      font-weight: 600;
      color: var(--_muted);
      cursor: pointer;
    }
    .jd-recently-viewed__clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-recently-viewed__clear:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-sm);
    }

    .jd-recently-viewed__list {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .jd-recently-viewed__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: 6px var(--jd-space-3);
      border-radius: var(--jd-radius-lg);
      font-size: 12.5px;
      color: var(--jd-color-foreground);
      text-decoration: none;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-recently-viewed__row:hover {
      background: var(--_hover);
    }
    /* 행은 목록에 꽉 차 있어 바깥 offset이 이웃 행에 잘린다 — 안쪽으로 그린다 */
    .jd-recently-viewed__row:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(-1 * var(--jd-focus-ring-offset));
    }
    .jd-recently-viewed__name {
      flex: 1;
      min-width: 0;
      font-weight: 700;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* 시세·등락은 좁은 사이드바에서도 한 덩어리다 — 한 글자씩 세로로 서면 수가 아니다(§5) */
    .jd-recently-viewed__price {
      flex-shrink: 0;
      font-size: 11px;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--jd-color-foreground);
    }
    .jd-recently-viewed__change {
      flex-shrink: 0;
      white-space: nowrap;
      min-width: 38px;
      text-align: right;
      font-size: 10.5px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--_muted);
    }
    .jd-recently-viewed__change[data-dir="up"] {
      color: var(--_up);
    }
    .jd-recently-viewed__change[data-dir="down"] {
      color: var(--_down);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-recently-viewed__row {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-resizable:not(:defined) {
      display: flex;
    }
  }
  @layer junds.components {
    jd-resizable {
      display: flex;
      flex-direction: row;
      overflow: hidden;
      box-sizing: border-box;
      height: 100%;
      font-family: var(--jd-font-sans);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }
    jd-resizable[direction="vertical"] {
      flex-direction: column;
    }

    /* v2 w-1.5 / h-1.5 — 원형(4px)보다 두껍다 */
    jd-resizable > .jd-split-pane__separator {
      inline-size: 6px;
    }
    /* 세로 분할 기하·커서는 파생 태그가 스스로 선언한다 — 원형 시트의 호스트 셀렉터
     (jd-split-pane[direction="vertical"])는 파생 태그에 걸리지 않는다 */
    jd-resizable[direction="vertical"] > .jd-split-pane__separator {
      inline-size: auto;
      block-size: 6px;
      cursor: row-resize;
    }

    jd-resizable .jd-split-pane__grip {
      display: block;
      position: absolute;
      inset-inline-start: 50%;
      inset-block-start: 50%;
      translate: -50% -50%;
      background: var(--jd-color-muted);
      border-radius: var(--jd-radius-full);
      inline-size: 4px;
      block-size: 24px;
    }
    jd-resizable[direction="vertical"] .jd-split-pane__grip {
      inline-size: 24px;
      block-size: 4px;
    }
  }

  @layer junds.components {
    jd-result {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      padding: var(--jd-space-12) var(--jd-space-6);
      text-align: center;
      font-family: var(--jd-font-sans);
    }

    jd-result .jd-empty-state__icon {
      width: auto;
      height: auto;
      background: none;
      margin-block-end: var(--jd-space-4);
      color: var(--jd-color-info); /* status 기본 info */
    }
    jd-result[status="success"] .jd-empty-state__icon {
      color: var(--jd-color-success);
    }
    jd-result[status="error"] .jd-empty-state__icon {
      color: var(--jd-color-danger);
    }
    jd-result[status="warning"] .jd-empty-state__icon {
      color: var(--jd-color-warning);
    }
    jd-result[status="404"] .jd-empty-state__icon,
    jd-result[status="403"] .jd-empty-state__icon {
      color: var(--jd-color-muted);
    }

    jd-result .jd-empty-state__title {
      font-size: var(--jd-text-xl);
      margin-block-end: var(--jd-space-2);
    }
    jd-result .jd-empty-state__desc {
      max-width: 28rem;
    }
    jd-result > [slot="action"] {
      margin-block-start: var(--jd-space-6);
    }
  }

  @layer junds.base {
    jd-rich-text-editor:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-rich-text-editor {
      display: block;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-rich-text-editor[data-focused] {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-rich-text-editor[data-disabled] {
      opacity: var(--jd-opacity-50);
      pointer-events: none;
    }

    .jd-rte__toolbar {
      display: flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-1-5) var(--jd-space-2);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border-light);
      background: color-mix(in srgb, var(--jd-color-muted) 8%, var(--jd-color-card));
      /* 호스트가 overflow:hidden 이라 좁은 폭에서는 넘친 버튼이 잘려 사라진다 —
         줄을 늘려 받는다(§6) */
      flex-wrap: wrap;
    }

    .jd-rte__tool {
      width: 1.75rem;
      height: 1.75rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      border-radius: var(--jd-radius-md);
      background: transparent;
      color: var(--jd-color-muted);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      cursor: pointer;
      flex-shrink: 0;
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-rte__tool:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
      color: var(--jd-color-foreground);
    }
    .jd-rte__tool:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-muted) 26%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    /* 툴바가 좁아 바깥 아웃라인이 이웃 버튼과 겹친다 — 링을 그림자로 준다(§1) */
    .jd-rte__tool:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    /* 활성 서식 — aria-pressed로 표시 */
    .jd-rte__tool[aria-pressed="true"] {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }
    .jd-rte__tool:disabled {
      cursor: not-allowed;
      opacity: var(--jd-opacity-50);
    }

    /* 버튼 글리프에 서식 미리보기(v2 font-extrabold/italic/underline/line-through) */
    .jd-rte__tool[data-style="bold"] {
      font-weight: var(--jd-weight-bold);
    }
    .jd-rte__tool[data-style="italic"] {
      font-style: italic;
    }
    .jd-rte__tool[data-style="underline"] {
      text-decoration: underline;
    }
    .jd-rte__tool[data-style="strike"] {
      text-decoration: line-through;
    }

    /* outline: none 의 대체 표시는 호스트의 [data-focused] 링이다 — 편집영역 자체에
       아웃라인을 그리면 컨테이너 안쪽에서 두 겹으로 보인다(§1) */
    .jd-rte__editor {
      position: relative;
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-foreground);
      outline: none;
      line-height: var(--jd-leading-relaxed);
      overflow-wrap: break-word;
    }
    /* 플레이스홀더 — 비었고 포커스 없을 때만(v2 조건 동일) */
    jd-rich-text-editor[data-empty]:not([data-focused]) .jd-rte__editor::before {
      content: attr(data-placeholder);
      color: var(--jd-color-muted);
      pointer-events: none;
    }

    /* 편집 영역 내부 블록 여백 정리 — prose-sm 근사 */
    .jd-rte__editor :where(h2) {
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-semibold);
      margin: var(--jd-space-2) 0 var(--jd-space-1);
    }
    .jd-rte__editor :where(ul, ol) {
      padding-left: var(--jd-space-5);
      margin: var(--jd-space-1) 0;
    }
    .jd-rte__editor :where(p) {
      margin: 0 0 var(--jd-space-1);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-rich-text-editor,
      .jd-rte__tool {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-sankey-diagram:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-sankey-diagram {
      display: inline-block;
      /* width/height 프롭(기본 560×320)은 뷰박스 비율일 뿐 캔버스 크기 약속이 아니다.
       상한을 두지 않으면 560px 그림이 그보다 좁은 카드를 밀고 나가고, 카드의 overflow가
       오른쪽 끝 — 즉 마지막 컬럼의 라벨 — 을 통째로 잘라 먹는다(§6). */
      max-width: 100%;
      line-height: 0;
      font-family: var(--jd-font-sans);
    }

    /* 표시 속성 width/height보다 CSS가 이긴다. height:auto면 viewBox가 비율을 대신
     말하므로 폭만 줄여도 그림이 찌그러지지 않는다(jd-bar-chart 선례). */
    .jd-sankey-diagram__svg {
      display: block;
      max-width: 100%;
      height: auto;
      /* 라벨 11px은 뷰박스 안 단위라 그림과 함께 줄어든다 — 무한정 접히면 §9 하한
       아래로 내려가므로, 칸이 더 좁을 때만 양보하는 바닥을 둔다(jd-bar-chart 선례) */
      min-width: min(100%, 20rem);
      /* 라벨은 노드 바깥에 그린다 — 캔버스 경계에서 잘리지 않게 넘칠 수 있게 둔다 */
      overflow: visible;
    }

    .jd-sankey-diagram__link {
      fill: none;
      stroke: var(--jd-sankey-diagram-stroke, var(--jd-color-primary));
      stroke-opacity: 0.35; /* v2 값 — 토큰 사다리에 35가 없어 리터럴 유지 */
      transition: stroke-opacity var(--jd-duration-fast) var(--jd-easing-default);
    }
    .jd-sankey-diagram__link:hover {
      stroke-opacity: 0.55;
    }

    .jd-sankey-diagram__node {
      fill: var(--jd-sankey-diagram-fill, var(--jd-color-primary));
    }

    .jd-sankey-diagram__label {
      fill: var(--jd-color-foreground);
      font-size: 11px; /* v2 fontSize=11 */
      pointer-events: none;
    }

    /* 그림의 텍스트 등가물 — 시각적으로만 숨긴다 (jd-comparison-grid 관용구) */
    .jd-sankey-diagram__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-sankey-diagram__link {
        transition: none;
      }
    }
  }

  @layer junds.components {
    
  /*
   * 호스트 기본값은 :where()로 특이도 0에 둔다. 그러지 않으면 [data-jd-chart](0,1,0)가
   * 컴포넌트 자신의 태그 규칙 jd-funnel-chart(0,0,1)를 이겨서, 파생이 display나
   * 팔레트 순서를 못 바꾼다(퍼널이 block·자기 색 순서를 되찾지 못하던 실측 함정).
   */
  :where([data-jd-chart]) {
    --jd-chart-1: var(--jd-color-primary);
    --jd-chart-2: var(--jd-color-success);
    --jd-chart-3: var(--jd-color-warning);
    --jd-chart-4: var(--jd-color-danger);
    --jd-chart-5: var(--jd-color-info);
    --jd-chart-6: #a855f7;
    --jd-chart-7: #ec4899;
    --jd-series-color: var(--jd-chart-1);
    display: inline-flex; align-items: center; gap: var(--jd-space-4);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
  }

  .jd-chart__svg { display: block; overflow: visible; }

  /* 축·격자 — v2 stroke="var(--border)" strokeDasharray="2 2" strokeOpacity=.4 */
  .jd-chart__gridline {
    stroke: var(--jd-color-border); stroke-dasharray: 2 2; stroke-opacity: .4;
  }
  .jd-chart__axisline { stroke: var(--jd-color-border); stroke-opacity: .4; }
  .jd-chart__tick {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 시리즈 — 색은 커스텀 프로퍼티 경유(표시 속성에 박지 않는다) */
  .jd-chart__line {
    fill: none; stroke: var(--jd-series-color); stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  .jd-chart__area {
    fill: var(--jd-series-color);
    fill-opacity: var(--jd-chart-fill-opacity, .15);
    stroke: none;
  }
  .jd-chart__dot { fill: var(--jd-series-color); }
  .jd-chart__bar { fill: var(--jd-series-color); }
  .jd-chart__value {
    font-size: 10px; fill: var(--jd-color-muted);
    font-variant-numeric: tabular-nums;
  }

  /* 범례 — v2 "flex flex-col gap-1 text-xs" */
  .jd-chart__legend { margin: 0; padding: 0; list-style: none; }
  .jd-chart__legend:not([hidden]) {
    display: flex; flex-direction: column; gap: var(--jd-space-1);
    font-size: var(--jd-text-xs);
  }
  .jd-chart__legend-item {
    display: flex; align-items: center; gap: var(--jd-space-2);
  }
  .jd-chart__swatch {
    flex-shrink: 0; width: 10px; height: 10px;
    border-radius: var(--jd-radius-sm); background: var(--jd-series-color);
  }
  .jd-chart__legend-item[data-dot] > .jd-chart__swatch { border-radius: var(--jd-radius-full); }
  .jd-chart__legend-name { color: var(--jd-color-foreground); }
  .jd-chart__legend-value {
    color: var(--jd-color-muted); font-variant-numeric: tabular-nums;
  }

  /*
   * 데이터 표 — 시각적으로만 숨긴다(display:none은 AT에서도 지워진다).
   * v2에서 스크린리더가 들을 수 있던 것은 "라인 차트"라는 이름 하나뿐이었다.
   *
   * 숨김 규칙은 **래퍼**가 쓴다. width:1px를 <table>에 직접 걸면 auto 테이블 레이아웃이
   * 내용 폭까지 늘어나(실측 97×140) 절대배치 상태로 문서 오른쪽 밖으로 나갈 수 있고,
   * display를 바꿔 줄이면 표 역할 자체가 접근성 트리에서 사라진다.
   */
  .jd-chart__data {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

    jd-scatter-plot {
      /* 계열색은 hue 팔레트에서만(§8). 공용 기본값은 success/warning/danger를 계열색으로
       써서 "4번 시리즈"와 "위험"이 한 화면에서 같은 색이 된다 — 계열은 뜻이 없다. */
      --jd-chart-1: var(--jd-color-hue-violet);
      --jd-chart-2: var(--jd-color-hue-teal);
      --jd-chart-3: var(--jd-color-hue-amber);
      --jd-chart-4: var(--jd-color-hue-blue);
      --jd-chart-5: var(--jd-color-hue-rose);
      --jd-chart-6: var(--jd-color-hue-green);
      --jd-chart-7: var(--jd-color-hue-orange);
      /* 480px 뷰박스가 카드보다 넓으면 오른쪽 끝 x축 라벨이 잘린 채 끝났다(§6) */
      max-width: 100%;
      flex-wrap: wrap;
    }
    /* width/height는 표시 속성이라 CSS가 이긴다. height:auto면 viewBox가 비율을
     대신 말한다. min-width는 플렉스 자식의 min-width:auto(=내용 폭 480) 바닥을 풀되,
     범례 옆에서 뭉개지지 않게 컨테이너가 더 좁을 때만 양보하도록 잡는다. */
    jd-scatter-plot > .jd-chart__svg {
      max-width: 100%;
      height: auto;
      min-width: min(100%, 15rem);
    }

    .jd-chart__point {
      fill: var(--jd-series-color);
      fill-opacity: 0.8;
      stroke: var(--jd-series-color);
      stroke-width: 1;
    }
    .jd-chart__point[data-bubble] {
      fill-opacity: 0.5;
    }

    jd-scatter-plot:not(:defined) {
      display: inline-flex;
    }
  }

  @layer junds.components {
    jd-scroll-area {
      position: relative;
      display: block;
      /* max-height와 소비자 padding/border 병용이 기본 사용례 — v2 preflight(border-box)와
       같은 총높이 상한이 되도록 자기 선언한다(DEC-014-9 · DEC-024-2 위반 계열) */
      box-sizing: border-box;
      overflow-x: hidden;
      overflow-y: auto; /* orientation 기본 vertical */
      scrollbar-width: thin;
      scrollbar-color: var(--jd-color-border) transparent;
    }
    jd-scroll-area[orientation="horizontal"] {
      overflow-x: auto;
      overflow-y: hidden;
    }
    jd-scroll-area[orientation="both"] {
      overflow: auto;
    }

    jd-scroll-area::-webkit-scrollbar {
      width: var(--jd-space-2);
      height: var(--jd-space-2);
    }
    jd-scroll-area::-webkit-scrollbar-track {
      background: transparent;
    }
    jd-scroll-area::-webkit-scrollbar-thumb {
      background: var(--jd-color-border);
      border-radius: var(--jd-radius-full);
    }
    jd-scroll-area::-webkit-scrollbar-thumb:hover {
      background: var(--jd-color-muted-light);
    }

    jd-scroll-area:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
  }

  @layer junds.components {
    jd-scroll-progress {
      display: block;
      box-sizing: border-box;
      position: fixed;
      inset-inline: 0;
      inset-block-start: 0;
      z-index: var(--jd-z-overlay);
      height: var(--jd-scroll-progress-thickness, 3px);
      pointer-events: none;
      overflow: hidden;
    }
    jd-scroll-progress[position="bottom"] {
      inset-block-start: auto;
      inset-block-end: 0;
    }

    .jd-scroll-progress__bar {
      width: 100%;
      height: 100%;
      transform-origin: 0 50%;
      transform: scaleX(var(--jd-scroll-progress-scale, 0));
      background: var(--jd-scroll-progress-color, var(--jd-color-primary));
      transition: transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    jd-scroll-progress:dir(rtl) .jd-scroll-progress__bar {
      transform-origin: 100% 50%;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-scroll-progress__bar {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-scroll-spy {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
    }
    jd-scroll-spy[data-empty] {
      display: none;
    }

    .jd-scroll-spy__list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-scroll-spy__row {
      display: flex;
      min-width: 0;
      /* 들여쓰기 단계 × 12px — v2 (level - minLevel) * 12 동형 */
      padding-inline-start: calc(var(--jd-scroll-spy-depth, 0) * 12px);
    }

    .jd-scroll-spy__item {
      flex: 1;
      min-width: 0;
      display: block;
      box-sizing: border-box;
      text-align: start;
      text-decoration: none;
      padding-block: var(--jd-space-1-5);
      padding-inline: var(--jd-space-3);
      border-radius: var(--jd-radius-md);
      border-inline-start: var(--jd-border-medium) solid transparent;
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      transition: color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-scroll-spy__item:hover {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card-hover);
    }
    .jd-scroll-spy__item:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-scroll-spy__item[aria-current] {
      border-inline-start-color: var(--jd-color-primary);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
      background: color-mix(in srgb, var(--jd-color-primary) 5%, transparent);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-scroll-spy__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-search-bar {
      display: block;
      width: 100%;
    }

    jd-search-bar .jd-search-input__box {
      height: 2.5rem;
    } /* v2 md h-10 */
    jd-search-bar .jd-search-input__icon > svg {
      width: 16px;
      height: 16px;
    }
    jd-search-bar[disabled] .jd-search-input__box {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-search-bar[size="sm"] .jd-search-input__box {
      height: 2rem;
      padding-inline: var(--jd-space-2-5);
    }
    jd-search-bar[size="sm"] .jd-search-input__input {
      font-size: var(--jd-text-xs);
    }
    jd-search-bar[size="lg"] .jd-search-input__box {
      height: 3rem;
      padding-inline: var(--jd-space-4);
    }
    jd-search-bar[size="lg"] .jd-search-input__input {
      font-size: var(--jd-text-lg);
    }
  }

  @layer junds.components {
    jd-search-box {
      position: relative;
      display: flex;
      flex-direction: column;
      width: 100%;
      font-family: var(--jd-font-sans);
      --_up: var(--jd-fin-up, #e11d48);
      --_down: var(--jd-fin-down, #2563eb);
      --_muted: var(--jd-fin-muted, var(--jd-color-muted));
      --_soft: var(--jd-fin-soft-100, var(--jd-color-card-hover));
    }
    jd-search-box:not(:defined) {
      display: block;
    }

    /* 호스트 변형 — Combobox의 jd-combobox[...] 규칙 대응(태그가 달라 재선언) */
    jd-search-box[disabled] > .jd-combobox__control {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    jd-search-box[error] > .jd-combobox__control {
      border-color: var(--jd-color-danger);
    }
    jd-search-box[error] > .jd-combobox__control:focus-within {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-search-box > .jd-combobox__control {
      border-radius: var(--jd-radius-full);
    }
    jd-search-box > .jd-combobox__popup {
      border-radius: var(--jd-radius-xl, 16px);
      overflow: hidden;
      max-height: 60vh;
    }
    jd-search-box .jd-combobox__empty {
      display: none;
    } /* v2엔 빈 상태 문구 없음 — 푸터가 대신 */

    /* ⌘K 힌트 — 데스크톱만(v2 hidden md:inline-flex) */
    .jd-search-box__kbd {
      display: none;
      align-items: center;
      gap: 4px;
      flex-shrink: 0;
      padding: 2px 7px;
      border-radius: 6px;
      background: var(--_soft);
      border: 1px solid var(--jd-color-border);
      color: var(--_muted);
      font: inherit;
      font-size: 10px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
    }
    .jd-search-box__kbd > svg {
      width: 10px;
      height: 10px;
    }
    @media (min-width: 768px) {
      .jd-search-box__kbd {
        display: inline-flex;
      }
    }

    /* 지우기 */
    .jd-search-box__clear {
      display: inline-grid;
      place-items: center;
      flex-shrink: 0;
      width: 20px;
      height: 20px;
      margin: 0;
      padding: 0;
      border: 0;
      background: none;
      cursor: pointer;
      color: var(--_muted);
      border-radius: var(--jd-radius-full);
    }
    .jd-search-box__clear[hidden] {
      display: none;
    }
    .jd-search-box__clear > svg {
      width: 14px;
      height: 14px;
    }
    .jd-search-box__clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-search-box__clear:focus-visible {
      outline: 2px solid var(--jd-color-focus);
      outline-offset: 1px;
    }

    /* 결과 행 — 콤보의 .jd-combobox__option 위에 검색 외형을 덧입힌다 */
    .jd-search-box__hit {
      justify-content: space-between;
      padding: 12px 18px;
    }
    .jd-search-box__hit + .jd-search-box__hit {
      border-top: 1px solid var(--jd-color-border);
    }

    .jd-search-box__main {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-search-box__name {
      font-weight: 700;
      font-size: 13.5px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-search-box__badge {
      flex-shrink: 0;
      font-size: 10px;
      font-weight: 800;
      padding: 1px 6px;
      border-radius: var(--jd-radius-full);
      background: var(--_soft);
      color: var(--_muted);
      border: 1px solid var(--jd-color-border);
    }
    .jd-search-box__badge[hidden] {
      display: none;
    }
    .jd-search-box__sub {
      font-size: 11px;
      color: var(--_muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-search-box__sub[hidden] {
      display: none;
    }

    .jd-search-box__aside {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-shrink: 0;
      font-variant-numeric: tabular-nums;
    }
    .jd-search-box__price {
      font-size: 12.5px;
      font-weight: 600;
    }
    .jd-search-box__price[hidden] {
      display: none;
    }
    .jd-search-box__change {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      font-size: 12px;
      font-weight: 700;
      color: var(--_muted);
    }
    .jd-search-box__change[hidden] {
      display: none;
    }
    .jd-search-box__change > svg {
      width: 11px;
      height: 11px;
    }
    .jd-search-box__change[data-dir="up"] {
      color: var(--_up);
    }
    .jd-search-box__change[data-dir="down"] {
      color: var(--_down);
    }
    .jd-search-box__code {
      font-size: 11px;
      font-weight: 700;
      color: var(--_muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-search-box__code[hidden] {
      display: none;
    }

    /* 전체 검색 푸터 */
    .jd-search-box__footer {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 4px;
      width: 100%;
      box-sizing: border-box;
      padding: var(--jd-space-2) var(--jd-space-3);
      border: 0;
      border-top: 1px solid var(--jd-color-border);
      background: var(--_soft);
      color: var(--jd-fin-accent-strong, var(--jd-color-primary));
      font: inherit;
      font-size: 12.5px;
      font-weight: 700;
      cursor: pointer;
    }
    .jd-search-box__footer[hidden] {
      display: none;
    }
    .jd-search-box__footer-chevron {
      width: 12px;
      height: 12px;
    }
    .jd-search-box__footer:hover {
      filter: brightness(0.97);
    }
    .jd-search-box__footer:focus-visible {
      outline: 2px solid var(--jd-color-focus);
      outline-offset: -2px;
    }
  }

  @layer junds.components {
    jd-search-input {
      display: block;
      width: 100%;
    }

    .jd-search-input__box {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      width: 100%;
      height: 2.25rem;
      padding-inline: var(--jd-space-3); /* md 기본 — v2 h-9/px-3 */
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    /* 포커스 링은 박스가 갖는다 — 내부 input의 outline 제거를 상쇄하는 단일 지표 */
    .jd-search-input__box:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-search-input[disabled] .jd-search-input__box {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-search-input__icon {
      display: flex;
      flex-shrink: 0;
      pointer-events: none;
      color: var(--jd-color-muted);
    }

    .jd-search-input__input {
      flex: 1;
      min-width: 0;
      align-self: stretch;
      margin: 0;
      padding: 0;
      border: 0;
      background: transparent;
      outline: none;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }
    .jd-search-input__input::placeholder {
      color: var(--jd-color-muted-light);
    }
    .jd-search-input__input:disabled {
      cursor: not-allowed;
    }
    /* v2 [&::-webkit-search-cancel-button]:hidden — 자체 지우기 버튼과 중복 */
    .jd-search-input__input::-webkit-search-cancel-button {
      display: none;
    }

    .jd-search-input__spinner {
      display: flex;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }
    .jd-search-input__spinner[hidden] {
      display: none;
    }
    .jd-search-input__spinner > svg {
      animation: jd-search-spin 1s linear infinite;
    }
    @keyframes jd-search-spin {
      to {
        transform: rotate(360deg);
      }
    }

    .jd-search-input__clear {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      margin: 0;
      padding: var(--jd-space-0-5);
      border: 0;
      background: none;
      border-radius: var(--jd-radius-sm);
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-search-input__clear:hover {
      color: var(--jd-color-foreground);
    }
    .jd-search-input__clear:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 1px;
    }
    .jd-search-input__clear[hidden] {
      display: none;
    }

    .jd-search-input__end {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      flex-shrink: 0;
    }
    .jd-search-input__end[hidden] {
      display: none;
    }

    jd-search-input[size="sm"] .jd-search-input__box {
      height: 2rem;
      padding-inline: var(--jd-space-2-5);
      border-radius: var(--jd-radius-md);
    }
    jd-search-input[size="sm"] .jd-search-input__input {
      font-size: var(--jd-text-xs);
    }
    jd-search-input[size="lg"] .jd-search-input__box {
      height: 2.75rem;
      padding-inline: var(--jd-space-4);
      border-radius: var(--jd-radius-xl);
    }
    jd-search-input[size="lg"] .jd-search-input__input {
      font-size: var(--jd-text-lg);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-search-input__box,
      .jd-search-input__clear {
        transition: none;
      }
      /* 정지가 아니라 감속 — 로딩 지표는 계속 보여야 한다(jd-spinner 선례) */
      .jd-search-input__spinner > svg {
        animation-duration: 1.6s;
      }
    }
  }

  @layer junds.components {
    jd-section {
      display: block;
    }
    jd-section[border] {
      border: 1px solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
    }

    .jd-section__header {
      margin-bottom: var(--jd-space-4);
    }
    .jd-section__header[hidden] {
      display: none;
    }
    .jd-section__title {
      margin: 0;
      font-size: var(--jd-text-xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-foreground);
    }
    .jd-section__desc {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-muted);
    }

    .jd-section__body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    jd-security-badge {
      display: inline-flex;
      align-items: center;
      box-sizing: border-box;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-1) var(--jd-space-2);
      border: var(--jd-border-thin) solid var(--_jd-sec-border);
      border-radius: var(--jd-radius-full);
      background: var(--_jd-sec-bg);
      color: var(--_jd-sec-fg);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      white-space: nowrap;
      /* unverified 기본 (gray-50 / gray-200 / gray-600) */
      --_jd-sec-bg: var(--jd-color-neutral-25);
      --_jd-sec-border: var(--jd-color-neutral-200);
      --_jd-sec-fg: var(--jd-color-neutral-700);
    }
    jd-security-badge[level="critical"] {
      --_jd-sec-bg: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-red) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
      --_jd-sec-border: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-red) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-border-mix),
        transparent
      );
      --_jd-sec-fg: color-mix(
        in srgb,
        var(--jd-color-hue-red) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-security-badge[level="warning"] {
      --_jd-sec-bg: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-amber) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
      --_jd-sec-border: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-amber) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-border-mix),
        transparent
      );
      --_jd-sec-fg: color-mix(
        in srgb,
        var(--jd-color-hue-amber) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-security-badge[level="safe"] {
      --_jd-sec-bg: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-green) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
      --_jd-sec-border: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-green) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-border-mix),
        transparent
      );
      --_jd-sec-fg: color-mix(
        in srgb,
        var(--jd-color-hue-green) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-security-badge[level="verified"] {
      --_jd-sec-bg: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-blue) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
      --_jd-sec-border: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-hue-blue) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-border-mix),
        transparent
      );
      --_jd-sec-fg: color-mix(
        in srgb,
        var(--jd-color-hue-blue) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    jd-security-badge[size="sm"] {
      gap: var(--jd-space-1);
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      font-size: 10px;
    }
    jd-security-badge[size="lg"] {
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: var(--jd-text-sm);
    }

    .jd-security-badge__icon {
      display: inline-flex;
      flex-shrink: 0;
      width: 12px;
      height: 12px; /* md 기본 */
    }
    .jd-security-badge__icon[hidden] {
      display: none;
    }
    .jd-security-badge__icon > svg {
      width: 100%;
      height: 100%;
    }
    jd-security-badge[size="sm"] .jd-security-badge__icon {
      width: 10px;
      height: 10px;
    }
    jd-security-badge[size="lg"] .jd-security-badge__icon {
      width: 14px;
      height: 14px;
    }

    /* 심각도 보충 낱말 — 화면에는 없고 스크린리더에만 읽힌다 */
    .jd-security-badge__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.base {
    jd-security-checklist:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-security-checklist {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
    }

    .jd-security__header {
      padding: var(--jd-space-4) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-security__head-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      margin-block-end: var(--jd-space-2);
    }
    .jd-security__title {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-security__count {
      flex-shrink: 0;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-variant-numeric: tabular-nums;
    }
    .jd-security__count[data-level="ok"] {
      background: color-mix(in srgb, var(--jd-color-success) 12%, transparent);
      color: color-mix(
        in srgb,
        var(--jd-color-success) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    .jd-security__count[data-level="warn"] {
      background: color-mix(in srgb, var(--jd-color-warning) 12%, transparent);
      color: color-mix(
        in srgb,
        var(--jd-color-warning) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    .jd-security__count[data-level="bad"] {
      background: color-mix(in srgb, var(--jd-color-danger) 12%, transparent);
      color: color-mix(
        in srgb,
        var(--jd-color-danger) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }

    /* 진행 막대 */
    .jd-security__progress {
      display: flex;
      gap: var(--jd-space-0-5);
    }
    .jd-security__seg {
      height: 0.375rem;
      flex: 1 1 0;
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-color-muted) 25%, transparent);
    }
    .jd-security__seg[data-status="secure"] {
      background: var(--jd-color-success);
    }
    .jd-security__seg[data-status="insecure"] {
      background: var(--jd-color-danger);
    }
    .jd-security__seg[data-status="attention"] {
      background: var(--jd-color-warning);
    }

    /* 항목 */
    .jd-security__list {
      display: block;
    }
    .jd-security__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-5);
    }
    .jd-security__item:not(:first-child) {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border-light);
    }

    .jd-security__icon {
      flex-shrink: 0;
      width: 2rem;
      height: 2rem;
      border-radius: var(--jd-radius-full);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: color-mix(in srgb, var(--jd-color-muted) 14%, transparent);
      color: var(--jd-color-muted);
    }
    .jd-security__icon[data-status="secure"] {
      background: color-mix(in srgb, var(--jd-color-success) 14%, transparent);
      color: var(--jd-color-success);
    }
    .jd-security__icon[data-status="insecure"] {
      background: color-mix(in srgb, var(--jd-color-danger) 14%, transparent);
      color: var(--jd-color-danger);
    }
    .jd-security__icon[data-status="attention"] {
      background: color-mix(in srgb, var(--jd-color-warning) 14%, transparent);
      color: var(--jd-color-warning);
    }
    .jd-security__icon svg {
      width: 1rem;
      height: 1rem;
    }

    .jd-security__body {
      flex: 1 1 auto;
      min-width: 0;
    }
    .jd-security__item-title {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-security__item-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-security__action {
      flex-shrink: 0;
      cursor: pointer;
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      padding: var(--jd-space-1) var(--jd-space-2-5);
      border-radius: var(--jd-radius-md);
      border: var(--jd-border-thin) solid transparent;
      /* all 금지 — padding·font-size까지 대상이 되어 밀도 전환이 흐른다 (DEC-039) */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-security__action[data-variant="primary"] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-security__action[data-variant="primary"]:hover {
      background: var(--jd-color-primary-hover);
    }
    /* v2 bg-surface는 Tailwind의 밝은 패널색이다 — 다크 전용 토큰인 --jd-color-surface에
     foreground를 얹으면 라이트 모드에서 검은 글자가 검은 버튼에 묻힌다. 보조 버튼의
     면은 jd-button[variant=secondary]와 같은 어휘(card + border)로 맞춘다. */
    .jd-security__action[data-variant="secondary"] {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border-color: var(--jd-color-border);
      box-shadow: var(--jd-shadow-xs);
    }
    .jd-security__action[data-variant="secondary"]:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
      box-shadow: var(--jd-shadow-sm);
    }
    /* 눌린 면은 빛을 잃는다 */
    /* [data-variant]까지 붙여 변종 :hover(특이도 0,3,0)를 넘긴다 — 누르는 동안에도
     :hover가 참이라 특이도가 낮으면 눌림이 호버에 가린다 */
    .jd-security__action[data-variant]:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-security__action:focus-visible {
      /* 항목 행이 카드 overflow:hidden 안이라 outline이 잘린다 — 링을 그림자로 그린다 */
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-security__action {
        transition: none;
      }
      .jd-security__action[data-variant]:active {
        scale: none;
      }
    }
  }

  @layer junds.components {
    jd-segmented-control {
      position: relative;
      display: inline-flex;
      align-items: stretch;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-1);
      border-radius: var(--jd-radius-lg);
      /* 트랙은 "파인 홈", 인디케이터는 "떠 있는 카드"다. v2의 bg-gray-100을 그대로
       --jd-color-border-light로 번역하면 **다크에서 역전된다**(border-light #22203a가
       card #161329보다 밝아 인디케이터가 더 어두워진다). 배경을 어둡게 깎아 두 테마
       모두에서 트랙 < 인디케이터 순서를 지킨다 — 실브라우저 다크 스냅샷에서 발견. */
      background: color-mix(in srgb, var(--jd-color-background) 94%, #000);
      font-family: var(--jd-font-sans);
    }
    jd-segmented-control[full-width] {
      display: flex;
      width: 100%;
    }
    jd-segmented-control[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-segmented-control__indicator {
      position: absolute;
      top: var(--jd-space-1);
      bottom: var(--jd-space-1);
      left: 0;
      border-radius: var(--jd-radius-md);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-sm);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out),
        width var(--jd-duration-normal) var(--jd-easing-ease-out);
      pointer-events: none;
    }
    .jd-segmented-control__indicator[hidden] {
      display: none;
    }

    .jd-segmented-control__seg {
      position: relative;
      z-index: 1;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      border-radius: var(--jd-radius-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      cursor: pointer;
      user-select: none;
      white-space: nowrap;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md */
      padding: var(--jd-space-1-5) var(--jd-space-3-5);
      font-size: var(--jd-text-md);
    }
    jd-segmented-control[full-width] .jd-segmented-control__seg {
      flex: 1;
    }
    jd-segmented-control[size="sm"] .jd-segmented-control__seg {
      padding: var(--jd-space-1) var(--jd-space-2-5);
      font-size: var(--jd-text-xs);
    }
    jd-segmented-control[size="lg"] .jd-segmented-control__seg {
      padding: var(--jd-space-2) var(--jd-space-5);
      font-size: var(--jd-text-lg);
    }

    .jd-segmented-control__seg:hover {
      color: var(--jd-color-foreground);
    }
    .jd-segmented-control__seg[data-selected] {
      color: var(--jd-color-foreground);
    }
    .jd-segmented-control__seg[data-disabled] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
      color: var(--jd-color-muted);
    }

    /* 네이티브 radio는 시각적으로만 숨긴다 — 포커스·키보드·폼은 그대로 살아 있다 */
    .jd-segmented-control__input {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      border: 0;
      overflow: hidden;
      white-space: nowrap;
      clip-path: inset(50%);
    }
    .jd-segmented-control__seg:has(.jd-segmented-control__input:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: -1px;
    }

    .jd-segmented-control__icon {
      flex-shrink: 0;
    }
    .jd-segmented-control__icon[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-segmented-control__indicator,
      .jd-segmented-control__seg {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-segmented-pill:not(:defined) {
      display: inline-flex;
    }
  }
  @layer junds.components {
    /* 트랙 — v2: relative inline-flex items-center rounded-full p-1 border */
    jd-segmented-pill {
      position: relative;
      box-sizing: border-box; /* full-width 시 width:100% + padding + border 오버플로 방지 */
      display: inline-flex;
      align-items: center;
      gap: 0;
      padding: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-border-light);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      font-family: var(--jd-font-sans);
    }
    jd-segmented-pill[full-width] {
      display: flex;
      width: 100%;
    }

    /* 알약 — underline 잔재 제거 + 알약 기하 */
    jd-segmented-pill .jd-tabs__tab {
      position: relative;
      z-index: 1;
      gap: var(--jd-space-1-5);
      border-block-end: 0;
      margin-block-end: 0;
      border-radius: var(--jd-radius-full);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
      background: transparent;
      transition: color var(--jd-duration-normal) var(--jd-easing-ease-out),
        background var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
      /* size 기본 md — v2: px-4 py-1.5 text-[13px] */
      padding: var(--jd-space-1-5) var(--jd-space-4);
      font-size: var(--jd-text-sm);
    }
    jd-segmented-pill[full-width] .jd-tabs__tab {
      flex: 1;
    }

    jd-segmented-pill[size="sm"] .jd-tabs__tab {
      padding: var(--jd-space-1) var(--jd-space-3);
      font-size: 0.71875rem; /* v2 11.5px */
    }
    jd-segmented-pill[size="lg"] .jd-tabs__tab {
      padding: var(--jd-space-2) var(--jd-space-5);
      font-size: var(--jd-text-md); /* 14px */
    }

    jd-segmented-pill .jd-tabs__tab:hover:not(:disabled) {
      color: color-mix(in srgb, var(--jd-color-foreground) 75%, transparent);
      background: transparent;
    }
    jd-segmented-pill .jd-tabs__tab[aria-selected="true"] {
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-sm);
      border-block-end: 0;
    }

    /* 카운트 배지 — v2: min-w-18 rounded-full px-1.5 text-[10.5px] font-extrabold */
    jd-segmented-pill .jd-tabs__badge {
      min-width: 18px;
      font-size: 0.65625rem; /* v2 10.5px */
      font-weight: 800;
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
      color: var(--jd-color-muted);
    }
    jd-segmented-pill .jd-tabs__tab[aria-selected="true"] > .jd-tabs__badge {
      background: var(--jd-color-primary);
      color: #fff;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-segmented-pill .jd-tabs__tab {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-select {
      position: relative;
      display: inline-flex;
      flex-direction: column;
      width: fit-content;
    }
    jd-select[full-width] {
      display: flex;
      width: 100%;
    }

    /* ── 트리거 ─────────────────────────────────────────────── */
    .jd-select__trigger {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      cursor: pointer;
      text-align: start;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md — 기본값은 attribute 미반영(§1.3)이라 base가 담당 */
      height: 2.25rem;
      padding-inline: var(--jd-space-3);
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-lg);
    }
    .jd-select__trigger:focus-visible,
    jd-select[open] > .jd-select__trigger {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-select__trigger:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-select[size="sm"] > .jd-select__trigger {
      height: 2rem;
      padding-inline: var(--jd-space-2-5);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-md);
    }
    jd-select[size="lg"] > .jd-select__trigger {
      height: 2.75rem;
      padding-inline: var(--jd-space-4);
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-xl);
    }

    jd-select[error] > .jd-select__trigger {
      border-color: var(--jd-color-danger);
    }
    jd-select[error] > .jd-select__trigger:focus-visible,
    jd-select[error][open] > .jd-select__trigger {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }

    .jd-select__value {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
      overflow: hidden;
    }
    .jd-select__value[data-placeholder] {
      color: var(--jd-color-muted-light);
    }
    .jd-select__value-icon[hidden] {
      display: none;
    }
    .jd-select__value-text {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-select__chevron {
      width: 1rem;
      height: 1rem;
      flex-shrink: 0;
      color: var(--jd-color-muted);
      transition: transform var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-select[open] .jd-select__chevron {
      transform: rotate(180deg);
    }

    /* ── 팝업 ───────────────────────────────────────────────── */
    .jd-select__popup {
      position: absolute;
      top: 100%;
      inset-inline: 0;
      margin-block-start: var(--jd-space-1);
      z-index: var(--jd-z-dropdown);
      box-sizing: border-box;
      max-height: 15rem;
      overflow: auto;
      padding-block: var(--jd-space-1);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-xl);
      transform-origin: top center;
      animation: jd-select-pop var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-select__popup[hidden] {
      display: none;
    }
    @keyframes jd-select-pop {
      from {
        opacity: 0;
        transform: scale(0.97);
      }
    }

    .jd-select__search {
      position: sticky;
      top: 0;
      z-index: 1;
      padding: var(--jd-space-1-5) var(--jd-space-2);
      background: var(--jd-color-card);
    }
    .jd-select__search[hidden] {
      display: none;
    }
    .jd-select__search-input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      padding: var(--jd-space-1) var(--jd-space-2);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
    }
    .jd-select__search-input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
    }
    .jd-select__search-input::placeholder {
      color: var(--jd-color-muted-light);
    }

    /* ── 목록 ───────────────────────────────────────────────── */
    .jd-select__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    .jd-select__option {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-select__option:hover,
    .jd-select__option[data-active] {
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: var(--jd-color-primary-ink);
    }
    .jd-select__option[aria-selected="true"] {
      background: var(--jd-color-primary);
      color: #fff;
      font-weight: var(--jd-weight-medium);
    }
    .jd-select__option[data-disabled] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-select__option[data-disabled]:hover {
      background: none;
      color: var(--jd-color-foreground);
    }

    .jd-select__option-icon {
      flex-shrink: 0;
    }
    .jd-select__option-icon[hidden] {
      display: none;
    }
    .jd-select__option-label {
      flex: 1;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* v2는 선택 행이 bg-primary/text-white인데 체크만 text-primary라 보이지 않았다 */
    .jd-select__option-check {
      display: inline-flex;
      flex-shrink: 0;
      margin-inline-start: auto;
      visibility: hidden;
      color: currentColor;
    }
    .jd-select__option-check > svg {
      width: 1rem;
      height: 1rem;
    }
    .jd-select__option[aria-selected="true"] > .jd-select__option-check {
      visibility: visible;
    }

    .jd-select__empty {
      padding: var(--jd-space-2) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-muted-light);
      text-align: center;
    }
    .jd-select__empty[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-select__trigger,
      .jd-select__chevron,
      .jd-select__option {
        transition: none;
      }
      .jd-select__popup {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-settings-layout {
      display: flex;
      flex-direction: column;
      min-height: 480px;
      background: var(--jd-color-background);
      font-family: var(--jd-font-sans);
    }

    .jd-settings-layout__sidebar {
      box-sizing: border-box;
      width: 100%;
      padding: var(--jd-space-4);
      background: var(--jd-color-card);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-settings-layout__title {
      padding-inline: var(--jd-space-2);
      margin-bottom: var(--jd-space-4);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--jd-color-muted);
    }
    .jd-settings-layout__title[hidden] {
      display: none;
    }

    .jd-settings-layout__nav {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }

    .jd-settings-layout__group {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
    }

    .jd-settings-layout__group-label {
      padding-inline: var(--jd-space-2);
      padding-top: var(--jd-space-2);
      font-size: 0.625rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--jd-color-muted);
    }

    .jd-settings-layout__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      width: 100%;
      padding-inline: var(--jd-space-2);
      padding-block: var(--jd-space-1-5);
      border: 0;
      border-radius: var(--jd-radius-md);
      background: transparent;
      font-family: inherit;
      font-size: var(--jd-text-md);
      text-align: left;
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-settings-layout__item:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-settings-layout__item[aria-selected="true"] {
      background: var(--jd-color-primary-light);
      /* 틴트 위 글자색은 semantic 원색이 아니라 foreground와 섞은 값이다. primary 원색을
       primary-light 위에 그대로 쓰면 대비가 AA 미달(다크에서 특히) — foreground와 섞어
       양쪽 테마에서 함께 살린다(DEC-027 · blockquote/code.css 선례). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      font-weight: var(--jd-weight-medium);
    }
    .jd-settings-layout__item:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 1px;
    }

    .jd-settings-layout__icon {
      display: inline-flex;
      flex-shrink: 0;
      align-items: center;
    }
    .jd-settings-layout__icon[hidden] {
      display: none;
    }
    .jd-settings-layout__icon svg {
      width: 1rem;
      height: 1rem;
    }

    .jd-settings-layout__label {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    /* basis는 0이 아니라 auto다. 세로 배치(사이드바가 위)에서 flex:1은 본문의 기준
     높이를 0으로 만들고, 호스트의 min-height 480px에서 남은 만큼만 자란다 —
     본문이 그보다 길면 overflow:auto가 남은 내용을 잘라 위쪽만 보였다(실측).
     basis auto면 내용이 자기 높이를 말하고 호스트가 따라 늘어난다(§6). */
    .jd-settings-layout__content {
      flex: 1 1 auto;
      min-width: 0;
      /* 반대로 호스트 높이가 밖에서 고정된 경우에는 줄어들 수 있어야 스크롤이 산다 */
      min-height: 0;
      padding: var(--jd-space-6);
      overflow: auto;
    }
    .jd-settings-layout__panel[hidden] {
      display: none;
    }

    @media (min-width: 1024px) {
      jd-settings-layout {
        flex-direction: row;
      }
      /* 가로 배치 여부는 뷰포트가 정하는데 폭은 부모가 준다 — 넓은 화면의 좁은 칼럼
       안에서 220px 고정 사이드바가 본문 칸을 다 먹었다. 칸의 40%를 상한으로 둬
       본문이 항상 사이드바보다 넓게 남는다(§6). */
      .jd-settings-layout__sidebar {
        flex: 0 0 auto;
        width: min(var(--_jd-settings-sidebar-w, 220px), 40%);
        border-bottom: 0;
        border-right: var(--jd-border-thin) solid var(--jd-color-border);
      }
      .jd-settings-layout__content {
        padding: var(--jd-space-8);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-settings-layout__item {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-severity-badge {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      padding: var(--jd-space-1) var(--jd-space-2-5);
      font-size: var(--jd-text-xs);
      /* DEC-044 톤 레시피 — severity 4종은 앵커만 바꾼다(base.css --jd-tone-*) */
      --jd-tone: var(--jd-color-hue-gray); /* neutral 기본 */
      --jd-tone-ink-mix: 68%; /* 10~12px 텍스트의 AA 대비선 */
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }
    jd-severity-badge[size="sm"] {
      padding: var(--jd-space-0-5) var(--jd-space-2);
      font-size: 10px;
    }

    jd-severity-badge[severity="ok"] {
      --jd-tone: var(--jd-color-hue-green);
    }
    jd-severity-badge[severity="warn"] {
      --jd-tone: var(--jd-color-hue-amber);
    }
    jd-severity-badge[severity="danger"] {
      --jd-tone: var(--jd-color-hue-red);
    }
    jd-severity-badge[severity="info"] {
      --jd-tone: var(--jd-color-hue-blue);
    }

    /* 점은 틴트가 아니라 원색이다 — 배지 안에서 유일하게 채도가 살아 있는 지점 */
    jd-severity-badge[dot]::before {
      content: "";
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-tone);
    }
  }

  @layer junds.components {
    jd-show,
    jd-hide {
      display: contents;
    }

    /* jd-show[above=X] — X 미만에서 숨김 */
    @media (max-width: 639.98px) {
      jd-show[above="sm"] {
        display: none;
      }
    }
    @media (max-width: 767.98px) {
      jd-show[above="md"] {
        display: none;
      }
    }
    @media (max-width: 1023.98px) {
      jd-show[above="lg"] {
        display: none;
      }
    }
    @media (max-width: 1279.98px) {
      jd-show[above="xl"] {
        display: none;
      }
    }
    @media (max-width: 1535.98px) {
      jd-show[above="2xl"] {
        display: none;
      }
    }

    /* jd-show[below=Y] — Y 이상에서 숨김 */
    @media (min-width: 640px) {
      jd-show[below="sm"] {
        display: none;
      }
    }
    @media (min-width: 768px) {
      jd-show[below="md"] {
        display: none;
      }
    }
    @media (min-width: 1024px) {
      jd-show[below="lg"] {
        display: none;
      }
    }
    @media (min-width: 1280px) {
      jd-show[below="xl"] {
        display: none;
      }
    }
    @media (min-width: 1536px) {
      jd-show[below="2xl"] {
        display: none;
      }
    }

    /* jd-hide[above=X] — X 이상에서 숨김 */
    @media (min-width: 640px) {
      jd-hide[above="sm"] {
        display: none;
      }
    }
    @media (min-width: 768px) {
      jd-hide[above="md"] {
        display: none;
      }
    }
    @media (min-width: 1024px) {
      jd-hide[above="lg"] {
        display: none;
      }
    }
    @media (min-width: 1280px) {
      jd-hide[above="xl"] {
        display: none;
      }
    }
    @media (min-width: 1536px) {
      jd-hide[above="2xl"] {
        display: none;
      }
    }

    /* jd-hide[below=Y] — Y 미만에서 숨김 */
    @media (max-width: 639.98px) {
      jd-hide[below="sm"] {
        display: none;
      }
    }
    @media (max-width: 767.98px) {
      jd-hide[below="md"] {
        display: none;
      }
    }
    @media (max-width: 1023.98px) {
      jd-hide[below="lg"] {
        display: none;
      }
    }
    @media (max-width: 1279.98px) {
      jd-hide[below="xl"] {
        display: none;
      }
    }
    @media (max-width: 1535.98px) {
      jd-hide[below="2xl"] {
        display: none;
      }
    }
  }

  @layer junds.components {
    jd-sidebar {
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      box-sizing: border-box;
      position: relative;
      height: 100%;
      width: var(--_jd-sb-w, 264px);
      background: var(--jd-color-sidebar-bg);
      color: var(--jd-color-sidebar-text);
      font-family: var(--jd-font-sans);
      border-inline-end: var(--jd-border-thin) solid rgba(255, 255, 255, 0.05);
      transition: width var(--jd-duration-slow) var(--jd-easing-default);
    }

    .jd-sidebar__header {
      flex-shrink: 0;
      padding: var(--jd-space-4) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid rgba(255, 255, 255, 0.05);
    }
    .jd-sidebar__nav {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      padding: var(--jd-space-2);
    }
    .jd-sidebar__footer {
      flex-shrink: 0;
      padding: var(--jd-space-3);
      border-block-start: var(--jd-border-thin) solid rgba(255, 255, 255, 0.05);
    }

    .jd-sidebar__toggle {
      position: absolute;
      inset-block-start: var(--jd-space-6);
      inset-inline-end: -12px;
      z-index: 1;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 24px;
      height: 24px;
      padding: 0;
      cursor: pointer;
      color: var(--jd-color-muted);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-full);
      box-shadow: var(--jd-shadow-sm);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-sidebar__toggle:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-sidebar__toggle:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-sidebar__toggle-icon {
      transition: transform var(--jd-duration-normal) var(--jd-easing-default);
    }

    /* ── 접힘: 프로바이더 소유 + 자립 두 경로 ── */
    jd-sidebar-provider[collapsed] jd-sidebar,
    jd-sidebar[collapsed] {
      width: var(--_jd-sb-cw, 68px);
    }
    jd-sidebar-provider[collapsed] .jd-sidebar__toggle-icon,
    jd-sidebar[collapsed] .jd-sidebar__toggle-icon {
      transform: rotate(180deg);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-sidebar,
      .jd-sidebar__toggle-icon {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-sidebar-layout {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-6);
      align-items: flex-start;

      /* 사이드바가 한 줄에 있을 때의 폭 */
      --jd-sidebar-width: 16rem;
      /* 본문이 이보다 좁아지면 한 줄을 포기하고 쌓인다 */
      --jd-sidebar-content-min: 60%;
    }

    /* 사이드바 — 자기 폭을 유지하되, 쌓였을 때는 한 줄을 다 쓴다 */
    jd-sidebar-layout > :first-child {
      flex-grow: 1;
      flex-basis: var(--jd-sidebar-width);
    }

    /* 본문 — 남는 공간을 전부 먹고, 최소 폭이 안 되면 다음 줄로 내려간다 */
    jd-sidebar-layout > :last-child {
      flex-grow: 999;
      flex-basis: 0;
      min-inline-size: var(--jd-sidebar-content-min);
    }

    /* 사이드바를 오른쪽으로 — DOM 순서는 그대로 두고 시각 순서만 뒤집는다.
     본문을 먼저 읽는 것이 스크린 리더·탭 순서에 맞는 경우가 많아 마크업을
     바꾸게 하지 않는다. */
    jd-sidebar-layout[side="end"] > :first-child {
      order: 1;
    }
  }

  @layer junds.components {
    jd-sidebar-link {
      display: block;
    }

    .jd-sidebar-link__anchor {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-inline-start: 2px solid transparent;
      border-radius: var(--jd-radius-lg);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-sidebar-text);
      text-decoration: none;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-sidebar-link__anchor:hover {
      background: var(--jd-color-sidebar-hover);
    }
    .jd-sidebar-link__anchor:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    jd-sidebar-link[active] .jd-sidebar-link__anchor {
      background: var(--jd-color-sidebar-hover);
      color: #ffffff;
      border-inline-start-color: var(--jd-color-sidebar-active);
    }

    .jd-sidebar-link__icon {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1.25rem;
      height: 1.25rem;
    }
    .jd-sidebar-link__icon:empty {
      display: none;
    }
    .jd-sidebar-link__icon > svg {
      width: 100%;
      height: 100%;
    }

    .jd-sidebar-link__label {
      flex: 1 1 auto;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-sidebar-link__badge {
      flex-shrink: 0;
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      background: var(--jd-color-danger);
      color: #ffffff;
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      border-radius: var(--jd-radius-full);
      font-variant-numeric: tabular-nums;
    }
    .jd-sidebar-link__badge[hidden] {
      display: none;
    }

    /* ── 접힘: 라벨·badge 숨김, 아이콘만 중앙 ── */
    jd-sidebar-provider[collapsed] .jd-sidebar-link__label,
    jd-sidebar[collapsed] .jd-sidebar-link__label,
    jd-sidebar-provider[collapsed] .jd-sidebar-link__badge,
    jd-sidebar[collapsed] .jd-sidebar-link__badge {
      display: none;
    }
    jd-sidebar-provider[collapsed] .jd-sidebar-link__anchor,
    jd-sidebar[collapsed] .jd-sidebar-link__anchor {
      justify-content: center;
    }
  }

  @layer junds.components {
    jd-sidebar-provider {
      display: contents;
    }
  }

  @layer junds.components {
    jd-sidebar-section {
      display: block;
      margin-block-end: var(--jd-space-2);
    }

    .jd-sidebar-section__title {
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: color-mix(in srgb, var(--jd-color-sidebar-text) 50%, transparent);
    }
    .jd-sidebar-section__title[hidden] {
      display: none;
    }

    .jd-sidebar-section__items {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
    }

    jd-sidebar-provider[collapsed] .jd-sidebar-section__title,
    jd-sidebar[collapsed] .jd-sidebar-section__title {
      display: none;
    }
  }

  @layer junds.components {
    jd-signature-pad {
      display: inline-flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    .jd-signature-pad__canvas {
      display: block;
      box-sizing: content-box;
      color: var(--jd-color-foreground); /* 기본 획 색의 원천 (currentColor) */
      background: var(--jd-color-card);
      border: var(--jd-border-medium) dashed var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      cursor: crosshair;
      touch-action: none;
    }
    jd-signature-pad[disabled] .jd-signature-pad__canvas {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-signature-pad__actions {
      display: flex;
      gap: var(--jd-space-2);
    }

    .jd-signature-pad__button {
      margin: 0;
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-signature-pad__button:hover:not(:disabled) {
      background: var(--jd-color-card-hover);
    }
    .jd-signature-pad__button:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 2px;
    }
    .jd-signature-pad__button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    .jd-signature-pad__button--primary {
      color: #fff;
      background: var(--jd-color-primary);
      border-color: transparent;
    }
    .jd-signature-pad__button--primary:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }

    /* 서명 유무 통지 — 시각적으로는 감추고 AT에만 노출 */
    .jd-signature-pad__status {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-signature-pad__button {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: cols=1, gap=4(16px) */
    jd-simple-grid {
      display: grid;
      grid-template-columns: repeat(1, 1fr);
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    /* text 기본 — 줄 컨테이너 */
    jd-skeleton {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }

    /* 반짝이는 블록 자체 — 프리셋도 .jd-skeleton-block으로 이 규칙을 공유한다.
     span에 높이를 주려면 block이어야 한다(인라인은 height를 무시). */
    jd-skeleton[variant="circle"],
    jd-skeleton[variant="rect"],
    .jd-skeleton__line,
    .jd-skeleton-block {
      display: block;
      background: var(--jd-skeleton-color, var(--jd-color-neutral-200));
      border-radius: var(--jd-skeleton-radius, var(--jd-radius-sm));
      animation: jd-skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
    }
    jd-skeleton[variant="circle"] {
      border-radius: var(--jd-skeleton-radius, var(--jd-radius-full));
    }
    jd-skeleton[variant="rect"] {
      border-radius: var(--jd-skeleton-radius, var(--jd-radius-lg));
    }

    .jd-skeleton__line {
      height: 0.875rem;
      flex-shrink: 0;
    } /* v2 h-3.5 */

    [data-jd-theme="dark"] jd-skeleton,
    [data-theme="dark"] jd-skeleton,
    [data-jd-theme="dark"] .jd-skeleton-block,
    [data-theme="dark"] .jd-skeleton-block {
      --jd-skeleton-color: var(--jd-color-border);
    }

    @keyframes jd-skeleton-pulse {
      0%,
      100% {
        opacity: 1;
      }
      50% {
        opacity: 0.5;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-skeleton[variant="circle"],
      jd-skeleton[variant="rect"],
      .jd-skeleton__line,
      .jd-skeleton-block {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-skeleton-preset {
      display: block;
    } /* CE 기본 display:inline 방지 */

    /* ── card(기본) ─────────────────────────────────────── */
    /* default variant는 attribute로 나가지 않는다. 맨 호스트에 카드 규칙을 얹으면
     padding·gap이 표·프로필로 새므로 :not([variant])로 기본 경우만 집는다. */
    jd-skeleton-preset:not([variant]),
    jd-skeleton-preset[variant="card"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
      padding: var(--jd-space-5);
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
    }
    .jd-skeleton-preset__thumb {
      height: 10rem;
      --jd-skeleton-radius: var(--jd-radius-xl);
    }
    .jd-skeleton-preset__title {
      height: 1.25rem;
      width: 75%;
    }
    .jd-skeleton-preset__subtitle {
      height: 1rem;
      width: 50%;
    }
    .jd-skeleton-preset__actions {
      display: flex;
      gap: var(--jd-space-2);
    }
    .jd-skeleton-preset__chip {
      height: 2rem;
      width: 5rem;
      --jd-skeleton-radius: var(--jd-radius-lg);
    }

    /* ── table ──────────────────────────────────────────── */
    jd-skeleton-preset[variant="table"] {
      display: block;
      box-sizing: border-box;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
    }
    .jd-skeleton-preset__head,
    .jd-skeleton-preset__row {
      display: flex;
      gap: var(--jd-space-4);
      padding: var(--jd-space-3);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-skeleton-preset__head {
      background: var(--jd-color-border-light);
    }
    .jd-skeleton-preset__row:last-child {
      border-bottom: 0;
    }
    .jd-skeleton-preset__cell {
      height: 1rem;
      flex: 1;
      min-width: 0;
    }

    /* ── profile ────────────────────────────────────────── */
    jd-skeleton-preset[variant="profile"] {
      display: flex;
      align-items: center;
      gap: var(--jd-space-4);
    }
    .jd-skeleton-preset__avatar {
      width: 3.5rem;
      height: 3.5rem;
      flex-shrink: 0;
      --jd-skeleton-radius: var(--jd-radius-full);
    }
    .jd-skeleton-preset__body {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      flex: 1;
      min-width: 0;
    }
    .jd-skeleton-preset__name {
      height: 1.25rem;
      width: 8rem;
    }
    .jd-skeleton-preset__meta {
      height: 1rem;
      width: 12rem;
    }

    /* ── article ────────────────────────────────────────── */
    jd-skeleton-preset[variant="article"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
    .jd-skeleton-preset__headline {
      height: 2rem;
      width: 75%;
    }
    .jd-skeleton-preset__byline {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-skeleton-preset__byline .jd-skeleton-preset__avatar {
      width: 2rem;
      height: 2rem;
    }
    .jd-skeleton-preset__by-name {
      height: 1rem;
      width: 6rem;
    }
    .jd-skeleton-preset__by-date {
      height: 1rem;
      width: 5rem;
    }
    .jd-skeleton-preset__hero {
      height: 12rem;
      --jd-skeleton-radius: var(--jd-radius-xl);
    }
    .jd-skeleton-preset__para {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
    }
    .jd-skeleton-preset__p {
      height: 1rem;
      width: 100%;
    }
    .jd-skeleton-preset__p[data-last] {
      width: 83.333%;
    } /* v2 w-5/6 */

    /* ── list ───────────────────────────────────────────── */
    jd-skeleton-preset[variant="list"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    .jd-skeleton-preset__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
    }
    .jd-skeleton-preset__icon {
      width: 2.5rem;
      height: 2.5rem;
      flex-shrink: 0;
      --jd-skeleton-radius: var(--jd-radius-lg);
    }
    .jd-skeleton-preset__item .jd-skeleton-preset__body {
      gap: var(--jd-space-1-5);
    }
    .jd-skeleton-preset__item-title {
      height: 1rem;
      width: 66.666%;
    }
    .jd-skeleton-preset__item-sub {
      height: 0.75rem;
      width: 33.333%;
    }
  }

  @layer junds.components {
    jd-slider {
      display: block;
      width: 100%;
      --_jd-slider-color: var(--jd-color-primary);
    }
    jd-slider[color="success"] {
      --_jd-slider-color: var(--jd-color-success);
    }
    jd-slider[color="warning"] {
      --_jd-slider-color: var(--jd-color-warning);
    }
    jd-slider[color="danger"] {
      --_jd-slider-color: var(--jd-color-danger);
    }
    jd-slider[disabled] {
      opacity: var(--jd-opacity-50);
    }

    .jd-slider__header {
      display: flex;
      justify-content: space-between;
      align-items: baseline;
      margin-bottom: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-slider__header[hidden] {
      display: none;
    }
    /* 값·경계 숫자는 tabular-nums — 드래그 중 자리수가 바뀔 때 폭이 흔들리면
     헤더 전체가 좌우로 떨린다 (DEC-039) */
    .jd-slider__header,
    .jd-slider__mark-label {
      font-variant-numeric: tabular-nums;
    }
    .jd-slider__display {
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }

    .jd-slider__input {
      appearance: none;
      -webkit-appearance: none;
      display: block;
      width: 100%;
      margin: 0;
      padding: 0;
      background: transparent;
      cursor: pointer;
      height: 1.25rem; /* 썸 히트 영역 */
    }
    jd-slider[disabled] .jd-slider__input {
      cursor: not-allowed;
    }

    /* 트랙 — 채움은 그라디언트 % (v2 fill div 등가). 미채움 구간에 인셋 그림자를
     넣어 '파인 홈'이 되게 한다 — 평평한 회색 바는 채움이 위에 얹힌 관계를 못 만든다. */
    .jd-slider__input::-webkit-slider-runnable-track {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: linear-gradient(
        to right,
        var(--_jd-slider-color) var(--_jd-slider-pct, 0%),
        var(--jd-color-control-track) var(--_jd-slider-pct, 0%)
      );
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-slider__input::-moz-range-track {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-track);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-slider__input::-moz-range-progress {
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--_jd-slider-color);
    }

    /* 썸 — 흰 원 + 컬러 보더. 그림자는 knob(썸 지름에 맞춘 2겹)이고, 호버·드래그에서
     지름이 아니라 **바깥 링**이 자라게 한다 — 지름이 변하면 트랙 정렬이 흔들린다. */
    .jd-slider__input::-webkit-slider-thumb {
      appearance: none;
      -webkit-appearance: none;
      width: 1.125rem;
      height: 1.125rem;
      margin-top: -6px; /* (18-6)/2 */
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      border: 2px solid var(--_jd-slider-color);
      box-shadow: var(--jd-shadow-knob);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-slider__input::-moz-range-thumb {
      width: 1.125rem;
      height: 1.125rem;
      box-sizing: border-box;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      border: 2px solid var(--_jd-slider-color);
      box-shadow: var(--jd-shadow-knob);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-slider__input:hover::-webkit-slider-thumb {
      box-shadow: var(--jd-shadow-knob),
        0 0 0 6px color-mix(in srgb, var(--_jd-slider-color) 14%, transparent);
    }
    .jd-slider__input:hover::-moz-range-thumb {
      box-shadow: var(--jd-shadow-knob),
        0 0 0 6px color-mix(in srgb, var(--_jd-slider-color) 14%, transparent);
    }
    .jd-slider__input:active::-webkit-slider-thumb {
      box-shadow: var(--jd-shadow-knob),
        0 0 0 9px color-mix(in srgb, var(--_jd-slider-color) 20%, transparent);
    }
    .jd-slider__input:active::-moz-range-thumb {
      box-shadow: var(--jd-shadow-knob),
        0 0 0 9px color-mix(in srgb, var(--_jd-slider-color) 20%, transparent);
    }
    /* 포커스 링은 트랙 전체가 아니라 컨트롤 경계에 — 색은 슬라이더 색을 따른다 */
    .jd-slider__input:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--_jd-slider-color) 55%, transparent);
      outline-offset: var(--jd-focus-ring-offset);
    }

    jd-slider[size="sm"] .jd-slider__input::-webkit-slider-runnable-track {
      height: 4px;
    }
    jd-slider[size="sm"] .jd-slider__input::-moz-range-track {
      height: 4px;
    }
    jd-slider[size="sm"] .jd-slider__input::-moz-range-progress {
      height: 4px;
    }
    jd-slider[size="sm"] .jd-slider__input::-webkit-slider-thumb {
      width: 0.875rem;
      height: 0.875rem;
      margin-top: -5px; /* (14-4)/2 */
    }
    jd-slider[size="sm"] .jd-slider__input::-moz-range-thumb {
      width: 0.875rem;
      height: 0.875rem;
    }

    /* 마크 — 트랙 아래 틱+라벨 (v2 동형) */
    .jd-slider__marks {
      position: relative;
      height: 0;
    }
    .jd-slider__marks[hidden] {
      display: none;
    }
    .jd-slider__mark {
      position: absolute;
      top: 0;
      transform: translateX(-50%);
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    .jd-slider__tick {
      width: 2px;
      height: 6px;
      margin-top: 2px;
      background: var(--jd-color-neutral-300);
    }
    .jd-slider__mark-label {
      margin-top: 2px;
      font-size: 10px;
      white-space: nowrap;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-muted);
    }
    jd-slider:has(.jd-slider__mark-label) {
      margin-bottom: var(--jd-space-6);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-slider__input::-webkit-slider-thumb {
        transition: none;
      }
      .jd-slider__input::-moz-range-thumb {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-snackbar {
      display: none;
    }
    jd-snackbar[open] {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      position: fixed;
      z-index: var(--jd-z-toast);
      box-sizing: border-box;
      /* 좁은 화면에서 글자를 줄이는 대신 줄 수를 늘린다 — min-width가 알약을 무너지지
       않게 잡아 주고, 넘치는 문장은 max-width 안에서 접힌다. 본문 크기를 md 아래로
       내리면 어두운 면 위 흰 글자가 그 자리에서 읽히지 않는다. */
      min-width: min(17rem, calc(100vw - 2rem));
      max-width: min(28rem, calc(100vw - 2rem));
      padding: var(--jd-space-3) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
      /* surface의 짝은 on-surface다 — 라이트에서도 어두운 면이므로 잉크가 모드를
       따라가면 안 된다 (DEC-044) */
      color: var(--jd-color-on-surface);
      background: var(--jd-color-surface-overlay);
      border-radius: var(--jd-radius-xl);
      /* 떠 있는 것은 그림자만으로는 배경에서 떨어지지 않는다 — 위에서 받는 빛
       한 줄과 하이라이트 테두리가 알약에 두께를 준다 */
      border: var(--jd-border-thin) solid var(--jd-color-highlight);
      box-shadow: var(--jd-shadow-lg), inset 0 1px 0 var(--jd-color-highlight);
      animation: jd-snackbar-in var(--jd-duration-normal) var(--jd-easing-ease-out);
      /* position 기본 bottom(중앙) */
      inset-block-end: var(--jd-space-6);
      inset-inline-start: 50%;
      transform: translateX(-50%);
    }
    jd-snackbar[position="top"][open] {
      inset-block-end: auto;
      inset-block-start: var(--jd-space-6);
      animation-name: jd-snackbar-in-top;
    }
    jd-snackbar[position="bottom-left"][open] {
      inset-inline-start: var(--jd-space-6);
      transform: none;
    }
    jd-snackbar[position="bottom-right"][open] {
      inset-inline-start: auto;
      inset-inline-end: var(--jd-space-6);
      transform: none;
    }

    /* 의미색 변종은 원색 위라 잉크가 흰색으로 고정된다(on-surface는 원색 위에서
     회색기가 돌아 탁해진다) */
    jd-snackbar[variant="success"][open],
    jd-snackbar[variant="error"][open],
    jd-snackbar[variant="warning"][open],
    jd-snackbar[variant="info"][open] {
      color: #ffffff;
    }
    jd-snackbar[variant="success"][open] {
      background: var(--jd-color-success);
    }
    jd-snackbar[variant="error"][open] {
      background: var(--jd-color-danger);
    }
    jd-snackbar[variant="warning"][open] {
      background: var(--jd-color-warning);
    }
    jd-snackbar[variant="info"][open] {
      background: var(--jd-color-info);
    }

    .jd-snackbar__message {
      flex: 1;
      /* 플렉스 자식 기본 min-width:auto는 긴 URL 한 덩어리에 알약을 밀어낸다 */
      min-width: 0;
      overflow-wrap: anywhere;
    }
    jd-snackbar > [slot="action"] {
      flex-shrink: 0;
    }

    @keyframes jd-snackbar-in {
      from {
        opacity: 0;
        transform: translate(-50%, 1rem);
      }
    }
    @keyframes jd-snackbar-in-top {
      from {
        opacity: 0;
        transform: translate(-50%, -1rem);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      jd-snackbar[open] {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-social-feed {
      display: block;
      max-width: 42rem;
      margin-inline: auto;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* 스토리 줄은 부모 폭을 넘는 게 정상이다 — 잘린 채 끝나는 것과 굴릴 수 있는 것은
     다르다. 가장자리 마스크가 '오른쪽에 더 있다'를 말하고, overscroll 가둠이
     페이지 뒤로가기 제스처를 막는다. */
    .jd-social-feed__stories {
      padding: var(--jd-space-3) var(--jd-space-2);
      border-bottom: var(--jd-border-thin) solid var(--jd-color-border);
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: thin;
      -webkit-mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
      mask-image: linear-gradient(90deg, #000 0 calc(100% - 24px), transparent);
    }
    .jd-social-feed__stories-list {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-3);
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-social-feed__story {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
      width: 4rem;
      flex-shrink: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      padding: 0;
      transition: scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 링만 있고 반응이 없으면 누를 수 있는 것으로 읽히지 않는다 */
    .jd-social-feed__story:hover .jd-social-feed__story-name {
      color: var(--jd-color-foreground);
    }
    .jd-social-feed__story:active {
      scale: 0.96;
    }
    .jd-social-feed__story:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-radius: var(--jd-radius-md);
    }
    .jd-social-feed__story-ring {
      display: inline-flex;
      padding: 2px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-gradient-sunset);
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-social-feed__story:hover .jd-social-feed__story-ring {
      box-shadow: var(--jd-shadow-sm);
    }
    .jd-social-feed__story[data-state="seen"] .jd-social-feed__story-ring {
      background: var(--jd-color-border);
    }
    .jd-social-feed__story[data-state="live"] .jd-social-feed__story-ring {
      background: var(--jd-color-danger);
    }
    /* 아바타 테두리는 링과 사진 사이를 벌리는 '바탕 틈'이라 피드 배경색이어야 한다 —
     surface(라이트에서도 어두운 크롬)를 쓰면 밝은 피드에서 검은 테가 둘러진다. */
    .jd-social-feed__story-avatar {
      width: 3.25rem;
      height: 3.25rem;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      display: block;
      border: 2px solid var(--jd-color-card);
      background: var(--jd-color-neutral-100);
    }
    .jd-social-feed__story-avatar--ph {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-semibold);
      font-size: var(--jd-text-lg);
    }
    .jd-social-feed__story-name {
      max-width: 100%;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }

    .jd-social-feed__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-social-feed__item {
      padding: var(--jd-space-3) 0;
    }
    .jd-social-feed__item + .jd-social-feed__item {
      border-top: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-social-feed__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-16) var(--jd-space-4);
    }
    .jd-social-feed__empty-icon {
      font-size: var(--jd-text-4xl);
    }
    .jd-social-feed__empty-title {
      margin: 0;
      font-weight: var(--jd-weight-semibold);
    }
    .jd-social-feed__empty-desc {
      margin: 0;
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-social-feed__sentinel {
      padding: var(--jd-space-6) 0;
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--jd-color-muted);
    }
    .jd-social-feed__end {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-social-feed__spinner {
      width: 1.25rem;
      height: 1.25rem;
      color: var(--jd-color-primary-ink);
      animation: jd-social-feed-spin 0.7s linear infinite;
    }
    @keyframes jd-social-feed-spin {
      to {
        transform: rotate(360deg);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-social-feed__spinner {
        animation-duration: 1.6s;
      }
      .jd-social-feed__story,
      .jd-social-feed__story-ring,
      .jd-social-feed__story-name {
        transition: none;
      }
      .jd-social-feed__story:active {
        scale: none;
      }
    }
  }

  @layer junds.components {
    jd-social-share {
      display: inline-flex;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
    }

    .jd-social-share__btn {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 36px;
      height: 36px; /* md 기본 */
      padding: 0;
      border: 0;
      cursor: pointer;
      color: #fff;
      text-decoration: none;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-semibold);
      border-radius: var(--jd-radius-full); /* circle 기본 */
      /* 채운 원판은 위에서 빛을 받는다 — 인셋 하이라이트가 없으면 색종이로 읽힌다 */
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      /* all 금지 — 대상 속성을 지목한다(DEC-039). 확대는 transform이 아니라 scale로
       써야 :active의 축소가 같은 속성을 이어받아 매끄럽게 되돌아간다. */
      transition: box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-social-share__btn:hover {
      scale: 1.1;
      box-shadow: var(--jd-shadow-md), inset 0 1px 0 var(--jd-color-highlight);
    }
    /* 눌린 면은 빛을 잃는다 */
    .jd-social-share__btn:active {
      scale: 0.97;
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-social-share__btn:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    jd-social-share[size="sm"] .jd-social-share__btn {
      width: 28px;
      height: 28px;
    }
    jd-social-share[size="lg"] .jd-social-share__btn {
      width: 44px;
      height: 44px;
    }
    jd-social-share[shape="square"] .jd-social-share__btn {
      border-radius: var(--jd-radius-md);
    }

    .jd-social-share__glyph {
      font-size: var(--jd-text-xs);
      line-height: 1;
    }

    /* 플랫폼 브랜드 색 (v2 COLORS 승계) */
    .jd-social-share__btn[data-platform="twitter"] {
      background: #1da1f2;
    }
    .jd-social-share__btn[data-platform="facebook"] {
      background: #1877f2;
    }
    .jd-social-share__btn[data-platform="linkedin"] {
      background: #0a66c2;
    }
    .jd-social-share__btn[data-platform="kakao"] {
      background: #fee500;
      color: #3c1e1e;
    }
    .jd-social-share__btn[data-platform="telegram"] {
      background: #26a5e4;
    }
    .jd-social-share__btn[data-platform="whatsapp"] {
      background: #25d366;
    }
    /* 브랜드 없는 둘 — neutral 계단은 모드에 따라 뒤집혀 흰 글리프 대비가 무너진다.
     hue-gray는 모드 불변이라 라이트·다크 양쪽에서 같은 대비를 준다. */
    .jd-social-share__btn[data-platform="email"] {
      background: var(--jd-color-hue-gray);
    }
    .jd-social-share__btn[data-platform="copy"] {
      background: var(--jd-color-primary);
    }
    /* 복사 완료는 결과 보고다 — 1.5초 동안만 success로 바뀐다(element.ts가 data-copied) */
    .jd-social-share__btn[data-platform="copy"][data-copied] {
      background: var(--jd-color-success);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-social-share__btn {
        transition: none;
      }
      .jd-social-share__btn:hover {
        scale: none;
      }
    }
  }

  @layer junds.components {
    jd-sortable-list {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }

    .jd-sortable-list__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      box-sizing: border-box;
      min-width: 0;
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-card);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
      /* all 금지 — padding까지 대상이 되면 드롭 표시가 매 프레임 리플로우를 만든다 */
      transition: opacity var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* 핸들이 없으면 행 전체가 드래그 표면이다 — 커서로 그 사실을 말한다 */
    jd-sortable-list:not([show-handle]) > .jd-sortable-list__item {
      cursor: grab;
    }
    jd-sortable-list:not([show-handle]) > .jd-sortable-list__item:active {
      cursor: grabbing;
    }
    .jd-sortable-list__item:hover {
      background: var(--jd-color-card-hover);
      border-color: color-mix(in srgb, var(--jd-color-border) 70%, var(--jd-color-muted-light));
    }
    .jd-sortable-list__item[data-grabbed] {
      opacity: var(--jd-opacity-40);
      box-shadow: none;
    }
    /* 드롭 자리는 **행 위 경계선**이다. 레이아웃을 밀지 않도록 테두리 두께가 아니라
     안쪽 그림자로 긋는다 — 두께가 바뀌면 목록 전체가 1행씩 출렁인다. */
    .jd-sortable-list__item[data-drop-target] {
      border-color: color-mix(in srgb, var(--jd-color-primary) 55%, transparent);
      box-shadow: inset 0 var(--jd-border-medium) 0 var(--jd-color-primary),
        var(--jd-shadow-sm);
    }
    .jd-sortable-list__item:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-sortable-list__handle {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      width: 1.5rem;
      height: 1.5rem;
      margin: 0;
      padding: 0;
      color: var(--jd-color-muted);
      background: none;
      border: 0;
      border-radius: var(--jd-radius-md);
      cursor: grab;
      touch-action: none;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-sortable-list__handle:hover {
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
    }
    .jd-sortable-list__handle:active {
      cursor: grabbing;
      background: color-mix(in srgb, var(--jd-color-muted) 18%, transparent);
    }
    .jd-sortable-list__handle:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-sortable-list__handle > svg {
      width: 0.875rem;
      height: 0.875rem;
    }

    .jd-sortable-list__content {
      flex: 1 1 0;
      min-width: 0;
      line-height: var(--jd-leading-snug);
      overflow-wrap: anywhere;
    }

    /* 시각적 숨김 — 이동 결과 공지용 */
    .jd-sortable-list__live {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      clip: rect(0 0 0 0);
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-sortable-list__item,
      .jd-sortable-list__handle {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: axis=vertical, size=4(16px) — 값은 update() 인라인이 담당 */
    jd-spacer {
      display: block;
      flex-shrink: 0;
      padding-block: var(--jd-space-4);
    }
    jd-spacer[axis="horizontal"] {
      display: inline-block;
      padding-block: 0;
      padding-inline: var(--jd-space-4);
    }
  }

  @layer junds.base {
    jd-sparkline:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-sparkline {
      display: inline-block;
      line-height: 0; /* svg 아래 baseline 여백 제거 */
      color: var(--jd-sparkline-color, var(--jd-finance-up, var(--jd-color-success)));
    }

    .jd-sparkline__svg {
      display: block;
      overflow: visible;
    }

    .jd-sparkline__line {
      fill: none;
      stroke: currentColor;
      stroke-linejoin: round;
      stroke-linecap: round;
    }
    .jd-sparkline__baseline {
      stroke: currentColor;
      opacity: var(--jd-opacity-25);
    }
    .jd-sparkline__dot-halo {
      fill: currentColor;
      opacity: var(--jd-opacity-20);
    }
    .jd-sparkline__dot {
      fill: currentColor;
    }
  }

  @layer junds.components {
    jd-spinner {
      display: inline-flex;
      color: var(--jd-color-primary-ink);
      width: 20px;
      height: 20px; /* md 기본 */
    }
    jd-spinner[size="xs"] {
      width: 14px;
      height: 14px;
    }
    jd-spinner[size="sm"] {
      width: 16px;
      height: 16px;
    }
    jd-spinner[size="lg"] {
      width: 28px;
      height: 28px;
    }
    jd-spinner[color="white"] {
      color: #fff;
    }
    jd-spinner[color="muted"] {
      color: var(--jd-color-muted);
    }

    .jd-spinner__svg {
      width: 100%;
      height: 100%;
      animation: jd-spin 1s linear infinite;
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-spinner__svg {
        animation-duration: 1.6s;
      }
    }
  }

  @layer junds.components {
    jd-split {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-4);
    }
    /* 세로 정렬을 바꾸고 싶으면 다른 컨테이너와 똑같이 align 스타일 프롭을 쓴다
     (align="start" → 인라인 align-items). 여기에 따로 규칙을 두지 않는 이유는
     어휘를 하나로 유지하기 위해서다 — jd-hstack과 같은 방식으로 동작해야 한다. */

    /* 줄바꿈 금지 — 넘쳐도 한 줄을 유지해야 하는 툴바 등 */
    jd-split[no-wrap] {
      flex-wrap: nowrap;
    }
  }

  @layer junds.base {
    jd-split-pane:not(:defined) {
      display: flex;
    }
  }
  @layer junds.components {
    jd-split-pane {
      display: flex;
      flex-direction: row;
      overflow: hidden;
      box-sizing: border-box;
      height: 100%;
      font-family: var(--jd-font-sans);
    }
    jd-split-pane[direction="vertical"] {
      flex-direction: column;
    }

    /* 패널은 폭이 드래그로 바뀐다 — 좁아진 칸에서 기본 CJK 줄바꿈은 글자 단위라
     SK하이닉 / 스처럼 낱말 한가운데가 끊긴다(§5). keep-all로 어절을 지키고,
     한 어절이 칸보다 길 때만 끊는다. 파생 태그(jd-resizable)도 이 규칙을 그대로 쓴다. */
    .jd-split-pane__pane {
      overflow: auto;
      min-width: 0;
      min-height: 0;
      word-break: keep-all;
      overflow-wrap: break-word;
    }
    .jd-split-pane__pane--start {
      flex: 0 0 auto;
    }
    .jd-split-pane__pane--end {
      flex: 1 1 0;
    }

    .jd-split-pane__separator {
      position: relative;
      flex: 0 0 auto;
      background: var(--jd-color-border);
      touch-action: none; /* 드래그 중 브라우저 스크롤 제스처가 포인터를 가로채지 않게 */
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* direction 기본 horizontal — v2 w-1 */
      inline-size: 4px;
      cursor: col-resize;
    }
    jd-split-pane[direction="vertical"] > .jd-split-pane__separator {
      inline-size: auto;
      block-size: 4px;
      cursor: row-resize;
    }
    .jd-split-pane__separator:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-split-pane__separator:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
      z-index: 1;
    }

    /* 파생(jd-resizable)이 켠다 */
    .jd-split-pane__grip {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-split-pane__separator {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-spoiler-block {
      display: block;
      position: relative;
      box-sizing: border-box;
      padding: var(--jd-space-4);
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-card-hover);
      font-family: var(--jd-font-sans);
    }
    jd-spoiler-block[type="caution"] {
      background: var(--jd-color-warning-light);
      border-color: color-mix(in srgb, var(--jd-color-warning) 30%, transparent);
    }

    .jd-spoiler-block__content {
      transition: filter var(--jd-duration-slower) var(--jd-easing-ease-out);
    }
    jd-spoiler-block:not([revealed]) .jd-spoiler-block__content {
      filter: blur(4px);
      user-select: none;
      pointer-events: none;
    }

    .jd-spoiler-block__cover {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .jd-spoiler-block__cover[hidden] {
      display: none;
    }

    .jd-spoiler-block__reveal {
      padding: var(--jd-space-2) var(--jd-space-4);
      border: 0;
      cursor: pointer;
      border-radius: var(--jd-radius-full);
      font-family: inherit;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      box-shadow: var(--jd-shadow-md);
      background: color-mix(in srgb, var(--jd-color-foreground) 80%, transparent);
      color: var(--jd-color-background);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-spoiler-block__reveal:hover {
      background: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-lg);
    }
    .jd-spoiler-block__reveal:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-spoiler-block[type="caution"] .jd-spoiler-block__reveal {
      background: var(--jd-color-warning);
      color: #fff;
    }
    jd-spoiler-block[type="caution"] .jd-spoiler-block__reveal:hover {
      background: color-mix(in srgb, var(--jd-color-warning) 90%, #000);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-spoiler-block__content,
      .jd-spoiler-block__reveal {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-spotlight:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-spotlight {
      display: none;
    }
    jd-spotlight[active] {
      display: block;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-max);
    }

    .jd-spotlight__canvas {
      position: absolute;
      inset: 0;
      display: block;
      width: 100%;
      height: 100%;
    }

    /* 딤은 모드와 무관하게 검은 면이다 — 그 위 글자를 --jd-color-foreground로 두면
     라이트 모드에서 검은 글자가 검은 면에 얹혀 안내문이 통째로 사라진다(§4).
     surface/on-surface 짝으로 말풍선을 세워 두 모드에서 같은 대비를 얻는다. */
    .jd-spotlight__content {
      position: absolute;
      translate: -50% 0;
      z-index: 1;
      box-sizing: border-box;
      /* 대상 중앙에 맞춰 옆으로 밀리므로 화면 밖으로 나가지 않게 상한을 둔다 */
      max-width: min(22rem, calc(100vw - 2rem));
      padding: var(--jd-space-4);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-surface-overlay);
      color: var(--jd-color-on-surface);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-on-surface) 14%, transparent);
      box-shadow: var(--jd-shadow-xl), inset 0 1px 0 rgba(255, 255, 255, 0.06);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
    }
    .jd-spotlight__content[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-spotlight[active] > .jd-spotlight__canvas {
        animation: jd-spotlight-in var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-spotlight[active] > .jd-spotlight__content {
        animation: jd-spotlight-rise var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
    }
    @keyframes jd-spotlight-in {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-spotlight-rise {
      from {
        opacity: 0;
        translate: -50% 6px;
      }
    }
  }

  @layer junds.base {
    jd-spotlight-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-spotlight-card {
      --jd-spotlight-card-color: color-mix(in srgb, var(--jd-color-primary) 8%, transparent);
      --jd-spotlight-card-size: 300px;
      --jd-spotlight-card-x: 50%;
      --jd-spotlight-card-y: 50%;

      display: block;
      position: relative;
      isolation: isolate; /* ::before의 z-index:-1이 호스트 배경 위·콘텐츠 아래에 들어가게 */
      overflow: hidden;
      box-sizing: border-box;
      padding: var(--jd-space-6);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-2xl);
      transition: box-shadow var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    jd-spotlight-card:hover {
      box-shadow: var(--jd-shadow-lg);
    }

    jd-spotlight-card::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      pointer-events: none;
      opacity: 0;
      transition: opacity var(--jd-duration-slow) var(--jd-easing-ease-out);
      background: radial-gradient(
        var(--jd-spotlight-card-size) circle at var(--jd-spotlight-card-x)
          var(--jd-spotlight-card-y),
        var(--jd-spotlight-card-color),
        transparent 60%
      );
    }
    jd-spotlight-card[data-hovered]::before {
      opacity: 1;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-spotlight-card,
      jd-spotlight-card::before {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* v2 기본값: direction=column, gap="md"(16px) */
    jd-stack {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
  }

  @layer junds.components {
    jd-star-button {
      display: inline-flex;
      --_jd-star-size: 18px;
    }

    .jd-star-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-1);
      border: 0;
      background: none;
      cursor: pointer;
      line-height: 0;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        background var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-star-button:hover:not(:disabled) {
      color: var(--jd-color-warning);
    }
    .jd-star-button:active:not(:disabled) {
      transform: scale(0.92);
    }
    .jd-star-button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-star-button:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-star-button__icon {
      width: var(--_jd-star-size);
      height: var(--_jd-star-size);
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
    }

    /* 활성 — v2: 획 색만 warning으로. 채우지 않는다. */
    jd-star-button[active] .jd-star-button {
      color: var(--jd-color-warning);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-star-button {
        transition: none;
      }
      .jd-star-button:active:not(:disabled) {
        transform: none;
      }
    }
  }

  @layer junds.components {
    jd-star-rating {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
    }
    jd-star-rating[size="sm"] {
      gap: var(--jd-space-0-5);
    }
    jd-star-rating[size="lg"] {
      gap: var(--jd-space-1-5);
    }

    .jd-star-rating__item {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      color: #d1d5db; /* v2 gray-300 — 빈 별 */
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out),
        transform var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-star-rating__item[data-filled] {
      color: #facc15;
    } /* v2 yellow-400 */
    jd-star-rating:not([readonly]) .jd-star-rating__item:hover {
      transform: scale(1.1);
    }
    jd-star-rating[readonly] .jd-star-rating__item {
      cursor: default;
    }

    /* 라디오는 시각적으로만 감춘다 — 포커스 링은 아래 :has로 별에 그린다 */
    .jd-star-rating__radio {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
    .jd-star-rating__item:has(.jd-star-rating__radio:focus-visible) {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: 2px;
      border-radius: var(--jd-radius-sm);
    }

    .jd-star-rating__icon {
      width: 1.5rem;
      height: 1.5rem;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.5;
    }
    .jd-star-rating__item[data-filled] .jd-star-rating__icon {
      fill: currentColor;
      stroke-width: 0;
    }
    jd-star-rating[size="sm"] .jd-star-rating__icon {
      width: 1rem;
      height: 1rem;
    }
    jd-star-rating[size="lg"] .jd-star-rating__icon {
      width: 2rem;
      height: 2rem;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-star-rating__item {
        transition: none;
      }
      jd-star-rating:not([readonly]) .jd-star-rating__item:hover {
        transform: none;
      }
    }
  }

  @layer junds.base {
    jd-starfield:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-starfield {
      display: block;
      position: relative;
      width: 100%;
      height: 100%;
      overflow: hidden;
      background: var(--jd-starfield-bg, #0b0d1a);
    }
    .jd-starfield__canvas {
      position: absolute;
      inset: 0;
      display: block;
    }
  }

  @layer junds.components {
    jd-stat {
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }

    .jd-stat__main {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-3);
    }
    .jd-stat__main > [slot="icon"] {
      display: flex;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }
    .jd-stat__text {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      flex: 1 1 auto;
      min-width: 0;
    }

    .jd-stat__label {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
    }

    .jd-stat__row {
      display: flex;
      align-items: baseline;
      flex-wrap: wrap;
      gap: var(--jd-space-1-5);
    }
    /* 값과 단위는 한 플렉스 아이템이다 — 형제로 두면 좁은 칸에서 줄이 그 사이로 갈려
     12,480,000 과 원 이 따로 논다(§5). 변화량만 다음 줄로 접히게 남긴다. */
    .jd-stat__pair {
      display: inline-flex;
      align-items: baseline;
      gap: var(--jd-space-1-5);
      white-space: nowrap;
    }
    .jd-stat__value {
      font-size: var(--jd-text-2xl);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-tight);
      color: var(--jd-color-foreground);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-stat__unit {
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      white-space: nowrap;
    }

    /* 투명 래퍼 — 변화량이 값과 같은 baseline 줄에 참여한다.
     MetricCard만 실제 상자로 승격해(display:flex) 다음 줄로 내린다. */
    .jd-stat__delta {
      display: contents;
    }
    .jd-stat__delta[hidden] {
      display: none;
    }

    .jd-stat__change {
      display: inline-flex;
      align-items: baseline;
      gap: var(--jd-space-1);
      white-space: nowrap;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      font-variant-numeric: tabular-nums;
      color: var(--_jd-stat-trend, var(--jd-color-muted));
    }
    .jd-stat__change[hidden] {
      display: none;
    }
    .jd-stat__change-label {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    /* 트렌드 색 단일 통로 — 파생 태그를 여기 한 줄에 모은다.
     지표의 증감은 금융 등락과 같은 축이라 --jd-finance-* 훅을 경유한다: 앱이 한국
     관례(적상승·청하락)를 켜려고 훅을 1회 덮어썼을 때, success/danger를 직접 박은
     지표만 반대 색으로 남으면 같은 화면에서 증감 색이 갈린다. */
    :where(jd-stat, jd-stat-card, jd-metric-card)[data-trend="up"] {
      --_jd-stat-trend: var(--jd-finance-up, var(--jd-color-success));
    }
    :where(jd-stat, jd-stat-card, jd-metric-card)[data-trend="down"] {
      --_jd-stat-trend: var(--jd-finance-down, var(--jd-color-danger));
    }
    :where(jd-stat, jd-stat-card, jd-metric-card)[data-trend="flat"] {
      --_jd-stat-trend: var(--jd-finance-flat, var(--jd-color-muted));
    }

    /* 화살표 옆 방향 낱말 — 눈에는 안 보이고 스크린리더에만 읽힌다
     (jd-visually-hidden과 같은 clip-path 관용구) */
    .jd-stat__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-stat__hint {
      margin: 0;
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    jd-stat[align="center"] .jd-stat__main {
      justify-content: center;
    }
    jd-stat[align="center"] .jd-stat__text {
      align-items: center;
      text-align: center;
    }
    jd-stat[align="center"] .jd-stat__row {
      justify-content: center;
    }
  }

  @layer junds.components {
    jd-stat-card {
      display: block;
      box-sizing: border-box;
      padding: var(--jd-space-4);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      font-family: var(--jd-font-sans);
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }

    /* v2 라벨줄 mb-2 — 라벨과 값 사이만 벌린다 */
    jd-stat-card .jd-stat__text {
      gap: var(--jd-space-2);
    }
    jd-stat-card .jd-stat__row {
      gap: var(--jd-space-2);
      align-items: flex-end;
    }
    /* 값·단위 묶음도 카드의 눈금(v2 gap-2)과 밑선 맞춤(items-end)을 그대로 따른다 */
    jd-stat-card .jd-stat__pair {
      gap: var(--jd-space-2);
      align-items: flex-end;
    }
    jd-stat-card .jd-stat__label {
      font-weight: var(--jd-weight-medium);
    }
    jd-stat-card .jd-stat__value {
      font-weight: var(--jd-weight-bold);
    }
    jd-stat-card .jd-stat__main > [slot="icon"] {
      color: var(--jd-color-muted-light);
    }
    jd-stat-card .jd-stat__hint {
      margin-block-start: calc(var(--jd-space-1) * -1);
    }

    /* StatCard 고유 — 변화량이 배경 있는 칩이다(Stat·MetricCard는 맨 텍스트) */
    jd-stat-card .jd-stat__change {
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-md);
      font-weight: var(--jd-weight-semibold);
      background: var(--_jd-stat-trend-bg, transparent);
      margin-block-end: var(--jd-space-0-5);
    }
    /* 칩 배경은 글자색과 같은 등락 훅에서 뽑는다 — success-light/danger-light를 직접
     쓰면 앱이 --jd-finance-*를 덮었을 때 글자만 뒤집히고 배경은 원래 색으로 남아
     빨간 글자에 초록 칩 같은 조합이 나온다. 12%는 -light 토큰의 눈맛에 맞춘 값. */
    jd-stat-card[data-trend="up"] {
      --_jd-stat-trend-bg: color-mix(
        in srgb,
        var(--jd-finance-up, var(--jd-color-success)) 12%,
        transparent
      );
    }
    jd-stat-card[data-trend="down"] {
      --_jd-stat-trend-bg: color-mix(
        in srgb,
        var(--jd-finance-down, var(--jd-color-danger)) 12%,
        transparent
      );
    }
    jd-stat-card[data-trend="flat"] {
      --_jd-stat-trend-bg: var(--jd-color-border-light);
    }

    jd-stat-card[clickable] {
      cursor: pointer;
    }
    jd-stat-card[clickable]:hover {
      background: var(--jd-color-card-hover);
      border-color: var(--jd-color-border);
      box-shadow: var(--jd-shadow-sm);
    }
    jd-stat-card[clickable]:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    @media (prefers-reduced-motion: reduce) {
      jd-stat-card {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-stats-grid {
      --jd-stats-grid-gap: var(--jd-space-4);
      /* 라벨 + 2xl 수치 + 단위가 한 줄에 서는 최소 카드 폭(패딩 2rem 포함) */
      --jd-stats-grid-col-min: 12rem;
      /* 미지정/기본(columns=4)의 좁은 화면 — 2열 */
      --_jd-sg-n: 2;
      display: grid;
      gap: var(--jd-stats-grid-gap);
      /* auto-fit이 아니라 auto-fill — 카드가 열 수보다 적을 때 빈 트랙을 접어 버리면
       카드 두 장이 화면 절반씩 차지한다. v2의 고정 grid-cols-N과 같은 폭을 유지한다. */
      grid-template-columns: repeat(
        auto-fill,
        minmax(
          min(
            100%,
            max(
              var(--jd-stats-grid-col-min),
              (100% - (var(--_jd-sg-n) - 1) * var(--jd-stats-grid-gap)) / var(--_jd-sg-n)
            )
          ),
          1fr
        )
      );
    }

    jd-stats-grid[columns="2"] {
      --_jd-sg-n: 2;
    }
    jd-stats-grid[columns="3"] {
      --_jd-sg-n: 3;
    }

    @media (min-width: 1024px) {
      /* 기본값 columns=4는 attribute로 반영되지 않으므로(§1.3 reflect는 set 시점)
       속성 없는 호스트도 여기서 4를 받는다 — [columns="4"]만 적으면 기본 사용이
       넓은 화면에서도 2열에 머물렀다. 2·3은 위 속성 셀렉터가 더 세서 그대로 남는다. */
      jd-stats-grid {
        --_jd-sg-n: 4;
      }
      jd-stats-grid[columns="5"] {
        --_jd-sg-n: 5;
      }
    }

    .jd-stats-grid__cell {
      /* 카드 안 긴 값이 트랙을 넘기지 않게 */
      min-width: 0;
      /* 지표 격자의 수치는 열끼리 눈금이 맞아야 한다 — 자릿수가 흔들리면 어긋난다(§5) */
      font-variant-numeric: tabular-nums;
    }
  }

  @layer junds.components {
    jd-status-dot {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      font-family: var(--jd-font-sans);
    }
    jd-status-dot::before {
      content: "";
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-neutral-400); /* neutral 기본 */
    }
    jd-status-dot[size="sm"]::before {
      width: 6px;
      height: 6px;
    }
    jd-status-dot[size="lg"]::before {
      width: 10px;
      height: 10px;
    }

    jd-status-dot[status="success"]::before {
      background: var(--jd-color-success);
    }
    jd-status-dot[status="warning"]::before {
      background: var(--jd-color-warning);
    }
    jd-status-dot[status="danger"]::before {
      background: var(--jd-color-danger);
    }
    jd-status-dot[status="info"]::before {
      background: var(--jd-color-primary);
    } /* v2 동형 */
    jd-status-dot[status="pulse"]::before {
      background: var(--jd-color-success);
      animation: jd-status-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
    }

    .jd-status-dot__label {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-foreground);
    }

    @keyframes jd-status-pulse {
      0%,
      100% {
        opacity: 1;
      }
      50% {
        opacity: 0.5;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-status-dot[status="pulse"]::before {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-stepper {
      display: block;
    }

    .jd-stepper__list {
      display: flex;
      align-items: center;
      gap: 0;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-stepper__step {
      display: flex;
      flex-direction: column;
      align-items: center;
      flex: 1 1 0;
      min-width: 0;
    }

    /* 원 + 연결선 — 가로에서는 한 줄로 나란히 */
    .jd-stepper__marker {
      display: flex;
      align-items: center;
      inline-size: 100%;
    }

    .jd-stepper__circle {
      inline-size: 2rem;
      block-size: 2rem;
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--jd-radius-full);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      background: var(--jd-color-border);
      color: var(--jd-color-muted);
      transition: background var(--jd-duration-slow) var(--jd-easing-ease-out),
        color var(--jd-duration-slow) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-stepper__circle > svg {
      inline-size: 1rem;
      block-size: 1rem;
    }

    .jd-stepper__step[data-status="completed"] > .jd-stepper__marker > .jd-stepper__circle,
    .jd-stepper__step[data-status="current"] > .jd-stepper__marker > .jd-stepper__circle {
      background: var(--jd-color-primary);
      color: #fff;
    }
    /* v2: ring-4 ring-primary-light */
    .jd-stepper__step[data-status="current"] > .jd-stepper__marker > .jd-stepper__circle {
      box-shadow: 0 0 0 4px var(--jd-color-primary-light);
    }

    .jd-stepper__line {
      flex: 1 1 auto;
      block-size: var(--jd-border-thin);
      margin-inline: var(--jd-space-2);
      background: var(--jd-color-border);
      transition: background var(--jd-duration-slow) var(--jd-easing-ease-out);
    }
    .jd-stepper__step[data-status="completed"] > .jd-stepper__marker > .jd-stepper__line {
      background: var(--jd-color-primary);
    }
    .jd-stepper__step[data-last] > .jd-stepper__marker > .jd-stepper__line {
      display: none;
    }

    /* 글줄은 자기 단계의 칸 안에서 끝난다. align-items:center만으로는 상자가
     내용 폭(fit-content)을 따라가 옆 단계의 글줄과 맞붙었다 — 폭을 칸에 못 박고
     좌우로 한 칸 띄워 두 줄이 되어도 이웃과 부딪치지 않게 한다(§5). */
    .jd-stepper__body {
      display: flex;
      flex-direction: column;
      align-items: center;
      inline-size: 100%;
      min-inline-size: 0;
      padding-inline: var(--jd-space-2);
      box-sizing: border-box;
      margin-block-start: var(--jd-space-2);
      text-align: center;
    }
    /* 기본 CJK 줄바꿈은 글자 단위라 좁은 단계에서 낱말 한가운데가 끊긴다 —
     어절은 지키고(keep-all) 한 어절이 칸보다 길 때만 끊는다. balance는 두 줄이
     될 때 길이를 고르게 나눠 옆 단계 쪽으로 한 줄만 길게 삐져나오지 않게 한다. */
    .jd-stepper__title {
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
      word-break: keep-all;
      overflow-wrap: break-word;
      text-wrap: balance;
    }
    .jd-stepper__step[data-status="upcoming"] .jd-stepper__title {
      color: var(--jd-color-muted);
    }
    .jd-stepper__description {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      margin-block-start: var(--jd-space-0-5);
      word-break: keep-all;
      overflow-wrap: break-word;
      text-wrap: balance;
    }
    .jd-stepper__description[hidden] {
      display: none;
    }

    /* 상태 텍스트 — 시각적으로만 숨긴다(AT에는 남는다) */
    .jd-stepper__status {
      position: absolute;
      inline-size: 1px;
      block-size: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    /* ── direction=vertical — v2: 행 배치 + 세로 연결선 ───────────────── */
    jd-stepper[direction="vertical"] > .jd-stepper__list {
      flex-direction: column;
      align-items: stretch;
    }
    jd-stepper[direction="vertical"] .jd-stepper__step {
      flex-direction: row;
      align-items: stretch;
      flex: 0 0 auto;
      gap: var(--jd-space-3);
    }
    jd-stepper[direction="vertical"] .jd-stepper__marker {
      flex-direction: column;
      inline-size: auto;
    }
    jd-stepper[direction="vertical"] .jd-stepper__line {
      inline-size: var(--jd-border-thin);
      block-size: auto;
      min-block-size: 1.5rem;
      margin-inline: auto;
      margin-block: var(--jd-space-1);
    }
    jd-stepper[direction="vertical"] .jd-stepper__body {
      align-items: flex-start;
      text-align: start;
      /* 세로 배치에서는 옆 단계가 없다 — 폭 못 박기·좌우 여백·balance를 되돌린다 */
      inline-size: auto;
      flex: 1 1 auto;
      padding-inline: 0;
      margin-block-start: 0;
      padding-block: var(--jd-space-0-5) var(--jd-space-6);
    }
    jd-stepper[direction="vertical"] .jd-stepper__title,
    jd-stepper[direction="vertical"] .jd-stepper__description {
      text-wrap: wrap;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-stepper__circle,
      .jd-stepper__line {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-sticky {
      display: block;
      box-sizing: border-box;
      position: sticky;
      z-index: var(--jd-affix-z, var(--jd-z-sticky));
      top: var(--jd-affix-top, 0px);
      bottom: var(--jd-affix-bottom, auto);
      left: var(--jd-affix-left, auto);
      right: var(--jd-affix-right, auto);
    }
  }

  @layer junds.base {
    jd-stock-top-bar:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-stock-top-bar {
      display: block;
      position: sticky;
      z-index: var(--jd-z-sticky);
      top: var(--jd-stock-top-bar-top, 53px);
      background: color-mix(in srgb, var(--jd-color-background) 92%, transparent);
      backdrop-filter: blur(12px);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-stock-top-bar__inner {
      max-width: 1600px;
      margin-inline: auto;
      padding: var(--jd-space-2-5) var(--jd-space-3) 0;
    }

    .jd-stock-top-bar__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    .jd-stock-top-bar__back {
      width: 36px;
      height: 36px;
      flex-shrink: 0;
      border: 0;
      background: none;
      cursor: pointer;
      border-radius: var(--jd-radius-full);
      display: grid;
      place-items: center;
      color: color-mix(in srgb, var(--jd-color-foreground) 60%, var(--jd-color-muted));
      /* background 단축이 아니라 색만 — 그리고 누름은 scale이라 전이 대상에 함께 적는다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-stock-top-bar__back:hover {
      background-color: var(--jd-color-border-light);
      color: var(--jd-color-foreground);
    }
    /* 눌린 면은 빛을 잃는다 — hover 색만으로는 클릭이 먹었는지 알 수 없다 */
    .jd-stock-top-bar__back:active {
      scale: 0.97;
      background-color: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
    }
    .jd-stock-top-bar__back:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-stock-top-bar__title-wrap {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
      flex: 1;
    }
    .jd-stock-top-bar__names {
      min-width: 0;
      flex: 1;
    }
    .jd-stock-top-bar__name-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-stock-top-bar__name {
      margin: 0;
      font-weight: 800;
      font-size: 1.0625rem; /* 17px */
      letter-spacing: var(--jd-tracking-tight);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-stock-top-bar__sector {
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      padding: 0 var(--jd-space-2);
      height: 20px;
      border-radius: var(--jd-radius-md);
      font-size: 0.65625rem; /* 10.5px */
      font-weight: var(--jd-weight-bold);
      background: var(--jd-color-border-light);
      color: color-mix(in srgb, var(--jd-color-foreground) 65%, var(--jd-color-muted));
    }
    .jd-stock-top-bar__sector[hidden] {
      display: none;
    }
    .jd-stock-top-bar__amount {
      margin-top: 1px;
      font-size: 0.6875rem; /* 11px */
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-stock-top-bar__amount[hidden] {
      display: none;
    }

    .jd-stock-top-bar__price-wrap {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-shrink: 0;
    }
    .jd-stock-top-bar__price-block {
      text-align: right;
    }
    .jd-stock-top-bar__price-block[data-trend="up"] {
      color: var(--jd-finance-up, var(--jd-color-success));
    }
    .jd-stock-top-bar__price-block[data-trend="down"] {
      color: var(--jd-finance-down, var(--jd-color-danger));
    }
    /* 시세는 숫자 한 덩어리다 — 좁은 상단바에서 "71,200"이 접히면 자릿수가 두 줄로 갈린다 */
    .jd-stock-top-bar__price {
      display: block;
      color: inherit;
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: var(--jd-text-2xl); /* 20px */
      line-height: 1;
      white-space: nowrap;
      letter-spacing: var(--jd-tracking-tight);
    }
    .jd-stock-top-bar__change {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: var(--jd-space-1);
      margin-top: var(--jd-space-0-5);
    }
    .jd-stock-top-bar__diff {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      color: inherit;
      font-variant-numeric: tabular-nums;
      font-weight: var(--jd-weight-bold);
      font-size: var(--jd-text-xs);
      white-space: nowrap;
    }
    .jd-stock-top-bar__pct {
      color: inherit;
      font-variant-numeric: tabular-nums;
      font-weight: var(--jd-weight-bold);
      font-size: var(--jd-text-xs);
      white-space: nowrap;
    }

    .jd-stock-top-bar__trailing {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }
    .jd-stock-top-bar__trailing[hidden] {
      display: none;
    }

    /* 탭 — v2 bm-tabs/bm-tab 밑줄 스크롤 행 */
    .jd-stock-top-bar__tabs {
      display: flex;
      gap: var(--jd-space-1);
      margin-top: var(--jd-space-2-5);
      overflow-x: auto;
      scrollbar-width: none;
    }
    .jd-stock-top-bar__tabs::-webkit-scrollbar {
      display: none;
    }
    .jd-stock-top-bar__tab {
      flex-shrink: 0;
      padding: var(--jd-space-2) var(--jd-space-1);
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
      text-decoration: none;
      white-space: nowrap;
      border-block-end: var(--jd-border-medium) solid transparent;
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-stock-top-bar__tab:hover {
      color: var(--jd-color-foreground);
      /* 밑줄이 미리 옅게 뜨면 "여길 누르면 여기가 선택된다"가 보인다 */
      border-block-end-color: color-mix(in srgb, var(--jd-color-primary) 35%, transparent);
    }
    .jd-stock-top-bar__tab:active {
      color: var(--jd-color-primary-ink);
      border-block-end-color: var(--jd-color-primary);
    }
    /* 탭 행이 overflow-x 스크롤 컨테이너라 바깥쪽 offset은 잘린다 — 링을 안쪽에 그린다 */
    .jd-stock-top-bar__tab:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: calc(var(--jd-focus-ring-offset) * -1);
      border-radius: var(--jd-radius-sm);
    }
    .jd-stock-top-bar__tab[data-active] {
      color: var(--jd-color-foreground);
      border-block-end-color: var(--jd-color-primary);
    }

    @media (min-width: 640px) {
      .jd-stock-top-bar__inner {
        padding-inline: var(--jd-space-4);
      }
    }
    @media (prefers-reduced-motion: reduce) {
      .jd-stock-top-bar__back,
      .jd-stock-top-bar__tab {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-story-circle {
      display: inline-flex;
      --_jd-story-size: 64px;
      --_jd-story-pad: 2.5px;
      --_jd-story-ring: linear-gradient(
        to top right,
        var(--jd-color-hue-rose),
        var(--jd-color-hue-pink),
        var(--jd-color-hue-amber)
      );
    }
    jd-story-circle[state="read"] {
      --_jd-story-pad: 2px;
      --_jd-story-ring: var(--jd-color-neutral-300);
    }
    /* live는 한 색의 명도 계단 — 회전 없이 "지금 켜져 있다"만 말한다 */
    jd-story-circle[state="live"] {
      --_jd-story-ring: linear-gradient(
        to top right,
        var(--jd-color-hue-rose),
        color-mix(in srgb, var(--jd-color-hue-rose) 72%, #000)
      );
    }
    jd-story-circle[state="muted"] {
      --_jd-story-pad: 2px;
      --_jd-story-ring: var(--jd-color-neutral-200);
    }
    [data-jd-theme="dark"] jd-story-circle[state="read"],
    [data-theme="dark"] jd-story-circle[state="read"] {
      --_jd-story-ring: var(--jd-color-neutral-800);
    }
    [data-jd-theme="dark"] jd-story-circle[state="muted"],
    [data-theme="dark"] jd-story-circle[state="muted"] {
      --_jd-story-ring: var(--jd-color-neutral-800);
    }

    .jd-story-circle {
      appearance: none;
      -webkit-appearance: none;
      border: 0;
      background: transparent;
      margin: 0;
      padding: var(--jd-space-1);
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      gap: var(--jd-space-1);
      cursor: pointer;
      border-radius: var(--jd-radius-md);
      font-family: var(--jd-font-sans);
      /* 누를 수 있는 것은 상태 3종을 전부 갖는다 — v2에는 focus만 있었다 */
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-story-circle:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-story-circle:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--jd-color-muted) 16%, transparent);
    }
    .jd-story-circle:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-story-circle__ring {
      position: relative;
      width: var(--_jd-story-size);
      height: var(--_jd-story-size);
      border-radius: var(--jd-radius-full);
      padding: var(--_jd-story-pad);
      background: var(--_jd-story-ring);
      display: inline-flex;
      box-sizing: border-box;
    }
    .jd-story-circle__frame {
      width: 100%;
      height: 100%;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-card);
      padding: var(--jd-space-0-5);
      box-sizing: border-box;
      display: flex;
    }
    .jd-story-circle__img,
    .jd-story-circle__fallback {
      width: 100%;
      height: 100%;
      border-radius: var(--jd-radius-full);
      object-fit: cover;
      display: block;
    }
    .jd-story-circle__fallback {
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-bold);
      background: color-mix(in srgb, var(--jd-color-primary) 15%, transparent);
      /* 틴트 위 이니셜: 원색 대신 foreground 혼합으로 대비 확보(emoji-picker 선례·§4). */
      color: color-mix(in srgb, var(--jd-color-primary) 65%, var(--jd-color-foreground));
      user-select: none;
    }
    .jd-story-circle__img[hidden],
    .jd-story-circle__fallback[hidden] {
      display: none;
    }

    .jd-story-circle__live {
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translate(-50%, 50%);
      padding: var(--jd-space-px) var(--jd-space-1-5);
      border-radius: var(--jd-radius-md);
      background: var(--jd-color-hue-rose);
      color: #fff;
      /* 9px는 읽을 수 있는 크기가 아니다 — 2xs(11px)가 하한이다(§9) */
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      letter-spacing: var(--jd-tracking-wide);
      line-height: var(--jd-leading-tight);
      box-shadow: var(--jd-shadow-xs), inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-story-circle__live[hidden] {
      display: none;
    }

    .jd-story-circle__name {
      max-width: 72px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-foreground);
    }
    .jd-story-circle__name[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-story-circle {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-strategy-panel:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-strategy-panel {
      /* 등락색은 직접 칠하지 않고 앱이 1회 덮어쓰는 훅을 경유한다 — success/danger를 박아
       두면 한국 관례 override가 이 패널만 비껴가 한 화면에서 매수·상승색이 갈라진다.
       매수 존·손절선도 v2에서 --bm-up/--bm-down이었으므로 같은 훅을 탄다. */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));

      display: block;
      /* 열 배분의 기준은 뷰포트가 아니라 이 패널이 실제로 받은 폭이다 */
      /* inline-size 컨테이너는 **내용이 폭을 정하지 못한다**. 부모가 준 폭을 명시적으로
         받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다(실측). */
      width: 100%;
      container: jd-sp / inline-size;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      /* 채움만 있는 면은 색종이로 읽힌다 — 얕은 그림자로 면을 띄운다 */
      box-shadow: var(--jd-shadow-xs);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    .jd-strategy-panel__body {
      display: block;
    }

    .jd-strategy-panel__tone {
      color: var(--_jd-sp-color, var(--jd-color-muted));
    }
    .jd-strategy-panel__accent-icon {
      color: var(--jd-color-primary-ink);
    }
    .jd-strategy-panel__tone-icon {
      color: var(--_jd-sp-color, var(--jd-color-muted));
    }

    /* ── 헤더 ── */
    .jd-strategy-panel__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__header-left {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-strategy-panel__header-right {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__title {
      margin: 0;
      font-weight: 800;
      font-size: var(--jd-text-md);
    }
    .jd-strategy-panel__num {
      font-variant-numeric: tabular-nums;
    }

    /* ── 상단 그리드: 추천 카드 + KPI ── */
    .jd-strategy-panel__top {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--jd-space-4);
      padding: var(--jd-space-4);
    }
    .jd-strategy-panel__rec {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--_jd-sp-bg, var(--jd-color-border-light));
    }
    .jd-strategy-panel__rec-icon {
      width: 40px;
      height: 40px;
      flex-shrink: 0;
      border-radius: var(--jd-radius-full);
      display: grid;
      place-items: center;
      background: var(--_jd-sp-strong, var(--_jd-sp-color, var(--jd-color-muted)));
      color: #fff;
    }
    .jd-strategy-panel__rec-main {
      flex: 1;
      min-width: 0;
    }
    .jd-strategy-panel__rec-caption {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
    }
    .jd-strategy-panel__rec-label {
      font-size: var(--jd-text-xl);
      font-weight: 800;
    }
    .jd-strategy-panel__rec-metric {
      text-align: right;
    }
    .jd-strategy-panel__rec-metric--divider {
      padding-inline-end: var(--jd-space-3);
      border-inline-end: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-color-foreground) 8%, transparent);
    }
    .jd-strategy-panel__rec-metric-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__rec-metric-value {
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: var(--jd-text-lg);
    }
    .jd-strategy-panel__rec-metric-unit {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      margin-inline-start: 2px;
      color: var(--jd-color-muted);
    }

    .jd-strategy-panel__kpis {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: var(--jd-space-2);
    }
    .jd-strategy-panel__kpi {
      min-width: 0;
      border-radius: var(--jd-radius-xl);
      text-align: center;
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-border-light);
    }
    /* 라벨은 두 줄로 접히면 안 되고, 값 + 단위는 한 덩어리다 */
    .jd-strategy-panel__kpi-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__kpi-value {
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: var(--jd-text-md);
      white-space: nowrap;
      margin-top: var(--jd-space-0-5);
      color: var(--jd-color-foreground);
    }
    .jd-strategy-panel__kpi[data-tone="buy"] .jd-strategy-panel__kpi-value {
      color: var(--jd-fin-up);
    }
    .jd-strategy-panel__kpi[data-tone="stop"] .jd-strategy-panel__kpi-value {
      color: var(--jd-fin-down);
    }
    .jd-strategy-panel__kpi-unit {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      margin-inline-start: 2px;
    }

    /* ── 근거 패널 (details) ── */
    .jd-strategy-panel__reason {
      padding: 0 var(--jd-space-4) var(--jd-space-3);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__reason-summary {
      cursor: pointer;
      list-style: none;
      user-select: none;
      padding-block: var(--jd-space-3);
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: 0.78125rem;
      font-weight: 800;
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-strategy-panel__reason-summary::-webkit-details-marker {
      display: none;
    }
    /* 접히는 것에는 셰브런이 있어야 한다 — 마커를 지웠으면 대신 그려 준다.
     기본 마커를 지운 자리에 아무 어포던스도 없으면 이 줄은 그냥 문장으로 읽힌다. */
    .jd-strategy-panel__reason-summary::after {
      content: "";
      flex-shrink: 0;
      width: 7px;
      height: 7px;
      margin-inline-start: var(--jd-space-1);
      border-inline-end: var(--jd-border-medium) solid var(--jd-color-muted);
      border-block-end: var(--jd-border-medium) solid var(--jd-color-muted);
      rotate: 45deg;
      transition: rotate var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    .jd-strategy-panel__reason[open] > .jd-strategy-panel__reason-summary::after {
      rotate: -135deg;
    }
    /* 누를 수 있는 것은 세 상태를 전부 가진다 */
    .jd-strategy-panel__reason-summary:hover {
      color: var(--jd-color-primary-ink);
    }
    .jd-strategy-panel__reason-summary:active {
      color: var(--jd-color-primary-hover);
    }
    .jd-strategy-panel__reason-summary:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-strategy-panel__reason-chip {
      margin-inline-start: auto;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      background: var(--_jd-sp-bg, var(--jd-color-border-light));
      color: var(--_jd-sp-color, var(--jd-color-muted));
      white-space: nowrap;
    }
    .jd-strategy-panel__reason-body {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
      gap: var(--jd-space-3);
      margin-top: var(--jd-space-1);
    }
    .jd-strategy-panel__reason-card {
      min-width: 0;
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-3);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-relaxed);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__reason-card--soft {
      background: var(--jd-color-border-light);
    }
    .jd-strategy-panel__reason-heading {
      font-size: var(--jd-text-2xs);
      font-weight: 800;
      color: var(--jd-color-muted);
      margin-block-end: var(--jd-space-2);
    }
    .jd-strategy-panel__reason-p {
      margin: 0 0 var(--jd-space-2-5);
    }

    .jd-strategy-panel__breakdown {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }
    .jd-strategy-panel__breakdown-row {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-strategy-panel__breakdown-main {
      min-width: 0;
      flex: 1;
    }
    .jd-strategy-panel__breakdown-label {
      font-weight: var(--jd-weight-bold);
    }
    .jd-strategy-panel__breakdown-detail {
      font-size: var(--jd-text-2xs);
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__breakdown-value {
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: 0.78125rem;
      flex-shrink: 0;
    }
    .jd-strategy-panel__breakdown-value[data-trend="up"] {
      color: var(--jd-fin-up);
    }
    .jd-strategy-panel__breakdown-value[data-trend="down"] {
      color: var(--jd-fin-down);
    }
    .jd-strategy-panel__breakdown-value[data-trend="text"] {
      color: var(--jd-color-foreground);
    }
    .jd-strategy-panel__breakdown-total {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding-block-start: var(--jd-space-1-5);
      margin-block-start: var(--jd-space-1);
      border-block-start: var(--jd-border-thin) dashed var(--jd-color-border);
    }
    .jd-strategy-panel__breakdown-total-label {
      font-weight: 800;
    }
    .jd-strategy-panel__breakdown-total-value {
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: var(--jd-text-md);
    }

    .jd-strategy-panel__reason-criteria {
      margin-block-start: var(--jd-space-2);
      padding-block-start: var(--jd-space-2);
      font-size: var(--jd-text-2xs);
      line-height: var(--jd-leading-relaxed);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__reason-criteria strong {
      font-weight: 800;
      color: var(--jd-color-foreground);
    }

    .jd-strategy-panel__reasons {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
    }
    .jd-strategy-panel__reason-item {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
    }
    .jd-strategy-panel__reason-dot {
      margin-top: 5px;
      flex-shrink: 0;
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
    }
    .jd-strategy-panel__tone-bgdot {
      background: var(--_jd-sp-color, var(--jd-color-muted));
    }
    .jd-strategy-panel__reason-disclaimer {
      margin-block-start: var(--jd-space-3);
      padding-block-start: var(--jd-space-2);
      font-size: var(--jd-text-2xs);
      line-height: var(--jd-leading-relaxed);
      border-block-start: var(--jd-border-thin) dashed var(--jd-color-border);
      color: var(--jd-color-muted);
    }

    /* ── 존 (매수/익절/손절) ── */
    .jd-strategy-panel__zones {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
      gap: var(--jd-space-4);
      padding: 0 var(--jd-space-4) var(--jd-space-4);
    }
    .jd-strategy-panel__zone {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-strategy-panel__zone[data-tone="buy"] {
      --_z: var(--jd-fin-up);
    }
    .jd-strategy-panel__zone[data-tone="sell"] {
      --_z: var(--jd-color-primary);
    }
    .jd-strategy-panel__zone[data-tone="stop"] {
      --_z: var(--jd-fin-down);
    }
    .jd-strategy-panel__zone-head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      padding-inline: var(--jd-space-1);
    }
    .jd-strategy-panel__zone-icon {
      color: var(--_z);
    }
    .jd-strategy-panel__zone-title {
      margin: 0;
      font-size: 0.78125rem;
      font-weight: 800;
      color: var(--_z);
    }

    .jd-strategy-panel__level {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
    }
    .jd-strategy-panel__level-left {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-strategy-panel__level-desc {
      font-size: 0.71875rem;
      font-weight: var(--jd-weight-bold);
      line-height: var(--jd-leading-tight);
    }
    .jd-strategy-panel__level-right {
      white-space: nowrap;
      text-align: right;
      font-variant-numeric: tabular-nums;
    }
    .jd-strategy-panel__level-price {
      white-space: nowrap;
      font-weight: 800;
      font-size: var(--jd-text-md);
      color: var(--_z);
    }
    .jd-strategy-panel__level-dist {
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
    }

    .jd-strategy-panel__stop {
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-3-5) var(--jd-space-3);
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-fin-down) 30%, transparent);
      background: color-mix(in srgb, var(--jd-fin-down) 5%, transparent);
    }
    .jd-strategy-panel__stop-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-strategy-panel__stop-right {
      white-space: nowrap;
      text-align: right;
      font-variant-numeric: tabular-nums;
    }
    .jd-strategy-panel__stop-price {
      white-space: nowrap;
      font-weight: 800;
      font-size: var(--jd-text-xl);
      color: var(--jd-fin-down);
    }
    .jd-strategy-panel__stop-dist {
      white-space: nowrap;
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__stop-desc {
      margin: var(--jd-space-2) 0 0;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-fin-down);
    }

    .jd-strategy-panel__chip {
      display: inline-flex;
      align-items: center;
      flex-shrink: 0;
      padding: 1px var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
    }
    .jd-strategy-panel__chip[data-tone="buy"] {
      background: color-mix(in srgb, var(--jd-fin-up) 14%, transparent);
      color: color-mix(in srgb, var(--jd-fin-up) 78%, var(--jd-color-foreground));
    }
    .jd-strategy-panel__chip[data-tone="sell"] {
      background: color-mix(in srgb, var(--jd-color-primary) 14%, transparent);
      color: var(--jd-color-primary-ink);
    }
    .jd-strategy-panel__chip[data-tone="stop"] {
      background: color-mix(in srgb, var(--jd-color-info) 14%, transparent);
      color: var(--jd-color-info);
    }

    /* ── 포지션 ── */
    .jd-strategy-panel__positions {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-color-border-light);
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__position {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      min-width: 0;
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__position-label {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-bold);
      white-space: nowrap;
      color: var(--jd-color-muted);
    }
    .jd-strategy-panel__position-value {
      font-variant-numeric: tabular-nums;
      font-weight: 800;
      font-size: var(--jd-text-lg);
      white-space: nowrap;
      color: var(--jd-color-foreground);
    }
    .jd-strategy-panel__position[data-tone="info"] .jd-strategy-panel__position-value {
      color: var(--jd-color-info);
    }
    .jd-strategy-panel__position[data-tone="primary"] .jd-strategy-panel__position-value {
      color: var(--jd-color-primary-ink);
    }
    .jd-strategy-panel__position[data-tone="up"] .jd-strategy-panel__position-value {
      color: var(--jd-fin-up);
    }
    .jd-strategy-panel__position-note {
      font-size: var(--jd-text-2xs);
      font-weight: var(--jd-weight-semibold);
      white-space: nowrap;
      color: var(--jd-color-muted);
    }

    /* ── 노트 ── */
    .jd-strategy-panel__notes {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
      padding: var(--jd-space-3) var(--jd-space-4);
      font-size: 0.78125rem;
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-strategy-panel__note {
      display: flex;
      align-items: flex-start;
      gap: var(--jd-space-2);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-strategy-panel__note-icon {
      margin-top: 3px;
      flex-shrink: 0;
      color: var(--jd-color-muted);
    }

    /* ── 반응형 ──
     기준은 뷰포트가 아니라 이 패널이 실제로 받은 폭이다 — 사이드바나 2열 상세 안에 놓이면
     뷰포트는 1280px인데 패널은 360px이고, 그때 3열을 강제하면 값과 단위가 갈라진다.
     칸 수가 자유로운 곳(존·근거·포지션)은 질의 없이 내재적으로 접는다. */
    @container jd-sp (min-width: 44rem) {
      .jd-strategy-panel__top {
        grid-template-columns: minmax(0, 1fr) auto;
      }
      .jd-strategy-panel__kpis {
        gap: var(--jd-space-3);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-strategy-panel__reason-summary,
      .jd-strategy-panel__reason-summary::after {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-swipe-action {
      display: block;
      position: relative;
      overflow: hidden;
      font-family: var(--jd-font-sans);
    }

    .jd-swipe-action__panel {
      position: absolute;
      inset-block: 0;
      display: flex;
      align-items: stretch;
    }
    .jd-swipe-action__panel[hidden] {
      display: none;
    }
    .jd-swipe-action__panel[data-side="left"] {
      inset-inline-start: 0;
    }
    .jd-swipe-action__panel[data-side="right"] {
      inset-inline-end: 0;
    }

    .jd-swipe-action__button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: var(--_jd-swipe-button-width, 5rem);
      padding-inline: var(--jd-space-4);
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      color: #fff;
      background: var(--jd-color-muted);
      border: 0;
      cursor: pointer;
    }
    .jd-swipe-action__button[data-variant="danger"] {
      background: var(--jd-color-danger);
    }
    .jd-swipe-action__button[data-variant="primary"] {
      background: var(--jd-color-primary);
    }
    .jd-swipe-action__button[data-variant="success"] {
      background: var(--jd-color-success);
    }
    .jd-swipe-action__button[data-variant="warning"] {
      background: var(--jd-color-warning);
    }
    .jd-swipe-action__button:disabled {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }
    .jd-swipe-action__button:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-foreground);
      outline-offset: -3px;
    }

    .jd-swipe-action__content {
      position: relative;
      background: var(--jd-color-card);
      transform: translateX(var(--_jd-swipe-offset, 0px));
      transition: transform var(--jd-duration-slow) var(--jd-easing-ease-out);
      /* 세로 스크롤은 브라우저에, 가로 제스처는 우리에게 */
      touch-action: pan-y;
    }
    .jd-swipe-action__content[data-dragging] {
      transition-duration: 0s; /* v2: 드래그 중에는 손가락을 그대로 따라간다 */
      user-select: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-swipe-action__content {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-switch {
      display: inline-flex;
    }

    .jd-switch {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
    }
    /* disabled — 반투명은 트랙·썸만, 라벨은 muted 실색 (AA, DEC-027) */
    jd-switch[disabled] > .jd-switch {
      cursor: not-allowed;
    }
    jd-switch[disabled] .jd-switch__track {
      opacity: var(--jd-opacity-50);
    }
    jd-switch[disabled] .jd-switch__text {
      color: var(--jd-color-muted);
    }

    .jd-switch__track {
      position: relative;
      display: inline-flex;
      flex-shrink: 0;
      border: 0;
      margin: 0;
      padding: 0;
      cursor: inherit;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-track-strong);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
      width: 2.75rem;
      height: 1.5rem; /* md 기본 44×24 */
    }
    jd-switch[checked] .jd-switch__track {
      background: var(--jd-color-primary);
      /* 켜진 트랙은 홈이 아니라 발광면 — 인셋을 지우고 상단 하이라이트를 얹는다 */
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-switch__track:hover:not(:disabled) {
      background: var(--jd-color-neutral-400);
    }
    jd-switch[checked] .jd-switch__track:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    .jd-switch__track:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-switch__thumb {
      position: absolute;
      top: 50%;
      left: 3px;
      translate: 0 -50%;
      width: 1.125rem;
      height: 1.125rem; /* md 18px */
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      box-shadow: var(--jd-shadow-knob);
      transition: transform var(--jd-duration-normal) var(--jd-easing-overshoot);
    }
    jd-switch[checked] .jd-switch__thumb {
      transform: translateX(20px);
    }

    jd-switch[size="sm"] .jd-switch__track {
      width: 2.25rem;
      height: 1.25rem;
    } /* 36×20 */
    jd-switch[size="sm"] .jd-switch__thumb {
      width: 0.875rem;
      height: 0.875rem;
    } /* 14px */
    jd-switch[size="sm"][checked] .jd-switch__thumb {
      transform: translateX(16px);
    }

    jd-switch[size="lg"] .jd-switch__track {
      width: 3.5rem;
      height: 1.75rem;
    } /* 56×28 */
    jd-switch[size="lg"] .jd-switch__thumb {
      width: 1.375rem;
      height: 1.375rem;
    } /* 22px */
    jd-switch[size="lg"][checked] .jd-switch__thumb {
      transform: translateX(28px);
    }

    .jd-switch__text {
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }
    .jd-switch__text[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-switch__track,
      .jd-switch__thumb {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-switcher {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-4);
      /* 기본 임계값 — 두 칸이 나란히 서기엔 640px 정도가 하한이라는 경험값 */
      --jd-switcher-threshold: var(--jd-breakpoint-sm);
    }

    jd-switcher > * {
      flex-grow: 1;
      flex-basis: calc((var(--jd-switcher-threshold) - 100%) * 999);
    }

    /* 임계값은 브레이크포인트 이름으로 고른다 — jd-show·p="4 md:6"와 같은 어휘 */
    jd-switcher[threshold="sm"] {
      --jd-switcher-threshold: var(--jd-breakpoint-sm);
    }
    jd-switcher[threshold="md"] {
      --jd-switcher-threshold: var(--jd-breakpoint-md);
    }
    jd-switcher[threshold="lg"] {
      --jd-switcher-threshold: var(--jd-breakpoint-lg);
    }
    jd-switcher[threshold="xl"] {
      --jd-switcher-threshold: var(--jd-breakpoint-xl);
    }
    jd-switcher[threshold="2xl"] {
      --jd-switcher-threshold: var(--jd-breakpoint-2xl);
    }
  }

  @layer junds.components {
    jd-table {
      display: block;
      overflow: hidden; /* 모서리 반경 안쪽으로 스크롤러를 자른다 */
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      font-family: var(--jd-font-sans);
    }

    /* 스크롤러 — max-height는 프로퍼티가 넣는 CSS 변수로 받는다(호스트 무관, 파생 공유) */
    .jd-table__scroll {
      overflow: auto;
      max-height: var(--_jd-table-max-height, none);
    }

    .jd-table {
      width: 100%;
      border-collapse: collapse;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }

    .jd-table__caption {
      caption-side: top;
      padding: var(--jd-space-3) var(--jd-space-4);
      text-align: start;
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-table__caption[hidden] {
      display: none;
    }
    /* 접근 이름만 남기고 시각적으로 감춤 — v2에는 표 이름 자체가 없었다 */
    .jd-table__caption--hidden {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    .jd-table__th {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-muted);
      text-align: start;
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-table__td {
      color: var(--jd-color-foreground);
      text-align: start;
    }

    .jd-table__th[data-align="left"],
    .jd-table__td[data-align="left"] {
      text-align: left;
    }
    .jd-table__th[data-align="center"],
    .jd-table__td[data-align="center"] {
      text-align: center;
    }
    .jd-table__th[data-align="right"],
    .jd-table__td[data-align="right"] {
      text-align: right;
    }

    .jd-table__row {
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-table__body > .jd-table__row:last-child {
      border-block-end: 0;
    }

    .jd-table__empty {
      padding: var(--jd-space-8) var(--jd-space-4);
      text-align: center;
      color: var(--jd-color-muted);
    }

    /* 행 크기 — resolvedSize(size ?? compact)가 data-size로 온다 */
    jd-table[data-size="sm"] .jd-table__th {
      padding: var(--jd-space-2) var(--jd-space-3);
    }
    jd-table[data-size="sm"] .jd-table__td {
      padding: var(--jd-space-1-5) var(--jd-space-3);
    }
    jd-table[data-size="md"] .jd-table__th,
    jd-table[data-size="md"] .jd-table__td {
      padding: var(--jd-space-3) var(--jd-space-4);
    }
    jd-table[data-size="lg"] .jd-table__th,
    jd-table[data-size="lg"] .jd-table__td {
      padding: var(--jd-space-4) var(--jd-space-5);
    }

    /* 모디파이어 — v2 striped는 rowIndex % 2 === 1(=두 번째 행부터) */
    jd-table[striped] .jd-table__body > .jd-table__row:nth-child(even) {
      background: color-mix(in srgb, var(--jd-color-card-hover) 50%, transparent);
    }
    jd-table[hoverable] .jd-table__body > .jd-table__row:hover {
      background: var(--jd-color-card-hover);
    }
    jd-table[bordered] .jd-table__th,
    jd-table[bordered] .jd-table__td {
      border: var(--jd-border-thin) solid var(--jd-color-border);
    }
    jd-table[sticky-header] .jd-table__th {
      position: sticky;
      inset-block-start: 0;
      z-index: var(--jd-z-sticky);
    }

    /* 행 활성화 — v2는 마우스 전용이었다. 포커스 링은 토큰 통일(§8) */
    jd-table[row-clickable] .jd-table__body > .jd-table__row {
      cursor: pointer;
    }
    .jd-table__body > .jd-table__row:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: -2px;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-table__row {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-table-of-contents {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
    }
    jd-table-of-contents[data-empty] {
      display: none;
    }

    .jd-table-of-contents__heading {
      margin: 0 0 var(--jd-space-2);
      font-size: var(--jd-text-xs);
      text-transform: uppercase;
      letter-spacing: var(--jd-tracking-wide);
      color: var(--jd-color-muted);
    }
    .jd-table-of-contents__heading[hidden] {
      display: none;
    }

    jd-table-of-contents .jd-scroll-spy__item {
      padding-block: var(--jd-space-0-5);
      padding-inline: var(--jd-space-2) 0;
      border-radius: 0;
    }
    jd-table-of-contents .jd-scroll-spy__item:hover {
      background: transparent;
      border-inline-start-color: var(--jd-color-border);
    }
    jd-table-of-contents .jd-scroll-spy__item[aria-current] {
      background: transparent;
    }
    jd-table-of-contents .jd-scroll-spy__item:focus-visible {
      border-radius: var(--jd-radius-sm);
    }
  }

  @layer junds.components {
    /* 기본 variant=underline — v2: flex border-b border-border gap-0 */
    jd-tabs {
      display: flex;
      align-items: flex-end;
      gap: 0;
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }

    .jd-tabs__tab {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: var(--jd-space-1-5);
      margin: 0;
      border: 0;
      background: transparent;
      cursor: pointer;
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-medium);
      line-height: var(--jd-leading-none);
      white-space: nowrap;
      color: var(--jd-color-muted);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        border-color var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out),
        opacity var(--jd-duration-normal) var(--jd-easing-ease-out),
        scale var(--jd-duration-normal) var(--jd-easing-ease-out),
        transform var(--jd-duration-normal) var(--jd-easing-ease-out);
      /* size 기본 md — v2 underline: px-4 py-2.5 text-sm */
      padding: var(--jd-space-2-5) var(--jd-space-4);
      font-size: var(--jd-text-md);
      /* underline 고유: 3px 밑줄 + 컨테이너 경계선과 겹치기 */
      border-block-end: var(--jd-border-thick) solid transparent;
      margin-block-end: calc(-1 * var(--jd-border-thin));
    }
    .jd-tabs__tab:hover:not(:disabled) {
      color: color-mix(in srgb, var(--jd-color-foreground) 80%, transparent);
      border-block-end-color: var(--jd-color-border);
    }
    .jd-tabs__tab:active:not(:disabled) {
      scale: 0.95;
    }
    .jd-tabs__tab:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-tabs__tab:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-tabs__tab[aria-selected="true"] {
      color: var(--jd-color-foreground);
      border-block-end-color: var(--jd-color-primary);
    }

    .jd-tabs__icon {
      display: inline-flex;
      flex-shrink: 0;
    }
    .jd-tabs__icon[hidden] {
      display: none;
    }
    .jd-tabs__icon > svg {
      width: 1em;
      height: 1em;
    }

    /* 배지 — v2: rounded-full px-1.5 text-[10px] font-semibold */
    .jd-tabs__badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding-inline: var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      font-size: 0.625rem;
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-normal);
      background: var(--jd-color-border-light);
      color: var(--jd-color-muted);
    }
    .jd-tabs__badge[hidden] {
      display: none;
    }
    .jd-tabs__tab[aria-selected="true"] > .jd-tabs__badge {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }

    /* size=sm — v2 underline: px-3 py-2 text-xs */
    jd-tabs[size="sm"] > .jd-tabs__tab {
      padding: var(--jd-space-2) var(--jd-space-3);
      font-size: var(--jd-text-xs);
    }

    /* ── variant=pills — v2: inline-flex gap-1, 경계선 없음 ───────────── */
    jd-tabs[variant="pills"] {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      border-block-end: 0;
    }
    jd-tabs[variant="pills"] > .jd-tabs__tab {
      border-block-end: 0;
      margin-block-end: 0;
      border-radius: var(--jd-radius-full);
      padding: var(--jd-space-1-5) var(--jd-space-3-5);
    }
    jd-tabs[variant="pills"][size="sm"] > .jd-tabs__tab {
      padding: var(--jd-space-1) var(--jd-space-2-5);
    }
    jd-tabs[variant="pills"] > .jd-tabs__tab:hover:not(:disabled) {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    jd-tabs[variant="pills"] > .jd-tabs__tab[aria-selected="true"] {
      background: var(--jd-color-primary);
      color: #fff;
      box-shadow: var(--jd-shadow-md);
    }
    jd-tabs[variant="pills"] > .jd-tabs__tab[aria-selected="true"] > .jd-tabs__badge {
      background: color-mix(in srgb, #fff 20%, transparent);
      color: #fff;
    }

    /* ── variant=segment — v2: 회색 트랙 안의 흰 알약 ─────────────────── */
    jd-tabs[variant="segment"] {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      border-block-end: 0;
      padding: var(--jd-space-1);
      border-radius: var(--jd-radius-lg);
      background: var(--jd-color-border-light);
    }
    jd-tabs[variant="segment"] > .jd-tabs__tab {
      border-block-end: 0;
      margin-block-end: 0;
      border-radius: var(--jd-radius-md);
      padding: var(--jd-space-1-5) var(--jd-space-3);
    }
    jd-tabs[variant="segment"][size="sm"] > .jd-tabs__tab {
      padding: var(--jd-space-1) var(--jd-space-2-5);
    }
    jd-tabs[variant="segment"] > .jd-tabs__tab:hover:not(:disabled) {
      color: color-mix(in srgb, var(--jd-color-foreground) 80%, transparent);
    }
    jd-tabs[variant="segment"] > .jd-tabs__tab[aria-selected="true"] {
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      box-shadow: var(--jd-shadow-sm);
    }
    jd-tabs[variant="segment"] > .jd-tabs__tab[aria-selected="true"] > .jd-tabs__badge {
      background: var(--jd-color-primary);
      color: #fff;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-tabs__tab {
        transition: none;
      }
      .jd-tabs__tab:active:not(:disabled) {
        scale: none;
      }
    }
  }

  @layer junds.components {
    jd-tag {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      white-space: nowrap;
      --jd-tone: var(--jd-color-hue-gray); /* gray 기본 */
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), transparent);
      color: color-mix(in srgb, var(--jd-tone) var(--jd-tone-ink-mix), var(--jd-tone-ink-toward));
    }
    jd-tag[color="primary"] {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
    }
    jd-tag[color="blue"] {
      --jd-tone: var(--jd-color-hue-blue);
    }
    jd-tag[color="green"] {
      --jd-tone: var(--jd-color-hue-green);
    }
    jd-tag[color="red"] {
      --jd-tone: var(--jd-color-hue-red);
    }
    jd-tag[color="orange"] {
      --jd-tone: var(--jd-color-hue-orange);
    }
    jd-tag[color="purple"] {
      --jd-tone: var(--jd-color-hue-purple);
    }
    jd-tag[color="teal"] {
      --jd-tone: var(--jd-color-hue-teal);
    }

    .jd-tag__close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-inline-start: var(--jd-space-0-5);
      padding: 0;
      border: 0;
      background: transparent;
      color: inherit;
      cursor: pointer;
      transition: opacity var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-tag__close:hover {
      opacity: 0.7;
    }
    .jd-tag__close:focus-visible {
      outline: var(--jd-border-medium) solid color-mix(in srgb, currentColor 40%, transparent);
      outline-offset: 1px;
      border-radius: var(--jd-radius-sm);
    }
  }

  @layer junds.components {
    jd-tag-input {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      box-sizing: border-box;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      cursor: text;
      transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
      /* size 기본 md */
      min-height: 2.25rem;
      gap: var(--jd-space-1-5);
      padding-inline: var(--jd-space-3);
      padding-block: var(--jd-space-1);
      font-size: var(--jd-text-md);
    }
    jd-tag-input:focus-within {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-tag-input[error] {
      border-color: var(--jd-color-danger);
    }
    jd-tag-input[error]:focus-within {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger);
    }
    jd-tag-input[disabled] {
      opacity: var(--jd-opacity-50);
      cursor: not-allowed;
    }

    jd-tag-input[size="sm"] {
      min-height: 2rem;
      gap: var(--jd-space-1);
      padding-inline: var(--jd-space-2);
      font-size: var(--jd-text-xs);
    }
    jd-tag-input[size="lg"] {
      min-height: 2.75rem;
      gap: var(--jd-space-2);
      padding-inline: var(--jd-space-4);
      font-size: var(--jd-text-lg);
    }

    .jd-tag-input__tag {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      max-width: 100%;
      border-radius: var(--jd-radius-md);
      font-family: var(--jd-font-sans);
      font-weight: var(--jd-weight-medium);
      background: color-mix(in srgb, var(--jd-color-primary) 10%, transparent);
      color: var(--jd-color-primary-ink);
      /* 칩 size 기본 md */
      padding: var(--jd-space-0-5) var(--jd-space-2);
      font-size: var(--jd-text-xs);
    }
    jd-tag-input[size="sm"] .jd-tag-input__tag {
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      font-size: 0.625rem;
    }
    jd-tag-input[size="lg"] .jd-tag-input__tag {
      padding: var(--jd-space-1) var(--jd-space-2-5);
      font-size: var(--jd-text-md);
    }
    .jd-tag-input__tag-label {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-tag-input__remove {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      border: 0;
      background: transparent;
      color: inherit;
      cursor: pointer;
      transition: color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-tag-input__remove[hidden] {
      display: none;
    }
    .jd-tag-input__remove:hover {
      color: var(--jd-color-danger);
    }
    .jd-tag-input__remove:focus-visible {
      outline: var(--jd-border-medium) solid color-mix(in srgb, currentColor 40%, transparent);
      outline-offset: 1px;
      border-radius: var(--jd-radius-sm);
    }

    .jd-tag-input__input {
      flex: 1;
      min-width: 5rem; /* v2 min-w-[80px] */
      margin: 0;
      padding: 0;
      border: 0;
      outline: none;
      background: transparent;
      color: var(--jd-color-foreground);
      font-family: var(--jd-font-sans);
      font-size: inherit;
    }
    .jd-tag-input__input::placeholder {
      color: var(--jd-color-muted);
    }
    .jd-tag-input__input:disabled {
      cursor: not-allowed;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-tag-input,
      .jd-tag-input__remove {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-testimonial-card:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-testimonial-card {
      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    /* ── card (기본) ── */
    jd-testimonial-card[variant="card"] {
      border: var(--jd-border-thin) solid var(--jd-color-border);
      background: var(--jd-color-card);
      border-radius: var(--jd-radius-xl);
      padding: var(--jd-space-5);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-testimonial-card[variant="card"]:hover {
      box-shadow: var(--jd-shadow-md);
    }
    jd-testimonial-card[variant="card"][highlighted] {
      border-color: var(--jd-color-primary);
      box-shadow: var(--jd-shadow-md),
        0 0 0 1px color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }

    /* ── quote ── */
    jd-testimonial-card[variant="quote"] {
      position: relative;
      padding: var(--jd-space-8) var(--jd-space-6);
    }
    jd-testimonial-card[variant="quote"] .jd-testimonial-card__quote::before {
      content: "\\201C";
      position: absolute;
      top: var(--jd-space-2);
      inset-inline-start: 0;
      font-family: var(--jd-font-serif);
      font-size: 3.75rem; /* text-6xl */
      line-height: 1;
      color: color-mix(in srgb, var(--jd-color-primary) 20%, transparent);
      user-select: none;
      pointer-events: none;
    }
    jd-testimonial-card[variant="quote"] .jd-testimonial-card__quote {
      position: static;
      font-size: var(--jd-text-lg);
      font-style: italic;
      line-height: var(--jd-leading-relaxed);
    }

    /* ── minimal ── */
    jd-testimonial-card[variant="minimal"] {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
    }
    jd-testimonial-card[variant="minimal"] .jd-testimonial-card__author {
      margin-top: 0;
      gap: var(--jd-space-2);
      align-items: center;
    }
    jd-testimonial-card[variant="minimal"] .jd-testimonial-card__avatar {
      display: none;
    }
    jd-testimonial-card[variant="minimal"] .jd-testimonial-card__meta {
      flex-direction: row;
      align-items: baseline;
      gap: var(--jd-space-1-5);
      font-size: var(--jd-text-xs);
    }
    jd-testimonial-card[variant="minimal"] .jd-testimonial-card__role {
      color: var(--jd-color-muted);
    }
    jd-testimonial-card[variant="minimal"] .jd-testimonial-card__role::before {
      content: "· ";
    }

    /* ── 공통 조각 ── */
    .jd-testimonial-card__stars {
      display: flex;
      align-items: center;
      gap: 2px;
      margin-bottom: var(--jd-space-2);
    }
    .jd-testimonial-card__star {
      flex-shrink: 0;
    }

    .jd-testimonial-card__quote {
      margin: 0;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-color-foreground);
    }

    .jd-testimonial-card__author {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      margin-top: var(--jd-space-4);
    }
    .jd-testimonial-card__avatar {
      flex-shrink: 0;
      width: 2.5rem;
      height: 2.5rem;
      border-radius: var(--jd-radius-full);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: var(--jd-color-primary);
      color: #fff;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      background-size: cover;
      background-position: center;
    }
    .jd-testimonial-card__avatar[data-image] {
      background-color: transparent;
    }
    .jd-testimonial-card__meta {
      display: flex;
      flex-direction: column;
      min-width: 0;
      flex: 1;
    }
    .jd-testimonial-card__name {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      font-style: normal;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-testimonial-card__role {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-testimonial-card__logo {
      flex-shrink: 0;
      opacity: var(--jd-opacity-60);
    }

    @media (prefers-reduced-motion: reduce) {
      jd-testimonial-card[variant="card"] {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-text {
      display: block;
      font-size: var(--jd-text-lg);
      line-height: var(--jd-leading-relaxed);
    }
    jd-text[as="span"],
    jd-text[as="strong"],
    jd-text[as="em"],
    jd-text[as="small"],
    jd-text[as="label"] {
      display: inline;
    }

    .jd-text {
      margin: 0;
      font-size: inherit;
      line-height: inherit;
    }

    jd-text[dimmed] {
      color: var(--jd-color-muted);
    }
    jd-text[mono] {
      font-family: var(--jd-font-mono);
    }

    jd-text[truncate] {
      overflow: hidden;
    }
    jd-text[truncate] > .jd-text {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  @layer junds.components {
    jd-text-field {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1-5);
    }

    .jd-text-field__label {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
    .jd-text-field__label[hidden] {
      display: none;
    }
    jd-text-field[required] > .jd-text-field__label::after {
      content: "*";
      margin-inline-start: var(--jd-space-0-5);
      color: var(--jd-color-danger);
    }

    .jd-text-field__control {
      position: relative;
      display: flex;
      align-items: center;
      min-width: 0;
    }

    /* 입력면은 불투명(DEC-039). v2 이식본의 "card 80% + backdrop-filter: blur(4px)"는
     조상 배경이 투명하면 브라우저가 백드롭 루트를 새로 잡아 다크에서 밝은 회색
     슬래브로 렌더됐다(실측). 흐림은 진짜 오버레이 전용. */
    .jd-text-field__input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      caret-color: var(--jd-color-primary-ink);
      /* all 금지 — height/padding까지 트랜지션 대상이 되어 size 전환·리플로우가 흐른다 */
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
      /* size 기본 md — 디폴트는 attribute 미반영(§1.3)이라 base가 담당. v2: 40px */
      height: 2.5rem;
      padding-inline: var(--jd-space-3-5);
      font-size: var(--jd-text-md);
      border-radius: var(--jd-radius-xl);
    }
    .jd-text-field__slot {
      position: absolute;
      z-index: 1;
      top: 50%;
      translate: 0 -50%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      max-width: calc(50% - var(--jd-space-3));
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-none);
    }
    .jd-text-field__slot:empty {
      display: none;
    }
    .jd-text-field__slot--start {
      inset-inline-start: var(--jd-space-3-5);
      pointer-events: none;
    }
    .jd-text-field__slot--end {
      inset-inline-end: var(--jd-space-3-5);
    }
    .jd-text-field__control:has(> .jd-text-field__slot--start:not(:empty)) > .jd-text-field__input {
      padding-inline-start: 2.75rem;
    }
    .jd-text-field__control:has(> .jd-text-field__slot--end:not(:empty)) > .jd-text-field__input {
      padding-inline-end: 2.75rem;
    }
    .jd-text-field__input::placeholder {
      /* 램프 400 — 두 모드에서 같은 '읽히지만 물러나는' 위치. 이전의 muted-light 60%는
       라이트에서 2.1:1로 사실상 보이지 않았다. */
      color: var(--jd-color-neutral-400);
    }
    .jd-text-field__input::selection {
      background: color-mix(in srgb, var(--jd-color-primary) 26%, transparent);
    }
    /* 호버 피드백 — 입력면에 호버 상태가 없으면 '누를 수 있는 곳'이라는 신호가 없다 */
    .jd-text-field__input:hover:not(:disabled):not(:focus) {
      border-color: var(--jd-color-neutral-300);
      background: var(--jd-color-control-surface-hover);
    }
    .jd-text-field__input:focus {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-color: var(--jd-color-primary);
      background: var(--jd-color-control-surface);
    }
    /* disabled에 opacity를 걸면 테두리·글자가 함께 흐려져 '고장난 필드'로 읽힌다 →
     면과 글자를 각각 실색으로 낮춘다(AA 유지, DEC-027과 동일 원칙) */
    .jd-text-field__input:disabled {
      cursor: not-allowed;
      background: var(--jd-color-control-surface-muted);
      border-color: var(--jd-color-border-light);
      color: var(--jd-color-neutral-500);
    }
    .jd-text-field__input:disabled::placeholder {
      color: var(--jd-color-neutral-400);
    }

    /* size — v2 Input: sm 32px / lg 48px (md는 base) */
    jd-text-field[size="sm"] > .jd-text-field__control > .jd-text-field__input {
      height: 2rem;
      padding-inline: var(--jd-space-3);
      font-size: var(--jd-text-xs);
      border-radius: var(--jd-radius-lg);
    }
    jd-text-field[size="sm"] > .jd-text-field__control > .jd-text-field__slot {
      font-size: var(--jd-text-xs);
    }
    jd-text-field[size="sm"] > .jd-text-field__control > .jd-text-field__slot--start {
      inset-inline-start: var(--jd-space-3);
    }
    jd-text-field[size="sm"] > .jd-text-field__control > .jd-text-field__slot--end {
      inset-inline-end: var(--jd-space-3);
    }
    jd-text-field[size="lg"] > .jd-text-field__control > .jd-text-field__input {
      height: 3rem;
      padding-inline: var(--jd-space-4);
      font-size: var(--jd-text-lg);
      border-radius: var(--jd-radius-xl);
    }
    jd-text-field[size="lg"] > .jd-text-field__control > .jd-text-field__slot {
      font-size: var(--jd-text-lg);
    }
    jd-text-field[size="lg"] > .jd-text-field__control > .jd-text-field__slot--start {
      inset-inline-start: var(--jd-space-4);
    }
    jd-text-field[size="lg"] > .jd-text-field__control > .jd-text-field__slot--end {
      inset-inline-end: var(--jd-space-4);
    }

    /* invalid는 메시지 유무와 독립. error 문자열도 하위 호환으로 같은 시각 훅이다. */
    jd-text-field[invalid] > .jd-text-field__control > .jd-text-field__input,
    jd-text-field[error]:not([error=""]) > .jd-text-field__control > .jd-text-field__input {
      border-color: var(--jd-color-danger);
    }
    jd-text-field[invalid] > .jd-text-field__control > .jd-text-field__input:focus,
    jd-text-field[error]:not([error=""]) > .jd-text-field__control > .jd-text-field__input:focus {
      border-color: var(--jd-color-danger);
      outline: var(--jd-focus-ring-danger);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-text-field__error {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1);
      margin: 0;
      font-size: var(--jd-text-xs);
      font-family: var(--jd-font-sans);
      color: var(--jd-color-danger);
    }
    .jd-text-field__error[hidden] {
      display: none;
    }
    .jd-text-field__error > svg {
      flex-shrink: 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-text-field__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-textarea {
      display: block;
      position: relative;
    }

    .jd-textarea__input {
      display: block;
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      min-height: 80px;
      resize: vertical;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
      font-size: var(--jd-text-md);
      line-height: var(--jd-leading-normal);
      /* text-field와 동일 계약: 입력면은 불투명, 흐림 없음 (DEC-039) */
      background: var(--jd-color-control-surface);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      caret-color: var(--jd-color-primary-ink);
      border-radius: var(--jd-radius-xl);
      /* 카운터(우하단 절대배치)와 글자가 겹치지 않도록 아래 여백을 카운터 높이만큼 준다 */
      padding: var(--jd-space-2-5) var(--jd-space-3-5);
      transition: border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        box-shadow var(--jd-duration-snap) var(--jd-easing-ease-out);
    }
    /* show-count는 maxLength>0일 때만 실제로 배지가 뜨므로(element.ts) 속성이 아니라
     '배지가 보이는가'로 판정한다 — :has (DEC-004 에버그린 전제) */
    jd-textarea:has(> .jd-textarea__count:not([hidden])) > .jd-textarea__input {
      padding-bottom: var(--jd-space-6);
    }
    .jd-textarea__input::placeholder {
      color: var(--jd-color-neutral-400);
    }
    .jd-textarea__input::selection {
      background: color-mix(in srgb, var(--jd-color-primary) 26%, transparent);
    }
    .jd-textarea__input:hover:not(:disabled):not(:focus) {
      border-color: var(--jd-color-neutral-300);
      background: var(--jd-color-control-surface-hover);
    }
    .jd-textarea__input:focus {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
      border-color: var(--jd-color-primary);
      background: var(--jd-color-control-surface);
    }
    .jd-textarea__input:disabled {
      cursor: not-allowed;
      background: var(--jd-color-control-surface-muted);
      border-color: var(--jd-color-border-light);
      color: var(--jd-color-neutral-500);
    }

    jd-textarea[auto-resize] > .jd-textarea__input {
      resize: none;
      overflow: hidden;
    }

    jd-textarea[error] > .jd-textarea__input {
      border-color: var(--jd-color-danger);
    }
    jd-textarea[error] > .jd-textarea__input:focus {
      border-color: var(--jd-color-danger);
      outline: var(--jd-focus-ring-danger);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-textarea__count {
      position: absolute;
      bottom: var(--jd-space-2);
      right: var(--jd-space-3);
      /* muted-light는 AA 미달 → muted (DEC-027) */
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      pointer-events: none;
    }
    .jd-textarea__count[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-textarea__input {
        transition: none;
      }
    }
  }

  @layer junds.components {
    /* 카운터가 절대배치라 호스트가 컨테이닝 블록이어야 한다 */
    jd-textarea-autosize {
      display: block;
      position: relative;
    }

    jd-textarea-autosize > .jd-textarea__input {
      min-height: 0;
      resize: none;
      border-radius: var(--jd-radius-md);
      padding: var(--jd-space-2) var(--jd-space-3);
    }

    jd-textarea-autosize[error] > .jd-textarea__input {
      border-color: var(--jd-color-danger);
    }
    jd-textarea-autosize[error] > .jd-textarea__input:focus {
      border-color: var(--jd-color-danger);
      box-shadow: var(--jd-shadow-focus-ring-danger), var(--jd-shadow-xs);
    }

    jd-textarea-autosize > .jd-textarea__count {
      bottom: var(--jd-space-1);
      right: var(--jd-space-2);
      font-variant-numeric: tabular-nums;
    }
  }

  @layer junds.components {
    jd-theme-card {
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-accent: var(--jd-color-success);
      /* 12% 틴트 위 원색 글자는 12px에서 AA에 못 미친다 — 잉크 쪽으로 섞어 대비 확보 */
      --jd-fin-accent-strong: color-mix(
        in srgb,
        var(--jd-fin-accent) 65%,
        var(--jd-color-foreground)
      );
      --jd-fin-muted: var(--jd-color-muted);
      --jd-fin-text: var(--jd-color-foreground);
      --jd-fin-border: var(--jd-color-border);
      --jd-fin-card: var(--jd-color-card);
      --jd-fin-soft: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
      --jd-fin-warning: var(--jd-color-warning);

      display: block;
      box-sizing: border-box;
      height: 100%;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-theme-card * {
      box-sizing: border-box;
    }

    .jd-theme-card {
      display: flex;
      flex-direction: column;
      height: 100%;
      overflow: hidden;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      /* 리터럴 그림자는 다크에서 검은 위에 검은 그림자로 사라진다 — 모드별로 갈리는
       토큰 그림자를 쓴다(라이트 잉크 그림자 ↔ 다크 헤어라인 + 깊은 드롭). */
      box-shadow: var(--jd-shadow-xs);
      transition: box-shadow var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-theme-card:hover {
      box-shadow: var(--jd-shadow-md);
    }

    /* 헤더 */
    .jd-theme-card__header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3-5) var(--jd-space-4) var(--jd-space-2-5);
    }
    .jd-theme-card__heading {
      min-width: 0;
    }
    .jd-theme-card__title-row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }
    .jd-theme-card__star {
      color: var(--jd-fin-warning);
      font-size: 14px;
      line-height: 1;
    }
    .jd-theme-card__name {
      margin: 0;
      font-size: 15px;
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-theme-card__headline {
      margin: var(--jd-space-1) 0 0;
      font-size: 12px;
      color: var(--jd-fin-muted);
      line-height: var(--jd-leading-tight);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-theme-card__total {
      flex-shrink: 0;
      align-self: flex-start;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      background: color-mix(in srgb, var(--jd-fin-accent) 12%, transparent);
      color: var(--jd-fin-accent-strong);
    }

    /* 스파크라인 */
    .jd-theme-card__chart {
      padding: 0 var(--jd-space-4) var(--jd-space-1);
      opacity: 0.9;
    }
    .jd-theme-card__spark {
      display: block;
      width: 100%;
      height: 32px;
    }
    .jd-theme-card__spark-line {
      fill: none;
      stroke: var(--jd-fin-accent);
      stroke-width: 1.5;
      stroke-linejoin: round;
      stroke-linecap: round;
      vector-effect: non-scaling-stroke;
    }
    .jd-theme-card__spark-area {
      fill: color-mix(in srgb, var(--jd-fin-accent) 14%, transparent);
      stroke: none;
    }

    /* 종목 목록 */
    .jd-theme-card__list {
      list-style: none;
      margin: 0;
      padding: 0;
      flex: 1;
    }
    .jd-theme-card__empty {
      padding: var(--jd-space-6) var(--jd-space-4);
      text-align: center;
      font-size: 12px;
      color: var(--jd-fin-muted);
    }
    .jd-theme-card__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      text-decoration: none;
      color: inherit;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-theme-card__row:hover {
      background-color: var(--jd-fin-soft);
    }
    /* 눌린 면은 빛을 잃는다 — 행 전체가 링크라 hover보다 한 단 더 눌러 클릭을 알린다 */
    .jd-theme-card__row:active {
      background-color: color-mix(in srgb, var(--jd-color-foreground) 12%, transparent);
    }
    /* 카드가 overflow:hidden이라 바깥쪽 offset은 잘린다 — 링을 행 안쪽에 그린다.
     색은 강조색이 아니라 포커스 링 단일 레시피를 따른다(DEC-039). */
    .jd-theme-card__row:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: -2px;
      border-radius: var(--jd-radius-md);
    }

    .jd-theme-card__stock-name {
      min-width: 0;
      flex: 1;
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
    }
    .jd-theme-card__king {
      color: var(--jd-fin-warning);
    }
    .jd-theme-card__hot {
      flex-shrink: 0;
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-up);
    }
    .jd-theme-card__stock-label {
      font-size: 13px;
      font-weight: var(--jd-weight-bold);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-theme-card__num {
      flex-shrink: 0;
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      line-height: var(--jd-leading-tight);
      font-variant-numeric: tabular-nums;
    }
    /* 가격·거래대금은 숫자 + 단위 한 덩어리다 — 좁은 카드에서 "1,840"과 "억"이 갈리면 안 된다 */
    .jd-theme-card__price {
      font-size: 13px;
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-theme-card__price[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-theme-card__price[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-theme-card__amount {
      font-size: 10.5px;
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-fin-muted);
      white-space: nowrap;
    }

    .jd-theme-card__pct {
      flex-shrink: 0;
      font-variant-numeric: tabular-nums;
      font-size: 12.5px;
      font-weight: 800;
      white-space: nowrap;
    }
    .jd-theme-card__pct[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-theme-card__pct[data-dir="down"] {
      color: var(--jd-fin-down);
    }
    .jd-theme-card__pct[data-hot] {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      font-size: 12px;
      padding: 2px 7px;
      border-radius: var(--jd-radius-md);
      letter-spacing: -0.005em;
    }
    /* hot pill: 14% 틴트 위 원색 up/down 글자는 대비가 얕다 — hue는 유지하고 글자를
     foreground 쪽으로 섞어 대비 확보(03-web-arch §4.3, 라이트/다크 양쪽 대응). */
    .jd-theme-card__pct[data-hot][data-dir="up"] {
      background: color-mix(in srgb, var(--jd-fin-up) 14%, transparent);
      color: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
    }
    .jd-theme-card__pct[data-hot][data-dir="down"] {
      background: color-mix(in srgb, var(--jd-fin-down) 14%, transparent);
      color: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
    }
    .jd-theme-card__pct-arrow {
      font-size: 10px;
      line-height: 1;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-theme-card,
      .jd-theme-card__row {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-theme-drill-down {
      --jd-fin-up: var(--bm-up, var(--jd-color-success));
      --jd-fin-down: var(--bm-down, var(--jd-color-danger));
      --jd-fin-accent: var(--bm-accent, #14b8a6);
      --jd-fin-accent-strong: var(--bm-accent-strong, #0d9488);
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-warning: var(--bm-warning, var(--jd-color-warning));
    }

    jd-theme-drill-down > .jd-modal__panel {
      width: 560px;
      max-width: 95vw;
      max-height: 85vh;
      color: var(--jd-fin-text);
      font-variant-numeric: tabular-nums;
      box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
    }
    jd-theme-drill-down .jd-modal__panel * {
      box-sizing: border-box;
    }

    /* 헤더 */
    .jd-theme-drill-down__header {
      position: sticky;
      top: 0;
      z-index: 1;
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-fin-card);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-theme-drill-down__pill {
      font-size: 14px;
      font-weight: 800;
      padding: var(--jd-space-1) var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      background: color-mix(in srgb, var(--jd-fin-accent) 12%, transparent);
      color: var(--jd-fin-accent-strong);
      border: var(--jd-border-thin) solid color-mix(in srgb, var(--jd-fin-accent) 32%, transparent);
    }
    .jd-theme-drill-down__title {
      font-size: 13px;
      font-weight: 800;
      margin-inline-start: var(--jd-space-1);
    }
    .jd-theme-drill-down__close {
      margin-inline-start: auto;
      width: 32px;
      height: 32px;
      padding: 0;
      display: inline-grid;
      place-items: center;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
      cursor: pointer;
      transition: filter var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-theme-drill-down__close:hover {
      filter: brightness(0.94);
    }
    .jd-theme-drill-down__close:focus-visible {
      outline: var(--jd-border-medium) solid var(--jd-fin-accent-strong);
      outline-offset: 1px;
    }

    .jd-theme-drill-down__empty {
      padding: var(--jd-space-6);
      text-align: center;
      font-size: 12px;
      color: var(--jd-fin-muted);
    }

    /* 통계 4칸 */
    .jd-theme-drill-down__stats {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: var(--jd-space-2);
      padding: var(--jd-space-4);
    }
    .jd-theme-drill-down__stat {
      padding: var(--jd-space-2) var(--jd-space-2-5);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-fin-soft);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-theme-drill-down__stat-label {
      font-size: 10px;
      font-weight: 800;
      color: var(--jd-fin-muted);
    }
    .jd-theme-drill-down__stat-value {
      margin-top: var(--jd-space-0-5);
      font-size: 13px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    .jd-theme-drill-down__stat-value[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-theme-drill-down__stat-value[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    /* 섹션 */
    .jd-theme-drill-down__section {
      padding: 0 var(--jd-space-4) var(--jd-space-4);
    }
    .jd-theme-drill-down__section-title {
      font-size: 11px;
      font-weight: 800;
      letter-spacing: 0.05em;
      margin-block-end: var(--jd-space-2);
      color: var(--jd-fin-muted);
    }
    .jd-theme-drill-down__list {
      list-style: none;
      margin: 0;
      padding: 0;
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
    }

    /* 등장 일자 행 */
    .jd-theme-drill-down__day {
      display: grid;
      grid-template-columns: 70px 1fr auto;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-theme-drill-down__day:nth-child(even) {
      background: var(--jd-fin-soft);
    }
    .jd-theme-drill-down__day:last-child {
      border-block-end: 0;
    }
    .jd-theme-drill-down__date {
      font-size: 12px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-theme-drill-down__chips {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-1);
      min-width: 0;
    }
    .jd-theme-drill-down__chip {
      font-size: 9.5px;
      font-weight: 800;
      padding: 1px var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-theme-drill-down__chip[data-current] {
      background: color-mix(in srgb, var(--jd-fin-accent) 18%, transparent);
      color: var(--jd-fin-accent-strong);
      border-color: color-mix(in srgb, var(--jd-fin-accent) 36%, transparent);
    }
    .jd-theme-drill-down__pct {
      font-size: 12px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-theme-drill-down__pct[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-theme-drill-down__pct[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    /* 왕관 종목 행 */
    .jd-theme-drill-down__leader {
      display: grid;
      grid-template-columns: auto 1fr auto auto;
      align-items: center;
      gap: var(--jd-space-2-5);
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-theme-drill-down__leader:nth-child(even) {
      background: var(--jd-fin-soft);
    }
    .jd-theme-drill-down__leader:last-child {
      border-block-end: 0;
    }
    .jd-theme-drill-down__crown {
      color: var(--jd-fin-warning);
      flex-shrink: 0;
    }
    .jd-theme-drill-down__leader-name {
      font-size: 12.5px;
      font-weight: 800;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-theme-drill-down__leader-count {
      font-size: 10.5px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-theme-drill-down__leader-nums {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      line-height: var(--jd-leading-tight);
    }
    .jd-theme-drill-down__leader-close {
      font-size: 12px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-theme-drill-down__leader-avg {
      font-size: 10.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .jd-theme-drill-down__leader-avg[data-dir="up"] {
      color: var(--jd-fin-up);
    }
    .jd-theme-drill-down__leader-avg[data-dir="down"] {
      color: var(--jd-fin-down);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-theme-drill-down__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-theme-news-summary {
      --jd-fin-up: var(--bm-up, var(--jd-color-success));
      --jd-fin-down: var(--bm-down, var(--jd-color-danger));
      --jd-fin-up-soft: var(
        --bm-up-soft,
        color-mix(in srgb, var(--jd-color-success) 14%, transparent)
      );
      --jd-fin-down-soft: var(
        --bm-down-soft,
        color-mix(in srgb, var(--jd-color-danger) 14%, transparent)
      );
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
      box-shadow: var(--jd-shadow-sm);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-theme-news-summary * {
      box-sizing: border-box;
    }

    /* 스켈레톤 */
    jd-theme-news-summary .jd-theme-news-summary__skeleton {
      padding: var(--jd-space-4);
    }
    jd-theme-news-summary .jd-theme-news-summary__bar {
      height: 12px;
      margin-block-end: var(--jd-space-2);
      border-radius: var(--jd-radius-sm);
      background: linear-gradient(
        90deg,
        var(--jd-fin-soft) 25%,
        color-mix(in srgb, var(--jd-fin-muted) 14%, transparent) 37%,
        var(--jd-fin-soft) 63%
      );
      background-size: 400% 100%;
      animation: jd-tns-shimmer 1.4s ease infinite;
    }
    jd-theme-news-summary .jd-theme-news-summary__bar:first-child {
      height: 16px;
    }
    jd-theme-news-summary .jd-theme-news-summary__bar:last-child {
      margin-block-end: 0;
    }
    @keyframes jd-tns-shimmer {
      0% {
        background-position: 100% 0;
      }
      100% {
        background-position: 0 0;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-theme-news-summary .jd-theme-news-summary__bar {
        animation: none;
      }
    }

    /* 빈 결과 */
    jd-theme-news-summary .jd-theme-news-summary__empty {
      padding: var(--jd-space-4);
      font-size: var(--jd-text-xs);
      color: var(--jd-fin-muted);
    }

    /* 헤더 */
    jd-theme-news-summary .jd-theme-news-summary__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3-5) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-theme-news-summary .jd-theme-news-summary__title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
      min-width: 0;
    }
    jd-theme-news-summary .jd-theme-news-summary__icon {
      color: var(--jd-fin-accent);
      flex-shrink: 0;
    }
    jd-theme-news-summary .jd-theme-news-summary__meta {
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    jd-theme-news-summary .jd-theme-news-summary__tone {
      display: grid;
      place-items: center;
      flex-shrink: 0;
      height: 24px;
      padding: 0 var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: 11px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
      background: var(--jd-fin-soft);
    }
    jd-theme-news-summary .jd-theme-news-summary__tone[data-state="positive"] {
      color: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
      background: var(--jd-fin-up-soft);
    }
    jd-theme-news-summary .jd-theme-news-summary__tone[data-state="negative"] {
      color: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
      background: var(--jd-fin-down-soft);
    }

    /* 문장 목록 */
    jd-theme-news-summary .jd-theme-news-summary__list {
      list-style: none;
      margin: 0;
      counter-reset: jd-tns;
      padding: var(--jd-space-4) var(--jd-space-5);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2-5);
    }
    jd-theme-news-summary .jd-theme-news-summary__item {
      counter-increment: jd-tns;
      position: relative;
      padding-inline-start: 30px;
      font-size: 13.5px;
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-fin-text);
    }
    jd-theme-news-summary .jd-theme-news-summary__item::before {
      content: counter(jd-tns);
      position: absolute;
      inset-inline-start: 0;
      inset-block-start: 1px;
      width: 20px;
      height: 20px;
      border-radius: var(--jd-radius-md);
      display: grid;
      place-items: center;
      font-size: 10.5px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
    }

    /* 키워드 푸터 */
    jd-theme-news-summary .jd-theme-news-summary__terms {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-wrap: wrap;
      padding: var(--jd-space-3) var(--jd-space-5);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-theme-news-summary .jd-theme-news-summary__terms-label {
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
      margin-inline-end: var(--jd-space-1);
    }
    jd-theme-news-summary .jd-theme-news-summary__term-list {
      display: contents;
    }
    jd-theme-news-summary .jd-theme-news-summary__chip {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: 700;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-text);
    }
    jd-theme-news-summary .jd-theme-news-summary__chip-count {
      font-size: 10px;
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      opacity: 0.6;
    }
  }

  @layer junds.components {
    jd-theme-pill-card {
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }
    jd-theme-pill-card * {
      box-sizing: border-box;
    }

    .jd-theme-pill-card {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2-5) var(--jd-space-3);
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
      color: var(--jd-fin-text);
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-theme-pill-card:hover {
      background: var(--jd-fin-soft);
    }

    .jd-theme-pill-card__name {
      min-width: 0;
      font-size: 13px;
      font-weight: var(--jd-weight-bold);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-theme-pill-card__total {
      flex-shrink: 0;
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      background: var(
        --jd-fin-orange-soft,
        color-mix(
          in srgb,
          color-mix(in srgb, var(--jd-color-hue-orange) var(--jd-tone-lift), #ffffff)
            var(--jd-tone-bg-mix),
          transparent
        )
      );
      color: var(
        --jd-fin-orange,
        color-mix(
          in srgb,
          var(--jd-color-hue-orange) var(--jd-tone-ink-mix),
          var(--jd-tone-ink-toward)
        )
      );
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-theme-pill-card {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-theme-tag-list {
      --jd-fin-cat-2: var(--bm-cat-2, var(--jd-color-hue-pink));
      --jd-fin-cat-3: var(--bm-cat-3, var(--jd-color-hue-teal));
      --jd-fin-cat-4: var(--bm-cat-4, var(--jd-color-hue-amber));
      --jd-fin-cat-5: var(--bm-cat-5, var(--jd-color-hue-violet));
      --jd-fin-cat-8: var(--bm-cat-8, var(--jd-color-hue-green));

      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }
    jd-theme-tag-list * {
      box-sizing: border-box;
    }

    .jd-theme-tag-list {
      display: flex;
      flex-wrap: wrap;
      gap: var(--jd-space-1-5);
    }
    /* 회전 색은 칩마다 앵커 한 줄(--_jd-tt-hue)로만 갈리고, 면·글자·호버·눌림은
     전부 그 앵커에서 파생한다 — 상태를 새로 넣을 때 다섯 벌을 고칠 일이 없다. */
    .jd-theme-tag-list__chip {
      --_jd-tt-hue: var(--jd-fin-cat-3); /* data-accent="0" 기본 */
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-0-5);
      padding: var(--jd-space-0-5) var(--jd-space-2);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-thin) solid transparent;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-bold);
      text-decoration: none;
      white-space: nowrap;
      /* 12% 틴트 위 원색 cat 글자는 대비 미달(cat-4 amber ~1.9:1) — 글자를 foreground 쪽으로
       섞어 대비를 올리되 색상(hue)은 유지한다(03-web-arch §4.3, 라이트/다크 양쪽 대응). */
      background: color-mix(in srgb, var(--_jd-tt-hue) 12%, transparent);
      color: color-mix(in srgb, var(--_jd-tt-hue) 65%, var(--jd-color-foreground));
      transition: background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        border-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    .jd-theme-tag-list__chip[data-accent="1"] {
      --_jd-tt-hue: var(--jd-fin-cat-2);
    }
    .jd-theme-tag-list__chip[data-accent="2"] {
      --_jd-tt-hue: var(--jd-fin-cat-4);
    }
    .jd-theme-tag-list__chip[data-accent="3"] {
      --_jd-tt-hue: var(--jd-fin-cat-8);
    }
    .jd-theme-tag-list__chip[data-accent="4"] {
      --_jd-tt-hue: var(--jd-fin-cat-5);
    }
    /* 호버는 실색 전환 — filter: brightness는 글자까지 함께 밝혀 틴트 위 글자가 녹고,
     칩마다 GPU 레이어를 새로 만든다. 틴트를 한 단 올리고 테두리를 드러낸다. */
    .jd-theme-tag-list__chip:hover {
      background: color-mix(in srgb, var(--_jd-tt-hue) 20%, transparent);
      border-color: color-mix(in srgb, var(--_jd-tt-hue) 34%, transparent);
    }
    .jd-theme-tag-list__chip:active {
      scale: 0.97;
      background: color-mix(in srgb, var(--_jd-tt-hue) 28%, transparent);
    }
    .jd-theme-tag-list__chip:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }
    .jd-theme-tag-list__hash {
      opacity: var(--jd-opacity-70);
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-theme-tag-list__chip {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-theme-toggle {
      display: inline-flex;
    }
    .jd-theme-toggle {
      display: inline-grid;
      place-items: center;
      width: 36px;
      height: 36px;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-full);
      background: transparent;
      color: var(--jd-color-muted);
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-theme-toggle:hover {
      background: color-mix(in srgb, var(--jd-color-foreground) 6%, transparent);
      color: var(--jd-color-foreground);
    }
    .jd-theme-toggle:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-theme-toggle > svg {
      display: block;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-theme-toggle {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-thinking-indicator {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
    }

    .jd-thinking-indicator__anim {
      display: inline-flex;
      align-items: center;
    }
    .jd-thinking-indicator__piece {
      display: block;
      flex-shrink: 0;
      background: var(--jd-thinking-color, currentColor);
    }

    /* dots */
    .jd-thinking-indicator__anim[data-variant="dots"] {
      gap: var(--jd-space-1);
    }
    .jd-thinking-indicator__anim[data-variant="dots"] > .jd-thinking-indicator__piece {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      animation: jd-think-bounce 1.4s var(--jd-easing-ease-in-out) infinite;
    }
    .jd-thinking-indicator__anim[data-variant="dots"] > .jd-thinking-indicator__piece:nth-child(2) {
      animation-delay: 0.16s;
    }
    .jd-thinking-indicator__anim[data-variant="dots"] > .jd-thinking-indicator__piece:nth-child(3) {
      animation-delay: 0.32s;
    }

    /* pulse */
    .jd-thinking-indicator__anim[data-variant="pulse"] > .jd-thinking-indicator__piece {
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
      animation: jd-think-pulse 1.4s var(--jd-easing-ease-in-out) infinite;
    }

    /* wave */
    .jd-thinking-indicator__anim[data-variant="wave"] {
      align-items: flex-end;
      gap: var(--jd-space-0-5);
      height: 12px;
    }
    .jd-thinking-indicator__anim[data-variant="wave"] > .jd-thinking-indicator__piece {
      width: 2px;
      height: 100%;
      border-radius: var(--jd-radius-full);
      transform-origin: bottom;
      animation: jd-think-wave 1s var(--jd-easing-ease-in-out) infinite;
    }
    .jd-thinking-indicator__anim[data-variant="wave"] > .jd-thinking-indicator__piece:nth-child(2) {
      animation-delay: 0.1s;
    }
    .jd-thinking-indicator__anim[data-variant="wave"] > .jd-thinking-indicator__piece:nth-child(3) {
      animation-delay: 0.2s;
    }
    .jd-thinking-indicator__anim[data-variant="wave"] > .jd-thinking-indicator__piece:nth-child(4) {
      animation-delay: 0.3s;
    }

    /* typewriter */
    .jd-thinking-indicator__anim[data-variant="typewriter"] > .jd-thinking-indicator__piece {
      width: 2px;
      height: 14px;
      border-radius: var(--jd-radius-sm);
      animation: jd-think-blink 1s steps(2) infinite;
    }

    .jd-thinking-indicator__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @keyframes jd-think-bounce {
      0%,
      80%,
      100% {
        transform: translateY(0);
        opacity: 0.4;
      }
      40% {
        transform: translateY(-3px);
        opacity: 1;
      }
    }
    @keyframes jd-think-pulse {
      0%,
      100% {
        transform: scale(0.8);
        opacity: 0.5;
      }
      50% {
        transform: scale(1.2);
        opacity: 1;
      }
    }
    @keyframes jd-think-wave {
      0%,
      100% {
        transform: scaleY(0.4);
      }
      50% {
        transform: scaleY(1);
      }
    }
    @keyframes jd-think-blink {
      0%,
      100% {
        opacity: 1;
      }
      50% {
        opacity: 0;
      }
    }

    /* 움직임을 끄고 조각만 남긴다 — 대기 상태는 role=status 문장이 이미 말한다 */
    @media (prefers-reduced-motion: reduce) {
      .jd-thinking-indicator__piece {
        animation: none;
        opacity: 0.6;
      }
      .jd-thinking-indicator__anim[data-variant="wave"] > .jd-thinking-indicator__piece {
        transform: scaleY(0.7);
      }
    }
  }

  @layer junds.components {
    
  [data-jd-picker-field] { position: relative; display: inline-flex; }

  /* v2: div.flex.items-center.gap-2.h-9.px-3.border.bg-white.rounded-lg — 진짜 button으로 승격 */
  .jd-picker-field__trigger {
    display: inline-flex; align-items: center; gap: var(--jd-space-2);
    height: 2.25rem; padding-inline: var(--jd-space-3); margin: 0;
    box-sizing: border-box; max-width: 100%;
    font-family: var(--jd-font-sans); font-size: var(--jd-text-md);
    color: var(--jd-color-foreground); text-align: start;
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg); cursor: pointer;
    transition: border-color var(--jd-duration-fast) var(--jd-easing-ease-out),
                box-shadow var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-picker-field__trigger:focus-visible {
    outline: none; border-color: var(--jd-color-primary);
    box-shadow: var(--jd-shadow-focus-ring);
  }
  .jd-picker-field__trigger[aria-expanded="true"] {
    border-color: var(--jd-color-primary); box-shadow: var(--jd-shadow-focus-ring);
  }
  .jd-picker-field__trigger:disabled {
    opacity: var(--jd-opacity-50); cursor: not-allowed;
    background: var(--jd-color-card-hover);
  }
  .jd-picker-field__icon {
    display: inline-flex; flex-shrink: 0; color: var(--jd-color-muted);
  }
  .jd-picker-field__value {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .jd-picker-field__value[data-placeholder] { color: var(--jd-color-muted-light); }

  /* v2는 Portal+fixed라 스크롤하면 패널이 떨어져 나갔다 — absolute로 좌표 동기화를 브라우저에 위임 */
  .jd-picker-field__panel {
    position: absolute; top: calc(100% + var(--jd-space-1));
    inset-inline-start: 0; z-index: var(--jd-z-popover);
    box-sizing: border-box;
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg); box-shadow: var(--jd-shadow-lg);
  }
  .jd-picker-field__panel[hidden] { display: none; }
  [data-jd-picker-field][data-placement="top"] > .jd-picker-field__panel {
    top: auto; bottom: calc(100% + var(--jd-space-1));
  }

  @media (prefers-reduced-motion: no-preference) {
    .jd-picker-field__panel:not([hidden]) {
      animation: jd-picker-field-in var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
  }
  @keyframes jd-picker-field-in { from { opacity: 0; transform: scale(.97); } }


    .jd-time-picker__panel {
      display: flex;
    }

    .jd-time-picker__col {
      width: 4rem;
      height: 12rem;
      overflow-y: auto;
      overscroll-behavior: contain;
      padding-block: var(--jd-space-1);
      box-sizing: border-box;
      scrollbar-width: thin;
    }
    .jd-time-picker__col + .jd-time-picker__col:not([hidden]) {
      border-inline-start: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-time-picker__col[hidden] {
      display: none;
    }
    .jd-time-picker__col:focus-visible {
      outline: none;
    }

    .jd-time-picker__opt {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 2rem;
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      cursor: pointer;
      user-select: none;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-time-picker__opt:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-time-picker__opt[aria-selected="true"] {
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-primary-ink);
      background: var(--jd-color-primary-light);
    }
    /* aria-activedescendant는 실제 포커스를 옮기지 않는다 — 활성 항목 링을 직접 그린다 */
    .jd-time-picker__col:focus-visible .jd-time-picker__opt[data-active] {
      outline: var(--jd-border-medium) solid var(--jd-color-primary);
      outline-offset: calc(-1 * var(--jd-border-medium));
    }

    /* AM/PM 열 — 두 항목이 높이를 반씩(v2 flex-1) */
    .jd-time-picker__col[data-col="period"] {
      display: flex;
      flex-direction: column;
    }
    .jd-time-picker__col[data-col="period"] > .jd-time-picker__opt {
      flex: 1;
      height: auto;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-time-picker__opt {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-timeline {
      display: block;
    }

    .jd-timeline__list {
      display: block;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-timeline__item {
      display: flex;
      gap: var(--jd-space-3);
      padding-block-end: var(--jd-space-6);
      --_jd-timeline-dot: var(--jd-color-muted-light);
      --_jd-timeline-ring: var(--jd-color-border);
    }
    .jd-timeline__item[data-last] {
      padding-block-end: 0;
    }

    .jd-timeline__item[data-color="primary"] {
      --_jd-timeline-dot: var(--jd-color-primary);
      --_jd-timeline-ring: var(--jd-color-primary-light);
    }
    .jd-timeline__item[data-color="success"] {
      --_jd-timeline-dot: var(--jd-color-success);
      --_jd-timeline-ring: var(--jd-color-success-light);
    }
    .jd-timeline__item[data-color="warning"] {
      --_jd-timeline-dot: var(--jd-color-warning);
      --_jd-timeline-ring: var(--jd-color-warning-light);
    }
    .jd-timeline__item[data-color="danger"] {
      --_jd-timeline-dot: var(--jd-color-danger);
      --_jd-timeline-ring: var(--jd-color-danger-light);
    }

    /* ── 마커 열 (점/아이콘 + 연결선) ─────────────────────────────── */
    .jd-timeline__marker {
      display: flex;
      flex-direction: column;
      align-items: center;
      flex-shrink: 0;
      align-self: stretch;
    }

    .jd-timeline__dot {
      box-sizing: border-box;
      flex-shrink: 0;
      inline-size: 0.75rem;
      block-size: 0.75rem;
      margin-block-start: var(--jd-space-1);
      border-radius: var(--jd-radius-full);
      border: var(--jd-border-medium) solid var(--_jd-timeline-ring);
      background: var(--_jd-timeline-dot);
    }
    /* 아이콘이 있으면 v2처럼 32px 원형 배지가 된다 — 링 없이 색면 + 흰 글자 */
    .jd-timeline__dot[data-icon] {
      inline-size: 2rem;
      block-size: 2rem;
      margin-block-start: 0;
      border: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      color: #fff;
    }
    .jd-timeline__dot[data-icon] > svg {
      inline-size: 1rem;
      block-size: 1rem;
    }

    .jd-timeline__line {
      flex: 1 1 auto;
      inline-size: var(--jd-space-px);
      margin-block-start: var(--jd-space-1);
      background: var(--jd-color-border);
    }
    .jd-timeline__item[data-last] .jd-timeline__line {
      display: none;
    }
    jd-timeline[line-style="dashed"] .jd-timeline__line {
      inline-size: 0;
      background: none;
      border-inline-start: var(--jd-border-thin) dashed var(--jd-color-border);
    }

    /* ── 본문 열 ──────────────────────────────────────────────── */
    .jd-timeline__body {
      flex: 1 1 0;
      min-inline-size: 0;
      padding-block-start: var(--jd-space-px);
      font-family: var(--jd-font-sans);
    }
    .jd-timeline__head {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-inline-size: 0;
    }
    .jd-timeline__title {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-timeline__time {
      flex-shrink: 0;
      font-size: 10px;
      color: var(--jd-color-muted-light);
      font-variant-numeric: tabular-nums;
    }
    .jd-timeline__desc {
      margin-block-start: var(--jd-space-0-5);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-muted);
    }
    .jd-timeline__time[hidden],
    .jd-timeline__desc[hidden] {
      display: none;
    }
  }

  @layer junds.components {
    jd-toast {
      position: fixed;
      z-index: var(--jd-z-toast);
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      width: min(22rem, calc(100vw - 2rem));
      pointer-events: none; /* 빈 영역이 아래 UI를 막지 않는다 */
      /* position 기본 top-right */
      inset-block-start: var(--jd-space-6);
      inset-inline-end: var(--jd-space-6);
    }
    jd-toast[position="top-left"] {
      inset-inline-end: auto;
      inset-inline-start: var(--jd-space-6);
    }
    jd-toast[position="bottom-right"] {
      inset-block-start: auto;
      inset-block-end: var(--jd-space-6);
      flex-direction: column-reverse;
    }
    jd-toast[position="bottom-left"] {
      inset-block-start: auto;
      inset-block-end: var(--jd-space-6);
      inset-inline-end: auto;
      inset-inline-start: var(--jd-space-6);
      flex-direction: column-reverse;
    }
    jd-toast[position="top"] {
      inset-inline: 0;
      margin-inline: auto;
    }
    jd-toast[position="bottom"] {
      inset-block-start: auto;
      inset-block-end: var(--jd-space-6);
      inset-inline: 0;
      margin-inline: auto;
      flex-direction: column-reverse;
    }

    /* 변종 색은 **혼합비가 모드를 따라가는** 톤 레시피를 경유한다(DEC-044).
     의미색 앵커(success #2f8f57 등)는 라이트에서 옅은 틴트 위 글자가 AA를 넘도록
     600~700단에 둔 값이라, 다크에서 그 앵커를 5%만 섞으면 카드와 구분이 사라진 어두운
     면이 남는다 — 토스트가 배경에 잠기고 글자만 떠 있는 것처럼 읽혔다(실측).
     다크에서만 앵커를 흰 쪽으로 들어 올린 뒤(face) 섞으면 면이 확실히 위로 뜬다. */
    .jd-toast__item {
      position: relative;
      pointer-events: auto;
      box-sizing: border-box;
      min-width: 0;
      padding: var(--jd-space-3-5) var(--jd-space-8) var(--jd-space-3-5) var(--jd-space-4);
      font-family: var(--jd-font-sans);
      --jd-tone: var(--jd-color-info);
      --jd-tone-face: color-mix(in srgb, var(--jd-tone) var(--jd-tone-lift), #ffffff);
      background: color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-bg-mix), var(--jd-color-card));
      border: var(--jd-border-thin) solid
        color-mix(in srgb, var(--jd-tone-face) var(--jd-tone-border-mix), transparent);
      border-radius: var(--jd-radius-xl);
      /* 떠 있는 것은 lg 이상 + 위에서 받는 빛 */
      box-shadow: var(--jd-shadow-lg), inset 0 1px 0 var(--jd-color-highlight);
      animation: jd-toast-in var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-toast__item[data-variant="success"] {
      --jd-tone: var(--jd-color-success);
    }
    .jd-toast__item[data-variant="warning"] {
      --jd-tone: var(--jd-color-warning);
    }
    .jd-toast__item[data-variant="danger"] {
      --jd-tone: var(--jd-color-danger);
    }

    .jd-toast__title {
      margin: 0;
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      line-height: var(--jd-leading-snug);
      color: var(--jd-color-foreground);
      overflow-wrap: anywhere;
    }
    .jd-toast__desc {
      margin: var(--jd-space-0-5) 0 0;
      font-size: var(--jd-text-sm);
      line-height: var(--jd-leading-normal);
      color: var(--jd-color-muted);
      overflow-wrap: anywhere;
    }
    .jd-toast__close {
      position: absolute;
      inset-block-start: var(--jd-space-2);
      inset-inline-end: var(--jd-space-2);
      width: 1.5rem;
      height: 1.5rem;
      padding: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: none;
      cursor: pointer;
      font-size: var(--jd-text-md);
      line-height: 1;
      color: var(--jd-color-muted);
      border-radius: var(--jd-radius-md);
      transition: color var(--jd-duration-snap) var(--jd-easing-ease-out),
        background-color var(--jd-duration-snap) var(--jd-easing-ease-out),
        scale var(--jd-duration-press) var(--jd-easing-ease-out);
    }
    /* 틴트된 면 위이므로 hover 배경도 카드색이 아니라 잉크에서 뽑는다 —
     card-hover를 얹으면 변종 틴트가 그 자리만 지워진다. */
    .jd-toast__close:hover {
      color: var(--jd-color-foreground);
      background: color-mix(in srgb, var(--jd-color-muted) 14%, transparent);
    }
    .jd-toast__close:active {
      scale: 0.94;
      background: color-mix(in srgb, var(--jd-color-muted) 22%, transparent);
    }
    .jd-toast__close:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    @keyframes jd-toast-in {
      from {
        opacity: 0;
        transform: translateY(-0.5rem);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-toast__item {
        animation: none;
      }
      .jd-toast__close {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-toggle {
      display: inline-flex;
    }

    .jd-toggle {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      cursor: pointer;
      user-select: none;
      font-family: var(--jd-font-sans);
    }
    /* disabled — 반투명은 트랙·썸만, 라벨은 muted 실색 (AA, DEC-027) */
    jd-toggle[disabled] > .jd-toggle {
      cursor: not-allowed;
    }
    jd-toggle[disabled] .jd-toggle__track {
      opacity: var(--jd-opacity-50);
    }
    jd-toggle[disabled] .jd-toggle__text {
      color: var(--jd-color-muted);
    }

    .jd-toggle__track {
      position: relative;
      display: inline-flex;
      flex-shrink: 0;
      border: 0;
      margin: 0;
      padding: 0;
      cursor: inherit;
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-track-strong);
      box-shadow: inset 0 1px 2px var(--jd-color-shade);
      transition: background-color var(--jd-duration-normal) var(--jd-easing-ease-out);
      width: 2.5rem;
      height: 1.375rem; /* md 기본 40×22 */
    }
    jd-toggle[checked] .jd-toggle__track {
      background: var(--jd-color-primary);
      box-shadow: inset 0 1px 0 var(--jd-color-highlight);
    }
    .jd-toggle__track:hover:not(:disabled) {
      background: var(--jd-color-neutral-400);
    }
    jd-toggle[checked] .jd-toggle__track:hover:not(:disabled) {
      background: var(--jd-color-primary-hover);
    }
    .jd-toggle__track:focus-visible {
      outline: var(--jd-focus-ring);
      outline-offset: var(--jd-focus-ring-offset);
    }

    .jd-toggle__thumb {
      position: absolute;
      top: 2px;
      left: 2px;
      width: 1rem;
      height: 1rem; /* md 16px */
      border-radius: var(--jd-radius-full);
      background: var(--jd-color-control-knob);
      box-shadow: var(--jd-shadow-knob);
      transition: transform var(--jd-duration-normal) var(--jd-easing-overshoot);
    }
    jd-toggle[checked] .jd-toggle__thumb {
      transform: translateX(18px);
    }

    jd-toggle[size="sm"] .jd-toggle__track {
      width: 2rem;
      height: 1.125rem;
    } /* 32×18 */
    jd-toggle[size="sm"] .jd-toggle__thumb {
      width: 0.875rem;
      height: 0.875rem;
    } /* 14px */
    jd-toggle[size="sm"][checked] .jd-toggle__thumb {
      transform: translateX(14px);
    }

    .jd-toggle__text {
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
    }
    .jd-toggle__text[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-toggle__track,
      .jd-toggle__thumb {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-tooltip:not(:defined) {
      display: inline-flex;
    }
  }
  @layer junds.components {
    jd-tooltip {
      position: relative;
      display: inline-flex;
    }

    /* 파생 기본값(0,1,1) — 명시 side/align attribute(0,2,0)가 언제나 이긴다 */
    jd-tooltip > .jd-popover__panel {
      --jd-popover-offset: var(--jd-space-2);
      top: auto;
      bottom: 100%;
      left: 50%;
      right: auto;
      margin-block: 0 var(--jd-popover-offset);
      --jd-popover-tx: -50%;

      z-index: var(--jd-z-tooltip);
      padding: var(--jd-space-1-5) var(--jd-space-2-5);
      font-size: var(--jd-text-xs);
      line-height: var(--jd-leading-snug);
      color: #ffffff;
      background: color-mix(in srgb, var(--jd-color-sidebar-bg) 95%, transparent);
      border-color: color-mix(in srgb, var(--jd-color-sidebar-hover) 50%, transparent);
      border-radius: var(--jd-radius-lg);
      box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.25), 0 8px 10px -6px rgba(0, 0, 0, 0.25);
      /* v2는 nowrap 고정이라 긴 설명이 상자 밖으로 삐져나갔다. width:max-content가
       짧은 문구는 여전히 한 줄로 잡아 주므로, 줄바꿈을 허용하고 상한만 좁히면
       "짧으면 한 줄 · 길면 두세 줄"이 된다 — 글자를 줄이는 대신 줄 수를 늘린다(§9). */
      white-space: normal;
      max-width: min(18rem, calc(100vw - 2rem));
      overflow-wrap: anywhere;
      /* 잉크 말풍선이라 꼬리도 잉크색이다 — 기하는 jd-popover 시트가 이미 갖고 있다 */
      --jd-popover-arrow: 5px;
      --jd-popover-arrow-face: color-mix(in srgb, var(--jd-color-sidebar-bg) 95%, transparent);
      /* 말풍선이 포인터를 가로채면 hover가 깜빡인다(v2 동일) */
      pointer-events: none;
    }
    /* 파생 기본값(side=top · align=center)도 attribute로 반영되지 않으므로(§1.3)
     꼬리 기하를 여기서 잡는다 — 명시 [side]/[align] 규칙(0,2,1)이 언제나 이긴다. */
    jd-tooltip > .jd-popover__panel::after {
      top: 100%;
      bottom: auto;
      left: 50%;
      right: auto;
      margin-inline-start: calc(-1 * var(--jd-popover-arrow));
      border-width: var(--jd-popover-arrow);
      border-bottom-width: 0;
      border-bottom-color: transparent;
      border-top-color: var(--jd-popover-arrow-face);
    }
  }

  @layer junds.components {
    jd-top-bar {
      --jd-fin-success: var(--bm-success, var(--jd-color-success));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );

      display: block;
      box-sizing: border-box;
      font-family: var(--jd-font-sans);
    }
    jd-top-bar * {
      box-sizing: border-box;
    }

    header.jd-top-bar {
      background: color-mix(in srgb, var(--jd-color-background) 88%, transparent);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-top-bar:not([static]) header.jd-top-bar {
      position: sticky;
      top: 0;
      z-index: var(--jd-z-header);
    }

    .jd-top-bar__inner {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      max-width: 1600px;
      margin-inline: auto;
    }
    @media (min-width: 1024px) {
      .jd-top-bar__inner {
        padding-inline: var(--jd-space-6);
      }
    }

    .jd-top-bar__brand {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      min-width: 0;
    }
    .jd-top-bar__brand[hidden] {
      display: none;
    }

    .jd-top-bar__search {
      flex: 1;
      min-width: 0;
      max-width: 42rem;
      display: flex;
      align-items: center;
    }
    .jd-top-bar__search[hidden] {
      display: none;
    }

    .jd-top-bar__meta {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-fin-muted);
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }
    .jd-top-bar__meta[hidden] {
      display: none;
    }
    /* v2: 날짜·상태 블록은 md 미만 숨김 */
    @media (max-width: 767px) {
      .jd-top-bar__meta {
        display: none;
      }
    }
    .jd-top-bar__timestamp[hidden] {
      display: none;
    }

    .jd-top-bar__status {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      font-size: 10.5px;
      font-weight: 800;
      padding: 1px var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
    }
    .jd-top-bar__status[hidden] {
      display: none;
    }
    .jd-top-bar__status-dot {
      width: 6px;
      height: 6px;
      border-radius: var(--jd-radius-full);
      background: currentColor;
      flex-shrink: 0;
    }
    /* 장중 알약: 14% 틴트 위 원색 success 글자(10.5px 800)는 대비 미달 — hue 유지하며
     글자를 foreground 쪽으로 섞어 대비 확보(03-web-arch §4.3). 점은 currentColor 상속. */
    .jd-top-bar__status[data-status="open"] {
      background: color-mix(in srgb, var(--jd-fin-success) 14%, transparent);
      color: color-mix(in srgb, var(--jd-fin-success) 65%, var(--jd-color-foreground));
    }
    @media (prefers-reduced-motion: no-preference) {
      .jd-top-bar__status[data-status="open"] .jd-top-bar__status-dot {
        animation: jd-top-bar-pulse 1.8s var(--jd-easing-ease-in-out) infinite;
      }
    }
    @keyframes jd-top-bar-pulse {
      50% {
        opacity: 0.35;
      }
    }

    .jd-top-bar__actions {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      flex-shrink: 0;
      margin-inline-start: auto;
    }
  }

  @layer junds.base {
    jd-tour:not(:defined) {
      display: none;
    }
  }
  @layer junds.components {
    jd-tour {
      display: none;
    }
    jd-tour[open] {
      display: block;
      position: fixed;
      inset: 0;
      z-index: var(--jd-z-max);
      font-family: var(--jd-font-sans);
    }

    .jd-tour__canvas {
      position: absolute;
      inset: 0;
      display: block;
      width: 100%;
      height: 100%;
    }

    .jd-tour__popover {
      box-sizing: border-box; /* width + padding + border — 배치 좌표가 실폭과 어긋나지 않게 */
      position: absolute;
      width: 18rem;
      max-width: calc(100vw - 2rem);
      background: var(--jd-color-card);
      color: var(--jd-color-foreground);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-xl);
      padding: var(--jd-space-4);
    }

    .jd-tour__title {
      margin: 0 0 var(--jd-space-1);
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-tour__desc {
      margin: 0 0 var(--jd-space-4);
      font-size: var(--jd-text-sm);
      color: var(--jd-color-muted);
      line-height: var(--jd-leading-relaxed);
    }
    .jd-tour__desc[hidden] {
      display: none;
    }

    .jd-tour__footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
    }
    .jd-tour__counter {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      font-variant-numeric: tabular-nums;
    }
    .jd-tour__actions {
      display: flex;
      gap: var(--jd-space-2);
    }

    .jd-tour__btn {
      padding: var(--jd-space-1) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      border-radius: var(--jd-radius-md);
      border: var(--jd-border-thin) solid transparent;
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out),
        color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-tour__btn[hidden] {
      display: none;
    }
    .jd-tour__btn:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-tour__btn--primary {
      background: var(--jd-color-primary);
      color: #fff;
    }
    .jd-tour__btn--primary:hover {
      background: color-mix(in srgb, var(--jd-color-primary) 90%, black);
    }
    .jd-tour__btn--ghost {
      background: transparent;
      border-color: var(--jd-color-border);
      color: var(--jd-color-foreground);
    }
    .jd-tour__btn--ghost:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-tour__btn--muted {
      background: transparent;
      color: var(--jd-color-muted);
    }
    .jd-tour__btn--muted:hover {
      color: var(--jd-color-foreground);
    }

    @media (prefers-reduced-motion: no-preference) {
      jd-tour[open] > .jd-tour__canvas {
        animation: jd-tour-fade var(--jd-duration-normal) var(--jd-easing-ease-out);
      }
      jd-tour[open] > .jd-tour__popover {
        animation: jd-tour-pop var(--jd-duration-normal) var(--jd-easing-default);
      }
    }
    @keyframes jd-tour-fade {
      from {
        opacity: 0;
      }
    }
    @keyframes jd-tour-pop {
      from {
        opacity: 0;
      }
    }
  }

  @layer junds.components {
    jd-trade-journal {
      --jd-fin-up: var(--bm-up, var(--jd-color-success));
      --jd-fin-down: var(--bm-down, var(--jd-color-danger));
      --jd-fin-up-soft: var(
        --bm-up-soft,
        color-mix(in srgb, var(--jd-color-success) 14%, transparent)
      );
      --jd-fin-down-soft: var(
        --bm-down-soft,
        color-mix(in srgb, var(--jd-color-danger) 14%, transparent)
      );
      --jd-fin-accent: var(--bm-accent-strong, var(--jd-color-primary));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-warning: var(--bm-warning, var(--jd-color-warning));

      display: block;
      box-sizing: border-box;
      /* 폼 4칸·스탯 4칸을 펼칠지는 뷰포트가 아니라 **이 카드가 실제로 받은 폭**이 정한다.
       뷰포트 미디어쿼리는 넓은 화면의 좁은 칼럼 안에서도 1fr 120 140 140을 그대로 깔아,
       카드의 overflow:hidden이 마지막 칸(단가)을 잘라 먹었다(실측 · §6). */
      /* inline-size 컨테이너는 내용이 폭을 정하지 못한다 — 부모가 준 폭을 명시적으로
       받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 카드가 통째로 사라진다. */
      width: 100%;
      container: jd-tj / inline-size;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-2xl);
      overflow: hidden;
      box-shadow: var(--jd-shadow-sm);
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
    }
    jd-trade-journal * {
      box-sizing: border-box;
    }

    jd-trade-journal .jd-trade-journal__skeleton {
      height: 128px;
      margin: var(--jd-space-5);
      border-radius: var(--jd-radius-lg);
      background: linear-gradient(
        90deg,
        var(--jd-fin-soft) 25%,
        color-mix(in srgb, var(--jd-fin-muted) 14%, transparent) 37%,
        var(--jd-fin-soft) 63%
      );
      background-size: 400% 100%;
      animation: jd-tj-shimmer 1.4s ease infinite;
    }
    @keyframes jd-tj-shimmer {
      0% {
        background-position: 100% 0;
      }
      100% {
        background-position: 0 0;
      }
    }
    @media (prefers-reduced-motion: reduce) {
      jd-trade-journal .jd-trade-journal__skeleton {
        animation: none;
      }
    }

    /* 헤더 */
    jd-trade-journal .jd-trade-journal__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3-5) var(--jd-space-5);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-trade-journal .jd-trade-journal__title {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
      font-size: var(--jd-text-sm);
      font-weight: 800;
      letter-spacing: var(--jd-tracking-tight);
    }
    jd-trade-journal .jd-trade-journal__icon {
      color: var(--jd-fin-accent);
    }
    jd-trade-journal .jd-trade-journal__toggle {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-1);
      height: 28px;
      padding: 0 var(--jd-space-3);
      border-radius: var(--jd-radius-full);
      font: inherit;
      font-size: var(--jd-text-xs);
      font-weight: 800;
      cursor: pointer;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-text);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      transition: background var(--jd-duration-fast) var(--jd-easing-default);
    }
    jd-trade-journal .jd-trade-journal__toggle[data-active="true"] {
      background: var(--jd-fin-accent);
      color: #fff;
      border-color: var(--jd-fin-accent);
    }
    jd-trade-journal .jd-trade-journal__toggle:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 스탯 바 */
    jd-trade-journal .jd-trade-journal__stats {
      display: grid;
      /* 1fr의 자동 최소 폭은 내용이다 — minmax(0,1fr)이라야 긴 수치가 트랙을 밀어
       칸을 넘기지 않는다(§6) */
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--jd-border-thin);
      background: var(--jd-fin-border);
    }
    jd-trade-journal .jd-trade-journal__stat {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-1);
      padding: var(--jd-space-3) var(--jd-space-4);
      background: var(--jd-fin-card);
    }
    jd-trade-journal .jd-trade-journal__stat-label {
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: var(--jd-tracking-wide);
      text-transform: uppercase;
      color: var(--jd-fin-muted);
    }
    jd-trade-journal .jd-trade-journal__stat-value {
      font-size: var(--jd-text-lg);
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-text);
    }
    jd-trade-journal .jd-trade-journal__stat-value[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-trade-journal .jd-trade-journal__stat-value[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    @container jd-tj (min-width: 34rem) {
      jd-trade-journal .jd-trade-journal__stats {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }

    /* 폼 */
    jd-trade-journal .jd-trade-journal__form {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-3);
      padding: var(--jd-space-4);
      background: var(--jd-fin-soft);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-trade-journal .jd-trade-journal__form-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--jd-space-2);
    }
    /* 네 칸(종목명 + 120 + 140 + 140)과 간격·좌우 패딩을 더하면 38rem이 바닥이다 —
     그보다 좁으면 위의 1열이 유지된다. 고정 칸도 minmax(0,·)로 바닥을 풀어,
     경계 근처에서 칸이 서로를 밀어내는 대신 함께 줄어들게 한다. */
    @container jd-tj (min-width: 38rem) {
      jd-trade-journal .jd-trade-journal__form-grid {
        grid-template-columns: minmax(0, 1fr) minmax(0, 120px) minmax(0, 140px) minmax(0, 140px);
      }
    }
    jd-trade-journal .jd-trade-journal__input {
      height: 40px;
      padding: 0 var(--jd-space-3);
      width: 100%;
      /* input의 자동 최소 폭은 size 속성이 만드는 내재 폭이다 — 격자 칸이 그 바닥에
       걸려 못 줄어들면서 폼 행 전체가 카드를 넘었다(§5) */
      min-width: 0;
      border-radius: var(--jd-radius-lg);
      font: inherit;
      font-size: var(--jd-text-sm);
      font-weight: 700;
      color: var(--jd-fin-text);
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      outline: none;
    }
    jd-trade-journal .jd-trade-journal__input:focus-visible {
      border-color: var(--jd-fin-accent);
      box-shadow: var(--jd-shadow-focus-ring);
    }
    jd-trade-journal .jd-trade-journal__num {
      font-variant-numeric: tabular-nums;
    }
    jd-trade-journal .jd-trade-journal__note {
      font-weight: var(--jd-weight-normal);
    }

    jd-trade-journal .jd-trade-journal__name-field {
      position: relative;
    }
    jd-trade-journal .jd-trade-journal__suggest {
      position: absolute;
      z-index: var(--jd-z-dropdown);
      inset-inline: 0;
      inset-block-start: calc(100% + var(--jd-space-1));
      list-style: none;
      margin: 0;
      padding: 0;
      max-height: 192px;
      overflow-y: auto;
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-lg);
      box-shadow: var(--jd-shadow-lg);
      overflow-x: hidden;
    }
    jd-trade-journal .jd-trade-journal__suggest-item {
      display: block;
      width: 100%;
      text-align: start;
      cursor: pointer;
      padding: var(--jd-space-2) var(--jd-space-3);
      font: inherit;
      font-size: var(--jd-text-sm);
      font-weight: 700;
      color: var(--jd-fin-text);
      background: none;
      border: 0;
    }
    jd-trade-journal .jd-trade-journal__suggest-item:hover,
    jd-trade-journal .jd-trade-journal__suggest-item:focus-visible {
      background: var(--jd-fin-soft);
      outline: none;
    }
    jd-trade-journal .jd-trade-journal__suggest-sector {
      margin-inline-start: var(--jd-space-2);
      font-size: 11px;
      font-weight: 400;
      color: var(--jd-fin-muted);
    }

    jd-trade-journal .jd-trade-journal__form-actions {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: var(--jd-space-2);
    }
    jd-trade-journal .jd-trade-journal__btn {
      height: 36px;
      padding: 0 var(--jd-space-4);
      border-radius: var(--jd-radius-full);
      font: inherit;
      font-size: var(--jd-text-xs);
      font-weight: 800;
      cursor: pointer;
    }
    jd-trade-journal .jd-trade-journal__btn--ghost {
      background: var(--jd-fin-card);
      color: var(--jd-fin-text);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-trade-journal .jd-trade-journal__btn--primary {
      background: var(--jd-fin-accent);
      color: #fff;
      border: 0;
    }
    jd-trade-journal .jd-trade-journal__btn--primary:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
    jd-trade-journal .jd-trade-journal__btn:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    /* 빈 상태 */
    jd-trade-journal .jd-trade-journal__empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-12) var(--jd-space-6);
    }
    jd-trade-journal .jd-trade-journal__empty-icon {
      color: var(--jd-fin-muted);
      margin-block-end: var(--jd-space-1);
    }
    jd-trade-journal .jd-trade-journal__empty-title {
      font-size: var(--jd-text-md);
      font-weight: 800;
    }
    jd-trade-journal .jd-trade-journal__empty-desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-fin-muted);
      max-width: 34ch;
    }

    /* 목록 */
    jd-trade-journal .jd-trade-journal__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    jd-trade-journal .jd-trade-journal__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-trade-journal .jd-trade-journal__list > .jd-trade-journal__row:first-child {
      border-block-start: none;
    }
    jd-trade-journal .jd-trade-journal__side {
      display: grid;
      place-items: center;
      flex-shrink: 0;
      height: 24px;
      padding: 0 var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      font-size: 10.5px;
      font-weight: 800;
    }
    jd-trade-journal .jd-trade-journal__side[data-side="buy"] {
      color: color-mix(in srgb, var(--jd-fin-up) 65%, var(--jd-color-foreground));
      background: var(--jd-fin-up-soft);
    }
    jd-trade-journal .jd-trade-journal__side[data-side="sell"] {
      color: color-mix(in srgb, var(--jd-fin-down) 65%, var(--jd-color-foreground));
      background: var(--jd-fin-down-soft);
    }

    jd-trade-journal .jd-trade-journal__row-main {
      min-width: 0;
      flex: 1;
    }
    jd-trade-journal .jd-trade-journal__row-top {
      display: flex;
      align-items: baseline;
      gap: var(--jd-space-2);
    }
    jd-trade-journal .jd-trade-journal__row-name {
      font-weight: 800;
      font-size: 13.5px;
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    jd-trade-journal .jd-trade-journal__row-spec {
      font-size: 11px;
      font-variant-numeric: tabular-nums;
      color: var(--jd-fin-muted);
      white-space: nowrap;
    }
    jd-trade-journal .jd-trade-journal__row-meta {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      margin-block-start: 2px;
      font-size: 11px;
      color: var(--jd-fin-muted);
      min-width: 0;
    }
    jd-trade-journal .jd-trade-journal__row-date {
      font-variant-numeric: tabular-nums;
      flex-shrink: 0;
    }
    jd-trade-journal .jd-trade-journal__row-note {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    jd-trade-journal .jd-trade-journal__review {
      text-align: end;
      flex-shrink: 0;
    }
    jd-trade-journal .jd-trade-journal__pct {
      display: block;
      font-weight: 800;
      font-size: 13px;
      font-variant-numeric: tabular-nums;
    }
    jd-trade-journal .jd-trade-journal__pct[data-tone="up"] {
      color: var(--jd-fin-up);
    }
    jd-trade-journal .jd-trade-journal__pct[data-tone="down"] {
      color: var(--jd-fin-down);
    }
    jd-trade-journal .jd-trade-journal__class {
      display: block;
      font-size: 10.5px;
      font-weight: 800;
      margin-block-start: 2px;
      color: var(--jd-fin-muted);
    }
    jd-trade-journal .jd-trade-journal__class[data-class="수익실현"] {
      color: var(--jd-fin-up);
    }
    jd-trade-journal .jd-trade-journal__class[data-class="손절"] {
      color: var(--jd-fin-down);
    }
    jd-trade-journal .jd-trade-journal__class[data-class="추격매수"] {
      color: color-mix(
        in srgb,
        var(--jd-color-hue-purple) var(--jd-tone-ink-mix),
        var(--jd-tone-ink-toward)
      );
    }
    jd-trade-journal .jd-trade-journal__class[data-class="물타기"] {
      color: var(--jd-fin-warning);
    }

    jd-trade-journal .jd-trade-journal__delete {
      display: grid;
      place-items: center;
      flex-shrink: 0;
      width: 28px;
      height: 28px;
      border-radius: var(--jd-radius-full);
      background: none;
      border: 0;
      cursor: pointer;
      color: var(--jd-fin-muted);
      transition: background var(--jd-duration-fast) var(--jd-easing-default);
    }
    jd-trade-journal .jd-trade-journal__delete:hover {
      background: var(--jd-fin-soft);
    }
    jd-trade-journal .jd-trade-journal__delete:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
  }

  @layer junds.components {
    jd-transfer {
      display: flex;
      /* 접기는 flex-direction이 아니라 wrap + 자식 basis로 낸다 — 컨테이너 질의는
       **조상** 컨테이너만 볼 수 있어 호스트가 자기 질의로 자신을 바꿀 수 없다.
       자식(패널·버튼 열)은 호스트를 컨테이너로 보므로 basis만 100%로 올리면 접힌다. */
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-3);
      box-sizing: border-box;
      /* 두 패널이 세로로 접히는 기준은 뷰포트가 아니라 **이 컴포넌트가 실제로 받은 폭**이다.
       뷰포트 미디어쿼리는 넓은 화면의 좁은 칼럼(문서 카드·사이드바) 안에서 가로 배치를
       고집해, 180px 하한 두 개 + 버튼 열이 칸을 넘고 오른쪽 패널이 잘린 채 끝났다(§6). */
      /* inline-size 컨테이너는 내용이 폭을 정하지 못한다 — 부모가 준 폭을 명시적으로
       받지 않으면 flex·inline 문맥에서 호스트가 0으로 접혀 통째로 사라진다(실측). */
      width: 100%;
      container: jd-transfer / inline-size;
      font-family: var(--jd-font-sans);
    }
    jd-transfer * {
      box-sizing: border-box;
    }

    .jd-transfer__panel {
      display: flex;
      flex-direction: column;
      /* basis 0 — 두 패널이 남은 폭을 정확히 반씩 나눈다. flex:1의 min-width:auto는
       목록 항목의 최소 폭을 바닥으로 삼아 패널을 못 줄이게 했다. */
      flex: 1 1 0;
      min-width: 0;
      overflow: hidden;
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-lg);
    }

    .jd-transfer__head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-2) var(--jd-space-3);
      background: var(--jd-color-card-hover);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-transfer__title {
      font-size: var(--jd-text-md);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-transfer__count {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }

    .jd-transfer__search {
      padding: var(--jd-space-2) var(--jd-space-3);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border);
    }
    .jd-transfer__search[hidden] {
      display: none;
    }
    .jd-transfer__search-input {
      width: 100%;
      box-sizing: border-box;
      margin: 0;
      padding: var(--jd-space-1) var(--jd-space-2);
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
    }
    .jd-transfer__search-input:focus {
      outline: none;
      border-color: var(--jd-color-primary);
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--jd-color-primary) 30%, transparent);
    }
    .jd-transfer__search-input::placeholder {
      color: var(--jd-color-muted-light);
    }

    .jd-transfer__list {
      max-height: 15rem;
      overflow-y: auto;
    }

    .jd-transfer__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: var(--jd-space-1-5) var(--jd-space-3);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-transfer__item:hover {
      background: var(--jd-color-card-hover);
    }
    .jd-transfer__item[data-disabled] {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-transfer__item[data-disabled]:hover {
      background: none;
    }

    .jd-transfer__check {
      margin: 0;
      flex-shrink: 0;
      cursor: inherit;
      width: 1rem;
      height: 1rem;
      accent-color: var(--jd-color-primary);
    }
    .jd-transfer__check:focus-visible {
      outline: var(--jd-border-medium) solid
        color-mix(in srgb, var(--jd-color-primary) 40%, transparent);
      outline-offset: 1px;
    }
    .jd-transfer__item-label {
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-transfer__empty {
      margin: 0;
      padding: var(--jd-space-4) var(--jd-space-3);
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
      text-align: center;
    }
    .jd-transfer__empty[hidden] {
      display: none;
    }

    .jd-transfer__actions {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-2);
      flex-shrink: 0;
    }
    .jd-transfer__move {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-1-5);
      color: var(--jd-color-foreground);
      background: var(--jd-color-card);
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      transition: background var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-transfer__move:hover:not(:disabled) {
      background: var(--jd-color-border-light);
    }
    .jd-transfer__move:disabled {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }
    .jd-transfer__move:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-transfer__move > svg {
      width: 1rem;
      height: 1rem;
    }

    /* 40rem 미만이면 나란히 세울 수 없다 — 패널 둘과 버튼 열이 칸을 넘기 전에 접는다.
     basis 100%는 각 자식을 자기 줄로 밀어낸다(DOM 순서가 이미 원본→버튼→대상). */
    @container jd-transfer (max-width: 40rem) {
      .jd-transfer__panel,
      .jd-transfer__actions {
        flex-basis: 100%;
      }
      .jd-transfer__actions {
        flex-direction: row;
        justify-content: center;
      }
      /* 세로 배치에서는 화살표도 세로로 — →는 아래, ←는 위를 가리킨다 */
      .jd-transfer__move > svg {
        transform: rotate(90deg);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-transfer__item,
      .jd-transfer__move {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-tree-nav {
      display: block;
      inline-size: 100%;
      padding-block: 0;
    }

    jd-tree-nav .jd-tree-view__row {
      color: var(--jd-color-muted);
    }

    jd-tree-nav .jd-tree-view__item[aria-selected="true"] > .jd-tree-view__row {
      background: color-mix(in srgb, var(--jd-color-muted) 12%, transparent);
      color: var(--jd-color-foreground);
      font-weight: var(--jd-weight-medium);
    }
  }

  @layer junds.components {
    jd-tree-view {
      display: block;
      padding-block: var(--jd-space-1);
    }

    .jd-tree-view__tree,
    .jd-tree-view__group {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-0-5);
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .jd-tree-view__group[hidden] {
      display: none;
    }

    .jd-tree-view__item {
      display: block;
      outline: none;
    }

    .jd-tree-view__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-1-5);
      /* v2: paddingLeft = depth*16 + 8 */
      padding-block: var(--jd-space-1);
      padding-inline: calc(var(--jd-tree-depth, 0) * 1rem + var(--jd-space-2)) var(--jd-space-2);
      border-radius: var(--jd-radius-md);
      cursor: pointer;
      font-family: var(--jd-font-sans);
      font-size: var(--jd-text-md);
      color: var(--jd-color-foreground);
      transition: background var(--jd-duration-normal) var(--jd-easing-ease-out),
        color var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-tree-view__row:hover {
      background: color-mix(in srgb, var(--jd-color-muted) 10%, transparent);
    }
    .jd-tree-view__item:focus-visible > .jd-tree-view__row {
      box-shadow: var(--jd-shadow-focus-ring);
    }
    .jd-tree-view__item[aria-selected="true"] > .jd-tree-view__row {
      background: var(--jd-color-primary-light);
      color: var(--jd-color-primary-ink);
      font-weight: var(--jd-weight-medium);
    }
    .jd-tree-view__item[aria-disabled="true"] > .jd-tree-view__row {
      opacity: var(--jd-opacity-40);
      cursor: not-allowed;
    }

    /* 잎 노드에서는 비어 있는 채 자리만 지킨다 (v2의 w-4 스페이서) */
    .jd-tree-view__chevron {
      display: inline-flex;
      flex-shrink: 0;
      align-items: center;
      justify-content: center;
      inline-size: 1rem;
      block-size: 1rem;
      color: var(--jd-color-muted);
      transition: rotate var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    .jd-tree-view__chevron > svg {
      inline-size: 1rem;
      block-size: 1rem;
    }
    .jd-tree-view__item[aria-expanded="true"] > .jd-tree-view__row > .jd-tree-view__chevron {
      rotate: 90deg;
    }

    .jd-tree-view__icon {
      display: inline-flex;
      flex-shrink: 0;
    }
    .jd-tree-view__icon[hidden] {
      display: none;
    }
    .jd-tree-view__icon > svg {
      inline-size: 1rem;
      block-size: 1rem;
    }

    .jd-tree-view__label {
      flex: 1 1 auto;
      min-inline-size: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .jd-tree-view__badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-inline-start: auto;
      flex-shrink: 0;
      min-inline-size: 1.25rem;
      block-size: 1.25rem;
      padding-inline: var(--jd-space-1-5);
      border-radius: var(--jd-radius-full);
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-medium);
      background: var(--jd-color-border);
      color: var(--jd-color-muted);
    }
    .jd-tree-view__badge[hidden] {
      display: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .jd-tree-view__row,
      .jd-tree-view__chevron {
        transition: none;
      }
    }
  }

  @layer junds.base {
    jd-treemap-chart:not(:defined) {
      display: inline-block;
    }
  }
  @layer junds.components {
    jd-treemap-chart {
      display: inline-block;
      line-height: 0;
      font-family: var(--jd-font-sans);
      /* 타일 색은 **범주**다. v2 승계 팔레트는 info/success/warning/danger를 순서대로
       썼는데, 그러면 네 번째 타일이 "위험"이라고 말한다 — 데이터에는 없는 뜻이고,
       보라·파랑·초록·주황이 한 그림 안에서 서로 싸운다. 계열색은 hue 램프에서만 뽑고
       (§8), 슬롯으로 노출해 소비자가 한 줄로 갈아끼울 수 있게 둔다(CHART_CSS 관용구).
       이웃한 두 슬롯이 색상축에서 멀어지도록 순서를 짰고 0번은 강조(브랜드)를 지킨다. */
      --jd-treemap-1: var(--jd-color-primary);
      --jd-treemap-2: var(--jd-color-hue-teal);
      --jd-treemap-3: var(--jd-color-hue-amber);
      --jd-treemap-4: var(--jd-color-hue-rose);
      --jd-treemap-5: var(--jd-color-hue-blue);
      --jd-treemap-6: var(--jd-color-hue-violet);
    }

    /* 400×250 고정 폭은 좁은 카드에서 오른쪽 타일을 잘라 냈다 — viewBox가 비율을 말하므로
     폭만 양보하면 그림 전체가 줄어든다(§6) */
    .jd-treemap-chart__svg {
      display: block;
      max-width: 100%;
      height: auto;
    }

    .jd-treemap-chart__rect {
      fill: var(--jd-treemap-chart-fill, var(--jd-color-primary));
      stroke: var(--jd-color-background);
      stroke-width: 2;
      opacity: 0.85; /* v2 값 — 토큰 사다리에 85가 없어 리터럴 유지 */
    }

    /**
   * v2는 타일 위 글자를 항상 흰색으로 박았다. 타일 색은 소비자가 넘기는 값이라
   * (밝은 색을 주면) 글자가 배경에 묻는다 — 게다가 타일 자체가 opacity .85라 대비가
   * 한 번 더 깎인다. 색을 바꾸면 데이터 색을 왜곡하므로, 글자에만 어두운 외곽선을
   * 깔아 어떤 타일 위에서도 읽히게 한다(paint-order로 획을 글자 뒤에 그린다).
   */
    .jd-treemap-chart__label,
    .jd-treemap-chart__value {
      fill: #fff; /* v2 승계 — 채도 높은 타일 위 텍스트 */
      paint-order: stroke;
      stroke: color-mix(
        in srgb,
        var(--jd-tone-ink-toward) 35%,
        transparent
      ); /* 타일 경계 — 모드마다 반대 방향 (DEC-044) */
      stroke-width: 2px;
      stroke-linejoin: round;
      pointer-events: none;
    }
    .jd-treemap-chart__label {
      font-size: 11px;
      font-weight: var(--jd-weight-semibold);
    }
    .jd-treemap-chart__value {
      font-size: 9px;
      opacity: var(--jd-opacity-80);
      font-variant-numeric: tabular-nums;
    }
    .jd-treemap-chart__label[hidden],
    .jd-treemap-chart__value[hidden] {
      display: none;
    }

    /* 그림의 텍스트 등가물 — 시각적으로만 숨긴다 (jd-comparison-grid 관용구) */
    .jd-treemap-chart__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-trust-indicator {
      display: block;
      box-sizing: border-box;
      overflow: hidden;
      border: var(--jd-border-thin) solid var(--jd-color-border);
      border-radius: var(--jd-radius-xl);
      background: var(--jd-color-card);
      font-family: var(--jd-font-sans);
    }

    .jd-trust-indicator__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-3);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-color-border-light);
      background: var(--jd-color-card-hover);
    }
    .jd-trust-indicator__header[hidden] {
      display: none;
    }
    .jd-trust-indicator__title {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-color-foreground);
    }
    .jd-trust-indicator__score-box {
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }
    .jd-trust-indicator__score {
      font-size: var(--jd-text-lg);
      font-weight: var(--jd-weight-bold);
      font-variant-numeric: tabular-nums;
      color: var(--_jd-trust-score, var(--jd-color-danger));
    }
    .jd-trust-indicator__count {
      font-size: 10px;
      color: var(--jd-color-muted);
    }
    jd-trust-indicator[data-score="high"] {
      --_jd-trust-score: var(--jd-color-success);
    }
    jd-trust-indicator[data-score="mid"] {
      --_jd-trust-score: var(--jd-color-warning);
    }

    .jd-trust-indicator__list {
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .jd-trust-indicator__item {
      display: flex;
      align-items: center;
      gap: var(--jd-space-3);
      padding: var(--jd-space-2-5) var(--jd-space-4);
      /* v2 divide-y — 첫 행 위에는 선이 없다 */
      --_jd-trust-color: var(--jd-color-muted);
      --_jd-trust-tint: var(--jd-color-neutral-100);
    }
    .jd-trust-indicator__item + .jd-trust-indicator__item {
      border-block-start: var(--jd-border-thin) solid var(--jd-color-border-light);
    }
    .jd-trust-indicator__item[data-status="pass"] {
      --_jd-trust-color: var(--jd-color-success);
      --_jd-trust-tint: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-success) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
    }
    .jd-trust-indicator__item[data-status="fail"] {
      --_jd-trust-color: var(--jd-color-danger);
      --_jd-trust-tint: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-danger) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
    }
    .jd-trust-indicator__item[data-status="warning"] {
      --_jd-trust-color: var(--jd-color-warning);
      --_jd-trust-tint: color-mix(
        in srgb,
        color-mix(in srgb, var(--jd-color-warning) var(--jd-tone-lift), #ffffff)
          var(--jd-tone-bg-mix),
        transparent
      );
    }

    .jd-trust-indicator__icon {
      display: inline-flex;
      flex-shrink: 0;
      width: 16px;
      height: 16px;
      color: var(--_jd-trust-color);
    }
    .jd-trust-indicator__icon > svg {
      width: 100%;
      height: 100%;
    }
    .jd-trust-indicator__icon circle {
      fill: var(--_jd-trust-tint);
      stroke: currentColor;
      stroke-width: 1;
    }
    .jd-trust-indicator__icon path {
      fill: none;
      stroke: currentColor;
      stroke-width: 1.5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .jd-trust-indicator__body {
      display: flex;
      flex-direction: column;
      flex: 1 1 auto;
      min-width: 0;
    }
    .jd-trust-indicator__label {
      font-size: var(--jd-text-sm);
      font-weight: var(--jd-weight-medium);
      color: var(--jd-color-foreground);
    }
    .jd-trust-indicator__desc {
      font-size: var(--jd-text-xs);
      color: var(--jd-color-muted);
    }
    .jd-trust-indicator__desc[hidden] {
      display: none;
    }

    .jd-trust-indicator__status {
      flex-shrink: 0;
      font-size: 10px;
      font-weight: var(--jd-weight-semibold);
      text-transform: uppercase;
      color: var(--_jd-trust-color);
    }

    .jd-trust-indicator__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    jd-typewriter {
      display: inline;
    }

    .jd-typewriter__typed {
      white-space: pre-wrap;
    }

    .jd-typewriter__cursor {
      margin-inline-start: 0.125rem; /* v2 ml-0.5 */
      color: var(--jd-color-primary-ink);
      animation: jd-typewriter-blink 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
    }
    .jd-typewriter__cursor[hidden] {
      display: none;
    }

    /* 낭독 전용 완성형 — jd-visually-hidden 관용구 */
    .jd-typewriter__sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    @keyframes jd-typewriter-blink {
      0%,
      100% {
        opacity: 1;
      }
      50% {
        opacity: 0.5;
      }
    }

    /* 감속 선호에서는 타이핑 자체가 멎는다(element가 완성형을 칠한다) — 커서도 정지 */
    @media (prefers-reduced-motion: reduce) {
      .jd-typewriter__cursor {
        animation: none;
      }
    }
  }

  @layer junds.components {
    jd-video-player {
      display: block;
      position: relative;
      box-sizing: border-box;
      padding: 0;
      border: 0;
      border-radius: var(--jd-radius-xl);
      overflow: hidden;
      background: #000;
      --_jd-audio-track: rgba(255, 255, 255, 0.3); /* v2 bg-white/30 */
    }

    jd-video-player > .jd-audio-player__media {
      display: block;
      width: 100%;
      height: auto;
      cursor: pointer;
    }

    jd-video-player > .jd-audio-player__controls {
      position: absolute;
      inset-inline: 0;
      inset-block-end: 0;
      flex-wrap: wrap;
      gap: var(--jd-space-2) var(--jd-space-3);
      padding: var(--jd-space-3);
      background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
      opacity: var(--jd-opacity-0);
      transition: opacity var(--jd-duration-normal) var(--jd-easing-ease-out);
    }
    jd-video-player:hover > .jd-audio-player__controls,
    jd-video-player:focus-within > .jd-audio-player__controls {
      opacity: var(--jd-opacity-100);
    }
    /* 호버가 없는 기기에서 v2는 컨트롤에 영영 닿을 수 없었다 — 상시 노출로 교정 */
    @media (hover: none) {
      jd-video-player > .jd-audio-player__controls {
        opacity: var(--jd-opacity-100);
      }
    }

    /* 시크·시간 줄을 위로(원형은 세로 스택이 오른쪽에 붙는 구조) */
    jd-video-player .jd-audio-player__body {
      order: -1;
      flex: 1 0 100%;
    }
    jd-video-player .jd-audio-player__title {
      color: #fff;
    }
    jd-video-player .jd-audio-player__time {
      font-size: var(--jd-text-xs);
      color: rgba(255, 255, 255, 0.8);
    }

    /* 재생 토글은 영상 위에서 투명 버튼(v2 text-white) */
    jd-video-player .jd-audio-player__toggle {
      width: auto;
      height: auto;
      padding: var(--jd-space-1);
      border-radius: var(--jd-radius-md);
      background: transparent;
      color: #fff;
    }
    jd-video-player .jd-audio-player__toggle:hover {
      background: rgba(255, 255, 255, 0.15);
    }
    jd-video-player .jd-audio-player__icon {
      width: 16px;
      height: 16px;
    }

    .jd-video-player__mute {
      margin-inline-start: auto;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: var(--jd-space-1);
      border: 0;
      border-radius: var(--jd-radius-md);
      background: transparent;
      color: #fff;
      cursor: pointer;
      transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
    }
    .jd-video-player__mute:hover {
      background: rgba(255, 255, 255, 0.15);
    }
    .jd-video-player__mute:focus-visible {
      outline: none;
      box-shadow: var(--jd-shadow-focus-ring);
    }

    .jd-video-player__icon {
      display: block;
    }
    .jd-video-player__icon--muted {
      display: none;
    }
    jd-video-player[data-muted] .jd-video-player__icon--sound {
      display: none;
    }
    jd-video-player[data-muted] .jd-video-player__icon--muted {
      display: block;
    }

    @media (prefers-reduced-motion: reduce) {
      jd-video-player > .jd-audio-player__controls {
        transition: none;
      }
      .jd-video-player__mute {
        transition: none;
      }
    }
  }

  @layer junds.components {
    jd-virtual-list {
      display: block;
      overflow: auto;
      height: var(--_jd-virtual-scroll-height, auto);
      overscroll-behavior: contain;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }
  }

  @layer junds.components {
    jd-virtual-scroll {
      display: block;
      overflow: auto;
      height: var(--_jd-virtual-scroll-height, auto);
      /* 스크롤 체이닝 차단 — 목록 끝에서 페이지가 딸려 움직이지 않는다 */
      overscroll-behavior: contain;
      font-family: var(--jd-font-sans);
      color: var(--jd-color-foreground);
    }

    .jd-virtual-scroll__sizer {
      position: relative;
      width: 100%;
    }

    .jd-virtual-scroll__item {
      position: absolute;
      inset-inline: 0;
      inset-block-start: 0;
      box-sizing: border-box;
      /* 고정 높이 안에서 넘치는 내용이 다음 행을 침범하지 않게 */
      overflow: hidden;
    }
  }

  @layer junds.components {
    jd-visually-hidden {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }

  @layer junds.components {
    /* v2 기본값: gap="md"(16px). align 기본은 stretch(CSS 기본) — 규칙 불필요 */
    jd-vstack {
      display: flex;
      flex-direction: column;
      gap: var(--jd-space-4);
    }
  }

  @layer junds.base {
    jd-watchlist-widget:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-watchlist-widget {
      /* 등락색은 직접 칠하지 않고 앱이 시작 시 1회 덮어쓰는 훅을 경유한다 — 직접 칠하면
       한국 관례(적상승) override가 이 위젯만 비껴가 한 화면에서 등락색이 갈라진다(§8) */
      --jd-fin-up: var(--jd-finance-up, var(--jd-color-success));
      --jd-fin-down: var(--jd-finance-down, var(--jd-color-danger));
      --jd-fin-muted: var(--bm-muted, var(--jd-color-muted));
      --jd-fin-text: var(--bm-text, var(--jd-color-foreground));
      --jd-fin-border: var(--bm-border, var(--jd-color-border));
      --jd-fin-card: var(--bm-card, var(--jd-color-card));
      --jd-fin-soft: var(
        --bm-soft-100,
        color-mix(in srgb, var(--jd-color-foreground) 6%, transparent)
      );
      --jd-fin-warning: var(--bm-warning, var(--jd-color-warning));
      --jd-fin-success: var(--bm-success, var(--jd-color-success));

      display: block;
      overflow: hidden;
      font-family: var(--jd-font-sans);
      color: var(--jd-fin-text);
      background: var(--jd-fin-card);
      border: var(--jd-border-thin) solid var(--jd-fin-border);
      border-radius: var(--jd-radius-xl);
    }
    jd-watchlist-widget * {
      box-sizing: border-box;
    }

    /* ── 헤더 ─────────────────────────────────────────── */
    .jd-wlw__header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      padding: var(--jd-space-3) var(--jd-space-4);
      border-block-end: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    jd-watchlist-widget[data-empty] .jd-wlw__header {
      border-block-end: none;
    }

    .jd-wlw__lead {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      flex-wrap: wrap;
      min-width: 0;
    }
    .jd-wlw__mark {
      color: var(--jd-fin-warning);
      font-size: 15px;
      line-height: 1;
    }
    .jd-wlw__title {
      margin: 0;
      font-size: var(--jd-text-md);
      font-weight: 800;
      line-height: var(--jd-leading-tight);
      color: var(--jd-fin-text);
    }
    .jd-wlw__status[hidden] {
      display: none;
    }

    .jd-wlw__source {
      font-size: 10px;
      font-weight: 800;
      letter-spacing: var(--jd-tracking-wide);
      padding: var(--jd-space-0-5) var(--jd-space-1-5);
      border-radius: var(--jd-radius-md);
      white-space: nowrap;
      background: var(--jd-fin-soft);
      color: var(--jd-fin-muted);
    }
    .jd-wlw__source[hidden] {
      display: none;
    }
    /* semantic 원색을 중립 틴트 위에 그대로 얹으면 대비 부족(특히 warning=amber) —
     전경색과 65:35로 섞어 가독 대비 확보(대비 규칙). --bm-* 브리지는 유지 */
    .jd-wlw__source[data-source="kis"] {
      color: color-mix(in srgb, var(--jd-fin-success) 65%, var(--jd-fin-text));
    }
    .jd-wlw__source[data-source="yahoo"] {
      color: color-mix(in srgb, var(--jd-fin-warning) 65%, var(--jd-fin-text));
    }

    .jd-wlw__add {
      flex-shrink: 0;
      font-family: inherit;
      font-size: var(--jd-text-xs);
      font-weight: var(--jd-weight-semibold);
      color: var(--jd-fin-muted);
      text-decoration: none;
      white-space: nowrap;
      background: none;
      border: 0;
      padding: 0;
      cursor: pointer;
    }
    .jd-wlw__add:hover {
      color: var(--jd-fin-text);
    }

    /* ── 빈 상태 ──────────────────────────────────────── */
    .jd-wlw__empty {
      margin: 0;
      padding: var(--jd-space-5) var(--jd-space-4);
      font-size: 12.5px;
      line-height: var(--jd-leading-relaxed);
      color: var(--jd-fin-muted);
    }
    .jd-wlw__empty[hidden] {
      display: none;
    }

    /* ── 목록 ─────────────────────────────────────────── */
    .jd-wlw__list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .jd-wlw__list[hidden] {
      display: none;
    }

    .jd-wlw__row {
      display: flex;
      align-items: center;
      gap: var(--jd-space-2);
      padding: 10px var(--jd-space-3);
      border-block-start: var(--jd-border-thin) solid var(--jd-fin-border);
    }
    .jd-wlw__row:first-child {
      border-block-start: 0;
    } /* divide-y: 첫 행 위 보더 없음 */

    .jd-wlw__star {
      flex-shrink: 0;
      display: inline-flex;
      padding: var(--jd-space-1);
      line-height: 0;
      color: var(--jd-fin-warning);
      background: none;
      border: 0;
      cursor: pointer;
    }
    .jd-wlw__star svg {
      display: block;
      width: 16px;
      height: 16px;
      fill: currentColor;
    }

    .jd-wlw__dot {
      flex-shrink: 0;
      width: 8px;
      height: 8px;
      border-radius: var(--jd-radius-full);
    }
    .jd-wlw__dot[hidden] {
      display: none;
    }

    .jd-wlw__link {
      flex: 1 1 auto;
      min-width: 0;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--jd-space-2);
      font: inherit;
      text-align: left;
      color: inherit;
      text-decoration: none;
      background: none;
      border: 0;
      padding: 0;
      cursor: pointer;
    }
    .jd-wlw__name {
      min-width: 0;
      font-size: 13.5px;
      font-weight: var(--jd-weight-bold);
      color: var(--jd-fin-text);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .jd-wlw__meta {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      gap: var(--jd-space-2);
    }

    /* 키보드 사용자 초점 링 — v2에는 없었다 */
    .jd-wlw__star:focus-visible,
    .jd-wlw__link:focus-visible,
    .jd-wlw__add:focus-visible {
      outline: none;
      border-radius: var(--jd-radius-sm);
      box-shadow: var(--jd-shadow-focus-ring);
    }
  }

  @layer junds.base {
    jd-watermark:not(:defined) {
      display: block;
    }
  }
  @layer junds.components {
    jd-watermark {
      --jd-watermark-color: rgba(0, 0, 0, 0.08);
      display: block;
      position: relative;
    }
    [data-jd-theme="dark"] jd-watermark,
    [data-theme="dark"] jd-watermark {
      --jd-watermark-color: rgba(255, 255, 255, 0.08);
    }

    .jd-watermark__layer {
      position: absolute;
      inset: 0;
      z-index: 10;
      pointer-events: none;
      user-select: none;
      -webkit-user-select: none;
      background-repeat: repeat;
    }
  }

  @layer junds.components {
    /* v2 기본값: wrap=wrap, gap="sm"(8px), align=center — jd-group과 동형(별칭 파생) */
    jd-wrap {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--jd-space-2);
    }
    jd-wrap[no-wrap] {
      flex-wrap: nowrap;
    }
  }

  @layer junds.components {
    
  [data-jd-grid-picker] {
    display: inline-block; box-sizing: border-box;
    padding: var(--jd-space-3);
    font-family: var(--jd-font-sans); color: var(--jd-color-foreground);
    background: var(--jd-color-card);
    border: var(--jd-border-thin) solid var(--jd-color-border);
    border-radius: var(--jd-radius-lg);
    user-select: none;
  }

  .jd-grid-picker__header {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: var(--jd-space-3);
  }
  .jd-grid-picker__label {
    font-size: var(--jd-text-md); font-weight: var(--jd-weight-semibold);
  }
  .jd-grid-picker__nav {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; padding: 0;
    color: inherit; background: none; border: 0;
    border-radius: var(--jd-radius-md); cursor: pointer;
    transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-grid-picker__nav:hover:not(:disabled) { background: var(--jd-color-card-hover); }
  .jd-grid-picker__nav:focus-visible { outline: none; box-shadow: var(--jd-shadow-focus-ring); }
  .jd-grid-picker__nav:disabled { opacity: var(--jd-opacity-40); cursor: not-allowed; }

  .jd-grid-picker__grid {
    display: grid; gap: var(--jd-space-1); width: 12.5rem;
  }
  .jd-grid-picker__cell {
    padding: var(--jd-space-2); margin: 0;
    font-family: inherit; font-size: var(--jd-text-md);
    color: var(--jd-color-foreground); background: none; border: 0;
    border-radius: var(--jd-radius-md); cursor: pointer;
    transition: background-color var(--jd-duration-fast) var(--jd-easing-ease-out);
  }
  .jd-grid-picker__cell:hover:not(:disabled) { background: var(--jd-color-card-hover); }
  .jd-grid-picker__cell:focus-visible { outline: none; box-shadow: var(--jd-shadow-focus-ring); }
  .jd-grid-picker__cell[aria-pressed="true"] {
    color: #fff; background: var(--jd-color-primary);
  }
  .jd-grid-picker__cell[aria-pressed="true"]:hover:not(:disabled) {
    background: var(--jd-color-primary-hover);
  }
  .jd-grid-picker__cell:disabled {
    opacity: var(--jd-opacity-30); cursor: not-allowed; background: none;
  }

  @media (prefers-reduced-motion: reduce) {
    .jd-grid-picker__nav, .jd-grid-picker__cell { transition: none; }
  }


    jd-year-picker > .jd-grid-picker__grid > .jd-grid-picker__cell {
      padding-inline: var(--jd-space-1);
      font-variant-numeric: tabular-nums;
    }
    jd-year-picker > .jd-grid-picker__header > .jd-grid-picker__label {
      font-variant-numeric: tabular-nums;
    }
  }