/* 디자인 토큰 — 색 · 글꼴 · 둥글기 · 그림자 · 폭은 **여기에만** 적는다 (#237, docs/2.architecture/16.UI_SYSTEM.md)
   다른 파일은 var(--이름) 으로만 쓴다. 값을 바꾸면 API 화면과 MCP 화면이 함께 바뀐다 */
:root{
  /* 바탕 · 글 */
  --ink:#0C1526;--ink-2:#132038;--paper:#F4F6F5;--card:#fff;--text:#15202E;--muted:#586675;--faint:#8a97a6;
  --line:#E3E7E6;--line-strong:#9aa7b4;--head:#fafbfb;--hover:#fafcff;--hover-strong:#f1f4f7;--track:#eef1f4;
  --line-soft:#d6dbda;--line-hover:#b9c1c0;--line-cool:#b9c6d6;--code-bg:#f5f7f9;
  /* 어두운 바탕(메뉴 · 로그인 왼쪽 · 툴팁) 위의 글 */
  --on-dark:#fff;--on-dark-2:#e8edf4;--on-dark-3:#dbe4f2;--on-dark-muted:#b8c6da;--on-dark-faint:#93a4bc;--on-dark-dim:#8fa0b8;
  --ink-deep:#07101f;
  --on-dark-soft:#c3cfe0;--on-dark-nav:#aebbd0;--on-dark-link:#c7d2e2;--on-dark-note:#8b9cb5;--on-dark-quiet:#7d8da6;
  --on-dark-cap:#9fb0c7;--on-dark-blue:#cfe0ff;--on-dark-line:rgba(255,255,255,.12);
  --ink-pane:#0a1220;
  /* 브랜드 */
  --blue:#3D6DF0;--blue-deep:#254BB5;--blue-bright:#7AA2FF;--live:#37E0C8;--gold:#E6B15E;--gold-deep:#a8741f;--violet:#7B61FF;--teal:#12A594;
  --aqua:#37C8B4;--blue-soft:#eef3ff;--blue-soft-line:#d4e0ff;
  /* 상태 — 글자색 / 바탕색. 칩 · 요약 · 증감이 모두 이 넷을 쓴다 */
  --ok:#0a6b5d;--ok-bg:rgba(18,165,148,.13);--ok-strong:#0f7a67;--ok-line:#9fd9cd;--ok-soft:#effaf6;--ok-soft-line:#bfe6da;
  --warn:#8a4b06;--warn-bg:#fff1dc;--warn-line:#e8c9a6;--warn-text:#b0530c;--warn-bar:#e0791d;
  --warn-soft:#fffaf0;--warn-soft-line:#f1d7ae;--warn-chip-line:#eadfcb;--warn-chip-hot:#e8b774;
  --bad:#9b2c2c;--bad-bg:#fdecea;--bad-line:#e9b7b7;--bad-strong:#b3261e;--bad-soft-line:#f1cdc9;
  --info:#1f45b3;--info-bg:#eaf0ff;
  --mute-bg:#eef1f4;
  /* 올릴 파일을 끌어 놓는 칸 (지금 배포하기) · 불러오는 중인 미리보기 칸 (갤러리) */
  --drop-line:#c6cfd8;--skeleton:#e9edec;--skeleton-shine:#f3f5f4;
  /* 켜고 끄는 스위치 */
  --switch-on:#0f9d85;--switch-off:#c9d0cf;
  /* 서비스 상태 — 상태 페이지 막대 · 바닥글 점 · 관리자 결과 비율 */
  --state-good:var(--teal);--state-poor:var(--gold);--state-bad:#D64545;--state-unknown:#C9D0CF;
  /* 그래프 눈금 */
  --grid:#e5e9ee;--grid-base:#cfd6de;--grid-zero:#b6c0cb;
  /* 여러 개를 색으로 나눌 때 (사이트별 저장 공간) — 순서대로 돌려 쓴다 */
  --series-1:#3D6DF0;--series-2:#37E0C8;--series-3:#E6B15E;--series-4:#D97F97;
  --series-5:#8F74D0;--series-6:#5FAE9C;--series-7:#E09A52;--series-8:#7D9E52;
  /* 소개 화면의 그림 (#239) — 편집기 창(신호등 · 코드 색)과 고양이 갤러리 칸(바탕 두 색 + 고양이 색) */
  --tl-red:#ff5f57;--tl-yellow:#febc2e;--tl-green:#28c840;
  --code-tab:#6f8099;--code-comment:#5d7089;--code-ln:#3f5068;
  --tile-1a:#dce6ff;--tile-1b:#b9c9f5;--tile-1:#6f87d8;--tile-2a:#ffe6cc;--tile-2b:#f7cfa2;--tile-2:var(--series-7);
  --coffee:#7a4a2a;              /* 첫 화면 요금 제목 옆 커피 (#574) — 두 테마에 같다 */
  --tile-3a:#d6f3ec;--tile-3b:#aee0d4;--tile-3:var(--series-6);--tile-4a:#ffdfe6;--tile-4b:#f6bccb;--tile-4:var(--series-4);
  --tile-5a:#e7ddff;--tile-5b:#c9b6f2;--tile-5:var(--series-5);--tile-6a:#e4f2cf;--tile-6b:#c6de9f;--tile-6:var(--series-8);
  /* 상단 메뉴 (#510) — 밝은 테마는 흰 반투명 띠(시안 A). 어두운 테마 값은 아래 [data-theme] 묶음 */
  --gn-bg:rgba(255,255,255,.88);--gn-line:#e3e8ef;--gn-fg:#3b4a5c;--gn-on:#15202e;--gn-dim:#6b7a8d;--gn-accent:var(--blue);
  --gn-hover:#f1f4f8;--gn-on-bg:#eaf0ff;--gn-menu-bg:rgba(255,255,255,.98);--gn-menu-line:#e6ebf1;--gn-menu-fg:#2b3a4c;
  --gn-admin:#FFEFD9;--gn-admin-hover:#FFE3BD;--gn-admin-fg:#8A4300;
  --gn-chip:#f1f4f8;--gn-paid:#e8f0ff;--gn-paid-fg:#254BB5;--gn-seg-on:#fff;--gn-seg-shadow:0 1px 2px rgba(15,23,42,.12);
  --gn-panel:#fff;--gn-shadow:0 18px 40px -12px rgba(15,23,42,.22);
  --pressed:var(--ink);
  /* 모양 */
  --r-sm:7px;--r:10px;--r-lg:14px;--r-pill:999px;
  --shadow-pop:0 14px 30px rgba(12,21,38,.14);--shadow-tip:0 10px 24px rgba(0,0,0,.25);
  --sans:"Apple SD Gothic Neo","Malgun Gothic","Noto Sans KR",system-ui,-apple-system,sans-serif;
  --mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,monospace;
  /* 폭 5단계 (#167 · 2XL #578) — S <640 폭 전체 · M 640~1023 폭 전체 · L 1024~1439 최대 1160 · XL 1440~1919 최대 1400 · 2XL >=1920 최대 1760 */
  --wrap:100%;--gutter:16px;--gn-h:62px
}
@media (min-width:640px){:root{--gutter:24px}}
@media (min-width:1024px){:root{--wrap:1160px;--gutter:32px}}
@media (min-width:1440px){:root{--wrap:1400px}}
@media (min-width:1920px){:root{--wrap:1760px}}           /* 2XL — 큰 모니터에서 양옆을 비우지 않는다 (#578) */

