/* ============================================================
 * cortex — axe-ui bundle.css (auto-generated by scripts/sync-axe-ui.sh)
 *
 * SSOT: /Users/axe/axelabs/src/lib/{tokens,styles}/
 * 운영: 본 파일은 직접 편집 X. 갱신은 scripts/sync-axe-ui.sh 재실행.
 * ============================================================ */


/* ====== fonts.css  (src: /Users/axe/axelabs/src/lib/tokens/fonts.css, URL rewritten) ====== */

/* ============================================================
 * AXE Labs — fonts
 *
 *  Clash Display     : 헤딩 · 로고 · 메뉴       (Fontshare CDN)
 *  Pretendard Var.   : 본문 · UI · 라벨         (jsDelivr dynamic-subset)
 *  Sarasa Term K     : 코드 · 터미널 · 박스아트  (self-host woff2)
 *  D2Coding          : Sarasa 미설치 시 폴백     (jsDelivr CDN)
 *
 *  Sarasa Term K 를 self-host 하려면:
 *    cd /Users/axe/axelabs && npm run fonts:install
 *  파일이 없어도 D2Coding 폴백으로 한·영 박스 정렬은 보장됨.
 * ============================================================ */

/* Clash Display 는 app/layout.tsx <head><link> 로 로드.
 * Fontshare URL 의 f[]= 대괄호가 Next.js CSS @import 파이프라인에서
 * 떨궈지는 이슈 회피. Pretendard / D2Coding 는 @import 정상 동작. */
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css");
@import url("https://cdn.jsdelivr.net/gh/Joungkyun/font-d2coding@1.3.2/d2coding.css");

/* unicode-range 의도적 미설정 — Sarasa Fixed K 는 ASCII·한글·박스 모두 처리하며,
 * 한글:ASCII 정확히 2:1 너비를 보장하기 위해 영문도 같은 폰트가 그려야 함.
 *
 * 이전엔 unicode-range 명시했으나 CSS minifier 가 `U+1100-11FF` 를 wildcard
 * `u+11??` 로 압축 → Chrome 이 invalid 로 해석 → 전체 @font-face 거부 →
 * 폰트 로딩 실패 → fallback (Menlo) 으로 렌더 → 한글이 1.4× 가변폭 → 박스 깨짐.
 *
 * (이 함정은 dev (next dev, unminified) 에서는 안 보이고 production 빌드에서만
 * 발현되므로 진단 어려움.  unicode-range 없이 두면 모든 글자 매칭 + minifier
 * 가 만질 게 없음.) */
/* Sarasa Fixed K — Regular(400) 만 self-host.
 *
 * Bold(700) 제거 이유:
 *   - 코드/박스/표 의 mono 자리에 bold 거의 안 씀 (decorative 영향 X)
 *   - Cloudflare edge 가 Bold 파일에 transient 503 을 영구 캐시하는 함정 발견
 *     (2026-05-23, docs.axelabs.ai) — Regular 만 200, Bold 만 503 → 페이지
 *     안 `<strong>` 만 fallback (Pretendard Bold) 으로 빠지면서 한글 가변폭
 *     → 박스 안 markdown ** 굵게 라인만 misalign.
 *   - font-weight: 700 시 browser 가 Regular 를 algorithmic-bold 로 그리거나
 *     stack 의 다음 폰트 (Pretendard Bold) 로 fallback — 본문 외 위치라
 *     의미상 무관.
 *
 * unicode-range 도 *의도적 미설정* — minifier 의 wildcard 변환이 Chrome 에서
 * 거부됨 (이전 함정).  Regular 하나만 두면 minifier 가 만질 게 없음. */
@font-face {
  font-family: "Sarasa Fixed K";
  src: url("/cortex/static/fonts/SarasaFixedK-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* 본문 / UI / 디스플레이 *공통* sans 스택 — Pretendard 1순위.
   * default 헤딩 페이스도 이걸로 받음 (Clash 는 옵션이므로 강제 X). */
  --font-sans:
    "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont,
    "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* --font-display = 디스플레이 자리 (h1·h2·card title·logo 등) 의 의미적 슬롯.
   * 현재 sans 와 동일 — 즉 default 는 Pretendard.  옵션 디스플레이 페이스를
   * 적용하고 싶으면 컴포넌트 측에서 var(--font-clash) 또는 다른 토큰을 명시. */
  --font-display: var(--font-sans);

  /* Clash Display *옵션* 슬롯 — "여기는 명시적으로 Clash 로 가고 싶다" 는
   * 자리만 var(--font-clash) 직접 참조.  default 가 아님.
   * Fontshare CDN 로드 (app/layout.tsx <link>). */
  --font-clash: "Clash Display", "Inter", system-ui, sans-serif;

  /* Sarasa Fixed K — 한글이 ASCII 의 정확히 2× 너비.
   * D2Coding 은 동아시아 punctuation (·, fullwidth 괄호) 에 약점이 있어 폴백.
   * 박스 정렬에는 Sarasa 가 결정적. */
  --font-mono:
    "Sarasa Fixed K", "D2Coding", "JetBrains Mono", "SF Mono", Menlo, Consolas,
    monospace;
}

/* ====== colors.css  (src: /Users/axe/axelabs/src/lib/tokens/colors.css) ====== */

/* ============================================================
 * AXE Labs — colors
 *
 *  - Light: warm Sand-tinted 12-step (Radix Sand inspired)
 *  - Dark : wine-tinted, brand navy(#1A0610) 를 gray-1 로 앵커
 *  - Accent: #E3FF66 (dark) / #7A8F1F (light, AA contrast)
 *
 *  Step 의미 (Radix scale 패턴 동일):
 *    1  App background          7  UI element border
 *    2  Subtle / elevated bg    8  Hover border / focus
 *    3  UI element bg            9  Solid bg (disabled, placeholder dot)
 *    4  Hover UI bg            10  Hover solid
 *    5  Active UI bg            11  Low-contrast text  (caption)
 *    6  Subtle border, divider 12  High-contrast text (body)
 * ============================================================ */

/* -------- LIGHT (default) -------- */
/* warm cream paper — 순백 회피, 모니터 직사광 부담 감소
 * Anthropic #FAF9F5, Toss off-white, Linear 의 light-mode 노선 참고.
 *
 * 두 토글 전략 모두 지원:
 *   - data-theme="light|dark"  (axelabs 메인 앱 + 직접 토글)
 *   - .light / .dark           (next-themes class 기본값 — Nextra docs 등) */
:root,
[data-theme="light"],
.light {
  color-scheme: light;

  /* 브랜드 fixed colors — 모드 무관 동일 값.
   *   noir   : 다크 모드 배경의 와인-블랙 (Pinot Noir 톤). 거의 검정에 와인 hue.
   *   claret : 라이트 모드 의 brand + accent. AXE 시그니처 와인색.
   *   neon   : 다크 모드 의 brand + accent. 에너지 컬러.
   *
   * 시멘틱 `--accent` 가 모드 따라 둘 중 하나로 자동 매핑되므로
   * Logo 와 CTA 버튼이 같은 브랜드 색을 공유. */
  --brand-noir: #1a0610;
  --brand-claret: #821f3b;
  --brand-neon: #e3ff66;

  --gray-1: #f5f1e8;   /* App bg — warm cream paper */
  --gray-2: #efeadf;   /* Subtle bg / 카드 elevated 비교 시 살짝 진한 톤 */
  --gray-3: #e8e2d4;
  --gray-4: #ddd6c5;
  --gray-5: #d2cab7;
  --gray-6: #c4bba6;
  --gray-7: #b1a78f;
  --gray-8: #978b71;
  --gray-9: #756a52;
  --gray-10: #5d5440;
  --gray-11: #423a2b;
  --gray-12: #1f1a13;

  --bg-base: var(--gray-1);
  --bg-subtle: var(--gray-2);
  --bg-elevated: #faf6ec;   /* bg-base 보다 살짝 밝지만 순백 절대 X */
  --bg-overlay: rgb(31 26 19 / 0.55);

  --text-primary: var(--gray-12);
  --text-secondary: var(--gray-11);
  --text-tertiary: var(--gray-10);
  --text-muted: var(--gray-9);
  --text-inverse: var(--gray-1);

  --border-subtle: var(--gray-6);
  --border-default: var(--gray-7);
  --border-strong: var(--gray-8);

  /* accent = 브랜드 강조색 (claret/neon). 다음 자리에 사용:
   *   - Logo
   *   - Prose 링크 (color + hover)
   *   - Input · ChatInput focus border (+ accent-soft 박스 그림자)
   *   - Card 인터랙티브 hover 보더
   *   - Badge variant "accent"
   *   - Callout 좌측 보더 (각 variant 별)
   *   - ToolCall 이름 색
   *   - ::selection 배경, :focus-visible outline
   * Primary CTA 는 별도 --cta (행동 자리는 의미 부담 없는 ink). */
  --accent: var(--brand-claret);
  --accent-hover: #6b1830;
  --accent-fg: #ffffff;
  --accent-soft: rgb(130 31 59 / 0.10);

  /* cta = Primary 버튼 등 행동 자리. 모드 따라 ink 인버전.
   * Vercel · Linear · Anthropic 의 black/cream CTA 패턴. */
  --cta: var(--gray-12);
  --cta-hover: var(--gray-11);
  --cta-fg: var(--gray-1);

  --success: #2b7a3f;
  --warning: #b8651a;
  --danger: #c4321f;
  --info: #2860b8;

  --success-soft: #e9f6ec;
  --warning-soft: #fbf0e0;
  --danger-soft: #fbe7e2;
  --info-soft: #e6eefb;

  --shadow-sm: 0 1px 2px rgb(31 26 22 / 0.06);
  --shadow-md: 0 4px 12px rgb(31 26 22 / 0.08);
  --shadow-lg: 0 12px 32px rgb(31 26 22 / 0.10);
}

/* -------- DARK -------- */
[data-theme="dark"],
.dark {
  color-scheme: dark;

  /* 브랜드 fixed 값은 light 와 동일 */
  --brand-noir: #1a0610;
  --brand-claret: #821f3b;
  --brand-neon: #e3ff66;

  --gray-1: #1a0610;
  --gray-2: #220b17;
  --gray-3: #2c1320;
  --gray-4: #371b2a;
  --gray-5: #432435;
  --gray-6: #532e42;
  --gray-7: #6b4055;
  --gray-8: #8a5872;
  --gray-9: #6e5563;
  --gray-10: #897185;
  --gray-11: #b8a8b2;
  --gray-12: #f2e8ee;

  --bg-base: var(--gray-1);
  --bg-subtle: var(--gray-2);
  --bg-elevated: var(--gray-3);
  --bg-overlay: rgb(0 0 0 / 0.65);

  --text-primary: var(--gray-12);
  --text-secondary: var(--gray-11);
  --text-tertiary: var(--gray-10);
  --text-muted: var(--gray-9);
  --text-inverse: var(--gray-1);

  --border-subtle: var(--gray-6);
  --border-default: var(--gray-7);
  --border-strong: var(--gray-8);

  /* dark accent = neon (브랜드 강조용). CTA 는 별도 ink-inverted. */
  --accent: var(--brand-neon);
  --accent-hover: #eeff94;
  --accent-fg: var(--brand-noir);
  --accent-soft: rgb(227 255 102 / 0.10);

  --cta: var(--gray-12);     /* dark 의 gray-12 = off-white #F2E8EE */
  --cta-hover: var(--gray-11);
  --cta-fg: var(--gray-1);   /* dark 의 gray-1 = noir */

  --success: #58d17a;
  --warning: #f0a961;
  --danger: #f26a55;
  --info: #6ba8ff;

  --success-soft: rgb(88 209 122 / 0.10);
  --warning-soft: rgb(240 169 97 / 0.10);
  --danger-soft: rgb(242 106 85 / 0.10);
  --info-soft: rgb(107 168 255 / 0.10);

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.40);
  --shadow-md: 0 4px 12px rgb(0 0 0 / 0.45);
  --shadow-lg: 0 12px 32px rgb(0 0 0 / 0.55);
}

