/* IrEun 모바일 — 순수 모바일 앱 (PC 와 다른 디자인). 화면 개편 B+C (2026-10-29) · 12차 로그인 가운데 정렬·도구 허브 · 19차 모바일 디자인 시스템 (2026-10-30)
   B: 카드 면·그림자 없이 흰 묶음 목록(설정 앱처럼) · 탭은 바닥에 붙은 막대 · 대화 답은 말풍선 없이 문서처럼 · 유리·흐림·메시 배경 없음
   C: 대화가 첫 칸 · IrEun 이 오늘 요약·승인·상태를 대화 첫머리에서 먼저 알려 줌 · 답 옆에 아바타
   아바타: 테두리·고리·배경 원 없음. 투명 전신(avatar-bot.png) 위에 눈만 SVG 로 얹어 깜빡인다.
   19차 규칙: 글자 13px 이상 · 글자 대비 AA(4.5:1) · 누르는 곳 44px 이상(주 동작 48) · 안전 영역(노치·홈 바) · 세로 스크롤 대신 하위 탭·쪽 넘김·시트
   움직임: 120 / 200 / 320ms, transform·opacity 만. prefers-reduced-motion 또는 설정 "움직임 줄이기"(html.calm)면 전부 끔.
   26차 M (10-30, 사용자 요청 "참고 이미지처럼 색 조합·레이아웃 고도화"): B 의 "유리·흐림·메시 없음"을 의도적으로 뒤집는다 —
   밝은 바탕(크림·연보라·연피치 빛 번짐) 위에 흰 반투명 유리 카드(backdrop-filter) + 1px 흰 테두리 + 부드러운 그림자. 브랜드 = Viola(--vi-*), 날씨·경고·따뜻한 강조 = Sunset(--su-*), 유리 = --g-*.
   라이트 전용 그대로 · 글자 대비 AA 그대로 · 왼쪽 강조선·아이콘 고리 없음. 그라데이션은 배경 빛 번짐과 강조(주 단추·내 말풍선·날씨)에만. */
@font-face { font-family: "FA"; src: url("/m/fa-solid-900.woff2") format("woff2"); font-weight: 900; font-display: block; } /* Font Awesome Free, SIL OFL 1.1 */

/* ───────── 1. 토큰 ───────── */
:root {
  color-scheme: light;
  /* 26차 M 공용 팔레트 (텔레그램 카드 그림과 같은 값). Viola = 브랜드 · Sunset = 날씨·경고·따뜻한 강조 · Glass = 유리 면 */
  /* 값 = design\목업\27_참고자료분석.html 통합 팔레트 (텔레그램 카드와 공유). 오키드 #C254B8 · Sunset #EA6113 은 글자에 안 쓴다(흰 바탕 4.0:1·3.4:1) */
  --vi-ink: #2A1636; --vi-ink2: #6B6275;                                  /* 글자 15.4:1 · 보조 글자 5.4:1 */
  --vi-700: #6B1A96; --vi-900: #4A1E3F; --vi-400: #C254B8;                /* viola(주 강조) · plum(진한 글자 강조·눌림) · orchid(장식·그라데이션만) */
  --vi-200: #E6D6F0; --vi-100: #F4EEF6; --vi-peach: #F5C77E; --vi-cream: #FBE3C4;
  --su-600: #EA6113; --su-500: #F88F22; --su-400: #FBB931; --su-200: #FFE3B3; --su-100: #FFF4E4; --su-text: #B84A0C;   /* su-text 는 흰·크림 면 위 글자 전용 (5.2:1) */
  --t-sand: #F6E3B8; --t-terra: #F3C9B5; --t-sage: #D5E5D3; --t-slate: #D4DDEE; --t-lav: #E6D6F0;                       /* 도구 아이콘 타일 */
  --g-bg: #FBF6F0; --g-glow-1: #F3E6F5; --g-glow-2: #FFE3B3;
  --g-card: rgba(255,255,255,.78); --g-card-hi: rgba(255,255,255,.9); --g-line: rgba(255,255,255,.92); --g-edge: rgba(107,26,150,.14);
  --g-blur: blur(18px) saturate(150%);
  --g-sh: 0 1px 2px rgba(74,30,63,.04), 0 6px 24px rgba(74,30,63,.08);
  --g-sh-bar: 0 8px 24px rgba(74,30,63,.10);
  --g-glow: radial-gradient(100% 55% at 0% -6%, var(--g-glow-1) 0%, var(--g-glow-1) 22%, rgba(243,230,245,0) 70%), radial-gradient(90% 50% at 104% 6%, var(--g-glow-2) 0%, rgba(255,227,179,.6) 26%, rgba(255,227,179,0) 68%), radial-gradient(110% 45% at 20% 110%, var(--g-glow-1) 0%, rgba(243,230,245,0) 70%);
  --vi-grad: linear-gradient(135deg, #6B1A96 0%, #C254B8 55%, #F5C77E 100%);   /* 브랜드 그라데이션 (장식·큰 면) */
  --vi-grad2: linear-gradient(135deg, #6B1A96 0%, #8A2FA8 100%);               /* 흰 글자를 얹는 단추·내 말풍선 (어느 점에서도 흰 글자 AA) */
  --su-grad: linear-gradient(135deg, var(--su-200) 0%, var(--su-100) 42%, rgba(255,255,255,.78) 100%);
  /* 앱이 쓰는 이름 (값은 위 팔레트). --faint 는 아이콘·선 전용 */
  --bg: var(--g-bg); --card: #FFFFFF; --line: #ECE3EF; --line2: #F3EDF4; --border: #DCD0E2; --fill: #F6F0F4; --fill2: #F0E8F1;
  --fg: var(--vi-ink); --mut: var(--vi-ink2); --faint: #A398AD; --ph: #756D7F;
  --ac: var(--vi-700); --ach: var(--vi-900); --acs: var(--vi-100);
  --warm: var(--su-text); --warms: var(--su-100);
  --ok: #0F7A4C; --oks: #E7F5EE; --warn: #8F5506; --warns: #FDF1DC; --err: #B22F3A; --errs: #FBE6E8;   /* 상태 알약 쌍 (글자/바탕, 모두 4.5:1 이상) */
  --dot-ok: #16955F; --dot-warn: #C77A0A; --dot-err: #D63A45; --dot-off: #C9BFD0;
  --k-local: #30B0C7; --k-claude: #AF52DE; --k-free: #0A84FF;
  --scrim: rgba(31,20,48,.30);
  /* 글자 단계 (최소 13) */
  --fs-1: 13px; --fs-2: 14px; --fs-3: 15px; --fs-4: 17px; --fs-5: 20px; --fs-6: 28px;
  /* 간격 (4 단위) */
  --g1: 4px; --g2: 8px; --g3: 12px; --g4: 16px; --g5: 20px; --g6: 24px;
  /* 반경 */
  --r: 12px; --r-s: 8px; --r-pill: 22px;
  /* 누르는 높이: 보통 44 · 주 동작 48 */
  --tap: 44px; --tap-l: 48px;
  /* 틀 */
  --tab-h: 74px; --comp-h: 64px; --hd-h: 56px;   /* 26차 M: 탭 = 떠 있는 알약 64 + 아래 틈 10 · 입력 띠 = 58 + 위 틈 6 */
  /* 움직임 */
  --d1: 120ms; --d2: 200ms; --d3: 320ms;
  --ease: cubic-bezier(.2,.7,.2,1); --ease-io: cubic-bezier(.4,0,.2,1);
  --t: var(--d2) var(--ease); --t-in: var(--d2) var(--ease);
  /* 안전 영역 */
  --safe-t: env(safe-area-inset-top, 0px); --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px); --safe-r: env(safe-area-inset-right, 0px);
}
/* 22차 M: 아래 안전 영역은 시작할 때(그리고 화면을 돌릴 때만) 한 번 잰 값으로 고정한다 — 브라우저 도구 막대가 숨었다 나타날 때 inset 이 흔들려도 바닥 바·입력 띠가 따라 움직이지 않게 (app.js 가 html 에 --sb 를 px 로 적는다) */
/* 26차 M: --sb = 홈 바(--sb0, app.js 가 한 번 잰 값) + 텔레그램 Mini App 이 보이는 칸 아래로 가린 높이(--tgb, app.js tgFit). 텔레그램 밖에서는 --tgb = 0 */
html { --tgb: 0px; --sb: calc(var(--sb0, var(--safe-b)) + var(--tgb)); }
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; min-height: 100%; overscroll-behavior-y: none; }   /* 브라우저 당겨서 새로고침 대신 앱 것 */
/* 빛 번짐 바탕: 화면에 고정된 한 장(스크롤해도 그대로 · background-attachment: fixed 는 폰에서 느려서 안 씀) */
body::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background: var(--g-glow), var(--bg); }
body { background: var(--bg); color: var(--fg); font: var(--fs-2)/1.5 -apple-system, "Pretendard", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif; -webkit-text-size-adjust: 100%; overflow-x: hidden;
  word-break: keep-all; overflow-wrap: anywhere; }   /* 22차 M: 한글은 낱말 중간에서 줄을 바꾸지 않는다 (아주 긴 낱말만 아무 데서나) */
p, .say span:not(.av), .meta, .msg, .empty, .notice span, .doc .tx, .lg-say span { text-wrap: pretty; }   /* 마지막 줄에 글자 하나만 남지 않게 */
button { font: inherit; color: inherit; }
input, textarea, select { font: inherit; color: var(--fg); outline: 0; -webkit-appearance: none; appearance: none; border-radius: 0; }   /* iOS·안드로이드 기본 모양(둥근 테·안쪽 그림자) 초기화 */
input[type=search]::-webkit-search-decoration, input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
input::placeholder, textarea::placeholder { color: var(--ph); }
:focus-visible { outline: 2px solid var(--ac); outline-offset: 2px; }