/* 구역 — 관리자 화면은 바탕만 아주 옅은 주황 (#234). document(area="admin") 이 <html data-area> 를 단다 */
:root[data-area="admin"]{--paper:#FFF6EC}

/* 어두운 테마 (#510) — 사용자가 '어둡게' 를 골랐거나, '시스템 설정 따름'(기본)인데 기기가 어두운 모드일 때.
   두 경우가 같은 값을 쓰도록 한 벌만 적고 두 선택자에 붙인다. 고른 값은 <html data-theme> 에 있다(shell.THEME_BOOT) */
:root[data-theme="dark"]{color-scheme:dark;
  --paper:#0B111C;--card:#121A28;--text:#E6ECF4;--muted:#9AA8BA;--faint:#6F7D90;
  --line:#223047;--line-strong:#3A4A63;--head:#0F1724;--hover:#162133;--hover-strong:#1A273B;--track:#1A2537;
  --line-soft:#2A3850;--line-hover:#3A4A63;--line-cool:#34445E;--code-bg:#0F1724;
  --blue-soft:#16264A;--blue-soft-line:#27407A;
  --ok:#5FD3BE;--ok-bg:rgba(55,224,200,.14);--ok-strong:#4CC7B0;--ok-line:#1F5C52;--ok-soft:#0F2622;--ok-soft-line:#1F4A42;
  --warn:#F0B66B;--warn-bg:#2E2213;--warn-line:#5A4223;--warn-text:#F5A35A;--warn-soft:#241B10;--warn-soft-line:#4A3820;
  --warn-chip-line:#4A3E2A;--warn-chip-hot:#B8853F;
  --bad:#FF9C94;--bad-bg:#2E1517;--bad-line:#5C2A2D;--bad-strong:#FF7A70;--bad-soft-line:#4E2629;
  --info:#9DB9FF;--info-bg:#16264A;--mute-bg:#1A2537;
  --drop-line:#33435C;--skeleton:#1A2537;--skeleton-shine:#223047;--switch-off:#3A4A63;
  --state-unknown:#3A4A63;--grid:#1E2A3D;--grid-base:#2A3850;--grid-zero:#3A4A63;
  --shadow-pop:0 14px 30px rgba(0,0,0,.45);--pressed:var(--blue);
  --gn-bg:rgba(11,17,28,.94);--gn-line:rgba(255,255,255,.1);--gn-fg:var(--on-dark-nav);--gn-on:var(--on-dark);--gn-dim:var(--on-dark-dim);
  --gn-accent:var(--blue-bright);--gn-hover:rgba(255,255,255,.07);--gn-on-bg:rgba(255,255,255,.09);
  --gn-menu-bg:rgba(17,26,42,.97);--gn-menu-line:rgba(255,255,255,.1);--gn-menu-fg:var(--on-dark-3);
  --gn-admin:rgba(255,160,60,.16);--gn-admin-hover:rgba(255,160,60,.26);--gn-admin-fg:#FFC98A;
  --gn-chip:rgba(255,255,255,.08);--gn-paid:rgba(61,109,240,.28);--gn-paid-fg:var(--on-dark-blue);
  --gn-seg-on:rgba(255,255,255,.16);--gn-seg-shadow:none;--gn-panel:var(--ink);--gn-shadow:0 24px 50px -12px rgba(0,0,0,.6)}
:root[data-theme="dark"][data-area="admin"]{--paper:#17120C}

/* 기본 — 요소 모양과 작은 도우미 (#237). 부품은 components.css, 값은 tokens.css */
*{box-sizing:border-box}
/* 세로 스크롤바 자리를 늘 비워 둔다 — 긴 화면에만 스크롤바가 생겨 틀 전체가 7.5px 옆으로 밀렸다 (#313) */
html{scrollbar-gutter:stable}
body{margin:0;background:var(--paper);color:var(--text);font-family:var(--sans);
  line-height:1.7;word-break:keep-all;-webkit-font-smoothing:antialiased}
a{color:var(--blue)}
main{padding:40px 0 64px}
h1{font-size:1.7rem;letter-spacing:-.025em;margin:0 0 6px}
h2{font-size:1rem;margin:0 0 12px}
h2.sec{font-size:.82rem;color:var(--muted);margin:0 0 8px;letter-spacing:.02em}
@media (max-width:640px){main{padding:28px 0 48px}h1{font-size:1.4rem}}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--gutter)}
.lead{color:var(--muted);margin:0 0 28px;font-size:.96rem}
.lead.warn{color:var(--warn-text);font-weight:700}
/* 한 덩어리로 읽혀야 하는 것은 줄을 바꾸지 않는다 — "운영\n중" · "2026-\n10-27" 처럼 깨졌다 */
.nowrap{white-space:nowrap}
.mono{font-family:var(--mono);font-size:.84rem}
.dim{color:var(--muted)}
.red{color:var(--bad-strong)}
.notes{margin:0;padding-left:18px;font-size:.9rem;color:var(--muted)}
.notes li{margin:4px 0}