/* OS 다크 모드 자동 적용 — 명시적 light 선택이 없을 때만 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not(.light) {
    color-scheme: dark;

    --brand-noir: #1a0610;
    --brand-claret: #821f3b;
    --brand-neon: #e3ff66;

    --gray-1: #1a0610;
    --gray-2: #220b17;
    --gray-3: #2c1320;
    --gray-4: #371b2a;
    --gray-5: #432435;
    --gray-6: #532e42;
    --gray-7: #6b4055;
    --gray-8: #7e4f66;
    --gray-9: #8e6477;
    --gray-10: #a07a8b;
    --gray-11: #b8a8b2;
    --gray-12: #f2e8ee;

    --bg-base: var(--gray-1);
    --bg-subtle: var(--gray-2);
    --bg-elevated: var(--gray-3);
    --bg-overlay: rgb(0 0 0 / 0.65);

    --text-primary: var(--gray-12);
    --text-secondary: var(--gray-11);
    --text-tertiary: var(--gray-10);
    --text-muted: var(--gray-9);
    --text-inverse: var(--gray-1);

    --border-subtle: var(--gray-6);
    --border-default: var(--gray-7);
    --border-strong: var(--gray-8);

    --accent: var(--brand-neon);
    --accent-hover: #eeff94;
    --accent-fg: var(--brand-noir);
    --accent-soft: rgb(227 255 102 / 0.10);

    --cta: var(--gray-12);
    --cta-hover: var(--gray-11);
    --cta-fg: var(--gray-1);

    --success: #58d17a;
    --warning: #f0a961;
    --danger: #f26a55;
    --info: #6ba8ff;

    --success-soft: rgb(88 209 122 / 0.10);
    --warning-soft: rgb(240 169 97 / 0.10);
    --danger-soft: rgb(242 106 85 / 0.10);
    --info-soft: rgb(107 168 255 / 0.10);

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.40);
    --shadow-md: 0 4px 12px rgb(0 0 0 / 0.45);
    --shadow-lg: 0 12px 32px rgb(0 0 0 / 0.55);
  }
}

/* ====== typography.css  (src: /Users/axe/axelabs/src/lib/tokens/typography.css) ====== */

/* ============================================================
 * AXE Labs — typography
 *
 *  스케일 — 16 px base, ±10% 컴파운딩 (ratio 1.1 / 0.9).
 *  큰 헤딩 (3xl/4xl/5xl) 만 `clamp()` 로 모바일 자동 축소 —
 *  본문은 16 px 변동 없음 (한글 가독성 표준).
 *
 *    text-xs    12.96 px   (16 × 0.9²)        고정
 *    text-sm    14.4  px   (16 × 0.9)         고정
 *    text-base  16    px                       고정  <-- 본문
 *    text-lg    17.6  px   (16 × 1.1)         고정
 *    text-xl    19.36 px   (16 × 1.1²)        고정
 *    text-2xl   21.30 px   (16 × 1.1³)        고정
 *    text-3xl   19.36~23.43 px (mobile~desktop)   <-- clamp
 *    text-4xl   21.30~25.77 px (mobile~desktop)   <-- clamp
 *    text-5xl   23.43~28.34 px (mobile~desktop)   <-- clamp  <-- Hero
 *
 *  Clamp 공식: 모바일 (375vw) 에서 한 단계 아래 토큰값까지 내려가고,
 *  데스크탑 (1280vw) 에서 현행 유지. 그 사이는 선형 보간.
 *
 *  자간 (letter-spacing)
 *    본문      0
 *    UI label  0
 *    헤딩     -0.015em      (한·영 모두 안전)
 *    숫자(tabular) 0  + variant-numeric: tabular-nums
 *
 *  줄높이 (line-height)
 *    본문      1.6           (한글 받침 여유)
 *    UI dense  1.5
 *    헤딩 (h3+)1.3
 *    h1/h2     1.15          (display)
 *    code      1.55
 *
 *  Prose 폭 — 680 px (Linear 624 ~ Anthropic 728 의 중간)
 * ============================================================ */

:root {
  /* 본문 인근 — 고정 (모바일/데스크탑 동일). */
  --text-xs: 0.81rem; /*    12.96 px  (16 × 0.9²) */
  --text-sm: 0.9rem; /*     14.4  px  (16 × 0.9) */
  --text-base: 1rem; /*     16    px  <-- 본문 (고정) */
  --text-lg: 1.1rem; /*     17.6  px  (16 × 1.1) */
  --text-xl: 1.21rem; /*    19.36 px  (16 × 1.1²) */
  --text-2xl: 1.331rem; /*  21.30 px  (16 × 1.1³) */

  /* 큰 헤딩 — fluid clamp(min, preferred, max).
   * 모바일 (≤ 375 px) 에선 min 으로 클램프되어 한 단계 아래 토큰값까지 down,
   * 데스크탑 (≥ 1280 px) 에선 max 로 클램프되어 현행 사이즈 유지. */
  --text-3xl: clamp(1.21rem,   1.104rem + 0.45vw,   1.4641rem); /* 19.36 ~ 23.43 px */
  --text-4xl: clamp(1.331rem,  1.216rem + 0.49vw,   1.6105rem); /* 21.30 ~ 25.77 px */
  --text-5xl: clamp(1.4641rem, 1.337rem + 0.5425vw, 1.7716rem); /* 23.43 ~ 28.34 px  <-- Hero */

  /* 줄높이 */
  --leading-tight: 1.15;
  --leading-heading: 1.3;
  --leading-normal: 1.5;
  --leading-body: 1.6;
  --leading-code: 1.55;
  --leading-relaxed: 1.75;

  /* 자간 */
  --tracking-tighter: -0.025em;
  --tracking-heading: -0.015em;
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
  --tracking-widest: 0.08em;

  /* 두께 (variable font axis) */
  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* 폭 */
  --prose-max: 42.5rem; /* 680 px */
  --content-max: 75rem; /* 1200 px */
}