/* Font Awesome (쓰는 것만) */
.fa { font-family: "FA"; font-weight: 900; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; }
.fa-key::before { content: "\f084"; } .fa-paper-plane::before { content: "\f1d8"; } .fa-gauge-high::before { content: "\f625"; }
.fa-microchip::before { content: "\f2db"; } .fa-cloud::before { content: "\f0c2"; } .fa-inbox::before { content: "\f01c"; }
.fa-rotate::before { content: "\f2f1"; } .fa-gear::before { content: "\f013"; } .fa-broom::before { content: "\f51a"; }
.fa-xmark::before { content: "\f00d"; } .fa-comments::before { content: "\f086"; } .fa-check::before { content: "\f00c"; }
.fa-stop::before { content: "\f04d"; } .fa-bell::before { content: "\f0f3"; } .fa-copy::before { content: "\f0c5"; }
.fa-rotate-right::before { content: "\f2f9"; } .fa-circle-notch::before { content: "\f1ce"; } .fa-triangle-exclamation::before { content: "\f071"; }
.fa-lock::before { content: "\f023"; } .fa-eye::before { content: "\f06e"; } .fa-eye-slash::before { content: "\f070"; } .fa-plus::before { content: "\2b"; }
.fa-chevron-right::before { content: "\f054"; } .fa-chevron-left::before { content: "\f053"; } .fa-chevron-down::before { content: "\f078"; }
.fa-right-from-bracket::before { content: "\f2f5"; } .fa-right-to-bracket::before { content: "\f2f6"; }
.fa-arrow-up::before { content: "\f062"; } .fa-wand-magic-sparkles::before { content: "\e2ca"; } .fa-arrow-right::before { content: "\f061"; }
.fa-robot::before { content: "\f544"; } .fa-circle-info::before { content: "\f05a"; } .fa-shield-halved::before { content: "\f3ed"; }
.fa-wave-square::before { content: "\f83e"; } .fa-plug::before { content: "\f1e6"; } .fa-mobile-screen::before { content: "\f3cf"; }
.fa-desktop::before { content: "\f390"; } .fa-user::before { content: "\f007"; } .fa-link::before { content: "\f0c1"; }
.fa-ban::before { content: "\f05e"; } .fa-envelope::before { content: "\f0e0"; } .fa-vial::before { content: "\f492"; }
.fa-screwdriver-wrench::before { content: "\f7d9"; } .fa-list-check::before { content: "\f0ae"; } .fa-pen::before { content: "\f304"; }
.fa-language::before { content: "\f1ab"; } .fa-circle-check::before { content: "\f058"; }
/* 12차 도구 */
.fa-toolbox::before { content: "\f552"; } .fa-cloud-sun::before { content: "\f6c4"; } .fa-building::before { content: "\f1ad"; }
.fa-image::before { content: "\f03e"; } .fa-download::before { content: "\f019"; } .fa-code::before { content: "\f121"; } .fa-file-lines::before { content: "\f15c"; }
.fa-comment::before { content: "\f075"; } .fa-location-dot::before { content: "\f3c5"; } .fa-magnifying-glass::before { content: "\f002"; }
.fa-paperclip::before { content: "\f0c6"; } .fa-stethoscope::before { content: "\f0f1"; } .fa-power-off::before { content: "\f011"; }
.fa-hourglass-half::before { content: "\f252"; } .fa-play::before { content: "\f04b"; }
.fa-microphone::before { content: "\f130"; }
/* 19차 */
.fa-star::before { content: "\f005"; } .fa-clock-rotate-left::before { content: "\f1da"; } .fa-sliders::before { content: "\f1de"; }
.fa-arrow-up-from-bracket::before { content: "\e09a"; } .fa-square-plus::before { content: "\f0fe"; } .fa-wifi::before { content: "\f1eb"; }
.fa-trash-can::before { content: "\f2ed"; } .fa-cloud-arrow-down::before { content: "\f0ed"; } .fa-hand-pointer::before { content: "\f25a"; }
.fa-database::before { content: "\f1c0"; } .fa-ellipsis::before { content: "\f141"; } .fa-arrow-left::before { content: "\f060"; }
/* 22차 M */
.fa-arrow-down::before { content: "\f063"; } .fa-up-right-from-square::before { content: "\f35d"; } .fa-user-plus::before { content: "\f234"; }
.fa-share-nodes::before { content: "\f1e0"; } .fa-user-slash::before { content: "\f506"; } .fa-unlock::before { content: "\f09c"; }
/* 26차 M 날씨 · 지도 */
.fa-sun::before { content: "\f185"; } .fa-moon::before { content: "\f186"; } .fa-cloud-moon::before { content: "\f6c3"; } .fa-cloud-rain::before { content: "\f73d"; }
.fa-cloud-showers-heavy::before { content: "\f740"; } .fa-snowflake::before { content: "\f2dc"; } .fa-cloud-bolt::before { content: "\f76c"; } .fa-smog::before { content: "\f75f"; }
.fa-wind::before { content: "\f72e"; } .fa-rainbow::before { content: "\f75b"; } .fa-temperature-high::before { content: "\f769"; } .fa-temperature-low::before { content: "\f76b"; }
.fa-hurricane::before { content: "\f751"; } .fa-umbrella::before { content: "\f0e9"; } .fa-map::before { content: "\f279"; }
.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ───────── 2. 공용 조각 ───────── */
.sp { flex: 1; }
.meta { font-size: var(--fs-1); color: var(--mut); }
.ell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.mono { font-family: Consolas, "D2Coding", ui-monospace, monospace; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dot-off); flex: none; display: inline-block; vertical-align: middle; }
.dot.ok { background: var(--dot-ok); } .dot.warn { background: var(--dot-warn); } .dot.err { background: var(--dot-err); }
.dot.local { background: var(--k-local); } .dot.claude { background: var(--k-claude); } .dot.free { background: var(--k-free); }
/* 아이콘 단추 44 */
.ib { width: var(--tap); height: var(--tap); border-radius: var(--r); border: 0; background: transparent; display: grid; place-items: center; font-size: 17px; flex: none; position: relative; cursor: pointer; color: var(--fg); transition: transform var(--d1) var(--ease), background var(--d1); }
.ib:active { transform: scale(.92); background: var(--fill2); }
.ib .nd { position: absolute; top: 9px; right: 9px; width: 9px; height: 9px; border-radius: 50%; background: var(--dot-err); border: 2px solid var(--bg); }
/* 단추: 보통 44 · 주 동작(.pri.wide) 48 */
.btn { font: inherit; font-weight: 700; font-size: var(--fs-3); border: 1px solid var(--border); background: var(--card); color: var(--fg); border-radius: var(--r); min-height: var(--tap); padding: 0 16px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer; white-space: nowrap; transition: transform var(--d1) var(--ease), background var(--d1), opacity var(--d1); }
.btn:active { transform: scale(.97); }
.btn.pri { background: var(--ac) var(--vi-grad2); border-color: transparent; color: #fff; box-shadow: 0 6px 16px -6px rgba(107,26,150,.45); }
.btn.pri:active { background: var(--ach); }
.btn:not(.pri):not(.ghost) { background: var(--g-card-hi); border-color: var(--g-edge); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--mut); }
.btn.danger { color: var(--err); }
.btn.sm { min-height: var(--tap); padding: 0 14px; font-size: var(--fs-2); border-radius: 10px; }
.btn.wide { width: 100%; min-height: var(--tap-l); }
.btn:disabled { opacity: .45; }
.tag { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 8px; border-radius: 6px; font-size: var(--fs-1); font-weight: 700; background: var(--fill2); color: var(--mut); flex: none; white-space: nowrap; }
.tag.ok { background: var(--oks); color: var(--ok); } .tag.warn { background: var(--warns); color: var(--warn); } .tag.err { background: var(--errs); color: var(--err); } .tag.ac { background: var(--acs); color: var(--ach); }
.tag.g-pub { background: #E8F7EC; color: #1F7A36; } .tag.g-int { background: #E6F1FF; color: #0059B8; } .tag.g-sen { background: #FFF2E0; color: #8A4E00; } .tag.g-forb { background: #FDECEE; color: #B8222E; }
.bar { height: 6px; border-radius: 3px; background: var(--fill2); overflow: hidden; display: block; }
.bar > i { display: block; height: 100%; border-radius: 3px; background: var(--faint); transform-origin: left center; transition: transform var(--d3) var(--ease); }
.bar.run > i { width: 40%; background: var(--ac); animation: run 1.1s ease-in-out infinite; }
@keyframes run { 0% { transform: translateX(-100%); } 100% { transform: translateX(260%); } }
/* 칩: 보이는 알약은 36, 누르는 곳은 44 (위아래 4px 투명) */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chips button, .sugs button, .chip { position: relative; isolation: isolate; height: var(--tap); padding: 0 14px; border: 0; background: none; font-size: var(--fs-2); font-weight: 600; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; color: var(--fg); transition: transform var(--d1) var(--ease); }
.chips button::before, .sugs button::before, .chip::before { content: ""; position: absolute; inset: 4px 0; z-index: -1; border-radius: 18px; background: var(--g-card-hi); border: 1px solid var(--g-edge); transition: background var(--d1), border-color var(--d1); }
.chips button:active, .sugs button:active, .chip:active { transform: scale(.96); }
.chips button.on { color: var(--ach); }
.chips button.on::before { border-color: var(--ac); background: var(--acs); }
.sugs button .fa { color: var(--faint); font-size: 13px; }
/* 스켈레톤 (불러오는 동안 · 반짝임 대신 옅게 숨쉬기) */
.sk { display: block; height: 14px; border-radius: 6px; background: var(--fill2); animation: skp 1.2s ease-in-out infinite; }
.sk.l { height: 20px; width: 60%; } .sk.s { width: 40%; } .sk.blk { height: 64px; border-radius: 10px; }
@keyframes skp { 50% { opacity: .45; } }
/* 빈 상태: 글리프 + 한 줄 + 설명 + (단추) */
.empty { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 8px 0 0; color: var(--mut); font-size: var(--fs-2); }
.empty b { color: var(--fg); font-size: var(--fs-4); }
.empty.c { align-items: center; text-align: center; padding: 28px 20px; }
.empty .ei { font-size: 28px; color: var(--faint); margin-bottom: 4px; }
/* 켜고 끄기 (줄 전체가 누르는 곳, 이건 그림) */
/* 26차 M: 이름을 .tg → .tgl 로 (html.tg 가 문서 전체를 46px 로 만들던 원인) */
.tgl { position: relative; width: 46px; height: 28px; border-radius: 14px; background: var(--border); flex: none; transition: background var(--d2); }
.tgl > i { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(74,30,63,.2); transition: transform var(--d2) var(--ease); }
[aria-pressed="true"] .tgl { background: var(--ac) var(--vi-grad2); }
[aria-pressed="true"] .tgl > i { transform: translateX(18px); }

/* ── 아바타: 투명 전신 + 눈 SVG. 테두리·고리·배경 원 없음 ── */
.av { --s: 40px; position: relative; display: inline-block; width: var(--s); height: var(--s); flex: none; line-height: 0; }
.av img.b { position: absolute; left: 5.43%; top: 0; width: 89.15%; height: 100%; display: block; -webkit-user-drag: none; user-select: none; }
.av svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.av .e { transform-box: fill-box; transform-origin: 50% 50%; animation: blink 6.2s ease-in-out infinite; fill: #14182A; }
.av .e .h { fill: #fff; opacity: .95; }
.av .e + .e { animation-delay: .02s; }
.av.fb img.b { left: 0; width: 100%; }   /* avatar-bot.png 를 못 받은 서버(옛 중계)면 눈이 그려진 avatar.png 로 */
.av.fb svg { display: none; }
.av.sm { --s: 28px; } .av.md { --s: 40px; } .av.lg { --s: 56px; } .av.xl { --s: 112px; }
.av .lk { transform: translate(var(--lx, 0px), var(--ly, 0px)); transition: transform 200ms cubic-bezier(.2,.7,.2,1); }   /* 눈이 보는 쪽 (로그인: 입력 칸) */
@keyframes blink { 0%, 44%, 48%, 100% { transform: scaleY(1); } 46% { transform: scaleY(.08); } }
/* 상태: 듣기(입력 중) · 생각(정하는 중) · 답하기(쓰는 중) · 잠(연결 끊김) */
.av[data-st="listen"] .e { animation: none; transform: scale(1.08); transition: transform var(--t); }
.av[data-st="think"] svg { animation: look 1.6s ease-in-out infinite alternate; }
.av[data-st="talk"] { animation: bob .9s ease-in-out infinite; }
.av[data-st="sleep"] .e { animation: none; transform: scaleY(.1); }
.av[data-st="shut"] .e { animation: none; transform: scaleY(.1); transition: transform 160ms ease; }      /* 비밀번호 칸: 눈 감기 */
.av[data-st="joy"] .e { animation: none; transform: scaleY(.42) translateY(-3px); transition: transform 160ms ease; }   /* 기쁨: 눈웃음 */
@keyframes look { from { transform: translate(-1.5%, -1%); } to { transform: translate(1.5%, -1%); } }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4%); } }