/* 상단 메뉴 · 바닥글 · 언어 칸 (#237) — 틀은 nav.html · footer.html, 글은 strings.json. 색 · 폭은 tokens.css 의 var() 로만 (#239) */
/* 색은 테마마다 tokens.css 의 --gn-* (#510) — 밝게: 흰 반투명 띠 · 어둡게: 남색 띠 */
.gnav{position:sticky;top:0;z-index:100;background:var(--gn-bg);backdrop-filter:saturate(140%) blur(10px);
    border-bottom:1px solid var(--gn-line);font-family:var(--sans)}
  .gnav *{box-sizing:border-box}
  .gnav [hidden]{display:none!important}
  .gnav a{text-decoration:none}
  .gnav-in{max-width:var(--wrap);margin:0 auto;padding:0 var(--gutter);display:flex;align-items:center;
    height:var(--gn-h);position:relative}
  .gnav-logo{display:flex;align-items:center;gap:10px;color:var(--gn-on);margin-right:18px;flex:none}
  /* 로고 표시 — 위쪽 화살표(올린다). 사이트 배지(share_card.BADGE_JS)와 같은 모양 (#508) */
  .gnav-mark{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;flex:none;
    background:linear-gradient(135deg,var(--blue),var(--live));box-shadow:0 0 0 1px rgba(255,255,255,.12) inset}
  .gnav-mark svg{width:14px;height:14px;fill:none;stroke:var(--on-dark);stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
  /* 메뉴 아이콘 — 얇은 선 하나의 모양 (#508) */
  .gnav-ic{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
  .gnav-brand{font-weight:800;font-size:1.02rem;letter-spacing:-.02em;line-height:1.2}
  .gnav-brand small{display:block;font-weight:500;font-size:.66rem;color:var(--gn-dim)}
  .gnav-alias{font-weight:600;font-size:.8rem;color:var(--gn-dim)}   /* 한국어 읽기(디플로이) — 영어 화면은 비어 있다 (#508) */
  /* 아주 좁은 화면(S 의 아래쪽) — 로고 부제가 줄지 않아 오른쪽 칸이 화면 밖으로 밀렸다(#243).
     그 폭에서는 메뉴 단추 · 언어 칸 · 폭 표시가 더 중요하다. 로고 옆 여백도 줄인다 */
  .gnav-short{display:none}
  /* 아주 좁은 휴대폰(320px 대) — 로고 옆 이름은 읽기 도구에만 남기고 화면에서는 뺀다. 그래야 로그인이 잘리지 않는다 (#656) */
  @media (max-width:359px){.gnav-brand{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}}
  @media (max-width:479px){.gnav-long{display:none}.gnav-short{display:inline}.gnav-brand small{display:none}.gnav-logo{margin-right:8px}#gnav-name,.gnav-tool .gnav-chev,#gnav-acct .gnav-chev,.gnav-alias,.gnav-tools .gnav-bp{display:none}.gnav-tool{padding:0 6px}.gnav-bp{margin-left:6px}}
  .gnav-links{display:flex;align-items:stretch;height:100%;margin-left:auto;gap:2px}
  .gnav-sep{width:1px;background:var(--gn-line);margin:20px 8px}
  .gnav-sep[hidden]{display:none}

  /* 항목 하나의 모양 — 링크든 풀다운이든 같다 */
  /* 항목은 높이 36 의 알약 — 올림 · 선택됨이 같은 자리에 바탕으로 보인다 (#508) */
  .gnav-item{position:relative;display:flex;align-items:center;gap:7px;height:36px;align-self:center;padding:0 11px;
    color:var(--gn-fg);font-size:.9rem;font-weight:600;white-space:nowrap;cursor:pointer;list-style:none;
    border-radius:9px;transition:color .12s,background .12s}
  .gnav-item::-webkit-details-marker{display:none}
  .gnav-item:hover{color:var(--gn-on);background:var(--gn-hover)}
  .gnav-item:focus-visible{outline:2px solid var(--gn-accent);outline-offset:1px}
  .gnav-item[aria-current="page"],.gnav-drop.is-on>.gnav-item{color:var(--gn-on);background:var(--gn-on-bg)}
  .gnav-item[aria-current="page"] .gnav-ic,.gnav-drop.is-on>.gnav-item .gnav-ic{opacity:1;color:var(--gn-accent)}

  /* 풀다운 — 갈매기가 뒤집혀 펼침을 알린다 */
  .gnav-drop{position:relative;display:flex}
  .gnav-chev{width:10px;height:10px;flex:none;transition:transform .15s}
  .gnav-drop[open]>.gnav-item{color:var(--gn-on);background:var(--gn-hover)}
  .gnav-drop[open] .gnav-chev{transform:rotate(180deg)}
  /* 풀다운 — 아이콘 + 글. 소개 메뉴는 설명 한 줄을 더 단다 (#508) */
  .gnav-menu{position:absolute;top:calc(100% + 4px);left:0;min-width:260px;background:var(--gn-menu-bg);backdrop-filter:blur(10px);
    border:1px solid var(--gn-menu-line);border-radius:14px;padding:6px;box-shadow:var(--gn-shadow)}
  .gnav-menu a{display:flex;align-items:center;gap:11px;color:var(--gn-menu-fg);padding:9px 10px;border-radius:9px;font-size:.88rem;font-weight:600}
  .gnav-menu a .gnav-ic{color:var(--gn-dim)}
  .gnav-menu a small{display:block;color:var(--gn-dim);font-size:.74rem;font-weight:500;margin-top:2px;white-space:nowrap}
  .gnav-menu a:hover,.gnav-menu a:focus-visible{background:var(--gn-hover);color:var(--gn-on);outline:none}
  .gnav-menu a:hover .gnav-ic,.gnav-menu a:focus-visible .gnav-ic{color:var(--gn-accent)}
  .gnav-grp{padding:10px 10px 4px;font-size:.68rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--gn-dim);opacity:.8}
  .gnav-menu a.gnav-out,.gnav-menu a.gnav-out .gnav-ic{color:var(--warn-bar)}
  /* 관리자 입구 — 일반 메뉴와 섞이지 않게 관리자 화면의 주황으로 칠한다. display 가 있어 hidden 을 직접 지킨다 */
  .gnav-menu a.gnav-admin{margin:4px 0;font-weight:700;color:var(--gn-admin-fg);background:var(--gn-admin)}
  .gnav-menu a.gnav-admin .gnav-ic{color:inherit}
  .gnav-menu a.gnav-admin:hover,.gnav-menu a.gnav-admin:focus-visible{color:var(--gn-admin-fg);background:var(--gn-admin-hover)}
  .gnav-menu a.gnav-admin:hover .gnav-ic,.gnav-menu a.gnav-admin:focus-visible .gnav-ic{color:inherit}
  .gnav-menu a.gnav-admin[hidden]{display:none}

  .gnav-menu-right{left:auto;right:0}
  .gnav-acct-menu{width:300px}
  /* 계정 카드 — 이름 · 메일 · 요금제 칩 (#508) */
  .gnav-menu .gnav-who{display:flex;align-items:center;gap:11px;padding:10px 10px 12px;color:var(--gn-dim);font-size:.76rem}
  .gnav-who-t{min-width:0;display:grid;gap:2px}.gnav-who-t span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .gnav-menu .gnav-who b{display:block;color:var(--gn-on);font-size:.92rem}
  .gnav-plan{margin-left:auto;flex:none;padding:3px 9px;border-radius:var(--r-pill);font-size:.68rem;font-weight:700;
    color:var(--gn-dim);background:var(--gn-chip)}
  .gnav-plan.is-paid{color:var(--gn-paid-fg);background:var(--gn-paid)}
  .gnav-menu hr{border:0;border-top:1px solid var(--gn-menu-line);margin:4px 4px}
  .gnav-avatar{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;flex:none;
    background:linear-gradient(135deg,var(--violet),var(--blue));color:var(--on-dark);font-weight:800;font-size:.72rem}
  .gnav-avatar-lg{width:38px;height:38px;font-size:.9rem}

  /* 지금 화면 폭 단계 (#188). 폭 규칙은 모든 화면이 같다 — S <640 · M 640~1023 · L 1024~1439 · XL 1440~1919 · 2XL >=1920 (#578) */
  .gnav-bp{display:inline-flex;align-items:center;gap:4px;margin-left:10px;color:var(--gn-dim);font-size:.7rem;font-weight:800;
    border:1px solid var(--gn-line);border-radius:6px;padding:2px 6px;flex:none;cursor:default}
  .gnav-bp:hover,.gnav-bp:focus-visible{color:var(--gn-on);border-color:var(--gn-dim);outline:0}
  .gnav-bp::after{content:"S"}
  @media (min-width:640px){.gnav-bp::after{content:"M"}}
  @media (min-width:1024px){.gnav-bp::after{content:"L"}}
  @media (min-width:1440px){.gnav-bp::after{content:"XL"}}
  @media (min-width:1920px){.gnav-bp::after{content:"2XL"}}
  /* 언어 [KR | EN] (#228) — 지금 언어가 칠해진다. 영어판이 있는 화면(<html data-langs>)에서만 보인다 */
  /* 오른쪽 도구 (#512) — [지구본 한 ▾] [테마 ▾] [폭] [이름 ▾]. 프로필이 맨 오른쪽 */
  .gnav-tools{display:flex;align-items:center;gap:2px;margin-left:8px;flex:none}
  .gnav-tool{padding:0 8px;gap:5px}
  .gnav-now{font-size:.74rem;font-weight:800;letter-spacing:.02em}
  .gnav-pref-menu{min-width:168px}
  .gnav-pref-menu a,.gnav-pref-menu button{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:0;border-radius:9px;
    background:none;font:inherit;font-size:.88rem;font-weight:600;color:var(--gn-menu-fg);cursor:pointer;text-align:left}
  .gnav-pref-menu button:hover,.gnav-pref-menu button:focus-visible{background:var(--gn-hover);color:var(--gn-on);outline:none}
  .gnav-pref-menu [aria-checked="true"],.gnav-pref-menu a[aria-current]{color:var(--gn-on);background:var(--gn-on-bg)}
  .gnav-pref-menu [aria-checked="true"] .gnav-ic{color:var(--gn-accent)}
  .gnav-tick{width:16px;height:16px;flex:none;display:grid;place-items:center}
  .gnav-pref-menu a[aria-current] .gnav-tick::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--gn-accent)}
  /* 한국어만 있는 화면의 English — 흐리게. 누를 수 없고, 마우스를 올리면 까닭이 보인다 */
  .gnav-pref-menu a.is-off{opacity:.42;cursor:not-allowed}
  .gnav-pref-menu a.is-off:hover{background:none;color:var(--gn-menu-fg)}
  /* 테마 — 닫혀 있을 때는 고른 것의 아이콘 하나만 */
  #gnav-theme>summary .is-system,#gnav-theme>summary .is-light,#gnav-theme>summary .is-dark{display:none}
  #gnav-theme[data-now="system"]>summary .is-system,#gnav-theme[data-now="light"]>summary .is-light,
  #gnav-theme[data-now="dark"]>summary .is-dark,#gnav-theme:not([data-now])>summary .is-system{display:block}
  /* 자리가 모자랄 때만 언어 · 테마를 지구본 하나로 합친다 (#696) — S 폭, 그리고 메뉴가 다 펼쳐져 빠듯한 900~1023. 640~899 는 메뉴가 햄버거로 들어가 두 단추가 들어간다 */
  #gnav-pref{display:none}
  #gnav-name{max-width:100px;overflow:hidden;text-overflow:ellipsis}
  /* 이 폭에서는 이름도 뺀다 — 아바타만 남기고, 전체 이름은 프로필 메뉴에서 본다 */
  @media (max-width:639px),(min-width:900px) and (max-width:1023px){#gnav-pref{display:flex}#gnav-lang,#gnav-theme,#gnav-name{display:none}}
  .gnav-burger{display:none}
  @media (prefers-reduced-motion:reduce){.gnav-chev,.gnav-item{transition:none}}

  /* 좁은 화면 — 한 줄에 다 못 넣는다. 햄버거를 열면 세로 목록, 선택된 것은 왼쪽 파란 막대 */
  @media (max-width:899px){
    .gnav-burger{display:block;margin-left:auto}
    .gnav-tools{margin-left:4px}
    .gnav-tools .gnav-menu-right{right:0}
    .gnav-menu-right{right:auto}
    .gnav-burger summary{list-style:none;color:var(--gn-on);cursor:pointer;width:42px;height:42px;display:grid;place-items:center;
      border-radius:10px}
    .gnav-burger summary::-webkit-details-marker{display:none}
    .gnav-burger summary:focus-visible{outline:2px solid var(--gn-accent)}
    .gnav-burger .x,.gnav-burger[open] .bars{display:none}
    .gnav-burger[open] .x{display:block}
    .gnav-links{display:none}
    .gnav-burger[open] + .gnav-links{display:flex;position:absolute;top:var(--gn-h);left:0;right:0;height:auto;
      flex-direction:column;background:var(--gn-panel);border-bottom:1px solid var(--gn-line);
      padding:8px var(--gutter) 14px;gap:2px;box-shadow:var(--gn-shadow)}
    .gnav-item{height:46px;border-radius:10px;align-self:stretch}
    .gnav-drop{flex-direction:column}
    .gnav-links .gnav-menu{position:static;box-shadow:none;border:0;background:transparent;backdrop-filter:none;padding:0 0 4px 14px;min-width:0;width:auto}
    .gnav-sep{width:auto;height:1px;margin:6px 0}
  }

/* 바닥글 */
.gfoot{background:var(--ink);color:var(--on-dark-note);font-size:.86rem;border-top:1px solid rgba(255,255,255,.08);padding:30px 0 44px;
    font-family:var(--sans);line-height:1.7;word-break:keep-all}
  .gfoot *{box-sizing:border-box}
  .gfoot-in{max-width:var(--wrap);margin:0 auto;padding:0 var(--gutter)}
  .gfoot a{color:var(--on-dark-link);text-decoration:none}
  .gfoot a:hover{color:var(--on-dark);text-decoration:underline}
  .gfoot-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 28px;
    padding-bottom:16px;border-bottom:1px solid rgba(255,255,255,.08);margin-bottom:14px}
  .gfoot-brand strong{color:var(--on-dark);font-weight:800;letter-spacing:-.01em;margin-right:8px}
  .gfoot-links{display:flex;flex-wrap:wrap;gap:6px 18px;font-weight:600;font-size:.84rem}
  .gfoot-status{display:inline-flex;align-items:center;gap:7px;font-weight:600;font-size:.84rem;color:var(--on-dark-link)}
  .gfoot-dot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--state-unknown)}
  /* 서비스 상태 점 — ui.js 가 /api/status 를 보고 data-tone 을 단다. 어두운 바닥이라 정상은 밝은 청록(--live) */
  .gfoot-dot[data-tone="good"]{background:var(--live)}.gfoot-dot[data-tone="poor"]{background:var(--state-poor)}
  .gfoot-dot[data-tone="bad"]{background:var(--state-bad)}
  .gfoot-biz{margin:0 0 4px;font-size:.78rem;color:var(--on-dark-quiet)}
  .gfoot-legal{margin-top:10px;font-size:.78rem;color:var(--on-dark-quiet)}
  .gfoot-legal p{margin:0 0 3px}
  .gfoot-legal a{white-space:nowrap}