/* 기본 본문 — 어떤 페이지에서도 보장되는 baseline */
html {
  font-size: 16px;
  /* 한국어 본문의 어절 단위 줄바꿈 — Toss/Daangn 패턴 */
  word-break: keep-all;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-normal);
  color: var(--text-primary);
  background: var(--bg-base);
  font-weight: var(--weight-regular);
}

/* 표 / 숫자 행렬 — 등폭 숫자 + 마이너스 표시 정렬 */
table,
.tabular-nums {
  font-variant-numeric: tabular-nums;
}

/* ====== spacing.css  (src: /Users/axe/axelabs/src/lib/tokens/spacing.css) ====== */

/* ============================================================
 * AXE Labs — spacing / radius / motion
 *
 *  4-grid (Linear, Vercel 표준) — 8 단계
 * ============================================================ */

:root {
  /* spacing */
  --space-0: 0;
  --space-1: 0.25rem; /*  4 px */
  --space-2: 0.5rem; /*   8 px */
  --space-3: 0.75rem; /* 12 px */
  --space-4: 1rem; /*    16 px */
  --space-5: 1.5rem; /*  24 px */
  --space-6: 2rem; /*    32 px */
  --space-7: 3rem; /*    48 px */
  --space-8: 4rem; /*    64 px */
  --space-9: 6rem; /*    96 px */
  --space-10: 8rem; /*  128 px */

  /* radius */
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-xl: 16px;
  --radius-2xl: 24px;
  --radius-full: 9999px;

  /* motion */
  --duration-fast: 120ms;
  --duration-base: 180ms;
  --duration-slow: 280ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* z-index */
  --z-base: 1;
  --z-sticky: 100;
  --z-overlay: 1000;
  --z-modal: 1100;
  --z-toast: 1200;
}

/* ====== reset.css  (src: /Users/axe/axelabs/src/lib/styles/reset.css) ====== */

/* ============================================================
 * AXE Labs — minimal reset
 *
 * 토큰 파일이 html/body 의 폰트·컬러·줄높이를 이미 잡으므로,
 * 이 파일은 여백·박스모델·기본 element 정상화만.
 * ============================================================ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

/* 헤딩 / 단락 / 리스트 / blockquote 의 기본 여백 제거.
 * 컴포넌트 / Prose 가 명시적으로 spacing 을 부여. */
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
dl,
figure,
blockquote,
pre,
hr {
  margin: 0;
}

/* 리스트 기본 padding 제거 */
ul,
ol {
  padding: 0;
}

/* 이미지 / 미디어 — block, 부모 폭에 맞춤 */
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* form element — 폰트 / 컬러 상속 */
input,
textarea,
select,
button {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

/* 표 — collapse 기본 + 헤더 정렬 명시 */
table {
  border-collapse: collapse;
  width: 100%;
}

th {
  text-align: left;
  font-weight: var(--weight-semibold, 600);
}

/* 강조 인라인 — italic 의 한글 폴백 정상화 */
i,
em {
  font-style: italic;
  font-feature-settings: "kern";
}

/* 모션 줄이기 환경 — 자동 disable */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* focus 가시성 — 키보드만 (마우스 클릭 시는 끔) */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* selection 색 */
::selection {
  background: var(--accent);
  color: var(--accent-fg);
}

/* ====== components.css base  (src: /Users/axe/axelabs/src/lib/styles/components.css, @imports stripped) ====== */

/* ============================================================
 * AXE Labs — component styles
 *
 * 모든 컴포넌트는 .axe- prefix.  Tailwind 의존 0.
 * CSS 변수로만 컬러·폰트·간격 참조 → light/dark 자동 전환.
 *
 * 그룹별 CSS 는 별도 파일 → 본 파일에서 @import.
 * 소비자는 components.css 만 import 해도 전 그룹 다 로드.
 * ============================================================ */

/* v2 component groups (Phase 1-14) — 그룹별 격리 + 한 곳 통합 */
/* Phase 14 — gap fill */
/* NOTE: tailwind-bridge.css 는 *opt-in* — 소비자가 Tailwind 쓸 때만 명시 import. */

/* ------- Logo ------- */
.axe-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  letter-spacing: 0.02em;
  color: var(--accent);
  text-decoration: none;
  font-size: var(--text-lg);
  line-height: 1;
  white-space: nowrap;
}

.axe-logo--sm {
  font-size: var(--text-base);
}
.axe-logo--lg {
  font-size: var(--text-2xl);
}

/* ------- TopNav ------- */
.axe-topnav {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-5);
  background: color-mix(in oklch, var(--bg-base) 92%, transparent);
  backdrop-filter: saturate(140%) blur(20px);
  -webkit-backdrop-filter: saturate(140%) blur(20px);
  border-bottom: 1px solid var(--border-subtle);
  /* 모바일 nav 가 참조 — 768px 미만에서 navbar 바로 아래에 fixed 로 펼침. */
  --axe-topnav-height: 56px;
}
.axe-topnav__left {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  min-width: 0;
  flex: 1 1 auto;     /* right 가 자리 양보 못 받게 */
  overflow: hidden;   /* items overflow 가 right 침범 안 함 */
}
.axe-topnav__items {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  /* items 많으면 가로 스크롤 — right (테마 토글 등) 절대 가리지 않음 */
  overflow-x: auto;
  scrollbar-width: none;       /* Firefox */
  -ms-overflow-style: none;    /* IE/old Edge */
  /* 우측 가장자리에 fade gradient — 더 있다는 시각 힌트 */
  mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
}
.axe-topnav__items::-webkit-scrollbar {
  display: none;               /* Chrome/Safari */
}
/* 스크롤 끝까지 갔으면 fade 제거 (다는 보임) — 단순화: scroll 위치 검사 안 함 (CSS 만으로 한계) */
.axe-topnav__item {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  letter-spacing: 0.005em;
  color: var(--text-secondary);
  white-space: nowrap;
  transition:
    color var(--duration-fast) var(--ease-out),
    background var(--duration-fast) var(--ease-out);
}
.axe-topnav__item:hover {
  color: var(--text-primary);
  background: var(--bg-subtle);
}
.axe-topnav__item[aria-current="page"],
.axe-topnav__item--active {
  color: var(--text-primary);
  font-weight: var(--weight-medium);
}
.axe-topnav__right {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 0 0 auto;     /* 우선순위 — 절대 줄지 않음 */
  margin-left: var(--space-4);
}

/* ------- Hamburger 버튼 (모바일 only) ------- */
.axe-topnav__hamburger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-left: var(--space-1);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}
.axe-topnav__hamburger:hover {
  background: var(--bg-subtle);
}
.axe-topnav__hamburger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 햄버거 line — open 시 X 로 변형. transform 만 애니메이션 → GPU. */
.axe-hamburger-line {
  transform-origin: center;
  transition:
    transform var(--duration-base) var(--ease-out),
    opacity var(--duration-fast) var(--ease-out);
}
.axe-topnav__hamburger-icon[data-open="true"] .axe-hamburger-line--top {
  transform: translateY(6px) rotate(45deg);
}
.axe-topnav__hamburger-icon[data-open="true"] .axe-hamburger-line--mid {
  opacity: 0;
  transform: scaleX(0);
}
.axe-topnav__hamburger-icon[data-open="true"] .axe-hamburger-line--bot {
  transform: translateY(-6px) rotate(-45deg);
}

/* ------- Mobile nav 오버레이 ------- */
.axe-mobile-nav {
  position: fixed;
  top: var(--axe-topnav-height, 56px);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-sticky);
  display: none;
  background: var(--bg-base);
  border-top: 1px solid var(--border-subtle);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* docs.axelabs.ai (Nextra) 와 동일한 슬라이드 패턴 — transform 만 변경.
   * translate3d 로 GPU layer 강제 → 60fps. */
  transform: translate3d(0, -100%, 0);
  transition: transform var(--duration-base) var(--ease-out);
  will-change: transform;
}
.axe-mobile-nav[data-open="true"] {
  transform: translate3d(0, 0, 0);
}
.axe-mobile-nav__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3);
}
.axe-mobile-nav__item {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  letter-spacing: 0.005em;
  color: var(--text-secondary);
  transition:
    color var(--duration-fast) var(--ease-out),
    background var(--duration-fast) var(--ease-out);
}
.axe-mobile-nav__item:hover,
.axe-mobile-nav__item:active {
  background: var(--bg-subtle);
  color: var(--text-primary);
}
.axe-mobile-nav__item[aria-current="page"],
.axe-mobile-nav__item--active {
  color: var(--text-primary);
  font-weight: var(--weight-medium);
}