/* ───────── 3. 화면 틀 ───────── */
.view { padding: calc(8px + var(--safe-t)) calc(16px + var(--safe-r)) calc(var(--tab-h) + 20px + var(--sb)) calc(16px + var(--safe-l)); display: flex; flex-direction: column; gap: 10px; max-width: 560px; margin: 0 auto; overflow-x: clip; }   /* 옆으로 미끄러지는 전환이 화면 폭을 늘리지 않게 */
/* 화면 전환: 탭 사이는 방향대로 짧게 밀기(200) · 한 겹 들어가기(도구 한 장·계정)는 320 · 처음은 페이드 */
.view:not([hidden]) { animation: vin var(--d2) var(--ease) backwards; }
html[data-nav="r"] .view:not([hidden]) { animation-name: vr; }
html[data-nav="l"] .view:not([hidden]) { animation-name: vl; }
html[data-nav="push"] .view:not([hidden]) { animation: push var(--d3) var(--ease) backwards; }
html[data-nav="pop"] .view:not([hidden]) { animation: pop var(--d3) var(--ease) backwards; }
@keyframes vin { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes vr { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
@keyframes vl { from { opacity: 0; transform: translateX(-18px); } to { opacity: 1; transform: none; } }
@keyframes push { from { opacity: 0; transform: translateX(48px); } to { opacity: 1; transform: none; } }
@keyframes pop { from { opacity: 0; transform: translateX(-32px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
/* 카드 등장: 순서대로 (--i) */
.rise { animation: min var(--d2) var(--ease) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
.hd { display: flex; align-items: center; gap: 6px; min-height: var(--hd-h); }
.hd h2 { margin: 0; font-size: var(--fs-6); font-weight: 700; letter-spacing: -.02em; line-height: 1.2; }
.hd h2.sm { font-size: var(--fs-5); display: flex; align-items: center; gap: 8px; }
.hd .tt { min-width: 0; flex: 1 1 auto; }
.hd .back { margin-left: -10px; }
.hd .ib { margin-right: -4px; }
.gl { font-size: var(--fs-1); font-weight: 700; color: var(--mut); margin: 8px 16px -4px; display: flex; gap: 8px; align-items: baseline; }
.foot { margin: -2px 16px 0; }

/* 묶음 목록 (설정 앱처럼): 유리 면 하나 · 줄 사이 1px (유리 면 공통 규칙은 맨 끝 15번) */
.grp { border-radius: var(--r); overflow: hidden; display: flex; flex-direction: column; }
.grp.grp > * + * { border-top: 1px solid var(--line); }
/* 한 화면에 안 들어가는 화면은 하위 탭으로 나눈다 (세로 스크롤 금지). 좌우로 밀어도 넘어간다 */
.seg2 { display: flex; gap: 2px; padding: 3px; border-radius: 14px; background: rgba(240,232,241,.72); border: 1px solid var(--g-line); flex: none; }
.seg2 button { flex: 1; min-width: 0; height: var(--tap); border: 0; border-radius: 11px; background: transparent; color: var(--mut); font-size: var(--fs-2); font-weight: 600; cursor: pointer; white-space: nowrap; transition: background var(--d2), color var(--d2); }
.seg2 button.on { background: var(--card); color: var(--ach); font-weight: 700; box-shadow: 0 2px 8px rgba(74,30,63,.10); }
.pn { display: flex; flex-direction: column; gap: 10px; }
.pn:not([hidden]) { animation: vin var(--d2) var(--ease) backwards; }
[data-pane="sum"] [data-p]:not([data-p="sum"]), [data-pane="pc"] [data-p]:not([data-p="pc"]), [data-pane="ops"] [data-p]:not([data-p="ops"]),
[data-pane="id"] [data-p]:not([data-p="id"]), [data-pane="tg"] [data-p]:not([data-p="tg"]), [data-pane="dev"] [data-p]:not([data-p="dev"]),
[data-pane="sec"] [data-p]:not([data-p="sec"]), [data-pane="link"] [data-p]:not([data-p="link"]), [data-pane="users"] [data-p]:not([data-p="users"]),
[data-pane="me"] [data-p]:not([data-p="me"]), [data-pane="app"] [data-p]:not([data-p="app"]), [data-pane="data"] [data-p]:not([data-p="data"]) { display: none !important; }
[data-pane] [data-p]:not([hidden]) { animation: vin var(--d2) var(--ease) backwards; }
.row { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 6px 16px; width: 100%; background: none; border: 0; text-align: left; font: inherit; font-size: var(--fs-3); color: var(--fg); }
button.row { cursor: pointer; transition: background var(--d1); }
button.row:active { background: var(--fill); }
.row .ri { width: 20px; text-align: center; color: var(--faint); font-size: 16px; flex: none; }
.row .tx { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.row .tx b { font-size: var(--fs-3); font-weight: 600; }
.row .tx .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .v { font-weight: 600; font-size: var(--fs-2); color: var(--mut); max-width: 46%; text-align: right; white-space: nowrap; }
.row .chev { color: var(--faint); font-size: 13px; }
.row.tall { min-height: 60px; }
.row.danger .tx b, .row.danger .ri { color: var(--err); }
.tags { display: flex; gap: 4px; margin-top: 3px; flex-wrap: wrap; }
/* 칸 이름이 붙은 입력 줄 (줄 전체가 누르는 곳) */
.fr { display: flex; align-items: center; gap: 8px; min-height: 52px; padding: 0 4px 0 16px; cursor: text; }
.fr .k { width: 84px; flex: none; font-size: var(--fs-2); font-weight: 600; color: var(--fg); }
.fr input { flex: 1; min-width: 0; height: 50px; border: 0; background: transparent; padding: 0; font-size: 16px; }
.fr input[readonly] { color: var(--mut); }
.fr:focus-within .k { color: var(--ac); }
.fr .btn.sm, .fr .ib { flex: none; }
.notice { flex-direction: row; gap: 10px; align-items: flex-start; padding: 12px 16px; }
.notice > .fa { color: var(--mut); margin-top: 3px; }
.notice b { display: block; font-size: var(--fs-2); }
.notice span { display: block; font-size: var(--fs-1); color: var(--mut); }
.lockn { display: flex; gap: 6px; align-items: flex-start; margin: 2px 4px 0; }
.lockn .fa { margin-top: 3px; }
/* 검색 칸 (설정) */
.srch { display: flex; align-items: center; gap: 8px; height: var(--tap-l); padding: 0 2px 0 14px; border-radius: var(--r); background: var(--card); border: 1px solid var(--border); flex: none; transition: border-color var(--d1); }   /* 22차 M: 입력 칸 규격과 같게 */
.srch:focus-within { border-color: var(--ac); }
.srch input:focus-visible { outline: 0; }
.srch .fa { color: var(--mut); font-size: 14px; }
.srch input { flex: 1; min-width: 0; height: 100%; border: 0; background: transparent; font-size: 16px; }
.srch .ib { width: var(--tap); height: var(--tap); }
.srch .ib[hidden] { display: none; }
#v-set[data-pane="q"] .seg2, #v-set[data-pane="q"] .foot { display: none; }
#v-set .nomatch { display: none !important; }

/* IrEun 이 먼저 말하는 줄 (아바타 + 말 한 줄 + 보조 한 줄) */
.say { display: flex; gap: 10px; align-items: flex-start; }
.say > div { min-width: 0; padding-top: 2px; }
.say b { display: block; font-size: var(--fs-3); font-weight: 700; line-height: 1.4; }
.say span:not(.av) { display: block; font-size: var(--fs-1); color: var(--mut); line-height: 1.45; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.say.big b { font-size: var(--fs-4); }
.say.big { margin: 4px 0 2px; }

/* ───────── 4. 스플래시 ───────── */
/* 22차 M: 아바타가 떠오르고(0~620ms) 워드마크가 뒤따른다(140ms~). 기다림이 짧으면 거기서 끝 — 단계 글은 600ms, 진행 막대는 900ms 가 지나야 보인다(늦을 때만 얌전히).
   걷힐 때는 살짝 커지며 사라지고(240ms) 그 아래 화면(로그인·대화)의 등장 모션이 이어 받는다. 다시 열 때(지난 흔적이 있음)는 다음 프레임에 걷힌다 */
.splash { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding-bottom: calc(10vh + var(--tgb)); background: var(--g-glow), var(--bg); transition: opacity 240ms ease, transform 240ms var(--ease); }
.splash .av { animation: sprise 620ms cubic-bezier(.2,.8,.2,1) both; }
.splash .wm { height: 34px; width: auto; animation: rise 460ms 140ms var(--ease) both; }
.sp-step { font-size: var(--fs-1); color: var(--mut); min-height: 20px; animation: fade 240ms 600ms ease both; }
.prog { width: 148px; height: 4px; border-radius: 2px; background: var(--fill2); overflow: hidden; display: block; animation: fade 240ms 900ms ease both; }
.prog > i { display: block; height: 100%; width: 100%; border-radius: 2px; background: var(--ac); transform-origin: left center; transform: scaleX(.12); transition: transform 360ms var(--ease); }
.splash.out { opacity: 0; transform: scale(1.03); pointer-events: none; }
@keyframes sprise { from { opacity: 0; transform: translateY(18px) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ── 키 넣기 (왼쪽 정렬 · 묶음 입력) ── */
.wm-top { height: 26px; width: auto; align-self: flex-start; margin: 20px 0 12px; }
.steps { list-style: none; margin: 0; padding: 0; counter-reset: s; }
.steps li { counter-increment: s; display: grid; grid-template-columns: 24px 1fr; column-gap: 12px; align-items: center; min-height: 54px; padding: 6px 16px; }
.steps li::before { content: counter(s); grid-row: 1 / 3; font-weight: 700; color: var(--mut); font-size: var(--fs-2); }
.steps b { font-size: var(--fs-2); font-weight: 600; } .steps span { font-size: var(--fs-1); color: var(--mut); }
#v-key .btn.wide { margin-top: auto; }

/* ───────── 5. 로그인 (12차 A "떠 있는 아바타형"): 가운데 정렬 · 아바타 → 워드마크 → 한 줄 인사 → 입력 → 단계 점
   진입: 아바타 떠오름(0ms) → 워드마크 글자 순서대로(260ms~) → 인사·입력·단추·단계 점 스태거(520ms~). 전부 transform·opacity ── */
#v-login { min-height: 100dvh; justify-content: center; align-items: center; padding-bottom: calc(7vh + var(--sb)); }
#v-login:not([hidden]) { animation: none; }
.lg-stage { width: 100%; max-width: 360px; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0; }
.lg-stage.out { opacity: 0; transform: scale(.97) translateY(-8px); transition: opacity 240ms ease, transform 240ms ease; }
.lg-hero { position: relative; display: flex; flex-direction: column; align-items: center; animation: lgrise 620ms cubic-bezier(.2,.8,.2,1) both; }
.av.lg-av { --s: 136px; animation: breathe 3.6s ease-in-out 700ms infinite; }
.lg-shadow { display: block; width: 76px; height: 10px; margin-top: 4px; border-radius: 50%; background: rgba(29,29,31,.10); filter: blur(3px); animation: shadow 3.6s ease-in-out 700ms infinite; }
@keyframes lgrise { from { opacity: 0; transform: translateY(28px) scale(.92); } to { opacity: 1; transform: none; } }
@keyframes breathe { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
@keyframes shadow { 0%, 100% { transform: scaleX(1); opacity: 1; } 50% { transform: scaleX(.86); opacity: .7; } }
.wmk { height: 40px; width: auto; margin: 18px 0 14px; overflow: visible; }
.wmk .wl { transform-box: fill-box; transform-origin: 50% 100%; animation: wl 380ms cubic-bezier(.2,.8,.2,1) both; animation-delay: calc(260ms + var(--i) * 70ms); }
@keyframes wl { from { opacity: 0; transform: translateY(10px) scale(.9); } to { opacity: 1; transform: none; } }
.lg-in { animation: rise 360ms var(--ease) both; animation-delay: calc(560ms + var(--d, 0) * 70ms); }
.lg-say { margin: 0 0 18px; display: flex; flex-direction: column; gap: 2px; min-height: 44px; }
.lg-say b { font-size: var(--fs-4); font-weight: 700; letter-spacing: -.01em; }
.lg-say span { font-size: var(--fs-1); color: var(--mut); }
.lgf { width: 100%; display: flex; flex-direction: column; gap: 10px; }
.lgf .fr { text-align: left; }
.lgf[data-dir="fwd"] .lg-pane:not([hidden]):not(.lg-in) { animation: slf 260ms var(--ease) both; }
.lgf[data-dir="back"] .lg-pane:not([hidden]):not(.lg-in) { animation: slb 260ms var(--ease) both; }
@keyframes slf { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
@keyframes slb { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: none; } }
.lg-aux { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.lg-aux:not(:has(:not([hidden]))) { display: none; }
/* ── 22차 M 입력 칸 (.fld): 라벨 위 고정 · 칸 48 · 반경 12 · 선 1px 하나. 초점 = 선 색만 강조색(두께 그대로, 그림자 없음) · 오류 = 빨간 선 + 아래 한 줄 사유 ── */
.flds { display: flex; flex-direction: column; gap: 12px; width: 100%; }
.fld { display: flex; flex-direction: column; gap: 6px; text-align: left; width: 100%; }
.fld .fl { font-size: var(--fs-1); font-weight: 700; color: var(--fg); padding-left: 2px; }
.fld .fi { position: relative; display: flex; align-items: center; height: var(--tap-l); border: 1px solid var(--border); border-radius: var(--r); background: var(--card); transition: border-color var(--d1); }
.fld .fi:focus-within { border-color: var(--ac); }
.fld .fi input { flex: 1; min-width: 0; height: 100%; border: 0; border-radius: var(--r); background: transparent; padding: 0 14px; font-size: 16px; color: var(--fg); }   /* 16px = 아이폰 확대 방지 */
.fld .fi input:focus-visible { outline: 0; }
.fld .fi input[readonly] { color: var(--mut); }
.fld .eye { flex: none; width: var(--tap); height: var(--tap); margin-right: 1px; border: 0; border-radius: 10px; background: transparent; color: var(--mut); font-size: 16px; display: grid; place-items: center; cursor: pointer; }
.fld .eye:active { background: var(--fill2); }
.fld .eye:focus-visible { outline-offset: -2px; }
.fld .why { font-size: var(--fs-1); color: var(--err); padding-left: 2px; line-height: 1.4; }
.fld.bad .fi, .fld.bad .cells i { border-color: var(--err); }
.fld .hint { font-size: var(--fs-1); color: var(--mut); padding-left: 2px; }
.fld .fi .btn.in { position: relative; flex: none; min-height: var(--tap); height: var(--tap); margin-right: 1px; border-radius: 10px; }   /* 칸 안 단추 (찾기): 칸 48 안에 44 */
.fld input.code6 { letter-spacing: .5em; font-variant-numeric: tabular-nums; font-weight: 700; text-align: center; padding-left: calc(14px + .5em); }
/* 브라우저 자동 채우기(노란 바탕) 덮기 */
.fld input:-webkit-autofill, .fld input:-webkit-autofill:focus { -webkit-box-shadow: 0 0 0 40px var(--card) inset; -webkit-text-fill-color: var(--fg); caret-color: var(--fg); transition: background-color 9999s; }
/* 계정 화면 (22차 M) */
.row.ib-row2 { gap: 8px; min-height: 56px; padding-left: 48px; }
.row.ib-row2 .btn { flex: none; }
.keybox { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; border-radius: var(--r); background: var(--card); }
.keybox code { font: 600 15px/1.6 Consolas, "D2Coding", ui-monospace, monospace; letter-spacing: .06em; word-break: break-all; color: var(--fg); }
.keybox .bt { display: flex; gap: 8px; flex-wrap: wrap; }
.keybox .bt .btn, .keybox .bt a.btn { font-size: var(--fs-2); text-decoration: none; }
.sh-form { display: flex; flex-direction: column; gap: 12px; }
.sh-form .acts2 { display: flex; gap: 8px; }
.sh-form .acts2 .btn { flex: 1; }
.urow .tx b { display: flex; align-items: center; gap: 6px; }
.wm-c { height: 34px; width: auto; margin: 14px 0 12px; animation: rise 460ms 140ms var(--ease) both; }
.jn-done { width: 100%; display: flex; flex-direction: column; gap: 12px; text-align: left; }
#v-join { min-height: 100dvh; justify-content: center; align-items: center; padding-bottom: calc(5vh + var(--sb)); }
#v-join:not([hidden]) { animation: none; }
/* 코드 6칸: 숨은 입력 하나 위에 칸 6개를 그린다 (붙여넣기·자동 채움은 입력이 그대로 받는다) */
.otp { position: relative; display: block; cursor: text; }
.otp .cells { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; }
.otp .cells i { height: 52px; border-radius: var(--r); background: var(--card); border: 1px solid var(--border); display: grid; place-items: center; font: 700 22px/1 -apple-system, "Pretendard", "Malgun Gothic", sans-serif; font-style: normal; color: var(--fg); font-variant-numeric: tabular-nums; transition: border-color var(--d1); }
.otp .cells i.cur { border-color: var(--ac); }
.otp input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; border: 0; font-size: 16px; caret-color: transparent; }
.st3 { list-style: none; margin: 18px 0 8px; padding: 0; display: flex; gap: 6px; align-items: center; justify-content: center; font-size: var(--fs-1); color: var(--mut); }
.st3 li { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; transition: color var(--d2); }
.st3 li + li::before { content: ""; width: 14px; height: 1px; background: var(--border); margin-right: 2px; }
.st3 li b { width: 24px; height: 24px; border-radius: 50%; display: inline-grid; place-items: center; font-size: var(--fs-1); background: var(--fill2); color: var(--mut); transition: background var(--d2), color var(--d2); }
.st3 li span { display: none; }
.st3 li.on { color: var(--fg); font-weight: 700; }
.st3 li.on span { display: inline; animation: rise var(--d2) ease both; }
.st3 li.on b { background: var(--ac); color: #fff; }
.st3 li.done b { background: var(--acs); color: var(--ach); }
#v-login .lockn { justify-content: center; margin: 0; }
/* 키보드가 올라오면 아바타를 줄여 한 화면에 */
body.kb .av.lg-av { --s: 72px; }
body.kb .wmk { height: 28px; margin: 8px 0 8px; }
body.kb #v-login .lockn, body.kb .lg-shadow, body.kb .st3 { display: none; }
body.kb .lg-say { margin-bottom: 10px; min-height: 0; }
body.kb #v-login { padding-bottom: 12px; padding-top: calc(4px + var(--safe-t)); }

/* ───────── 6. 대화 ───────── */
#v-chat { min-height: 100svh; padding-bottom: calc(var(--tab-h) + var(--comp-h) + 24px + var(--sb)); gap: 12px; }
.chat-hd { position: sticky; top: 0; z-index: 8; background-color: rgba(251,246,240,.78); -webkit-backdrop-filter: var(--g-blur); backdrop-filter: var(--g-blur); margin: 0 -16px; padding: calc(4px + var(--safe-t)) 12px 4px 16px; margin-top: calc(-8px - var(--safe-t)); }
.chat-hd .meta { display: block; }
.msgs { display: flex; flex-direction: column; gap: 16px; }
.mr { display: flex; gap: 10px; align-items: flex-start; }
.mr > .av { margin-top: 0; }
.msg { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--fs-3); line-height: 1.65; min-width: 0; }
.msg.me { align-self: flex-end; max-width: 84%; background: #E8E9EE; color: var(--fg); border-radius: 16px 16px 4px 16px; padding: 9px 14px; }
.msg.ai { flex: 1; padding: 3px 0 0; }   /* 말풍선 없이 문서처럼 */
/* ── 22차 M: 답 글 마크다운 (제목 · 목록 · 굵게 · 코드 · 표 · 인용 · 링크). 왼쪽 강조선 없이 면(흰 카드·회색 면)으로 나눈다 ── */
.md { white-space: normal; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.md > .mdd, .md > .mdt { display: contents; }
.md p { margin: 0; }
.md h3, .md h4 { margin: 4px 0 -2px; font-weight: 700; letter-spacing: -.01em; line-height: 1.4; }
.md h3 { font-size: var(--fs-4); } .md h4 { font-size: var(--fs-3); }
.md ul, .md ol { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 4px; }
.md li::marker { color: var(--mut); font-variant-numeric: tabular-nums; }
.md li > ul, .md li > ol { margin-top: 4px; }
.md b { font-weight: 700; }
.md a { color: var(--ach); text-decoration: underline; text-underline-offset: 2px; padding: 12px 2px; margin: -12px -2px; }   /* 줄 높이는 그대로, 누르는 곳은 44 */
.md code { font-family: Consolas, "D2Coding", ui-monospace, monospace; font-size: max(13px, .92em); background: var(--fill2); border-radius: 5px; padding: 1px 5px; }
.md hr { border: 0; height: 1px; background: var(--line); margin: 2px 0; width: 100%; }
.md blockquote { margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--fill2); color: var(--fg); font-size: var(--fs-2); }
.md blockquote p + p { margin-top: 6px; }
/* 코드 덩어리: 흰 카드 · 머리(언어 + 복사) · 폰에서는 줄을 접어 옆으로 밀 일이 없게 */
.cb { background: var(--card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.cbh { display: flex; align-items: center; min-height: var(--tap); padding-left: 12px; border-bottom: 1px solid var(--line2); font-size: var(--fs-1); color: var(--mut); font-weight: 600; }
.cbh span { flex: 1; min-width: 0; }
.cbh button { width: var(--tap); height: var(--tap); border: 0; background: transparent; color: var(--mut); font-size: 15px; cursor: pointer; border-radius: 10px; transition: transform var(--d1) var(--ease), background var(--d1); }
.cbh button:active { transform: scale(.9); background: var(--fill2); }
.cb pre { margin: 0; padding: 10px 12px 12px; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-all; font: 13px/1.6 Consolas, "D2Coding", ui-monospace, monospace; color: var(--fg); tab-size: 2; }
.cb pre code { background: none; padding: 0; font-size: inherit; border-radius: 0; }
/* 표: 흰 카드 · 폭 안에 맞춤(옆으로 넘치지 않게) */
.tbl { background: var(--card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.tbl table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: var(--fs-2); line-height: 1.45; }
.tbl th, .tbl td { padding: 8px 10px; text-align: left; vertical-align: top; overflow-wrap: anywhere; }
.tbl th { background: var(--fill); font-size: var(--fs-1); font-weight: 700; color: var(--mut); }
.tbl tr + tr td, .tbl tbody tr:first-child td { border-top: 1px solid var(--line2); }
.tbl .r { text-align: right; font-variant-numeric: tabular-nums; } .tbl .c { text-align: center; }
/* 날짜 줄 (대화 맨 위 · 날이 바뀔 때) */
.day { align-self: center; font-size: var(--fs-1); color: var(--mut); padding: 2px 10px; }
.new { animation: min var(--d2) var(--ease) backwards; }
.msg.me.new { transform-origin: right bottom; }
@keyframes min { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.caret { display: inline-block; width: 2px; height: 16px; background: var(--ac); vertical-align: -3px; margin-left: 2px; border-radius: 1px; animation: blinkc 1s steps(2) infinite; }
@keyframes blinkc { 50% { opacity: 0; } }
.info { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: var(--fs-1); color: var(--mut); white-space: normal; }
.info .dot { width: 7px; height: 7px; }
.acts { display: flex; gap: 2px; margin: -8px 0 0 30px; }
.acts button { width: var(--tap); height: var(--tap); border: 0; background: transparent; border-radius: 10px; color: var(--mut); font-size: 16px; cursor: pointer; transition: transform var(--d1) var(--ease), background var(--d1); }
.acts button:active { transform: scale(.9); background: var(--fill2); }
.stg { display: flex; flex-direction: column; gap: 6px; margin: -8px 0 0 38px; padding: 10px 12px; border-radius: var(--r); background: var(--card); font-size: var(--fs-1); color: var(--mut); max-width: 320px; animation: min var(--d2) var(--ease) backwards; }
.stg.sm { flex-direction: row; align-items: center; gap: 8px; padding: 6px 12px; min-height: 32px; border-radius: 16px; align-self: flex-start; max-width: calc(100% - 38px); }   /* 글이 오기 시작하면 한 줄로 줄인다 */
.stg.sm .ss, .stg.sm .bar { display: none; }
.stg.sm .ft { gap: 8px; min-width: 0; }
.stg.sm .ft > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stg .ss { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.stg .ss span { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; white-space: nowrap; transition: color var(--d2); }
.stg .ss span.d { color: var(--ok); } .stg .ss span.now { color: var(--ac); }
.stg .ss .ar { font-size: 9px; color: var(--faint); }
.stg .bar { height: 4px; }
.stg .ft { display: flex; justify-content: space-between; gap: 8px; }
.stg .ft b { color: var(--fg); font-variant-numeric: tabular-nums; }
.msg.err { flex: 1; background: var(--card); border-radius: var(--r); padding: 12px 14px; white-space: normal; }
.msg.err .t { display: flex; gap: 8px; align-items: center; font-weight: 700; color: var(--err); }
.msg.err p { margin: 6px 0 10px; font-size: var(--fs-2); color: var(--fg); }
.msg.err .bt { display: flex; gap: 8px; flex-wrap: wrap; }
.msg.err .bt .btn { font-size: var(--fs-2); padding: 0 12px; }
.sugs { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: 6px; }
/* 22차 M: 빈 대화의 예시 질문은 한 줄씩 (칩이 2+1 로 접히던 것) */
.empty .sugs { flex-direction: column; flex-wrap: nowrap; gap: 0; width: 100%; margin-top: 8px; background: var(--card); border-radius: var(--r); overflow: hidden; }
.empty .sugs button { height: 52px; width: 100%; padding: 0 16px; gap: 12px; font-size: var(--fs-3); font-weight: 500; justify-content: flex-start; text-align: left; transition: background var(--d1); }
.empty .sugs button::before { display: none; }
.empty .sugs button + button { border-top: 1px solid var(--line); }
.empty .sugs button:active { transform: none; background: var(--fill); }
.empty .sugs button .fa { width: 18px; text-align: center; color: var(--ac); font-size: 15px; }
.empty .sugs button .fa-arrow-up { margin-left: auto; color: var(--faint); font-size: 13px; transform: rotate(45deg); }
/* 대화 첫머리: 오늘 요약 카드 · 먼저 알려 주는 것 (승인 대기 · 엔진 이상) */
#brief:empty { display: none; }
#brief { display: flex; flex-direction: column; gap: 8px; }
.bc { flex: 1; min-width: 0; background: var(--card); border-radius: var(--r); padding: 10px 14px; display: flex; flex-direction: column; gap: 6px; }
.bc b { font-size: var(--fs-2); }
.bc .meta { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.bc .bt { display: flex; gap: 8px; flex-wrap: wrap; }
.bc .bt .btn { font-size: var(--fs-2); padding: 0 14px; }
.today { background: var(--card); border-radius: var(--r); padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.today .th { display: flex; align-items: center; gap: 10px; }
.today .th b { font-size: var(--fs-3); display: block; }
.today .th .meta { display: block; }
.kps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.kp { min-height: 66px; border-radius: 10px; background: var(--fill); border: 0; padding: 9px 12px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; text-align: left; font: inherit; color: var(--fg); cursor: pointer; transition: transform var(--d1) var(--ease), background var(--d1); }
.kp:active { transform: scale(.96); background: var(--fill2); }
.kp b { font-size: var(--fs-5); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.kp b small { font-size: var(--fs-1); font-weight: 600; color: var(--mut); margin-left: 1px; }
.kp span { font-size: var(--fs-1); color: var(--mut); }
.kp.hot { background: var(--acs); } .kp.hot b { color: var(--ach); }
.kp.bad b { color: var(--err); }
.today .ln { display: flex; align-items: center; gap: 8px; min-height: 22px; font-size: var(--fs-2); color: var(--fg); min-width: 0; }
.today .ln .fa { color: var(--faint); width: 18px; text-align: center; flex: none; }
.today .ln span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ban { display: flex; align-items: center; gap: 10px; padding: 6px 6px 6px 12px; border-radius: var(--r); background: var(--errs); color: var(--err); font-size: var(--fs-2); font-weight: 600; }
.ban button { height: var(--tap); min-width: 56px; border-radius: 10px; border: 1px solid rgba(200,0,26,.25); background: #fff; color: var(--err); font-size: var(--fs-1); font-weight: 700; padding: 0 12px; cursor: pointer; }
/* 입력: 탭 막대 바로 위에 붙은 흰 띠 (엄지 닿는 곳) */
/* 26차 M: 입력 띠도 떠 있는 유리 판 (탭 막대 위 6px) */
.composer { position: fixed; left: calc(12px + var(--safe-l)); right: calc(12px + var(--safe-r)); bottom: calc(var(--tab-h) + var(--sb) + 6px); z-index: 9; max-width: 536px; margin: 0 auto; display: flex; gap: 6px; align-items: flex-end; padding: 6px; border-radius: 26px; background-color: var(--g-card-hi); -webkit-backdrop-filter: var(--g-blur); backdrop-filter: var(--g-blur); border: 1px solid var(--g-edge); box-shadow: var(--g-sh-bar); }
.mdl { position: relative; height: var(--tap); border-radius: 22px; background: var(--fill); display: inline-flex; align-items: center; gap: 4px; padding: 0 8px 0 10px; flex: none; font-size: var(--fs-1); font-weight: 700; }
.mdl .fa { color: var(--ac); font-size: 13px; pointer-events: none; }
.mdl .fa-chevron-down { color: var(--faint); font-size: 10px; }
.mdl select { appearance: none; -webkit-appearance: none; border: 0; background: transparent; font-size: 16px; font-weight: 700; padding: 0 2px; max-width: 84px;   /* 16px = 눌러도 확대되지 않게 */ height: var(--tap); cursor: pointer; }
/* 22차 M: 입력 알약 — 글 · 음성 · 보내기가 한 면에. 누르면 흰 면 + 강조 테 (사각 초점선 대신) */
.cbox { flex: 1; min-width: 0; display: flex; align-items: flex-end; border-radius: 22px; background: var(--card); border: 1px solid var(--border); padding-left: 14px; transition: border-color var(--d1); }   /* 입력 칸 규격: 선 1px 하나 · 초점은 색만 */
.cbox:focus-within { border-color: var(--ac); }
.cbox .go, .cbox .mic { width: 42px; height: 42px; }   /* 칸(44) 안에 들어가게 · 누르는 곳은 아래 ::after 로 44 */
.cbox .go::after, .cbox .mic::after { content: ""; position: absolute; inset: -1px; }
.cbox .go, .cbox .mic { position: relative; }
.composer textarea { flex: 1; min-width: 0; resize: none; max-height: 120px; min-height: var(--tap); border: 0; background: transparent; padding: 11px 4px 11px 0; font-size: 16px; line-height: 1.4; }
.composer textarea:focus-visible { outline: 0; }
.composer .go { width: var(--tap); height: var(--tap); border-radius: 50%; border: 0; background: var(--ac); color: #fff; display: grid; place-items: center; font-size: 17px; flex: none; cursor: pointer; transition: transform var(--d1) var(--ease), background var(--d2), color var(--d2); }
.composer .go:active { transform: scale(.9); background: var(--ach); }
.composer .go[data-empty] { background: transparent; color: var(--faint); }   /* 글이 없으면 옅게 (누를 곳은 그대로 44) */
/* 음성 입력 (Web Speech API 가 있는 브라우저에서만 보임). 듣는 동안은 오류색 틴트 */
.composer .mic { width: var(--tap); height: var(--tap); border-radius: 50%; border: 0; background: transparent; color: var(--mut); display: grid; place-items: center; font-size: 17px; flex: none; cursor: pointer; transition: transform var(--d1) var(--ease), background var(--d1), color var(--d1); }
/* 맨 아래로 (위로 올려 읽는 중일 때만) */
.to-end { position: fixed; right: calc(14px + var(--safe-r)); bottom: calc(var(--tab-h) + var(--comp-h) + var(--sb) + 12px); z-index: 9; width: var(--tap); height: var(--tap); border-radius: 50%; border: 1px solid var(--line); background: var(--card); color: var(--fg); display: grid; place-items: center; font-size: 16px; cursor: pointer; animation: min var(--d2) var(--ease) both; transition: transform var(--d1) var(--ease); }
.to-end:active { transform: scale(.9); }
.to-end .nd { position: absolute; top: 6px; right: 6px; width: 9px; height: 9px; border-radius: 50%; background: var(--ac); border: 2px solid var(--card); }
body:not([data-v="chat"]) .to-end, body.kb .to-end { display: none; }
.composer .mic[hidden] { display: none; }
.composer .mic:active { transform: scale(.9); }
.composer .mic.on { background: var(--errs); color: var(--err); }

/* ───────── 7. 상태 ───────── */
.rs { display: grid; grid-template-columns: 70px 1fr 112px; align-items: center; gap: 10px; font-size: var(--fs-2); min-height: 48px; padding: 0 16px; }
.rs > span:first-child { color: var(--mut); }
.rs .v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
#res, #engines, #claude, #ops { display: flex; flex-direction: column; }
#res > * + *, #engines > * + *, #claude > * + *, #ops > * + * { border-top: 1px solid var(--line2); }
.eng { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 4px 16px; font-size: var(--fs-2); }
.eng .n { flex: 1; min-width: 0; }
.eng .n b { display: block; font-size: var(--fs-2); font-weight: 600; }
.eng .n span { font-size: var(--fs-1); color: var(--mut); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.line { font-size: var(--fs-2); padding: 12px 16px; }
.pad { padding: 10px 16px; }
.kv { display: flex; align-items: center; gap: 12px; min-height: 50px; padding: 4px 16px; font-size: var(--fs-3); color: var(--fg); }
.kv .k { flex: 1; color: var(--fg); }
.kv .v { font-weight: 700; font-variant-numeric: tabular-nums; }
.kv .v small { font-size: var(--fs-1); color: var(--mut); font-weight: 600; margin-left: 2px; }
.kv .s { font-size: var(--fs-1); color: var(--mut); }
button.kv { width: 100%; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; }
button.kv:active { background: var(--fill); }

/* ───────── 8. 도구 (12차 · 19차 즐겨찾기·기록) ───────── */
.tgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.tc { position: relative; min-width: 0; min-height: 100px; background: var(--card); border: 0; border-radius: var(--r); padding: 14px 14px 12px; text-align: left; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; cursor: pointer; font: inherit; color: var(--fg); animation: min 240ms var(--ease) backwards; animation-delay: calc(var(--i, 0) * 35ms); transition: transform var(--d1) var(--ease); }
.tc:active { transform: scale(.97); }
.tc > .fa { position: absolute; top: 14px; left: 14px; font-size: 20px; color: var(--ac); }
.tc b { font-size: var(--fs-3); font-weight: 700; }
.tc .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tc .tag { position: absolute; top: 10px; right: 10px; }
.tc.soon > .fa, .tc.soon b { color: var(--mut); }
.tc.wide { grid-column: 1 / -1; min-height: 88px; }
.tc.wide .now { position: absolute; top: 10px; right: 14px; font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tc .pin { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%; font-size: 13px; color: var(--faint); }
.tc .pin.on { color: var(--warn); }
.tgrid.edit .tc { animation: wob .32s ease-in-out infinite alternate; }
.tgrid.edit .tc:nth-child(2n) { animation-delay: -.16s; }
.tgrid.edit .tc .tag, .tgrid.edit .tc .now { display: none; }
@keyframes wob { from { transform: rotate(-.6deg); } to { transform: rotate(.6deg); } }
.tl-pg, .tl-hub, .tl-body { display: flex; flex-direction: column; gap: 10px; }
.tl-pg:not([hidden]) { animation: push var(--d3) var(--ease) backwards; }
.tl-hub:not([hidden]) { animation: vin var(--d2) var(--ease) backwards; }
html[data-nav="pop"] .tl-hub:not([hidden]) { animation: pop var(--d3) var(--ease) backwards; }
.tl-row { display: flex; gap: 8px; }
.tl-row .btn { flex: 1; }
.tl-ta { width: 100%; min-height: 104px; max-height: 150px; resize: none; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); padding: 12px 14px; font-size: 16px; line-height: 1.5; transition: border-color var(--d1); }
.tl-ta:focus { border-color: var(--ac); }
.tl-ta:focus-visible { outline: 0; }
.tl-file { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 6px 16px; background: var(--card); border-radius: var(--r); cursor: pointer; font-size: var(--fs-3); }
.tl-file input { display: none; }
.tl-file .ri { color: var(--faint); width: 20px; text-align: center; }
.tl-file .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.tl-file .tx b { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 주 동작은 엄지 닿는 바닥에 (도구 한 장): 탭 막대 바로 위, 키보드가 오르면 키보드 바로 위 */
.dock { position: fixed; left: 0; right: 0; bottom: calc(var(--tab-h) + var(--sb)); z-index: 9; padding: 8px calc(16px + var(--safe-r)) 8px calc(16px + var(--safe-l)); display: flex; gap: 8px; max-width: 560px; margin: 0 auto; }
.dock > * { flex: 1; }
.dock:not(:has(> :not([hidden]))), body:not([data-v="tool"]) .dock { display: none; }
body:has(#dock > :not([hidden])) #v-tool { padding-bottom: calc(var(--tab-h) + 86px + var(--sb)); }
body:not([data-v="chat"]) .composer { display: none; }   /* 입력 띠·바닥 단추는 화면 밖(고정)에 두어 화면 전환 모션에 끌려가지 않게 */
body.kb .dock { bottom: 0; padding-bottom: calc(8px + var(--tgb)); }
/* 문서형 결과 카드 */
.doc { background: var(--card); border-radius: var(--r); padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; animation: min 220ms var(--ease) backwards; }
.doc .dh { display: flex; align-items: center; gap: 8px; min-width: 0; }
.doc .dh b { font-size: var(--fs-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.doc .dh .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 50%; }
.doc .big { font-size: 26px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.doc .big small { font-size: var(--fs-2); color: var(--mut); font-weight: 600; margin-left: 6px; }
.doc .tx { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--fs-3); line-height: 1.6; min-height: 1.6em; }
.doc .tx.md { white-space: normal; }
.doc .md .cb, .doc .md .tbl, .doc .md blockquote { background: var(--fill); border-color: transparent; }   /* 흰 카드 안에서는 회색 면 */
.doc .md .tbl th { background: var(--fill2); }
.doc .md > ul + ul, .doc .md > ol + ol { margin-top: -6px; }   /* 쪽 나누기로 줄마다 끊은 목록이 한 목록처럼 */
.doc .pgrow { display: flex; justify-content: center; margin: -4px 0 -2px; }
.doc .pgrow .pg { margin-left: 0; }
/* 22차 M: 도구 허브 자리 잡기 (tools.js 를 받는 짧은 동안) */
.tcs { display: block; min-height: 100px; border-radius: var(--r); background: var(--card); animation: skp 1.2s ease-in-out infinite; }
.tcs.wide { grid-column: 1 / -1; min-height: 88px; }
.md-ms { position: fixed; left: 0; top: 0; height: 0; overflow: hidden; visibility: hidden; pointer-events: none; }   /* 쪽 나누기 잴 때만 쓰는 보이지 않는 판 (스크롤 길이에 안 잡힘) */
.md-ms > .md { height: auto; }
.doc .kvs { display: flex; flex-direction: column; }
.doc .kvs > div { display: flex; gap: 12px; min-height: 36px; align-items: center; font-size: var(--fs-2); }
.doc .kvs > div + div { border-top: 1px solid var(--line2); }
.doc .kvs span { width: 84px; flex: none; color: var(--mut); font-size: var(--fs-1); }
.doc .kvs b { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc .bt { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.doc .bt .btn { font-size: var(--fs-2); padding: 0 14px; border-radius: 10px; }
.doc .bt .btn[aria-label] { width: var(--tap); padding: 0; flex: none; }
.doc .pg { margin-left: auto; display: inline-flex; align-items: center; font-size: var(--fs-1); color: var(--mut); font-variant-numeric: tabular-nums; white-space: nowrap; }
.doc .pg button, .pgr button { width: var(--tap); height: var(--tap); border: 0; background: transparent; border-radius: 10px; color: var(--fg); cursor: pointer; }
.doc .pg button:disabled, .pgr button:disabled { color: var(--dot-off); }
.pgr { display: flex; align-items: center; justify-content: center; gap: 4px; font-size: var(--fs-1); color: var(--mut); font-variant-numeric: tabular-nums; }
.grp.notice > * + * { border-top: 0; }
.tl-body > div[id] { display: flex; flex-direction: column; gap: 10px; }
.tl-body:has(.doc) > .say, .tl-body:has(.msg.err) > .say { display: none; }   /* 결과가 나오면 처음 안내 줄은 접는다 (한 화면 유지) */
.ap:has(.cf:not([hidden])) .to { display: none; }
.tl-body > div[id]:empty { display: none; }
/* 16차: 사진 미리보기(테두리·고리 없음) · 만든 그림 · 카카오 보내기 확인 카드 */
.tl-thumb { width: 40px; height: 40px; flex: none; object-fit: cover; border-radius: var(--r-s); }
.tl-thumb[hidden] { display: none; }
.doc img.gen { width: 100%; max-height: 46vh; object-fit: contain; border-radius: 10px; background: var(--fill); }
.doc a.btn { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.cf.box .pv { background: var(--fill); border-radius: 10px; padding: 10px 12px; font-size: var(--fs-2); line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 9em; overflow: hidden; }

/* ───────── 9. 승인: "이걸 OO 로 보내도 될까?" 카드 · 좌우로 밀면 확인 줄이 열린다(보내기는 늘 직접 누름) ───────── */
#appr { display: flex; flex-direction: column; gap: 10px; }
.ap-w { position: relative; border-radius: var(--r); overflow: hidden; animation: min var(--d2) var(--ease) backwards; animation-delay: calc(var(--i, 0) * 50ms); }
.ap-w > .sw { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; padding: 0 22px; font-weight: 700; font-size: var(--fs-2); background: var(--fill2); color: var(--mut); }
.ap-w > .sw span { display: inline-flex; align-items: center; gap: 8px; opacity: 0; transition: opacity var(--d1), transform var(--d1) var(--ease); }
.ap-w[data-dir="r"] > .sw { background: var(--acs); color: var(--ach); }
.ap-w[data-dir="l"] > .sw { background: var(--errs); color: var(--err); }
.ap-w[data-dir="r"] > .sw span:first-child, .ap-w[data-dir="l"] > .sw span:last-child { opacity: 1; }
.ap-w.far > .sw span { transform: scale(1.08); }
.ap { position: relative; background: var(--card); border-radius: var(--r); padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; touch-action: pan-y; transition: opacity var(--d2) ease, transform var(--d2) var(--ease); }
.ap.drag { transition: none; }
.ap.gone { opacity: 0; transform: translateX(110%); }
.ap.gone.l { transform: translateX(-110%); }
.ap .mt { display: flex; align-items: center; gap: 6px; font-size: var(--fs-1); color: var(--mut); }
.ap .mt b { color: var(--fg); font-size: var(--fs-2); font-weight: 600; }
.ap .q { font-size: var(--fs-3); font-weight: 700; }
.ap .q em { font-style: normal; color: var(--ach); }
.ap .p { font-size: var(--fs-2); line-height: 1.55; color: var(--fg); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ap .to { display: flex; align-items: center; gap: 6px; font-size: var(--fs-1); color: var(--mut); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ap .to.fnd { flex-wrap: wrap; white-space: normal; }
.ap .acts2 { display: flex; gap: 8px; justify-content: flex-end; }
.ap .acts2 .btn { min-width: 104px; }
.ap .hint { font-size: var(--fs-1); color: var(--mut); display: flex; align-items: center; gap: 6px; }
/* 카드 안 확인 줄 (브라우저 confirm/prompt 대신) */
.ap .cf { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; border-top: 1px solid var(--line2); animation: min 160ms ease backwards; }
.ap .cf .meta { font-size: var(--fs-2); color: var(--fg); }
.ap .cf .fr { padding: 0 6px 0 12px; border: 1px solid var(--border); border-radius: 10px; min-height: 48px; }
.ap .cf .fr input { height: 46px; letter-spacing: .2em; font-variant-numeric: tabular-nums; }
.ap .cf .fr:focus-within, .cf.box .fr:focus-within { border-color: var(--ac); }
/* 계정 화면 재확인 칸: 그 묶음 위에 뜨고, 확인하는 동안 같은 하위 탭의 나머지는 접는다 (한 화면 유지) */
.cf.box { flex-direction: column; gap: 10px; padding: 14px 16px; animation: min 160ms ease backwards; }
.grp.cf.box > * + * { border-top: 0; }
.cf.box .meta { font-size: var(--fs-2); color: var(--fg); }
.cf.box .fr { padding: 0 6px 0 12px; border: 1px solid var(--border); border-radius: 10px; min-height: 48px; }
.cf.box .fr input { height: 46px; letter-spacing: .2em; font-variant-numeric: tabular-nums; }
.cf.box .acts2 { display: flex; gap: 8px; justify-content: flex-end; }
.cf.box .acts2 .btn { min-width: 104px; }
.pn:has(> .cf.box:not([hidden])) > :not(.cf) { display: none; }

/* ───────── 10. 시트 (아래에서 올라오는 판: 알림 목록 · 도구 기록 · 설치 안내) ───────── */
.sheet-bg { position: fixed; inset: 0; z-index: 40; background: var(--scrim); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); animation: fade var(--d2) ease both; }   /* 26차 M: 흐린 딤 */
.sheet-bg.out { opacity: 0; transition: opacity var(--d2) ease; }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 41; max-width: 560px; margin: 0 auto; max-height: calc(100dvh - 48px - var(--safe-t)); background-color: rgba(251,246,240,.94); -webkit-backdrop-filter: var(--g-blur); backdrop-filter: var(--g-blur); border: 1px solid var(--g-line); border-bottom: 0; box-shadow: 0 -12px 40px rgba(74,30,63,.16); border-radius: 22px 22px 0 0; padding: 0 calc(16px + var(--safe-r)) calc(16px + var(--sb)) calc(16px + var(--safe-l)); display: flex; flex-direction: column; gap: 10px; overflow: hidden; animation: shin var(--d3) var(--ease) both; touch-action: none; }
.sheet.out { transform: translateY(100%); transition: transform var(--d2) var(--ease-io); animation: none; }
.sheet.drag { animation: none; transition: none; }
@keyframes shin { from { transform: translateY(100%); } 70% { transform: translateY(-6px); } to { transform: none; } }   /* 26차 M: 살짝 튀어 자리 잡는 스프링 느낌 (transform 만) */
.sheet:focus { outline: 0; }
.sheet .grab { display: block; width: 40px; height: 5px; border-radius: 3px; background: var(--border); margin: 8px auto 0; flex: none; }
.sh-hd { display: flex; align-items: center; gap: 8px; min-height: var(--tap); }
.sh-hd h3 { margin: 0; font-size: var(--fs-4); font-weight: 700; flex: 1; min-width: 0; }
.sh-body { display: flex; flex-direction: column; gap: 10px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; }
/* 키보드가 오른 시트: 손잡이를 접고 칸 사이를 좁혀 주 단추가 키보드 위에 남게 */
body.kb .sheet .grab { display: none; }
body.kb .sheet { gap: 6px; padding-bottom: calc(10px + var(--sb)); }
body.kb .sh-form { gap: 8px; }
body.kb .sh-form .fld { gap: 4px; }
.ib-row { display: flex; gap: 8px; }
.ib-row .btn { flex: 1; }
.nt-i { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 6px 16px; width: 100%; border: 0; background: none; font: inherit; color: var(--fg); text-align: left; cursor: pointer; }
button.nt-i:active { background: var(--fill); }
.nt-i .chev { color: var(--faint); font-size: 13px; }
.nt-i .ri { width: 20px; text-align: center; color: var(--faint); flex: none; }
.nt-i.un .ri { color: var(--ac); }
.nt-i .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.nt-i .tx b { font-size: var(--fs-2); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nt-i.un .tx b { font-weight: 700; }
.ios { list-style: none; margin: 0; padding: 0; counter-reset: s; }
.ios li { counter-increment: s; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 6px 16px; font-size: var(--fs-3); }
.ios li::before { content: counter(s); width: 24px; height: 24px; border-radius: 50%; background: var(--acs); color: var(--ach); font-size: var(--fs-1); font-weight: 700; display: grid; place-items: center; flex: none; }
.ios li .fa { color: var(--ac); font-size: 18px; margin-left: auto; }

/* ───────── 11. 당겨서 새로고침 ───────── */
.ptr { position: fixed; top: calc(var(--safe-t) + 6px); left: 50%; z-index: 15; width: 40px; height: 40px; margin-left: -20px; border-radius: 50%; background: var(--card); border: 1px solid var(--line); display: grid; place-items: center; color: var(--ac); font-size: 16px; opacity: 0; transform: translateY(-56px); pointer-events: none; }
.ptr.back { transition: transform var(--d2) var(--ease), opacity var(--d2); }
.ptr.run i { animation: spin .8s linear infinite; }

/* ───────── 12. 연결 끊김 ───────── */
.offline { position: fixed; inset: 0; z-index: 30; background: var(--g-glow), var(--bg); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: calc(24px + var(--safe-t)) 32px calc(14vh + var(--sb)); text-align: center; animation: vin var(--d2) var(--ease) both; }
.offline b { font-size: var(--fs-5); }
.offline .btn { margin-top: 8px; min-width: 180px; min-height: var(--tap-l); }

/* ───────── 13. 바닥에 붙은 탭 막대 (선택 = 강조 알약이 미끄러짐 + 강조 글자) ───────── */
/* 22차 M 안정화 (삼성 인터넷 실기기 "하단 바가 계속 축소·확대"): 원인 = ① 바 높이가 env(safe-area-inset-bottom) 을 그대로 따라가서, 아래 도구 막대가 숨었다 나타날 때마다 inset 이 바뀌어 바가 커졌다 작아짐
   ② 키보드 판정이 visualViewport 높이 비율만 보고도 켜져서(주소창·도구 막대 변화) 바가 translateY 로 미끄러졌다 숨었다 함 ③ 선택 알약 미끄러짐·아이콘 튐 애니메이션.
   → 바는 고정 높이(--tab-h + 시작할 때 한 번 잰 --sb) · transform·transition·애니메이션 없음 · 선택 표시는 색과 알약 바탕(opacity)만 · 키보드 때는 즉시 숨김(visibility) */
/* 26차 M "비드" 탭 막대 (참고자료 27 TOP 2): 떠 있는 유리 알약(높이 64 · 반경 28 · 좌우 12 · 홈 바 + 10 위) + 선택 탭은 48px 브랜드 그라데이션 구슬이 14px 솟는다.
   틀(.tabs)은 22차 M 규칙 그대로 — 고정 높이(--tab-h + --sb) · 틀 자체엔 transform·transition·animation 없음. 움직이는 건 선택 표시(구슬·아이콘)의 transform·opacity 180ms 뿐이라 바가 흔들리지 않는다 */
.tabs { position: fixed; left: 0; right: 0; bottom: 0; z-index: 10; display: flex; padding: 0 calc(12px + var(--safe-r)) calc(var(--sb) + 10px) calc(12px + var(--safe-l)); height: calc(var(--tab-h) + var(--sb)); box-sizing: border-box; pointer-events: none; contain: layout; }
.tabs::before { content: ""; position: absolute; left: calc(12px + var(--safe-l)); right: calc(12px + var(--safe-r)); bottom: calc(var(--sb) + 10px); height: 64px; border-radius: 28px; background-color: rgba(255,255,255,.8); -webkit-backdrop-filter: blur(20px) saturate(150%); backdrop-filter: blur(20px) saturate(150%); border: 1px solid var(--g-edge); box-shadow: var(--g-sh-bar); }
.tabs button { position: relative; z-index: 1; flex: 1; min-width: 0; border: 0; background: transparent; color: var(--mut); font-size: var(--fs-1); font-weight: 600; height: 64px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding-top: 4px; cursor: pointer; pointer-events: auto; }
.tabs button .fa { position: relative; font-size: 19px; width: 48px; height: 30px; display: grid; place-items: center; color: var(--mut); transition: transform 180ms cubic-bezier(.2,.8,.2,1); }
.tabs button .fa::after { content: ""; position: absolute; left: 0; top: -9px; width: 48px; height: 48px; z-index: -1; border-radius: 50%; background: var(--ac) var(--vi-grad); box-shadow: 0 0 0 6px var(--bg), 0 8px 20px rgba(107,26,150,.35); opacity: 0; transform: scale(.6); transition: opacity 180ms cubic-bezier(.2,.8,.2,1), transform 180ms cubic-bezier(.2,.8,.2,1); }
.tabs button.on { color: var(--vi-700); font-weight: 700; }
.tabs button.on .fa { color: #fff; transform: translateY(-14px); }
.tabs button.on .fa::after { opacity: 1; transform: none; }
.tabs button.on span { transform: translateY(-4px); }
.tabs button:active .fa { transform: scale(.92); }
.tabs button.on:active .fa { transform: translateY(-14px) scale(.94); }
.tabs .ind { display: none; }
.tabs em { position: absolute; top: 2px; left: calc(50% + 8px); z-index: 2; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--err); color: #fff; font-size: var(--fs-1); font-style: normal; font-weight: 700; display: grid; place-items: center; line-height: 1; border: 2px solid #fff; box-sizing: content-box; }
.tabs button.on em { top: -14px; }
/* 키보드가 올라오면 탭 막대를 숨기고 입력 띠를 바닥에 */
body.kb .tabs { visibility: hidden; pointer-events: none; }   /* 미끄러지지 않고 바로 숨김 (22차 M) */
body.kb .composer { bottom: calc(6px + var(--tgb)); }
body.kb #v-chat { padding-bottom: calc(var(--comp-h) + 20px); }
body.kb .view { padding-bottom: 24px; }
body.kb:has(#dock > :not([hidden])) #v-tool { padding-bottom: 86px; }

/* ───────── 14. 위·아래 띠: 새 버전 · 알림(토스트, 엄지 쪽 아래) ───────── */
/* 새 버전 띠: 엄지 쪽(탭 막대·입력 띠 바로 위). 떠 있는 동안 화면 아래 여백을 늘려 아무것도 가리지 않게 */
body:has(#upd:not([hidden])) .view { padding-bottom: calc(var(--tab-h) + 88px + var(--sb)); }
body:has(#upd:not([hidden])) #v-chat { padding-bottom: calc(var(--tab-h) + var(--comp-h) + 92px + var(--sb)); }
body[data-v="chat"] .upd { bottom: calc(var(--tab-h) + var(--comp-h) + var(--sb) + 10px); }
body.kb .upd { display: none; }
body:has(#upd:not([hidden])) .toast { margin-bottom: 62px; }
.upd { position: fixed; left: 12px; right: 12px; bottom: calc(var(--tab-h) + var(--sb) + 10px); z-index: 21; max-width: 528px; margin: 0 auto; display: flex; align-items: center; gap: 10px; padding: 4px 4px 4px 14px; border-radius: 16px; background: var(--fg); color: #fff; font-size: var(--fs-2); box-shadow: 0 8px 24px rgba(42,22,54,.24); animation: min var(--d2) var(--ease) both; }
.upd span { flex: 1; }
.upd button { height: var(--tap); padding: 0 14px; border-radius: 10px; border: 0; background: #fff; color: var(--fg); font-weight: 700; font-size: var(--fs-2); cursor: pointer; }
.upd .x { background: transparent; color: #fff; width: var(--tap); padding: 0; }
.toast { position: fixed; left: 16px; right: 16px; bottom: calc(var(--tab-h) + var(--sb) + 12px); z-index: 20; max-width: 528px; margin: 0 auto; background: rgba(42,22,54,.94); color: #fff; border-radius: 16px; box-shadow: 0 8px 24px rgba(42,22,54,.24); padding: 12px 16px; font-size: var(--fs-2); animation: tin var(--d2) var(--ease) both; pointer-events: none; }
body[data-v="chat"] .toast { bottom: calc(var(--tab-h) + var(--comp-h) + var(--sb) + 12px); }
body[data-v="key"] .toast, body[data-v="login"] .toast, body[data-v="join"] .toast { bottom: calc(var(--sb) + 16px); }
body.kb .toast { bottom: calc(var(--comp-h) + 12px); }
.toast.out { opacity: 0; transform: translateY(8px); transition: opacity var(--d1) ease, transform var(--d1) ease; }
@keyframes tin { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
/* 햅틱 대신 짧은 튀김 (진동이 없는 폰에서도 눌렀다는 느낌) */
.tick { animation: tick var(--d1) var(--ease); }
@keyframes tick { 0% { transform: scale(.9); } 60% { transform: scale(1.08); } 100% { transform: none; } }

/* 25차 M: 스플래시 8초 단추 · 설정 "시작 성능" 카드 (막대 = 열기 · 로그인 확인 · 집 PC 요약, 느린 단계는 주황. 안쪽 세로 스크롤 없음) */
.sp-acts { display: flex; flex-direction: column; gap: 8px; width: min(260px, 70vw); margin-top: 6px; animation: fade 240ms ease both; }
.sp-acts .btn { width: 100%; min-height: var(--tap-l); }
.pf-body { padding: 2px 0 4px; }
.pf-r { display: flex; align-items: center; gap: 10px; min-height: 36px; }
.pf-t { flex: none; width: 62px; font-size: var(--fs-1); color: var(--mut); white-space: nowrap; }
.pf-b { flex: 1 1 auto; height: 10px; display: flex; border-radius: 5px; background: var(--fill2); overflow: hidden; }
.pf-b i { display: block; height: 100%; flex: none; background: var(--ac); }
.pf-b i + i { margin-left: 1px; }
.pf-b i.a, .pf-lg .k.a { background: var(--faint); }
.pf-b i.m, .pf-lg .k.m { background: #8E96E8; }
.pf-b i.d, .pf-lg .k.d { background: var(--ac); }
.pf-b i.o { background: var(--line); }
.pf-b i.slow, .pf-lg .k.s { background: var(--dot-warn); }
.pf-v { flex: none; min-width: 44px; text-align: right; font-size: var(--fs-2); font-weight: 600; color: var(--mut); }
.pf-r .tag { flex: none; }
.pf-lg { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 6px 0 0; }
.pf-lg .k { display: inline-block; width: 10px; height: 10px; border-radius: 3px; }
.pf-lg .k:not(:first-child) { margin-left: 6px; }
.pf-fl { margin: 4px 0 0; }
.pf-nav { display: flex; align-items: center; gap: 4px; min-height: var(--tap); margin-top: 4px; }
.pf-nav .sp { flex: 1; }
.pf-nav .ib:disabled { opacity: .35; }

[hidden] { display: none !important; }
/* 움직임 줄이기: 기기 설정 또는 앱 설정 */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } }
html.calm *, html.calm *::before, html.calm *::after { transition: none !important; animation: none !important; }

/* ───────── 15. 26차 M 유리 면 · Viola/Sunset 덮기 (앞 규칙의 흰 면을 유리로 바꾼다 — 같은 선택자를 뒤에 두어 덮음) ───────── */
.grp, .today, .bc, .doc, .tc, .ap, .msg.err, .stg, .keybox, .tl-file, .tcs, .to-end, .ptr, .empty .sugs {
  background-color: var(--g-card); -webkit-backdrop-filter: var(--g-blur); backdrop-filter: var(--g-blur); border: 1px solid var(--g-line); box-shadow: var(--g-sh); }
.today, .doc, .tc, .ap { border-radius: 16px; }
.cb, .tbl { background-color: rgba(255,255,255,.86); border-color: var(--line); border-radius: 12px; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .grp, .today, .bc, .doc, .tc, .ap, .msg.err, .stg, .keybox, .tl-file, .tcs, .to-end, .ptr, .empty .sugs, .tabs::before, .composer, .chat-hd, .sheet { background-color: rgba(255,255,255,.96); }
}
/* 글자 체계: 제목 28/700 · 화면 머리 20/700 · 본문 15/1.65 · 보조 13/1.45. 한글 제목은 자간 살짝 좁게 */
.hd h2 { color: var(--fg); letter-spacing: -.025em; }
.gl { color: var(--mut); letter-spacing: .01em; }
.md h3 { font-size: var(--fs-4); color: var(--fg); } .md h4 { color: var(--ach); }
.md b { color: var(--fg); }
.md li::marker { color: var(--vi-700); }
.md blockquote { background: rgba(244,238,246,.8); }
.md code { background: var(--vi-100); color: var(--vi-900); }
/* 내 말풍선: 브랜드 진보라 그라데이션 + 흰 글자 (어느 점에서도 6.9:1 이상) */
.msg.me { background: var(--ac) var(--vi-grad2); color: #fff; border-radius: 18px 18px 6px 18px; box-shadow: 0 6px 16px -8px rgba(107,26,150,.5); }
.msg.ai { color: var(--fg); }
.composer .go { background: var(--ac) var(--vi-grad2); }
.cbox { background: #fff; border-color: transparent; border-radius: 20px; padding-left: 12px; }
.mdl { background: var(--vi-100); color: var(--ach); border-radius: 20px; padding: 0 6px 0 10px; gap: 2px; }
.composer { left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); padding: 5px; gap: 5px; }
.composer textarea::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mdl select { color: var(--ach); }
.chat-hd .meta { color: var(--mut); }
.stg .ss span.now { color: var(--ach); }
.caret { background: var(--vi-400); }
/* 오늘 요약 숫자 칸: 연보라 유리 · 승인 대기가 있으면 Sunset(따뜻한 경고) */
.kp { background: rgba(244,238,246,.78); border: 1px solid rgba(255,255,255,.8); border-radius: 12px; }
.kp b { color: var(--fg); }
.kp.hot { background: var(--su-grad); background-color: var(--su-100); }
.kp.hot b { color: var(--su-text); }   /* 큰 숫자(20/700)라 큰 글자 기준 · 작은 글자는 진한 갈색으로 */
.kp.hot b small, .kp.hot span { color: var(--warn); }
/* 오늘 요약 날씨 판 (누르면 날씨 카드) */
.wxs { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 64px; padding: 8px 12px; border: 1px solid rgba(255,255,255,.8); border-radius: 14px; background-color: rgba(244,238,246,.7); font: inherit; color: var(--fg); text-align: left; cursor: pointer; transition: transform var(--d1) var(--ease); }
.wxs:active { transform: scale(.98); }
.empty .sugs button { height: 48px; }
/* 키 작은 폰(높이 800 미만): 빈 대화 첫 화면이 한 화면에 들어가게 요약의 한 줄 정보(엔진 · Claude 한도)는 접는다 — 상태 탭에 그대로 있다 */
@media (max-height: 800px) { .today .ln { display: none; } .wxs { min-height: 56px; padding: 6px 12px; } }
.wxs.warm { background: var(--su-grad); background-color: var(--su-100); }
.wxs .wi { font-size: 26px; width: 34px; text-align: center; color: var(--vi-700); flex: none; }
.wxs.warm .wi { color: var(--su-600); }
.wxs > b { font-size: 26px; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1; flex: none; }
.wxs > b small { font-size: var(--fs-2); font-weight: 700; color: var(--mut); margin-left: 1px; }
.wxs .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.wxs .s1 { font-size: var(--fs-3); font-weight: 700; }
.wxs .s2 { font-size: var(--fs-1); color: var(--mut); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wxs .chev { color: var(--faint); font-size: 13px; }
/* 날씨 카드 (도구) */
.doc.wx { gap: 10px; padding: 14px; }
.doc.wx.warm { background: var(--su-grad); background-color: var(--su-100); }
.wxn { display: flex; align-items: center; gap: 12px; min-width: 0; }
.wxn .wi { font-size: 40px; width: 48px; text-align: center; color: var(--vi-700); flex: none; }
.wx.warm .wxn .wi { color: var(--su-600); }
.wxn .tp { font-size: 44px; font-weight: 800; letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; color: var(--fg); flex: none; }
.wx.warm .wxn .tp { color: var(--su-text); }
.wxn .tp small { font-size: var(--fs-4); font-weight: 700; color: var(--mut); margin-left: 2px; }
.wxn .tx { display: flex; flex-direction: column; min-width: 0; }
.wxn .tx b { font-size: var(--fs-4); font-weight: 700; }
.wxn .tx .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wxn .tag { background: rgba(255,255,255,.7); color: var(--mut); }
.wxr { display: flex; align-items: center; gap: 10px; font-size: var(--fs-1); color: var(--mut); font-variant-numeric: tabular-nums; white-space: nowrap; }
.wxr .rb { position: relative; flex: 1; height: 6px; border-radius: 3px; background: rgba(107,26,150,.10); }
.wxr .rb > i { position: absolute; inset: 0; border-radius: 3px; background: linear-gradient(90deg, #8FB7E8 0%, var(--su-400) 60%, var(--su-600) 100%); opacity: .85; }
.wxr .rb > em { position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%; background: #fff; box-shadow: 0 1px 4px rgba(74,30,63,.35); }
.wxh { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; padding: 6px 4px; border-radius: 12px; background: rgba(255,255,255,.62); }
.wxh .hc { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 0; border-radius: 10px; min-width: 0; }
.wxh .hc.now { background: rgba(255,255,255,.95); box-shadow: 0 2px 8px rgba(74,30,63,.08); }
.wxh .t { font-size: var(--fs-1); color: var(--mut); white-space: nowrap; }
.wxh .hc.now .t { color: var(--ach); font-weight: 700; }
.wxh .fa { font-size: 18px; color: var(--vi-700); height: 20px; }
.wx.warm .wxh .fa-sun, .wx.warm .wxh .fa-cloud-sun { color: var(--su-600); }
.wxh b { font-size: var(--fs-2); font-weight: 700; font-variant-numeric: tabular-nums; }
.wxh .pp { font-size: var(--fs-1); color: #2F5F9E; min-height: 18px; font-variant-numeric: tabular-nums; }
.wxd { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.wxd .dc { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; padding: 8px 10px; border-radius: 12px; background: rgba(255,255,255,.62); font-size: var(--fs-1); }
.wxd .t { font-weight: 700; color: var(--fg); flex: 1; }
.wxd .fa { color: var(--vi-700); font-size: 15px; flex: none; }
.wx.warm .wxd .fa-sun, .wx.warm .wxd .fa-cloud-sun { color: var(--su-600); }
.wxd b { flex: 1 0 100%; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wps { display: flex; flex-wrap: wrap; gap: 6px; }
.wp { display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 10px; border-radius: 999px; background: rgba(255,255,255,.72); font-size: var(--fs-1); color: var(--mut); white-space: nowrap; }
.wp .fa { font-size: 12px; color: var(--vi-700); }
.wp b { color: var(--fg); font-weight: 700; }
/* 위치 카드: 등고선 그림 지도 + 빛나는 핀 + 장소 이름 유리 라벨 (바깥 타일 없음) */
.doc.loc { gap: 10px; padding: 10px; }
.tl-body:has(#tw-loc .doc) #tw-res { display: none; }   /* 위치를 열면 날씨 카드 자리에 (한 화면 유지 · 구름 단추로 날씨로 돌아감) */
.doc.loc > :not(.map) { margin: 0 4px; }
.map { position: relative; height: 150px; border-radius: 14px; overflow: hidden; isolation: isolate; background-color: var(--g-bg);
  background-image: repeating-radial-gradient(circle at 62% 44%, rgba(194,84,184,0) 0 15px, rgba(194,84,184,.18) 15px 16px), repeating-radial-gradient(circle at 18% 90%, rgba(194,84,184,0) 0 19px, rgba(194,84,184,.12) 19px 20px), radial-gradient(60% 70% at 80% 10%, var(--g-glow-2) 0%, rgba(255,227,179,0) 70%); }
.map .rd { position: absolute; left: -10%; right: -10%; top: 58%; height: 10px; border-radius: 5px; background: rgba(255,255,255,.92); box-shadow: 0 0 0 1px rgba(107,26,150,.08); transform-origin: 50% 50%; }
.map .rd.main { height: 14px; top: 46%; }
.map .rd.v { left: auto; right: auto; top: -10%; bottom: -10%; width: 9px; height: auto; }
.map .blk { position: absolute; width: 64px; height: 38px; border-radius: 8px; background: rgba(213,229,211,.75); }
.map .blk.b2 { width: 52px; height: 30px; background: rgba(212,221,238,.8); }
.map .rv { position: absolute; left: -10%; right: -10%; bottom: -26px; height: 48px; border-radius: 50%; background: rgba(212,221,238,.7); transform: rotate(-6deg); }
.map .pin { position: absolute; left: 50%; top: 46%; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; background: var(--vi-700); box-shadow: 0 0 0 6px rgba(107,26,150,.16), 0 0 18px rgba(107,26,150,.4); }
.map .pin::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--vi-700); opacity: .5; animation: pulse 1.6s ease-out infinite; }
.map .pin .fa { display: none; }
@keyframes pulse { from { transform: scale(1); opacity: .5; } to { transform: scale(2.4); opacity: 0; } }
.map .pl { position: absolute; left: 50%; top: calc(46% + 14px); transform: translateX(-50%); max-width: calc(100% - 24px); padding: 6px 12px; border-radius: 12px; background-color: rgba(255,255,255,.86); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border: 1px solid #fff; box-shadow: 0 4px 14px rgba(74,30,63,.12); font-size: var(--fs-1); font-weight: 700; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.map .cap { position: absolute; left: 10px; top: 10px; height: 24px; padding: 0 10px; display: inline-flex; align-items: center; border-radius: 999px; background: rgba(255,255,255,.82); font-size: var(--fs-1); font-weight: 700; letter-spacing: .04em; color: var(--mut); }
.doc.loc .bt .btn[aria-label] { width: var(--tap); padding: 0; flex: none; }
.doc.loc .bt { flex-wrap: nowrap; }
.doc.loc .bt .btn.pri { flex: 1 1 auto; min-width: 0; padding: 0 10px; }
/* 도구 칸: 흰 유리 카드 + 파스텔 아이콘 타일(40 · 반경 10) + 같은 계열 색 번짐 그림자 (참고자료 27 TOP 4) */
.tc { padding: 56px 14px 11px; justify-content: flex-start; }
.tgrid { gap: 8px; }
.tc > .fa { top: 12px; left: 14px; width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center; font-size: 18px; background: var(--t-lav); color: var(--vi-700); }
.tc[data-tool="wx"] > .fa { background: var(--t-sand); color: var(--su-text); }
.tc[data-tool="bld"] > .fa { background: var(--t-slate); color: #2F4F86; }
.tc[data-tool="img"] > .fa { background: var(--t-terra); color: #8A3A1C; }
.tc[data-tool="code"] > .fa { background: var(--t-lav); color: var(--vi-700); }
.tc[data-tool="file"] > .fa { background: var(--t-sage); color: #2E5E36; }
.tc[data-tool="pc"] > .fa { background: var(--t-slate); color: #2F4F86; }
.tc[data-tool="kakao"] > .fa { background: var(--t-sand); color: #7A5200; }
.tc[data-tool="wx"] { box-shadow: 0 1px 2px rgba(74,30,63,.04), 0 8px 24px rgba(234,97,19,.14); }
.tc[data-tool="code"], .tc[data-tool="kakao"] { box-shadow: 0 1px 2px rgba(74,30,63,.04), 0 8px 24px rgba(107,26,150,.14); }
.tc.wide { padding-top: 12px; padding-left: 64px; min-height: 64px; justify-content: center; }
.tc.wide > .fa { top: 50%; margin-top: -18px; }
.tc.wide.warm { background: var(--su-grad); background-color: var(--su-100); }
.tc.wide .now { top: 50%; transform: translateY(-50%); font-size: 26px; font-weight: 800; color: var(--fg); }
.tc.wide.warm .now { color: var(--su-text); }
.tc.soon > .fa { background: var(--fill2); color: var(--mut); }
.tc .tag { background: var(--vi-100); color: var(--vi-900); border-radius: 999px; }
/* 승인 행: 순번 타일 + 대기 알약 + 점선 체크 (참고자료 27 TOP 5) */
.ap { gap: 6px; padding: 12px 14px; }
.ap .p { -webkit-line-clamp: 2; }
#v-appr > .say span:not(.av) { -webkit-line-clamp: 1; }
.view { padding-bottom: calc(var(--tab-h) + 12px + var(--sb)); }   /* 떠 있는 탭 알약 아래 틈(10)이 이미 있어 화면 아래 여백은 12 */
.ap .mt { gap: 10px; }
.ap .no { width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center; flex: none; background: var(--su-text); color: #fff; font-size: var(--fs-2); font-weight: 800; font-variant-numeric: tabular-nums; }
.ap .mtx { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.ap .mtm { display: flex; align-items: center; gap: 6px; font-size: var(--fs-1); color: var(--mut); white-space: nowrap; }
.ap .mtm .tag { height: 22px; }
.ap .ck { width: 28px; height: 28px; border-radius: 8px; border: 1.5px dashed #C9B8D3; flex: none; display: grid; place-items: center; font-style: normal; transition: background 180ms var(--ease), border-color 180ms var(--ease); }
.ap .ck.on { background: var(--dot-ok); border: 1.5px solid var(--dot-ok); color: #fff; font-size: 13px; }
.ap .tag.warn, .ap .tag.ok { border-radius: 999px; }
.ap .q em { color: var(--vi-700); }
.ap-w > .sw { border-radius: 16px; }
.ap-w[data-dir="r"] > .sw { background: var(--oks); color: var(--ok); }
/* 빈 상태 · 스켈레톤: 유리 위에서도 보이게 */
.sk, .tcs { background-color: rgba(230,214,240,.6); }
.empty .ei { color: var(--vi-400); opacity: .7; }
.empty .sugs button .fa { color: var(--vi-700); }
.empty .sugs button + button { border-top-color: var(--line); }
/* 설정 줄 아이콘 · 칩 · 시트 손잡이 · 로그인 단계 */
.row .ri, .nt-i .ri { color: var(--vi-700); opacity: .78; }
.row.danger .ri { opacity: 1; }
.kk .kks { min-height: 48px; }
body.kb #tk-st { display: none; }   /* 글을 쓰는 동안은 연결 상태 카드를 접어 입력 칸이 키보드 위에 남게 */
.kk .kks .ri.ok { color: var(--dot-ok); opacity: 1; } .kk .kks .ri.warn { color: var(--dot-warn); opacity: 1; }
.kk .kks .tx b { font-size: var(--fs-2); }
.sheet .grab { background: #D9CCE0; }
.st3 li.on b { background: var(--ac) var(--vi-grad2); }
.ios li::before { background: var(--vi-100); color: var(--vi-900); }
.ios li .fa { color: var(--vi-700); }
#lg-inst { margin-top: 6px; color: var(--ach); }
.ban { border: 1px solid rgba(178,47,58,.16); }
/* 텔레그램 Mini App 안: 맨 위 머리는 텔레그램이 그린다 → 여백만 조금 */
html.tgwa .chat-hd { padding-top: calc(2px + var(--safe-t)); }