/* 페이지를 옮길 때 메뉴가 사라졌다 다시 그려지지 않게 (#251) — 같은 사이트 안의 이동은 브라우저가 이전 화면에서
   새 화면으로 이어 준다(Cross-document View Transitions: Chrome · Edge 126+, Safari 18.2+). 메뉴는 이름을 붙여
   제자리에 그대로 두고, 본문만 짧게 바뀐다. 지원하지 않는 브라우저는 예전처럼 바로 바뀐다 */
@view-transition{navigation:auto}
.gnav{view-transition-name:gnav}
::view-transition-old(root),::view-transition-new(root){animation-duration:.14s}
::view-transition-group(gnav){animation:none}
@media (prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}

/* 화면 부품 모양 (#237, docs/2.architecture/16.UI_SYSTEM.md) — 이 파일이 정의한 클래스는 **다른 곳에서 다시 정의하지 않는다**
   (시험 test_ui_system 이 막는다). HTML 은 views/ui.py 의 함수가 짠다. 색 · 둥글기는 tokens.css 의 var() 로만 */

/* ── 로고 (로그인 화면) ─────────────────────────────────── */
.logo{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--on-dark)}
.logo .mark{width:30px;height:30px;border-radius:9px;flex:none;display:grid;place-items:center;font-weight:800;font-size:.95rem;color:var(--on-dark);
  background:linear-gradient(135deg,var(--blue),var(--live))}
.logo .mark svg{width:14px;height:14px;fill:none;stroke:var(--on-dark);stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
.brand{font-weight:800;letter-spacing:-.02em;color:var(--on-dark);font-size:1.05rem}
.brand small{display:block;font-weight:500;font-size:.68rem;color:var(--on-dark-dim);letter-spacing:0}

/* ── 카드 · 칸 나눔 ───────────────────────────────────── */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:22px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px}
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin-bottom:18px}
@media(max-width:1023px){.grid3{grid-template-columns:1fr}}
@media(max-width:780px){.grid2{grid-template-columns:1fr}}
.grid2>.card,.grid3>.card{margin:0}
.pnl header{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.pnl header h2{margin:0}.pnl>.dim{margin:2px 0 14px;font-size:.8rem}
.pnl-more{font-size:.8rem;white-space:nowrap}
h3.sub{font-size:.8rem;color:var(--muted);margin:18px 0 10px}

/* ── 단추 — 기본 · primary · ghost · 작게(sm) · 주의(warn) · 위험(danger) ───── */
.btn{display:inline-block;font:inherit;font-weight:700;font-size:.92rem;border-radius:var(--r);padding:10px 18px;cursor:pointer;
  text-decoration:none;border:1px solid var(--line);background:var(--card);color:var(--text)}
.btn:hover{border-color:var(--line-strong)}
.btn.primary{background:var(--blue);border-color:transparent;color:var(--on-dark)}
.btn.primary:hover{background:var(--blue-deep)}
.btn.ghost{background:var(--card)}
.btn.sm{font-size:.8rem;border-radius:var(--r-sm);padding:5px 10px}
.btn.warn{border-color:var(--warn-line);color:var(--warn)}
.btn.danger{border-color:var(--bad-line);color:var(--bad)}
.btn.danger.fill{background:var(--bad-strong);border-color:transparent;color:var(--on-dark)}
.btn.fill:disabled{opacity:.4}
/* 작은 글자 단추 — 목록 한 줄 안에 붙는 되돌리기 · 다시 하기 */
.btn.mini{font-size:.78rem;font-weight:400;border-radius:6px;padding:3px 8px;color:var(--blue)}
.btn:disabled{opacity:.55;cursor:not-allowed}
/* 어두운 바탕(소개 화면 머리 · 안내 상자) 위의 보조 단추 — 바탕이 비치고 테두리만 있다 (#239) */
.btn.on-dark{background:transparent;border-color:rgba(255,255,255,.22);color:var(--on-dark-2)}
.btn.on-dark:hover{border-color:rgba(255,255,255,.45)}
form.inline{display:inline-flex;gap:4px;align-items:center;margin:0}
form.inline select{font:inherit;font-size:.8rem;padding:4px 6px;border:1px solid var(--line);border-radius:var(--r-sm)}

/* ── 어두운 머리 띠 — 화면 제목 + 한 줄 설명 (갤러리 · 지금 배포하기, #239) ── */
.masthead{background:var(--ink);color:var(--on-dark);padding:28px 0 36px}
.masthead h1{margin:0 0 8px;font-size:1.9rem;letter-spacing:-.03em;line-height:1.6}
.masthead p{margin:0;color:var(--on-dark-soft)}

/* ── 상태 칩 — ok · warn · bad · info · mute ──────────────── */
.badge{display:inline-block;font-size:.74rem;font-weight:700;border-radius:var(--r-pill);padding:2px 9px;white-space:nowrap;line-height:1.5;
  background:var(--mute-bg);color:var(--muted)}
.badge.ok{background:var(--ok-bg);color:var(--ok)}.badge.warn{background:var(--warn-bg);color:var(--warn)}
.badge.bad{background:var(--bad-bg);color:var(--bad)}.badge.info{background:var(--info-bg);color:var(--info)}

/* ── 화면 머리 — 제목 · 요약 칩 · 한 줄 설명 ───────────────── */
.ph{margin:0 0 16px}
.ph-t{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}
.ph-t h1{margin:0}
.ph-s{display:flex;flex-wrap:wrap;gap:6px}
.hs{display:inline-flex;align-items:baseline;gap:5px;font-size:.8rem;color:var(--muted);background:var(--card);
  border:1px solid var(--line);border-radius:var(--r-pill);padding:3px 10px}
.hs b{color:var(--text);font-size:.9rem}
.hs.warn b{color:var(--warn-text)}.hs.bad b{color:var(--bad-strong)}.hs.ok b{color:var(--ok)}.hs.info b{color:var(--info)}
.ph-l{margin:8px 0 0;color:var(--muted);font-size:.88rem}

/* ── 도구줄 — 검색 · 거르기 단추 묶음 · 건수 ───────────────── */
.tb{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin:0 0 12px}
.tb-q,.tb input[type=search],.tb select{font:inherit;font-size:.88rem;padding:8px 12px;border:1px solid var(--line);border-radius:9px;background:var(--card)}
.tb-q,.tb-sq{min-width:260px;flex:0 1 320px}
.tb-sq{font:inherit;font-size:.88rem;padding:8px 12px;border:1px solid var(--line);border-radius:9px;background:var(--card)}
.tb-x{font-size:.82rem;color:var(--muted)}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;background:var(--card)}
.seg button,.seg a{font:inherit;font-size:.8rem;font-weight:600;border:0;background:none;color:var(--muted);padding:7px 11px;cursor:pointer;
  white-space:nowrap;text-decoration:none}