/* 브레이크포인트 — 768px. docs.axelabs.ai (Nextra md) 와 동일. */
@media (max-width: 767.98px) {
  .axe-topnav {
    padding: var(--space-3) var(--space-4);
    gap: var(--space-3);
  }
  .axe-topnav__items {
    display: none;
  }
  .axe-topnav__hamburger {
    display: inline-flex;
  }
  .axe-mobile-nav {
    display: block;
  }
}

/* ------- Button ------- */
.axe-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0 var(--space-4);
  height: 36px;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  line-height: 1;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
  white-space: nowrap;
  user-select: none;
  border: 1px solid transparent;
}
.axe-btn:disabled,
.axe-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}
.axe-btn:active:not(:disabled) {
  transform: scale(0.98);
}

.axe-btn--sm {
  height: 28px;
  padding: 0 var(--space-3);
  font-size: var(--text-xs);
}
.axe-btn--lg {
  height: 44px;
  padding: 0 var(--space-5);
  font-size: var(--text-base);
}

.axe-btn--primary {
  background: var(--cta);
  color: var(--cta-fg);
  font-weight: var(--weight-semibold);
}
.axe-btn--primary:hover:not(:disabled) {
  background: var(--cta-hover);
}

.axe-btn--secondary {
  background: var(--bg-elevated);
  border-color: var(--border-default);
  color: var(--text-primary);
}
.axe-btn--secondary:hover:not(:disabled) {
  border-color: var(--border-strong);
  background: var(--bg-subtle);
}

.axe-btn--ghost {
  background: transparent;
  color: var(--text-secondary);
}
.axe-btn--ghost:hover:not(:disabled) {
  background: var(--bg-subtle);
  color: var(--text-primary);
}

.axe-btn--danger {
  background: var(--danger);
  color: #fff;
}
.axe-btn--danger:hover:not(:disabled) {
  filter: brightness(0.95);
}

/* ------- Input ------- */
.axe-input {
  display: inline-flex;
  align-items: center;
  width: 100%;
  height: 36px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.4;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-input::placeholder {
  color: var(--text-muted);
}
.axe-input:hover {
  border-color: var(--border-strong);
}
.axe-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.axe-input--lg {
  height: 44px;
  font-size: var(--text-base);
}
.axe-input--textarea {
  height: auto;
  min-height: 80px;
  padding: var(--space-3);
  line-height: var(--leading-body);
  resize: vertical;
}

/* ------- Card ------- */
.axe-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  transition: border-color var(--duration-fast) var(--ease-out);
}
.axe-card--interactive {
  cursor: pointer;
}
.axe-card--interactive:hover {
  border-color: var(--accent);
}
.axe-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}
.axe-card__body {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}

/* ------- Callout ------- */
.axe-callout {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid;
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}
.axe-callout__icon {
  flex-shrink: 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
}
.axe-callout__content {
  flex: 1;
  min-width: 0;
}
.axe-callout__title {
  font-weight: var(--weight-semibold);
  margin-bottom: var(--space-1);
}

.axe-callout--info {
  background: var(--info-soft);
  border-color: var(--info);
  color: var(--text-primary);
}
.axe-callout--info .axe-callout__icon {
  color: var(--info);
}

.axe-callout--success {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--text-primary);
}
.axe-callout--success .axe-callout__icon {
  color: var(--success);
}

.axe-callout--warning {
  background: var(--warning-soft);
  border-color: var(--warning);
  color: var(--text-primary);
}
.axe-callout--warning .axe-callout__icon {
  color: var(--warning);
}

.axe-callout--danger {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--text-primary);
}
.axe-callout--danger .axe-callout__icon {
  color: var(--danger);
}

.axe-callout--note {
  background: var(--bg-subtle);
  border-color: var(--border-subtle);
  color: var(--text-secondary);
}
.axe-callout--note .axe-callout__icon {
  color: var(--text-tertiary);
}

/* ------- Badge ------- */
.axe-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wide);
  line-height: 1.4;
  background: var(--bg-subtle);
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
}
.axe-badge--accent {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: transparent;
}
.axe-badge--success {
  background: var(--success-soft);
  color: var(--success);
  border-color: transparent;
}
.axe-badge--warning {
  background: var(--warning-soft);
  color: var(--warning);
  border-color: transparent;
}
.axe-badge--danger {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: transparent;
}
.axe-badge--info {
  background: var(--info-soft);
  color: var(--info);
  border-color: transparent;
}

/* ------- CodeBlock ------- */
.axe-codeblock {
  position: relative;
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.axe-codeblock__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  background: color-mix(in oklch, var(--bg-subtle) 80%, var(--bg-base));
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.axe-codeblock__lang {
  text-transform: lowercase;
  letter-spacing: 0.04em;
}
.axe-codeblock__copy {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  transition: color var(--duration-fast) var(--ease-out);
}
.axe-codeblock__copy:hover {
  color: var(--text-primary);
  background: var(--bg-base);
}
.axe-codeblock__pre {
  margin: 0;
  padding: var(--space-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--leading-code);
  color: var(--text-primary);
  /* 한글·ASCII 박스 정렬 핵심:
   * 1) Sarasa Term K / D2Coding 이 한글을 정확히 2× 너비로 렌더
   * 2) keep-all 해제 — 코드는 그대로 보여줌 */
  word-break: normal;
  white-space: pre;
  tab-size: 4;
  font-variant-ligatures: contextual;
  font-feature-settings: "calt" 1;
}
.axe-codeblock__pre code {
  font-family: inherit;
  font-size: inherit;
}

/* 인라인 code */
.axe-code-inline,
:not(pre) > code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  padding: 0.125em 0.4em;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  word-break: break-all;
}

/* ------- Table ------- */
.axe-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
}
.axe-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-variant-numeric: tabular-nums;
}
.axe-table thead th {
  text-align: left;
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.axe-table tbody td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-primary);
  vertical-align: top;
}
.axe-table tbody tr:last-child td {
  border-bottom: 0;
}
.axe-table tbody tr:hover td {
  background: var(--bg-subtle);
}

/* ------- Prose (마크다운 본문 래퍼) -------
 * 단일 클래스로 임의 마크다운 트리에 prose 스타일 부여.
 * docs.axelabs.ai 처럼 정보 밀도 높은 페이지에 .axe-prose 한 줄로. */
.axe-prose {
  max-width: var(--prose-max);
  color: var(--text-primary);
  font-size: var(--text-base);
  line-height: var(--leading-body);
}

.axe-prose > * + * {
  margin-top: var(--space-4);
}
.axe-prose > h1 + *,
.axe-prose > h2 + *,
.axe-prose > h3 + * {
  margin-top: var(--space-3);
}
.axe-prose > * + h2 {
  margin-top: var(--space-7);
}
.axe-prose > * + h3 {
  margin-top: var(--space-6);
}

.axe-prose h1,
.axe-prose h2,
.axe-prose h3,
.axe-prose h4,
.axe-prose h5,
.axe-prose h6 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-heading);
  color: var(--text-primary);
}
.axe-prose h1 {
  font-size: var(--text-4xl);
  line-height: var(--leading-tight);
}
.axe-prose h2 {
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}
.axe-prose h3 {
  font-size: var(--text-xl);
  line-height: var(--leading-heading);
}
.axe-prose h4 {
  font-size: var(--text-lg);
  line-height: var(--leading-heading);
}
.axe-prose h5,
.axe-prose h6 {
  font-size: var(--text-base);
  line-height: var(--leading-heading);
}

.axe-prose p {
  font-size: var(--text-base);
  line-height: var(--leading-body);
  letter-spacing: 0;
  color: var(--text-primary);
}

.axe-prose a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--duration-fast) var(--ease-out);
}
.axe-prose a:hover {
  color: var(--accent-hover);
}

.axe-prose ul,
.axe-prose ol {
  padding-left: var(--space-5);
  line-height: var(--leading-body);
}
.axe-prose ul {
  list-style: disc;
}
.axe-prose ol {
  list-style: decimal;
}
.axe-prose li::marker {
  color: var(--text-tertiary);
}
.axe-prose li + li {
  margin-top: var(--space-1);
}
.axe-prose li p {
  margin-top: 0;
}
.axe-prose li > ul,
.axe-prose li > ol {
  margin-top: var(--space-1);
}

.axe-prose blockquote {
  border-left: 3px solid var(--border-strong);
  padding: var(--space-2) var(--space-4);
  color: var(--text-secondary);
  font-style: italic;
}

.axe-prose hr {
  border: 0;
  height: 1px;
  background: var(--border-subtle);
  margin: var(--space-6) 0;
}

.axe-prose strong {
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.axe-prose img {
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

/* prose 안의 표·코드블록은 위에서 정의한 클래스 스타일을 그대로 받도록
 * 동일 셀렉터 사용 */
.axe-prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.axe-prose table thead th {
  text-align: left;
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.axe-prose table tbody td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}
.axe-prose table tbody tr:last-child td {
  border-bottom: 0;
}

.axe-prose pre {
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--leading-code);
  word-break: normal;
  white-space: pre;
  tab-size: 4;
}
.axe-prose pre code {
  background: transparent;
  border: 0;
  padding: 0;
  font-size: inherit;
}

/* ------- Chat — AI-first ------- */
.axe-chat-input {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-chat-input:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.axe-chat-input__textarea {
  width: 100%;
  border: 0;
  background: transparent;
  resize: none;
  outline: none;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  min-height: 1.5em;
  max-height: 12em;
}
.axe-chat-input__textarea::placeholder {
  color: var(--text-muted);
}
.axe-chat-input__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.axe-chat-input__hint {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-family: var(--font-mono);
}

/* MessageBubble */
.axe-message {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) 0;
}
.axe-message__avatar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  /* gray-9 = Radix scale 의 "solid bg" tier. avatar 같은 UI 마크용. */
  background: var(--gray-9);
  color: var(--bg-base);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}
.axe-message--user .axe-message__avatar {
  background: var(--accent);
  color: var(--accent-fg);
}
.axe-message__body {
  flex: 1;
  min-width: 0;
  color: var(--text-primary);
  font-size: var(--text-base);
  line-height: var(--leading-body);
}
.axe-message__role {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin-bottom: var(--space-1);
}
.axe-message__content > * + * {
  margin-top: var(--space-3);
}

/* StreamingMarkdown — pulse cursor */
.axe-stream-cursor {
  display: inline-block;
  width: 0.5em;
  height: 1em;
  background: var(--accent);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: axe-blink 1s steps(2, end) infinite;
}
@keyframes axe-blink {
  0%, 50% {
    opacity: 1;
  }
  50.01%, 100% {
    opacity: 0;
  }
}

/* ToolCallCard */
.axe-toolcall {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--leading-code);
  overflow: hidden;
}
.axe-toolcall__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  user-select: none;
  background: color-mix(in oklch, var(--bg-subtle) 80%, var(--bg-base));
  border-bottom: 1px solid transparent;
  transition: background var(--duration-fast) var(--ease-out);
}
.axe-toolcall__header:hover {
  background: color-mix(in oklch, var(--bg-subtle) 60%, var(--bg-base));
}
.axe-toolcall[data-open="true"] .axe-toolcall__header {
  border-bottom-color: var(--border-subtle);
}
.axe-toolcall__name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--accent);
  font-weight: var(--weight-semibold);
}
.axe-toolcall__status {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}
.axe-toolcall__chevron {
  color: var(--text-tertiary);
  transition: transform var(--duration-fast) var(--ease-out);
}
.axe-toolcall[data-open="true"] .axe-toolcall__chevron {
  transform: rotate(90deg);
}
.axe-toolcall__body {
  padding: var(--space-3);
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: normal;
  overflow-x: auto;
}

/* CommandPalette (⌘K) */
.axe-cmdk-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: var(--bg-overlay);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 12vh;
}
.axe-cmdk {
  width: min(560px, 92vw);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.axe-cmdk__input {
  width: 100%;
  padding: var(--space-4);
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  border-bottom: 1px solid var(--border-subtle);
}
.axe-cmdk__input::placeholder {
  color: var(--text-muted);
}
.axe-cmdk__list {
  max-height: 400px;
  overflow-y: auto;
  padding: var(--space-2);
}
.axe-cmdk__group {
  margin-bottom: var(--space-2);
}
.axe-cmdk__group-label {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-tertiary);
  padding: var(--space-2) var(--space-3);
}
.axe-cmdk__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}
.axe-cmdk__item[aria-selected="true"],
.axe-cmdk__item:hover {
  background: var(--bg-subtle);
}
.axe-cmdk__item-meta {
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.axe-cmdk__empty {
  padding: var(--space-6);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* kbd 키 표기 */
.axe-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5em;
  padding: 0 0.4em;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle);
  border-bottom-width: 2px;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 0.85em;
  line-height: 1.6;
}

/* ============================================================
 * Dialog (Modal) — Radix Dialog 위 styling
 *
 *  size variant: sm 440 / md 560 / lg 720 / xl 960 / full 100vw
 *  data-state="open|closed" 으로 Radix 가 트랜지션 트리거.
 *  prefers-reduced-motion 존중.
 * ============================================================ */
.axe-dialog__overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  backdrop-filter: blur(2px);
  z-index: 50;
  animation: axe-dialog-overlay-in 160ms ease-out;
}
.axe-dialog__overlay[data-state="closed"] {
  animation: axe-dialog-overlay-out 120ms ease-in forwards;
}

.axe-dialog__content {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100vw - 2 * var(--space-4));
  max-height: calc(100vh - 2 * var(--space-4));
  max-height: calc(100dvh - 2 * var(--space-4));
  overflow: auto;
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-6);
  z-index: 51;
  animation: axe-dialog-content-in 180ms cubic-bezier(0.16, 1, 0.3, 1);
}
.axe-dialog__content[data-state="closed"] {
  animation: axe-dialog-content-out 140ms ease-in forwards;
}
.axe-dialog__content:focus { outline: none; }

.axe-dialog__content--sm   { max-width: 440px; }
.axe-dialog__content--md   { max-width: 560px; }
.axe-dialog__content--lg   { max-width: 720px; }
.axe-dialog__content--xl   { max-width: 960px; }
.axe-dialog__content--full {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  max-height: 100dvh;
  top: 0;
  left: 0;
  transform: none;
  border-radius: 0;
}

.axe-dialog__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-4);
  padding-right: var(--space-8); /* close X 자리 */
}

.axe-dialog__title {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  line-height: 1.3;
  color: var(--text-primary);
  margin: 0;
}

.axe-dialog__description {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-secondary);
  margin: 0;
}

.axe-dialog__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

@keyframes axe-dialog-overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes axe-dialog-overlay-out {
  to { opacity: 0; }
}
@keyframes axe-dialog-content-in {
  from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes axe-dialog-content-out {
  to { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
}

@media (prefers-reduced-motion: reduce) {
  .axe-dialog__overlay,
  .axe-dialog__content,
  .axe-dialog__overlay[data-state="closed"],
  .axe-dialog__content[data-state="closed"] {
    animation: none;
  }
}

/* ====== form.css  (src: /Users/axe/axelabs/src/lib/styles/form.css) ====== */

/* ============================================================
 * Form group — Select / Checkbox / Radio / Switch / Label / FormField
 *
 * Convention:
 *   - 모든 sizing 은 토큰 (var(--space-*), var(--text-*)).
 *   - focus ring = 2px box-shadow var(--accent-soft) + border var(--accent)
 *     (Input 과 동일).  ::focus-visible 만 — 마우스 클릭에 ring 안 뜸.
 *   - error 상태 = border var(--danger) + ring var(--danger-soft).
 *   - 다크/라이트 자동 — CSS var 만 사용.
 *   - prefers-reduced-motion 존중.
 * ============================================================ */

/* ------- Label (axe-label) — Radix Label wrap ------- */
.axe-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium, 500);
  line-height: 1.4;
  color: var(--text-primary);
  cursor: pointer;
  user-select: none;
}

/* ============================================================
 * Select (axe-select__*) — Radix Select
 * ============================================================ */