.seg button+button,.seg a+a{border-left:1px solid var(--line)}
.seg [aria-pressed="true"]{background:var(--pressed);color:var(--on-dark)}
.tb-n{font-size:.82rem;color:var(--muted);margin-left:auto}

/* ── 쪽 번호 ‹ 1 2 3 4 … 10 › (#548) — 서버(ui.pager)와 브라우저(ui.js, ui.paged)가 같은 모양 ─────── */
.pg{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:4px;margin:14px 0 4px}
.pg[hidden]{display:none}
.pg-b{font:inherit;font-size:.86rem;font-weight:600;min-width:36px;height:36px;padding:0 10px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:9px;background:var(--card);color:var(--text);cursor:pointer;text-decoration:none}
.pg-b:hover{background:var(--hover-strong)}
.pg-b[aria-current="page"]{background:var(--pressed);border-color:var(--pressed);color:var(--on-dark);cursor:default}
.pg-b:disabled,.pg-b[aria-disabled="true"]{opacity:.4;cursor:default;background:var(--card)}
.pg-gap{min-width:24px;text-align:center;color:var(--muted)}

/* ── 표 — 칸은 한 줄 + 말줄임, 둘째 정보는 아래 회색 한 줄 ─────── */
.tbl-w{padding:0;overflow-x:auto}
.tbl{width:100%;border-collapse:collapse;font-size:.86rem;table-layout:fixed}
.tbl th{font-size:.74rem;color:var(--muted);background:var(--head);font-weight:700;text-align:left;padding:10px 12px;
  border-bottom:1px solid var(--line);line-height:1.35;overflow:hidden;
  word-break:keep-all;overflow-wrap:anywhere}   /* 머리글은 두 줄까지 접힌다 — 잘린 채 숨지 않게 (#576) */
.tbl td{padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:middle;height:58px;overflow:hidden}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--hover)}
.tbl tr[hidden]{display:none}
.tbl .t1,.tbl .t2{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tbl .t2{font-size:.76rem;color:var(--muted);margin-top:2px}
.tbl .t1.mono{font-size:.8rem}
.tbl a{text-decoration:none}.tbl a:hover{text-decoration:underline}
.tbl .num{text-align:right}
.tbl th.ops,.tbl td.ops{text-align:right;overflow:visible}
/* 좁아서 옆으로 밀 때 — 무엇인지(첫 칸)와 할 일(처리 칸)은 양끝에 붙어 있다 */
.tbl th:first-child,.tbl td:first-child{position:sticky;left:0;z-index:2;background:var(--card)}
.tbl th:first-child{background:var(--head)}
.tbl th.ops,.tbl td.ops{position:sticky;right:0;z-index:2;background:var(--card);box-shadow:-10px 0 10px -10px rgba(12,21,38,.18)}
.tbl th.ops{background:var(--head)}
.tbl td.lift{z-index:30}
.tbl tbody tr:hover td:first-child,.tbl tbody tr:hover td.ops{background:var(--hover)}
.tbl td.ops>*{vertical-align:middle}
.tbl td.chk,.tbl th.chk{width:40px}
/* 칸 폭 — views/ui.py 의 WIDTHS 와 같아야 한다 */
.w-xs{width:80px}.w-s{width:108px}.w-m{width:150px}.w-l{width:210px}.w-xl{width:300px}
.clamp,.tbl .t1.clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:normal;line-height:1.45}
.empty{padding:32px;text-align:center;color:var(--muted)}
.empty.sm{padding:14px 0;text-align:left;font-size:.86rem}
.bulkbar{display:flex;align-items:center;gap:12px;margin:0 0 10px;padding:8px 12px;border:1px dashed var(--line);border-radius:var(--r);
  font-size:.86rem;background:var(--card)}
.bulkbar b{min-width:1.5em}
/* 사용자 일괄 설정 (#668) — 요금제 칸 · 한도 칸은 그 일을 골랐을 때만 보인다(화면 스크립트 없이 :has) */
.users-bulk{flex-wrap:wrap}
.users-bulk .when-plan,.users-bulk .when-limits,.users-bulk .when-grant{display:none}
.users-bulk:has(select[name=op] option[value="grant"]:checked) .when-grant{display:inline-flex;flex-wrap:wrap;gap:8px;align-items:center}
.users-bulk:has(select[name=op] option[value="plan"]:checked) .when-plan{display:inline-block}
.users-bulk:has(select[name=op] option[value="limits"]:checked) .when-limits{display:flex;flex-wrap:wrap;gap:8px;align-items:center;flex-basis:100%}
.lim{display:inline-flex;flex-direction:column;gap:2px;font-size:.78rem;color:var(--muted)}
.lim .input{width:7.5em}
/* 기간 이용권의 기간 칸 (#704) — '30 일 동안' 한 줄 */
.grant-days{display:inline-flex;align-items:center;gap:6px;font-size:.86rem;color:var(--text);white-space:nowrap}.grant-days .input{width:4.5em}
form.lims{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end}

/* ── 좁은 화면에서 줄을 카드로 쌓는 표 — <table class="… stack">, 칸마다 data-label="칸 이름" (#407).
      칸이 넷을 넘는 표를 S 에서 옆으로 밀게 두면 끝 칸(결과 · 관리)이 화면 밖에 있다. 이름표가 없는 칸은 카드의 제목 줄이다 ── */
@media (max-width:639px){
  table.stack,table.stack tbody,table.stack tr,table.stack td{display:block;width:100%;min-width:0}
  table.stack thead{display:none}
  table.stack tr{padding:12px 16px;border-bottom:1px solid var(--line)}
  table.stack tbody tr:last-child{border-bottom:0}
  table.stack td,table.stack td:first-child,table.stack td.ops,table.stack tbody tr:last-child td{border:0;padding:3px 0;height:auto;
    white-space:normal;overflow:visible;position:static;box-shadow:none;text-align:left;background:none}
  table.stack td[data-label]{display:flex;gap:2px 10px;align-items:baseline}
  table.stack td[data-label]::before{content:attr(data-label);color:var(--muted);font-size:.78rem;font-weight:400;flex:0 0 84px;font-family:var(--sans)}
  table.stack td[data-label]>*{min-width:0}
}

/* ── 자주 묻는 질문 — <details class="faq"><summary>질문</summary><p>답</p></details> (사용 설명서 · 소개 화면) ── */
.faq{border:1px solid var(--line);border-radius:var(--r);background:var(--card);margin-bottom:8px;padding:0 16px}
.faq summary{cursor:pointer;font-weight:700;padding:13px 0}
.faq p{margin:0 0 14px;color:var(--muted);line-height:1.7}