.axe-select__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  height: 36px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.4;
  text-align: left;
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-select__trigger:hover:not([data-disabled]) {
  border-color: var(--border-strong);
}
.axe-select__trigger:focus-visible,
.axe-select__trigger[data-state="open"] {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.axe-select__trigger[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.axe-select__trigger[data-placeholder] {
  color: var(--text-muted);
}
.axe-select__trigger--lg {
  height: 44px;
  font-size: var(--text-base);
}

/* error wiring — 부모 FormField--error 안 trigger 도 적용 */
.axe-form-field--error .axe-select__trigger {
  border-color: var(--danger);
}
.axe-form-field--error .axe-select__trigger:focus-visible,
.axe-form-field--error .axe-select__trigger[data-state="open"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-soft);
}

.axe-select__content {
  min-width: var(--radix-select-trigger-width);
  max-height: var(--radix-select-content-available-height);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  z-index: 60;
  animation: axe-select-in 140ms var(--ease-out, ease-out);
}
.axe-select__content[data-state="closed"] {
  animation: axe-select-out 100ms ease-in forwards;
}
.axe-select__viewport {
  padding: var(--space-1);
}
.axe-select__label {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
  color: var(--text-tertiary);
}
.axe-select__item {
  position: relative;
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-7);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: var(--text-sm);
  line-height: 1.4;
  cursor: pointer;
  user-select: none;
  outline: none;
}
.axe-select__item[data-highlighted] {
  background: var(--bg-subtle);
}
.axe-select__item[data-state="checked"] {
  color: var(--accent);
  font-weight: var(--weight-medium, 500);
}
.axe-select__item[data-disabled] {
  color: var(--text-muted);
  pointer-events: none;
}
.axe-select__indicator {
  position: absolute;
  left: var(--space-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}
.axe-select__separator {
  height: 1px;
  margin: var(--space-1) 0;
  background: var(--border-subtle);
}

@keyframes axe-select-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes axe-select-out {
  to { opacity: 0; transform: translateY(-4px); }
}

/* ============================================================
 * Checkbox (axe-checkbox) — Radix Checkbox  +  indeterminate
 * ============================================================ */
.axe-checkbox {
  --size: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--size);
  height: var(--size);
  flex: 0 0 var(--size);
  padding: 0;
  margin: 0;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-strong);
  background: var(--bg-elevated);
  color: var(--accent-fg);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-checkbox:hover:not([data-disabled]) {
  border-color: var(--accent);
}
.axe-checkbox:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
  border-color: var(--accent);
}
.axe-checkbox[data-state="checked"],
.axe-checkbox[data-state="indeterminate"] {
  background: var(--accent);
  border-color: var(--accent);
}
.axe-checkbox[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* indicator + 두 icon (check / dash) — data-state 로 표시 분기 */
.axe-checkbox__indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
.axe-checkbox__icon {
  display: none;
  color: var(--accent-fg);
}
.axe-checkbox[data-state="checked"] .axe-checkbox__icon--check {
  display: block;
}
.axe-checkbox[data-state="indeterminate"] .axe-checkbox__icon--dash {
  display: block;
}

/* error wiring */
.axe-form-field--error .axe-checkbox {
  border-color: var(--danger);
}
.axe-form-field--error .axe-checkbox:focus-visible {
  box-shadow: 0 0 0 3px var(--danger-soft);
}
.axe-form-field--error .axe-checkbox[data-state="checked"],
.axe-form-field--error .axe-checkbox[data-state="indeterminate"] {
  background: var(--danger);
  border-color: var(--danger);
}

/* ============================================================
 * Radio (axe-radio__*) — Radix RadioGroup
 * ============================================================ */
.axe-radio__group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.axe-radio__item {
  --size: 18px;
  width: var(--size);
  height: var(--size);
  flex: 0 0 var(--size);
  padding: 0;
  margin: 0;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  background: var(--bg-elevated);
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-radio__item:hover:not([data-disabled]) {
  border-color: var(--accent);
}
.axe-radio__item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
  border-color: var(--accent);
}
.axe-radio__item[data-state="checked"] {
  border-color: var(--accent);
}
.axe-radio__item[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.axe-radio__indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  position: relative;
}
.axe-radio__indicator::after {
  content: "";
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

/* error wiring */
.axe-form-field--error .axe-radio__item {
  border-color: var(--danger);
}
.axe-form-field--error .axe-radio__item:focus-visible {
  box-shadow: 0 0 0 3px var(--danger-soft);
}
.axe-form-field--error .axe-radio__item[data-state="checked"] {
  border-color: var(--danger);
}
.axe-form-field--error .axe-radio__indicator::after {
  background: var(--danger);
}

/* ============================================================
 * Switch (axe-switch) — Radix Switch
 * ============================================================ */
.axe-switch {
  --track-w: 36px;
  --track-h: 20px;
  --thumb: 16px;

  position: relative;
  width: var(--track-w);
  height: var(--track-h);
  flex: 0 0 var(--track-w);
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 999px;
  background: var(--border-default);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}
.axe-switch:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.axe-switch[data-state="checked"] {
  background: var(--accent);
}
.axe-switch[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.axe-switch__thumb {
  display: block;
  width: var(--thumb);
  height: var(--thumb);
  border-radius: 50%;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  transform: translateX(2px);
  transition: transform var(--duration-fast) var(--ease-out);
  will-change: transform;
}
.axe-switch[data-state="checked"] .axe-switch__thumb {
  transform: translateX(calc(var(--track-w) - var(--thumb) - 2px));
}

/* error wiring */
.axe-form-field--error .axe-switch:focus-visible {
  box-shadow: 0 0 0 3px var(--danger-soft);
}
.axe-form-field--error .axe-switch[data-state="checked"] {
  background: var(--danger);
}

/* ============================================================
 * FormField (axe-form-field) — wrapper layout
 * ============================================================ */
.axe-form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.axe-form-field__label {
  /* axe-label 상속 — 추가 spacing 만 */
}
.axe-form-field__required {
  color: var(--danger);
  font-weight: var(--weight-medium, 500);
  margin-left: 2px;
}
.axe-form-field__control {
  /* control wrapper — Input/Select/Checkbox 등이 들어옴 */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.axe-form-field__hint {
  margin: 0;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-tertiary);
}
.axe-form-field__error {
  margin: 0;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--danger);
}
/* error 상태일 때 wrap 안 Input 도 자동 적용 — aria-invalid 가 더 정석이지만
   FormField 의 명시적 error prop 만으로도 시각 동기화 */
.axe-form-field--error .axe-input,
.axe-input[aria-invalid="true"] {
  border-color: var(--danger);
}
.axe-form-field--error .axe-input:focus,
.axe-input[aria-invalid="true"]:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-soft);
}

/* ============================================================
 * Reduced motion
 * ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .axe-select__content,
  .axe-select__content[data-state="closed"],
  .axe-switch__thumb {
    animation: none;
    transition: none;
  }
}

/* ====== data-display.css  (src: /Users/axe/axelabs/src/lib/styles/data-display.css) ====== */

/* ============================================================
 * Data display (Phase 14 Wave 5)
 *   DataTable · Pagination · Chart (recharts wrap)
 *
 *   Phase 7 dashboard.css 와 별도 — Pipeline 은 운영자 status row,
 *   DataTable 은 일반 데이터 + 정렬/페이징.  스타일 분리해서 tree-shake
 *   가능, showcase page 에서 본 파일만 import.
 *
 *   원칙
 *     · token-only — Tailwind 0, hard-coded color 0.
 *     · CSS-only animation (hover transition, skeleton shimmer).
 *     · prefers-reduced-motion: reduce 시 모든 motion 정지/완화.
 *     · light/dark 자동 — CSS var 만 사용.
 * ============================================================ */

/* ============================================================
 * DataTable — sortable, paginatable generic data table.
 *   wrap > scroll > table.  PipelineTable 과 마크업 유사하지만
 *   sortable header 가 <button> 으로 들어가는 차이.
 * ============================================================ */
.axe-data-table {
  width: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden; /* radius clip */
}

.axe-data-table__scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.axe-data-table--sticky .axe-data-table__scroll {
  max-height: 480px;
  overflow-y: auto;
}

.axe-data-table__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  min-width: 600px;
}

.axe-data-table__thead {
  background: var(--bg-subtle);
}

.axe-data-table--sticky .axe-data-table__thead {
  position: sticky;
  top: 0;
  z-index: 1;
}

.axe-data-table__th {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}

.axe-data-table__th--right  { text-align: right; }
.axe-data-table__th--center { text-align: center; }

.axe-data-table__th--active {
  color: var(--text-primary);
}

.axe-data-table__th--sortable {
  padding: 0; /* button 이 padding 보유 */
}

.axe-data-table__sort-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  width: 100%;
  background: transparent;
  border: 0;
  padding: var(--space-3) var(--space-4);
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  text-align: inherit;
  cursor: pointer;
  font-family: inherit;
  transition: color var(--duration-fast, 120ms) var(--ease-out, ease-out);
}

.axe-data-table__th--right .axe-data-table__sort-btn  { justify-content: flex-end; }
.axe-data-table__th--center .axe-data-table__sort-btn { justify-content: center; }

.axe-data-table__sort-btn:hover {
  color: var(--text-primary);
}

.axe-data-table__sort-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}

.axe-data-table__sort-arrow {
  font-size: 0.8em;
  color: var(--text-muted);
  line-height: 1;
}

.axe-data-table__th--active .axe-data-table__sort-arrow {
  color: var(--accent);
}

.axe-data-table__tr {
  border-bottom: 1px solid var(--border-subtle);
  transition: background-color var(--duration-fast, 120ms) var(--ease-out, ease-out);
}

.axe-data-table__tr:last-child {
  border-bottom: 0;
}

.axe-data-table__tr:hover {
  background: color-mix(in oklch, var(--accent) 4%, transparent);
}