/* ── ⋯ 메뉴 · 떠 있는 창 — 줄 높이를 바꾸지 않고 더 보여 준다 ──────── */
.more{display:inline-block;position:relative}
.more summary{list-style:none;cursor:pointer;font-weight:800;color:var(--muted);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:3px 9px;line-height:1.3;background:var(--card);user-select:none}
.more summary::-webkit-details-marker{display:none}
.more[open] summary,.more summary:hover{border-color:var(--line-strong);color:var(--text)}
.more.full{margin-top:4px}
.more.full summary{font-size:.74rem;font-weight:700;padding:1px 8px}
.more-m{position:absolute;right:0;top:calc(100% + 4px);z-index:50;background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow-pop);padding:6px;min-width:190px;display:grid;gap:2px;text-align:left}
.more-m form{display:block;margin:0}
.more-m .btn{display:block;width:100%;text-align:left;border:0;background:none;padding:8px 10px;border-radius:var(--r-sm);font-weight:600;font-size:.84rem}
.more-m .btn:hover{background:var(--hover-strong)}
.more-m hr{border:0;border-top:1px solid var(--line);margin:4px 0}
/* 저마다 따로 적용되는 구역 (#691) — 칸과 단추를 한 상자에 묶고, 적용 단추는 위의 .more-m .btn 이 지운 채움을 되돌린다 */
.more-m:has(.more-sec){width:min(340px,calc(100vw - 32px));gap:8px;padding:8px;overflow:auto}
.more-sec{display:grid;gap:8px;padding:10px;border:1px solid var(--line);border-radius:var(--r-sm)}
.more-sec .more-h{padding:0;font-size:.82rem;color:var(--text)}
.more-sec form.plan{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:center}
.more-sec form.plan select{margin:0;width:100%;min-width:0}
.more-sec form.lims{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.more-sec .lim .input{width:100%}
.more-sec form.lims .btn{grid-column:1 / -1}
.more-sec .btn.primary{width:auto;text-align:center;padding:7px 14px;font-weight:700;background:var(--blue);color:var(--on-dark);white-space:nowrap}
.more-sec .btn.primary:hover{background:var(--blue-deep)}
.more-note{margin:0;font-size:.74rem;color:var(--muted)}
.more-h{font-size:.72rem;color:var(--muted);font-weight:700;padding:6px 10px 2px}
.more-m select{font:inherit;font-size:.82rem;padding:5px 7px;border:1px solid var(--line);border-radius:var(--r-sm);margin:2px 10px 6px;width:calc(100% - 20px)}
.pop-v{padding:0 10px 8px;font-size:.8rem;word-break:break-all;max-width:320px;white-space:normal}
.pop-v.long{white-space:pre-wrap;word-break:keep-all;max-width:440px;max-height:280px;overflow:auto;font-size:.86rem;line-height:1.6}

/* ── 쓰는 양 막대 (표 칸 안) — 한 줄: 막대 + 비율 ────────────── */
.meter{display:flex;align-items:center;gap:8px;white-space:nowrap;font-size:.84rem}
.meter-bar{width:90px;height:7px;border-radius:9px;background:var(--line);overflow:hidden;flex:none}
.meter-bar i{display:block;height:100%;background:var(--blue)}
.meter.warn{color:var(--warn-text);font-weight:700}.meter.warn .meter-bar i{background:var(--warn-bar)}

/* ── 지표 카드 · 증감 ──────────────────────────────────── */
.kps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:0 0 18px}
@media(max-width:1023px){.kps{grid-template-columns:repeat(2,minmax(0,1fr))}}
.kp{display:block;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px 16px 12px;color:inherit;
  text-decoration:none;min-width:0}
a.kp:hover{border-color:var(--line-cool);box-shadow:0 4px 14px rgba(12,21,38,.06)}
.kp-l{display:block;font-size:.8rem;color:var(--muted);font-weight:600}
.kp-v{display:block;font-size:1.65rem;letter-spacing:-.03em;line-height:1.25;margin:2px 0 4px}
.kp .dl{white-space:normal;flex-wrap:wrap;column-gap:6px}
.dl{display:inline-flex;align-items:baseline;gap:4px;font-size:.78rem;font-weight:700;white-space:nowrap}
.dl small{font-weight:500;color:var(--muted);white-space:nowrap}
.dl.up{color:var(--ok-strong)}.dl.down{color:var(--bad-strong)}.dl.flat{color:var(--muted);font-weight:600}

/* ── 그래프 — 막대 · 눈금 · 평균 · 즉시 툴팁 · 기간 전환 ─────────── */
.chc{margin:0 0 18px}
.chc-h{display:flex;flex-wrap:wrap;justify-content:space-between;gap:10px;align-items:flex-start;margin:0 0 6px}
.chc-h h2{margin:0 0 2px}.chc-h p{margin:0;font-size:.8rem}
.rng{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;flex:none}
.rng button{font:inherit;font-size:.78rem;font-weight:700;border:0;background:var(--card);color:var(--muted);padding:6px 11px;cursor:pointer}
.rng button+button{border-left:1px solid var(--line)}
.rng button[aria-pressed="true"]{background:var(--pressed);color:var(--on-dark)}
.chc .pn{display:none}
.chc[data-range="14"] .pn[data-days="14"],.chc[data-range="30"] .pn[data-days="30"],.chc[data-range="90"] .pn[data-days="90"]{display:block}
.grid2>.chc{margin:0}
.ch{position:relative;padding:22px 0 0 40px}
.ch-plot{position:relative;height:190px}
.ch-y{position:absolute;inset:0}
.ch-tick{position:absolute;left:0;right:0;border-top:1px dashed var(--grid);height:0}
.ch-tick:first-child{border-top:1px solid var(--grid-base)}
.ch-tick b{position:absolute;right:calc(100% + 8px);top:-.62em;font-size:.7rem;font-weight:600;color:var(--muted);white-space:nowrap}
.ch-avg{position:absolute;left:0;right:0;border-top:1.5px dashed var(--gold);z-index:2;pointer-events:none}
.ch-avg em{position:absolute;right:0;top:-1.45em;font-style:normal;font-size:.68rem;font-weight:700;color:var(--gold-deep);
  background:var(--card);padding:0 4px;border-radius:4px}
.ch-cols{position:absolute;inset:0;display:flex;align-items:flex-end;gap:3px}
.ch.dense .ch-cols{gap:1px}
.ch-col{flex:1 1 0;min-width:0;height:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:stretch;
  position:relative;cursor:default;outline:none;border-radius:4px}
.ch-col:hover,.ch-col:focus-visible{background:rgba(61,109,240,.07)}
.ch-v{font-size:.68rem;font-weight:700;color:var(--text);text-align:center;line-height:1;margin-bottom:3px;white-space:nowrap}
.ch-col.zero .ch-v{color:var(--grid-zero);font-weight:500}
.ch.dense .ch-v{display:none}
/* 좁은 화면에서 30 · 90일은 막대가 숫자보다 가늘다 — 숫자는 툴팁으로 */
@media(max-width:639px){.pn:not([data-days="14"]) .ch-v{display:none}}
.ch-stack{display:flex;flex-direction:column-reverse;border-radius:3px 3px 0 0;overflow:hidden;min-height:0}
.ch-stack i{display:block;min-height:0}
.ch-col:hover .ch-stack,.ch-col:focus-visible .ch-stack{filter:brightness(1.1) saturate(1.15)}
.ch-x{position:relative;height:18px;margin-top:6px;font-size:.7rem;color:var(--muted)}
.ch-x span{position:absolute;transform:translateX(-50%);white-space:nowrap}
/* 시간축 선 그래프 (#315, charts.timeline) — 눈금 · x축은 막대 그래프와 같은 칸을 쓴다 */
.ch.tl .ch-plot{height:120px}
.tl-svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.tl-hit{position:absolute;top:0;bottom:0;display:block}
.tl-hit:hover,.tl-hit:focus-visible{background:var(--hover);outline:none}
.ch-x span:first-child{transform:none}.ch-x span:last-child{transform:translateX(-100%)}
.ch-sum{margin:10px 0 0;font-size:.8rem;color:var(--muted)}
.ch-sum b{color:var(--text)}
.lg{display:flex;flex-wrap:wrap;gap:6px 16px;font-size:.8rem;color:var(--muted);margin:10px 0 0}
.lg span{display:inline-flex;align-items:center;gap:6px}
.lg i{width:10px;height:10px;border-radius:3px;display:inline-block}
.lg b{color:var(--text);font-weight:700}
.spark{display:block;width:100%;height:30px;margin-top:10px}
.hb{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.hb li{display:grid;grid-template-columns:minmax(60px,34%) minmax(0,1fr) auto;gap:10px;align-items:center;font-size:.84rem}
.hb-k{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hb-t{height:8px;background:var(--track);border-radius:9px;overflow:hidden}
.hb-t i{display:block;height:100%;background:var(--blue);border-radius:9px}
.hb-v{font-weight:700;white-space:nowrap;text-align:right}.hb-v small{color:var(--muted);font-weight:500;margin-left:2px}
.rt{display:flex;height:14px;border-radius:8px;overflow:hidden;background:var(--track)}
.rt i{display:block;min-width:3px}
#ch-tip{position:fixed;z-index:300;pointer-events:none;background:var(--ink);color:var(--on-dark-3);border-radius:9px;padding:8px 11px;
  font-size:.78rem;line-height:1.55;box-shadow:var(--shadow-tip);width:max-content;max-width:min(280px,calc(100vw - 16px));opacity:0;transition:opacity .06s}
#ch-tip.on{opacity:1}
#ch-tip b{color:var(--on-dark);display:block;font-size:.82rem}

/* ── 복사 단추 — data-copy 의 값을 복사하고 잠깐 data-done 글로 바뀐다(ui.js) ── */
.copy{flex:none;font:inherit;font-size:.72rem;padding:1px 7px;border:1px solid var(--line);border-radius:6px;background:var(--card);
  cursor:pointer;color:var(--muted)}
.copy.ok{color:var(--ok);border-color:var(--ok-line)}

/* ── 창(dialog) — data-dialog="아이디" 로 열고, data-close · 바깥(배경)을 누르면 닫는다(ui.js) ── */
.dlg{border:0;border-radius:16px;padding:0;width:min(720px,calc(100vw - 32px));max-height:calc(100vh - 48px);
  box-shadow:0 24px 60px rgba(0,0,0,.25);color:var(--text)}
.dlg::backdrop{background:rgba(12,21,38,.45)}
.dlg>header{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--line);position:sticky;top:0;
  background:var(--card)}
.dlg>header h2{margin:0;font-size:1.08rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.dlg-x{font:inherit;border:0;background:none;font-size:1.1rem;cursor:pointer;color:var(--muted)}
.dlg>section{padding:16px 22px;border-bottom:1px solid var(--line)}
.dlg>section:last-child{border-bottom:0}
.dlg>section>h3{margin:0 0 10px;font-size:.92rem}
/* 확인 · 알림 모달 (#336, ui.js 의 gn.confirm · gn.notice) — 브라우저 alert · confirm 대신 이것 하나 */
.dlg.sm{width:min(440px,calc(100vw - 32px))}
.dlg.sm>section p{margin:0;white-space:pre-line;color:var(--text);line-height:1.65}
.dlg>footer{display:flex;justify-content:flex-end;gap:8px;padding:14px 22px;background:var(--card)}
.dlg>footer .btn{padding:8px 16px;font-size:.88rem}
.btn[aria-busy="true"]{display:inline-flex;align-items:center;gap:7px;cursor:progress;opacity:.8}

/* ── 쌓은 막대 카드 — 전체 한도 안에서 무엇이 얼마나 차지하는지 (저장 공간) ── */
.stack-meter{margin:0 0 22px}
.stack-meter-t{margin:0 0 10px;font-size:.95rem}
.stack-meter-p{margin-left:8px;font-size:.82rem;color:var(--muted)}
.stack-meter-p.warn{color:var(--warn-text);font-weight:700}
.stack-meter-bar{display:flex;height:16px;border-radius:var(--r-pill);background:var(--track);overflow:hidden}
.stack-meter-bar i{display:block;height:100%}
.stack-meter-lg{display:flex;flex-wrap:wrap;gap:6px 16px;margin:10px 0 0;font-size:.84rem;color:var(--muted)}
.stack-meter-lg span{display:flex;align-items:center;gap:6px}
.stack-meter-lg b{width:10px;height:10px;border-radius:3px;display:inline-block}
.stack-meter-note{margin:8px 0 0;font-size:.8rem;color:var(--muted)}

/* ── 알림 상자 — 제목 + 목록. 줄마다 급한 정도(urgent · warn · info) ── */
/* 항목 · 값 목록(dl.kv) — 프로필 · 구독 화면이 같이 쓴다 (#340 에서 프로필 화면 것을 올렸다) */
.kv{display:grid;grid-template-columns:130px 1fr;gap:10px 16px;margin:0;font-size:.94rem}
.kv dt{color:var(--muted)}.kv dd{margin:0}
/* 한 줄 알림 띠(views/ui.banner) — 처리 결과 · 상태 안내. 여러 줄 알림 상자는 아래 .alert */
.banner{margin:0;padding:12px 14px;border-radius:var(--r);font-size:.9rem;border:1px solid var(--line);background:var(--card)}
.banner.ok{background:var(--ok-bg);border-color:var(--ok-line);color:var(--ok-strong)}
.banner.bad{background:var(--bad-bg);border-color:var(--bad-soft-line);color:var(--bad-strong)}
.banner.warn{background:var(--warn-bg);border-color:var(--warn-line);color:var(--warn-text)}
.banner.info{background:var(--info-bg);border-color:var(--blue-soft-line);color:var(--info)}
.alert{background:var(--warn-soft);border:1px solid var(--warn-soft-line);border-radius:var(--r-lg);padding:22px;margin:0 0 18px}
.alert>h2{font-size:.95rem;margin:0 0 8px}
.alert>ul{margin:0;padding-left:18px;font-size:.92rem}
.alert>ul>li{margin:4px 0}
.alert .lv-urgent{color:var(--bad-strong);font-weight:700}.alert .lv-warn{color:var(--warn)}.alert .lv-info{color:var(--muted)}

/* ── 결과 카드 — 한 가지 일이 끝났다고 알리고 다음 갈 곳을 준다 (가입 결과 · 로그인 시작) ── */
.result{max-width:520px;margin:0 auto;text-align:center}
.result-mark{width:52px;height:52px;border-radius:50%;display:grid;place-items:center;margin:0 auto 18px;
  font-size:1.5rem;font-weight:800;color:var(--ink-deep);background:var(--live)}
.result-mark.warn{background:var(--gold)}
.result-mark.bad{background:var(--bad-bg);color:var(--bad-strong);border:2px solid var(--bad-line)}
.result.is-bad h1{color:var(--bad-strong)}
.result-acct{margin:0 0 8px;font-family:var(--mono);font-size:.93rem;color:var(--text)}
.result-hint{color:var(--muted);font-size:.86rem;margin:14px 0 0}
.result-code{margin:18px 0 0;padding:14px 18px;border:1px dashed var(--line-strong);border-radius:var(--r);background:var(--head);
  font-family:var(--mono);font-size:1.7rem;font-weight:800;letter-spacing:.14em;user-select:all;display:inline-block}
.result-acts{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:26px}

/* ── 글 칸 — 이름 · 제목 · 확인용 메일 같은 한 줄 입력. 폭은 쓰는 화면이 정한다 ── */
.input{font:inherit;padding:9px 12px;border:1px solid var(--line);border-radius:9px;background:var(--card);color:var(--text)}
.input.sm{padding:7px 9px}
.input:focus-visible{outline:2px solid var(--blue);outline-offset:1px}

/* ── 선택 상자 — <select class="select">. 화살표는 직접 그린다(브라우저마다 모양이 다르다) ── */
.select{font:inherit;font-size:.92rem;padding:9px 34px 9px 12px;border:1px solid var(--line);border-radius:9px;color:var(--text);
  max-width:100%;cursor:pointer;appearance:none;-webkit-appearance:none;background-color:var(--card);background-repeat:no-repeat;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%;background-size:5px 5px}
.select:hover{border-color:var(--line-strong)}
.select:focus-visible{outline:2px solid var(--blue);outline-offset:1px}

/* ── 체크 상자 — <input type="checkbox" class="check">. 글과 함께면 <label class="check-l"> 로 감싼다 ── */
.check{appearance:none;-webkit-appearance:none;width:18px;height:18px;margin:0;border:1.5px solid var(--line-strong);border-radius:5px;
  background:var(--card);cursor:pointer;flex:none;display:inline-grid;place-content:center;vertical-align:-3px}
.check::after{content:"";width:9px;height:5px;border:2px solid var(--on-dark);border-top:0;border-right:0;
  transform:translateY(-1px) rotate(-45deg);opacity:0}
.check:checked{background:var(--blue);border-color:var(--blue)}
.check:checked::after{opacity:1}
.check:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.check:disabled{opacity:.5;cursor:not-allowed}
.check-l{display:inline-flex;align-items:center;gap:8px;font-size:.9rem;cursor:pointer}

/* ── 파일을 끌어다 놓는 칸 — <label class="drop" data-drop> 안에 <input type="file"> · <b> 큰 글 · <span> 작은 글.
      놓은 파일을 칸 안의 입력에 넣고 이름을 [data-drop-name] 에 적는 것은 ui.js 가 한다 ── */
.drop{display:block;border:2px dashed var(--drop-line);border-radius:var(--r-lg);padding:34px 18px;text-align:center;cursor:pointer;
  transition:border-color .15s,background .15s;position:relative}
.drop:hover,.drop.over,.drop:focus-within{border-color:var(--blue);background:var(--blue-soft)}
.drop.has{border-style:solid;border-color:var(--blue-soft-line);background:var(--blue-soft)}
.drop b{display:block;font-size:1.05rem;margin-bottom:4px}
.drop span{color:var(--muted);font-size:.9rem}
.drop input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.drop .drop-name{display:block;margin-top:10px;font-family:var(--mono);font-size:.88rem;color:var(--text);word-break:break-all}

/* ── 스위치 — <button role="switch" aria-checked> 안에 <i> 손잡이 + <span> 글 ── */
.switch{display:inline-flex;align-items:center;gap:8px;font:inherit;font-size:.84rem;font-weight:700;color:var(--text);
  background:none;border:0;padding:2px 0;cursor:pointer;white-space:nowrap}
.switch i{width:34px;height:20px;border-radius:var(--r-pill);background:var(--switch-off);position:relative;flex:none;transition:background .15s}
.switch i::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--card);
  box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