.axe-data-table__tr--clickable {
  cursor: pointer;
}

.axe-data-table__tr--clickable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.axe-data-table__td {
  padding: var(--space-3) var(--space-4);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}

.axe-data-table__td--right  { text-align: right; }
.axe-data-table__td--center { text-align: center; }

/* empty state */
.axe-data-table__tr--empty:hover { background: transparent; }
.axe-data-table__empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* skeleton rows */
.axe-data-table__tr--skeleton:hover { background: transparent; }

.axe-data-table__skel {
  display: inline-block;
  width: 70%;
  height: 12px;
  background-color: var(--bg-subtle);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklch, var(--text-primary) 6%, transparent) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  background-position: -150% 0;
  animation: axe-data-table-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

@keyframes axe-data-table-shimmer {
  0%   { background-position: -150% 0; }
  100% { background-position:  150% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .axe-data-table__tr,
  .axe-data-table__sort-btn {
    transition: none;
  }
  .axe-data-table__skel {
    animation: none;
    background-image: none;
  }
}

@media (max-width: 480px) {
  .axe-data-table__th,
  .axe-data-table__td,
  .axe-data-table__sort-btn {
    padding: var(--space-2) var(--space-3);
  }
  .axe-data-table__table {
    font-size: var(--text-xs);
  }
}

/* ============================================================
 * Pagination — page nav.
 *   info | list (이전 + page btns + 다음).
 *   compact 시 list 안의 페이지 버튼이 "current / total" 텍스트로 치환.
 * ============================================================ */
.axe-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-variant-numeric: tabular-nums;
}

.axe-pagination__info {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.axe-pagination__info-range {
  color: var(--text-primary);
  font-weight: var(--weight-medium);
}

.axe-pagination__info-sep {
  color: var(--text-muted);
}

.axe-pagination__info-total {
  color: var(--text-secondary);
}

.axe-pagination__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.axe-pagination__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 var(--space-2);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition:
    background-color var(--duration-fast, 120ms) var(--ease-out, ease-out),
    color var(--duration-fast, 120ms) var(--ease-out, ease-out),
    border-color var(--duration-fast, 120ms) var(--ease-out, ease-out);
}

.axe-pagination__btn:hover:not(:disabled):not(.axe-pagination__btn--active) {
  background: var(--bg-subtle);
  color: var(--text-primary);
}

.axe-pagination__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.axe-pagination__btn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.axe-pagination__btn--active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
  cursor: default;
}

.axe-pagination__btn--nav {
  font-size: var(--text-lg);
  line-height: 1;
}

.axe-pagination__ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 32px;
  color: var(--text-muted);
  font-size: var(--text-sm);
  user-select: none;
}

/* size sm */
.axe-pagination--size-sm .axe-pagination__btn {
  min-width: 28px;
  height: 28px;
  font-size: var(--text-xs);
}
.axe-pagination--size-sm .axe-pagination__btn--nav {
  font-size: var(--text-base);
}
.axe-pagination--size-sm .axe-pagination__ellipsis {
  height: 28px;
  font-size: var(--text-xs);
}

/* compact 모바일 */
.axe-pagination--compact {
  justify-content: center;
}
.axe-pagination__compact-label {
  display: inline-flex;
  align-items: baseline;
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.axe-pagination__compact-current {
  font-weight: var(--weight-semibold);
}
.axe-pagination__compact-sep {
  color: var(--text-muted);
  padding: 0 var(--space-1);
}
.axe-pagination__compact-total {
  color: var(--text-secondary);
}

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

/* ============================================================
 * Chart — recharts wrap container.
 *   recharts SVG 가 컨테이너 100% 차지 → axe-chart 가 height 지정자.
 *   tooltip 은 portal 아닌 inline div — axe-chart__tooltip 으로 자체 styling.
 *
 *   색 매핑 (Chart.tsx 와 동기화):
 *     · series color: --accent → --success → --warning → --danger → --info 순환
 *     · axis tick:    --text-secondary
 *     · grid line:    --border-subtle  (strokeDasharray 3 3)
 *     · tooltip bg:   --bg-elevated  border: --border-subtle
 *     · dashed line:  strokeDasharray 5 4  — series.dashed=true 시
 *     · gradient area: 0%→35% / 100%→2% (의미: 최근일수록 진함)
 * ============================================================ */
.axe-chart {
  width: 100%;
  color: var(--text-primary);
}

/* tooltip — recharts content 안에서 사용 */
.axe-chart__tooltip {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md, var(--shadow-sm, 0 2px 8px rgb(0 0 0 / 0.1)));
  padding: var(--space-2) var(--space-3);
  min-width: 120px;
  font-size: var(--text-xs);
  color: var(--text-primary);
  pointer-events: none;
}

.axe-chart__tooltip-label {
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  margin-bottom: var(--space-1);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--border-subtle);
}

.axe-chart__tooltip-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.axe-chart__tooltip-row {
  display: grid;
  grid-template-columns: 12px 1fr auto;
  align-items: center;
  gap: var(--space-2);
}

.axe-chart__tooltip-swatch {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-sm);
  display: inline-block;
}

.axe-chart__tooltip-name {
  color: var(--text-secondary);
}

.axe-chart__tooltip-value {
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

/* recharts text default 가 SVG fill — focus ring 은 SVG 가 자체 처리.
   reduced-motion 은 컴포넌트 prop 으로 animation false (Chart.tsx).  */

/* ====== dashboard.css  (src: /Users/axe/axelabs/src/lib/styles/dashboard.css) ====== */

/* ============================================================
 * Dashboard primitives (Phase 7)
 *   StatusLight · MetricCard · PipelineTable
 *
 *   본 파일은 components.css 통합 전 Phase 7 격리 CSS.  소비자는
 *   globals.css 또는 showcase page 에서 직접 import.
 *
 *   원칙
 *     · token-only — Tailwind 0, hard-coded color 0.
 *     · CSS-only animation (pulse / hover transition).
 *     · prefers-reduced-motion: reduce 시 모든 motion 정지/완화.
 *     · light/dark 자동 — CSS var 만 사용.
 * ============================================================ */

/* ============================================================
 * StatusLight — 색 dot (+ optional label / timestamp).
 *
 *   variant canonical: ok | warning | danger | muted | running
 *     ok      → --success
 *     warning → --warning
 *     danger  → --danger
 *     muted   → --text-muted (회색)
 *     running → --info       (파란 계열, pulse 권장)
 *
 *   size sm 8 / md 10 / lg 12 (px).  baseline 정렬은 inline-flex.
 * ============================================================ */
.axe-status-light {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  line-height: 1;
  vertical-align: middle;
}

.axe-status-light__dot {
  flex-shrink: 0;
  display: inline-block;
  border-radius: var(--radius-full);
  background: currentColor; /* color 는 variant 가 결정 */
  /* dot 자체에는 color 못 줌 → variant 가 .axe-status-light 의 color 를 세팅,
     dot 의 background: currentColor 로 상속. */
}

/* size — dot 만 영향, label 은 부모 font 추종. */
.axe-status-light--size-sm .axe-status-light__dot { width: 8px;  height: 8px;  }
.axe-status-light--size-md .axe-status-light__dot { width: 10px; height: 10px; }
.axe-status-light--size-lg .axe-status-light__dot { width: 12px; height: 12px; }

/* variant — currentColor 만 바꿈 (dot 은 currentColor 상속, label/timestamp 는
   별도 색 가짐).  light/dark 모두 token 으로 자동 적응. */
.axe-status-light--ok      { color: var(--success); }
.axe-status-light--warning { color: var(--warning); }
.axe-status-light--danger  { color: var(--danger);  }
.axe-status-light--muted   { color: var(--text-muted); }
.axe-status-light--running { color: var(--info);    }

/* label / timestamp 는 currentColor 무시하고 본 token 사용 — dot 만 컬러풀. */
.axe-status-light__label {
  color: var(--text-primary);
  font-weight: var(--weight-medium);
}
.axe-status-light__timestamp {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
}

/* Pulse — dot 만 깜박임.  label 영향 X.
   transform 대신 opacity + box-shadow ring 으로 — GPU 합성, layout 영향 0. */
.axe-status-light--pulse .axe-status-light__dot {
  animation: axe-status-light-pulse 1.6s ease-in-out infinite;
  box-shadow: 0 0 0 0 currentColor;
}

@keyframes axe-status-light-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklch, currentColor 50%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in oklch, currentColor 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in oklch, currentColor 0%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .axe-status-light--pulse .axe-status-light__dot {
    animation: none;
    box-shadow: none;
  }
}

/* ============================================================
 * MetricCard — KPI tile.
 *   layout: vertical stack (label → value → meta → sparkline).
 *   숫자 정렬: tabular-nums on value/delta/sparkline.
 * ============================================================ */