.switch[aria-checked="true"] i{background:var(--switch-on)}
.switch[aria-checked="true"] i::after{transform:translateX(14px)}
.switch:disabled{cursor:not-allowed;opacity:.6}
.switch:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:6px}

/* ── 처리 결과 한 줄 — 저장했습니다 · 못 했습니다. 스크립트가 ok · err 를 붙인다 ── */
.fmsg{font-size:.9rem;margin:10px 0 0}
.fmsg.ok{color:var(--ok-strong)}.fmsg.err{color:var(--bad-strong)}

/* ── 도는 표시 — 기다리는 중 ── */
.spin{width:15px;height:15px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;
  animation:spin .8s linear infinite;flex:none}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes blink{50%{opacity:0}}      /* 입력 커서 — 소개 흐름 · 이야기가 함께 쓴다 */
@media(prefers-reduced-motion:reduce){.spin{animation:none;border-right-color:currentColor;opacity:.5}}
/* 스스로 새로 고치는 영역 (#323, ui.live) — 최근 갱신 시각 · 주기 · 새로고침 단추 */
.lv-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px 14px;margin:-4px 0 12px;font-size:.8rem;color:var(--muted)}
.lv-at b{color:var(--text);font-variant-numeric:tabular-nums}
.lv-err{color:var(--bad-strong);font-weight:700}
.lv-btn{display:inline-flex;align-items:center;gap:7px;padding:6px 12px;font-size:.8rem}
.lv-btn[disabled]{opacity:.75;cursor:progress}
.lv[aria-busy="true"] [data-live-body]{opacity:.85;transition:opacity .2s}
/* 먼저 이동하고 나중에 채우는 자리 (#512, views/ui.lazy · skeleton) — 회색 줄이 은은하게 흐른다 */
.sk{display:grid;gap:12px}
.sk-line{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,var(--skeleton) 25%,var(--skeleton-shine) 50%,var(--skeleton) 75%);
  background-size:200% 100%;animation:sk-shine 1.2s ease-in-out infinite}
.sk-title{height:18px;width:38%!important;margin-bottom:6px}
@keyframes sk-shine{from{background-position:200% 0}to{background-position:-200% 0}}
@media (prefers-reduced-motion:reduce){.sk-line{animation:none}}
.lz-fail{display:flex;flex-wrap:wrap;align-items:center;gap:10px}

/* 김 나는 커피 (#574 · 공용 #652) — 그림은 coffee.svg, 화면은 COFFEE 자리표시만. 김이 위로 오르며 흐려지고, 움직임 줄이기면 멈춘 그림.
   글 옆에 붙일 때는 .with-cup 으로 감싼다 — 글이 두 줄이 되어도 잔이 홀로 다음 줄로 떨어지지 않게 한 줄(flex)에 둔다 */
.with-cup{display:flex;align-items:flex-end;gap:.12em}
.with-cup>span{min-width:0}
.coffee{flex:none;width:1.7em;height:1.7em;margin-bottom:-.12em;overflow:visible}
.coffee .cup{fill:var(--card);stroke:var(--text);stroke-width:2.6;stroke-linejoin:round;stroke-linecap:round}
.coffee .saucer{fill:var(--line);stroke:var(--text);stroke-width:2}
.coffee .brew{fill:var(--coffee)}
.coffee .steam{fill:none;stroke:var(--muted);stroke-width:2.8;stroke-linecap:round;opacity:0;
  transform-box:fill-box;transform-origin:50% 100%;animation:steam 3s ease-in-out infinite}
.coffee .s2{animation-delay:1s}.coffee .s3{animation-delay:2s}
@keyframes steam{0%{opacity:0;transform:translateY(6px) scaleY(.7)}30%{opacity:1}70%{opacity:.6}
  100%{opacity:0;transform:translate(2px,-10px) scaleY(1.15)}}
@media (prefers-reduced-motion:reduce){.coffee .steam{animation:none;opacity:.8}}
/* 어두운 바탕(머리 띠) 위 — 잔과 김을 밝게 */
.masthead .coffee .cup{fill:var(--ink-2);stroke:var(--on-dark)}
.masthead .coffee .saucer{fill:var(--on-dark-line);stroke:var(--on-dark)}
.masthead .coffee .steam{stroke:var(--on-dark-soft)}

/* 번갈아 보이는 문구 (#656) — data-rotate 를 단 요소 안의 .rotor-item 이 차례로 바뀐다. 동작은 ui.js.
   모든 문구를 한 칸에 겹쳐 둔다 — 높이가 가장 긴 문구로 고정되어 바뀔 때 아래 내용이 튀지 않는다.
   첫 문구는 JS 없이 보인다(검색 · 미리보기 · 깜빡임 규칙). 글자는 낱말째 묶어 낱말 중간에서 줄이 꺾이지 않는다 */
.rotor{display:grid}
.rotor>.rotor-item{grid-area:1/1;visibility:hidden}
.rotor>.rotor-item.on{visibility:visible}
.rotor-item .rw{display:inline-block;white-space:nowrap}
.rotor-item .rc{display:inline-block;opacity:0;transform:translateY(.32em);filter:blur(6px)}
.rotor-item.in .rc{animation:rotorIn .55s cubic-bezier(.2,.8,.2,1) forwards;animation-delay:calc(var(--i) * 32ms)}
.rotor-item.out{animation:rotorOut .7s ease forwards}
.rotor-item.still .rc{opacity:1;transform:none;filter:none}
@keyframes rotorIn{to{opacity:1;transform:none;filter:none}}
@keyframes rotorOut{to{opacity:0;filter:blur(5px);transform:translateY(-.12em)}}
@media (prefers-reduced-motion:reduce){.rotor-item .rc{opacity:1;transform:none;filter:none;animation:none!important}}