.axe-metric-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  /* sparkline 의 currentColor 상속용 base color. */
  color: var(--text-primary);
}

.axe-metric-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.axe-metric-card__label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--weight-medium);
}

.axe-metric-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.axe-metric-card__value {
  font-family: var(--font-display, inherit);
  font-size: var(--text-3xl);
  font-weight: var(--weight-semibold);
  line-height: 1.1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  /* 긴 값 줄바꿈 방지 — overflow ellipsis */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.axe-metric-card__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}

.axe-metric-card__delta {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
}

.axe-metric-card__delta--up   { color: var(--success); }
.axe-metric-card__delta--down { color: var(--danger); }
.axe-metric-card__delta--flat { color: var(--text-muted); }

.axe-metric-card__delta-arrow {
  font-size: 0.85em;
  line-height: 1;
}

.axe-metric-card__delta-label {
  color: var(--text-muted);
  font-weight: var(--weight-regular);
}

.axe-metric-card__helper {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.axe-metric-card__sparkline {
  display: block;
  width: 100%;
  height: 24px;
  margin-top: var(--space-1);
  color: var(--accent);
  opacity: 0.85;
  overflow: visible;
}

/* Loading skeleton — 자체 shimmer.  indicators.css 의 .axe-skeleton 안가져옴
   (Phase 7 self-contained). */
.axe-metric-card--loading {
  pointer-events: none;
}

.axe-metric-card__skel {
  background-color: var(--bg-subtle);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklch, var(--text-primary) 6%, transparent) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  background-position: -150% 0;
  border-radius: var(--radius-sm);
  animation: axe-metric-card-shimmer 1.4s ease-in-out infinite;
}

.axe-metric-card__skel--label  { width: 40%; height: 10px; }
.axe-metric-card__skel--value  { width: 70%; height: 28px; border-radius: var(--radius-md); }
.axe-metric-card__skel--helper { width: 55%; height: 10px; }

@keyframes axe-metric-card-shimmer {
  0%   { background-position: -150% 0; }
  100% { background-position:  150% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .axe-metric-card__skel {
    animation: none;
    background-image: none;
  }
}

/* ============================================================
 * PipelineTable — operator status table.
 *   wrap > scroll > table.  모바일 → 가로 스크롤.
 *   row hover: bg 미세 시프트.  clickable row 는 cursor + focus ring.
 * ============================================================ */
.axe-pipeline-table {
  width: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden; /* radius clip */
}

.axe-pipeline-table__scroll {
  width: 100%;
  overflow-x: auto;
  /* iOS momentum */
  -webkit-overflow-scrolling: touch;
}

.axe-pipeline-table__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  /* 모바일에서 너무 좁아지면 가로 스크롤이 의미 있도록 min-width 잡음.
     기본 600px — column.width 합산이 더 크면 자동으로 더 넓어짐. */
  min-width: 600px;
}

.axe-pipeline-table__thead {
  background: var(--bg-subtle);
}

.axe-pipeline-table__th {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}

.axe-pipeline-table__th--right  { text-align: right; }
.axe-pipeline-table__th--center { text-align: center; }
.axe-pipeline-table__th--status {
  width: 32px;
  padding-right: 0;
}

.axe-pipeline-table__tr {
  border-bottom: 1px solid var(--border-subtle);
  transition: background-color var(--duration-fast, 120ms) var(--ease-out, ease-out);
}

.axe-pipeline-table__tr:last-child {
  border-bottom: 0;
}

.axe-pipeline-table__tr:hover {
  background: color-mix(in oklch, var(--accent) 4%, transparent);
}

.axe-pipeline-table__tr--clickable {
  cursor: pointer;
}

.axe-pipeline-table__tr--clickable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.axe-pipeline-table__td {
  padding: var(--space-3) var(--space-4);
  color: var(--text-primary);
  /* numeric 정렬 — 좌측 텍스트는 자연스레 무시. */
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}

.axe-pipeline-table__td--right  { text-align: right; }
.axe-pipeline-table__td--center { text-align: center; }
.axe-pipeline-table__td--status {
  width: 32px;
  padding-right: 0;
  text-align: center;
}

/* empty state */
.axe-pipeline-table__tr--empty:hover { background: transparent; }
.axe-pipeline-table__empty {
  padding: var(--space-5) var(--space-4);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* skeleton rows */
.axe-pipeline-table__tr--skeleton:hover { background: transparent; }

.axe-pipeline-table__skel {
  display: inline-block;
  background-color: var(--bg-subtle);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklch, var(--text-primary) 6%, transparent) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  background-position: -150% 0;
  animation: axe-pipeline-table-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

.axe-pipeline-table__skel--dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
}

.axe-pipeline-table__skel--bar {
  width: 70%;
  height: 12px;
}

@keyframes axe-pipeline-table-shimmer {
  0%   { background-position: -150% 0; }
  100% { background-position:  150% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .axe-pipeline-table__tr {
    transition: none;
  }
  .axe-pipeline-table__skel {
    animation: none;
    background-image: none;
  }
}

/* 모바일 viewport (≤480px) — padding 줄이고 font 더 작게.
   그래도 가로 스크롤이 우선 — table min-width 가 살아있음. */
@media (max-width: 480px) {
  .axe-pipeline-table__th,
  .axe-pipeline-table__td {
    padding: var(--space-2) var(--space-3);
  }
  .axe-pipeline-table__table {
    font-size: var(--text-xs);
  }
}

/* ====== feedback.css  (src: /Users/axe/axelabs/src/lib/styles/feedback.css) ====== */

/* ============================================================
 * Phase 14 Wave 5 — Feedback group  (EmptyState · ErrorBoundary)
 *
 *  - 본 파일은 components.css 가 import 하지 않음 (owner 가 통합).
 *    showcase 와 통합 전 까지는 page 가 직접 side-effect import.
 *  - 표면은 transparent 또는 elevated.  semantic 색은 icon/border 만.
 *  - reduced-motion 존중, dark/light CSS var 자동.
 * ============================================================ */

/* ────────────────────────────────────────────────────────────
 * EmptyState
 *   - center-aligned column.  background: transparent → Card 안/밖 모두 자연.
 *   - icon → title → description → actions 순서.
 *   - size 가 padding + icon box + 폰트 크기 비례.
 *   - tone 이 icon 색 + (subtle) border accent 결정.
 * ──────────────────────────────────────────────────────────── */
.axe-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-5);
  background: transparent;
  border: 1px dashed var(--border-subtle);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
}

.axe-empty-state__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  font-size: 24px;
  line-height: 1;
}

.axe-empty-state__title {
  font-family: var(--font-display, var(--font-sans));
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.3;
}

.axe-empty-state__description {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
  max-width: 48ch;
}

.axe-empty-state__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* ── size variants ── */
.axe-empty-state--size-sm {
  padding: var(--space-5) var(--space-4);
  gap: var(--space-2);
}
.axe-empty-state--size-sm .axe-empty-state__icon {
  width: 36px;
  height: 36px;
  font-size: 18px;
}
.axe-empty-state--size-sm .axe-empty-state__title {
  font-size: var(--text-base);
}
.axe-empty-state--size-sm .axe-empty-state__description {
  font-size: var(--text-xs);
}

.axe-empty-state--size-lg {
  padding: var(--space-8) var(--space-6);
  gap: var(--space-4);
}
.axe-empty-state--size-lg .axe-empty-state__icon {
  width: 64px;
  height: 64px;
  font-size: 32px;
}
.axe-empty-state--size-lg .axe-empty-state__title {
  font-size: var(--text-xl);
}

/* ── tone variants — icon tint + border accent (subtle) ── */
.axe-empty-state--tone-success {
  border-color: color-mix(in srgb, var(--success) 35%, var(--border-subtle));
}
.axe-empty-state--tone-success .axe-empty-state__icon {
  background: var(--success-soft);
  color: var(--success);
}

.axe-empty-state--tone-warning {
  border-color: color-mix(in srgb, var(--warning) 35%, var(--border-subtle));
}
.axe-empty-state--tone-warning .axe-empty-state__icon {
  background: var(--warning-soft);
  color: var(--warning);
}

.axe-empty-state--tone-danger {
  border-color: color-mix(in srgb, var(--danger) 35%, var(--border-subtle));
}
.axe-empty-state--tone-danger .axe-empty-state__icon {
  background: var(--danger-soft);
  color: var(--danger);
}

/* ────────────────────────────────────────────────────────────
 * ErrorBoundary — default fallback 의 wrapper.
 *   - Callout(variant="danger") 가 본체.  여기서는 spacing + 액션 row 만.
 *   - custom fallback 을 쓰면 caller 책임.
 * ──────────────────────────────────────────────────────────── */
.axe-error-boundary {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.axe-error-boundary__detail {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}

.axe-error-boundary__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
