/* KETI 디자인 토큰과 공용 리셋 — STYLE.md 정본.
 * 각 화면의 HTML에서 화면 CSS보다 먼저 로드한다. */

  /* ===== KETI 디자인 토큰 (STYLE.md) — 모든 UI 공통 톤. 다크 기본 + data-theme="light" 토글 ===== */
  /* 콕핏 마운트(.cockpit-root)·임의 컨테이너에 data-theme 를 직접 걸어도 같은 팔레트가 서도록 선택자를 묶는다.
     ⚠️ `:root{` · `:root[data-theme="light"]{` 는 각 묶음의 **마지막 줄 맨 앞**에 둔다 — 대비 테스트가 그 줄로 블록을 찾는다. */
  [data-theme="dark"], .cockpit-root[data-theme="dark"],
  :root{                                    /* DARK (기본) — KETI 네이비 + 블루 */
    color-scheme:dark;                        /* 네이티브 컨트롤(체크박스·select·스크롤바·포커스 링)도 테마를 따르게 */
    --bg:#0a0e16; --panel:#0f1722; --card:#0e1620; --card2:#0b121b; --surface:#13243a;
    --line:#1f3a5c; --line2:#2f4f7c;
    --ink:#d6e6f5; --ink2:#9fc0e3; --dim:#7f97b3;
    --accent:#2e9be0; --accent2:#6cc4e8; --on-accent:#04223a;
    --teleop:#6cc4e8; --theme-accent:#2e9be0; --theme-on-accent:#04223a;   /* KETI 블루 / 라이트블루 */
    --ok:#2e9be0; --busy:#e3b96f; --err:#e36f6f; --help:#e3d36f; --off:#5a6f88;
    --idle:#9be36a;      /* IDLE=연두, --ok=일반 정상, --link-ok=링크 품질. */
    --link-ok:#3ddc84;   /* 연결 양호(초록) — base_state 색과 직교(연결품질 전용) */
    --map-floor:#1b3150; --map-wall3d:#e8f1fa; --map-unknown:#0c1421;   /* 3D 바닥판(자유공간) · 3D 벽 — 다크는 네이비 판 위 거의 흰 벽(블루프린트). 판이 배경과 붙지 않게 --surface 보다 한 단 밝게 */
    --err-bg:#2a1414; --err-line:#4a2b2b;
    /* path_plan 흐름/셰브런 하이라이트 — 다크: 화이트-핫 */
    --path-hot-g:color-mix(in srgb, var(--accent) 45%, #fff);
    --path-hot-l:color-mix(in srgb, var(--link-ok) 45%, #fff);
    /* 계층은 선이 아니라 명도로(계획안 원칙 5) — 패널보다 한 단 어두운 '우물' · 약한 구분선 · 포커스 링 */
    --bg-0:#06090f;      /* 패널보다 한 단 어두운 우물. */
    --line-soft:#172a41; /* 약한 구분선 — --panel 위 1.24:1(--line 은 1.56). 칸 **안쪽**을 나눌 때만 */
    --focus:#7fd4ff;     /* 포커스 링 — --bg 11.7:1 / --card 11.1:1. accent·err 위에선 1.9:1 이라 링을 요소 **바깥**에 그린다(아래 :focus-visible) */
    /* 콕핏 패널 표면(--cp-*) — 상태·스킬·미션·지연·업링크·키맵 카드가 공유한다. 캔버스는 cockpit.js chartPalette() 가 같은 값을 쓴다 */
    --cp-bg:#090d16; --cp-card:#111827; --cp-card-sub:#0b111e; --cp-border:rgba(148,163,184,0.16);
    --cp-text:#f1f5f9; --cp-text2:#cbd5e1; --cp-muted:#94a3b8; --cp-track:rgba(148,163,184,0.16);
    --cp-shadow:0 6px 18px rgba(0,0,0,0.35);
    --cp-sky:#38bdf8; --cp-sky-text:#7dd3fc; --cp-ok:#4ade80; --cp-warn:#fbbf24; --cp-warn-text:#fde047; --cp-crit:#f87171;
    --cp-series-op:#6366f1; --cp-series-net:#38bdf8; --cp-series-srv:#14b8a6;   /* Operator E2E · Internet · Server(= 업링크 Video · Control) */
    --cp-st-idle:#9be36a; --cp-st-busy:#60b8f0; --cp-st-teleop:#6cc4e8; --cp-st-help:#e3b96f; --cp-st-err:#f08080; --cp-st-off:#8fa3ba;   /* base_state 배지 글자 */
  }
  [data-theme="light"], html[data-theme="light"], body.light, body.theme-light, .cockpit-root[data-theme="light"],
  :root[data-theme="light"]{                /* LIGHT — KETI 로고 톤(흰 배경 + 블루) */
    color-scheme:light;
    --bg:#f4f8fc; --panel:#ffffff; --card:#ffffff; --card2:#eef4fa; --surface:#e6eef7;
    --line:#d2e0ee; --line2:#bcd0e6;
    --ink:#0a2540; --ink2:#3a5e82; --dim:#566f8a;   /* 라이트 --dim 은 흰 카드 위 4.5:1 을 넘겨야 한다(#6b86a3 은 3.8:1 — 9~13px 라벨이 전부 미달) */
    --accent:#0072ce; --accent2:#0098d8; --on-accent:#ffffff;
    --teleop:#0098d8; --theme-accent:#0072ce; --theme-on-accent:#ffffff;
    --ok:#0072ce; --busy:#8f5f10; --err:#c62d2d; --help:#7d5f00; --off:#9bb0c6;   /* busy·help·err 는 글자로도 20여 곳에 쓰인다 — 흰 카드 위 4.5:1 을 넘기는 값 */
    --idle:#397515;      /* 연두 — 흰 카드 위 글자로도 4.5:1 */
    --map-floor:#ffffff; --map-wall3d:#3a5e82; --map-unknown:#d2e0ee;   /* 라이트는 흰 판 위 네이비 벽 */
    --link-ok:#1ca15a;   /* 연결 양호(초록) */
    --err-bg:#fdecec; --err-line:#f4c9c9;
    /* 라이트: 흰 배경에서 화이트-핫은 소실 — 네이비쪽으로 믹스해 대비 확보 */
    --path-hot-g:color-mix(in srgb, var(--accent) 60%, #072a4a);
    --path-hot-l:color-mix(in srgb, var(--link-ok) 60%, #072a4a);
    --bg-0:#eaf2fa;      /* 우물 — --panel(#fff) 대비 1.13:1. ⚠️ 여기서 더 어둡게 하면 --dim 글자가 AA 를 깬다(#e8f0f8 에서 4.52, #e7eff8 에서 4.48 — 실측) */
    --line-soft:#e3ecf5;
    --focus:#00508f;     /* 라이트는 어두운 링 — --panel 위 8.25:1 */
    /* 콕핏 패널 표면 — 흰 카드 위 글자는 전부 4.5:1 이상(--cp-muted #64748b = 4.76:1) */
    --cp-bg:#f8fafc; --cp-card:#ffffff; --cp-card-sub:#f1f5f9; --cp-border:#e2e8f0;
    --cp-text:#0f172a; --cp-text2:#334155; --cp-muted:#64748b; --cp-track:#e2e8f0;
    --cp-shadow:0 4px 14px rgba(15,23,42,0.08);
    --cp-sky:#0284c7; --cp-sky-text:#0369a1; --cp-ok:#15803d; --cp-warn:#b45309; --cp-warn-text:#a16207; --cp-crit:#dc2626;
    --cp-series-op:#4f46e5; --cp-series-net:#0284c7; --cp-series-srv:#0d9488;
    --cp-st-idle:#3f7d17; --cp-st-busy:#0067b8; --cp-st-teleop:#0e7490; --cp-st-help:#8f5f10; --cp-st-err:#c62d2d; --cp-st-off:#566f8a;
  }
  /* ── 적응형 컬러 테마 프리셋 (P1~P8 · 다크/라이트 자동 대응) ──
     서버 설정(#cfgpalette) 또는 콕핏 사이트 설정([data-el="latpalette"])에서 선택 시
     차트 3-Series(--cp-series-op/net/srv)와 UI 장식(--theme-accent, --theme-on-accent,
     --surface, --line2)만 변환한다. 상태·링크·안전·키맵 역할 색은 팔레트와 무관하게 고정한다.
     --accent/--accent2는 KETI 블루/시안 의미색이며 --teleop도 고정 시안이다. */
  :root[data-palette="p1"], .cockpit-root[data-palette="p1"]{
    --theme-accent:#2e9be0; --theme-on-accent:#04223a; --surface:#13243a; --line2:#2f4f7c;
    --cp-series-op:#6366f1; --cp-series-net:#38bdf8; --cp-series-srv:#14b8a6;
  }
  :root[data-palette="p2"], .cockpit-root[data-palette="p2"]{
    --theme-accent:#3b82f6; --theme-on-accent:#041c3c; --surface:#13223d; --line2:#2d4a7c;
    --cp-series-op:#3b82f6; --cp-series-net:#f59e0b; --cp-series-srv:#10b981;
  }
  :root[data-palette="p3"], .cockpit-root[data-palette="p3"]{
    --theme-accent:#8b5cf6; --theme-on-accent:#090418; --surface:#1b1636; --line2:#43357a;
    --cp-series-op:#8b5cf6; --cp-series-net:#f43f5e; --cp-series-srv:#06b6d4;
  }
  :root[data-palette="p4"], .cockpit-root[data-palette="p4"]{
    --theme-accent:#38bdf8; --theme-on-accent:#04223a; --surface:#112638; --line2:#265475;
    --cp-series-op:#38bdf8; --cp-series-net:#fb923c; --cp-series-srv:#2dd4bf;
  }
  :root[data-palette="p5"], .cockpit-root[data-palette="p5"]{
    --theme-accent:#22d3ee; --theme-on-accent:#04222c; --surface:#112836; --line2:#225b70;
    --cp-series-op:#fb7185; --cp-series-net:#a3e635; --cp-series-srv:#22d3ee;
  }
  :root[data-palette="p6"], .cockpit-root[data-palette="p6"]{
    --theme-accent:#f59e0b; --theme-on-accent:#1f1200; --surface:#241c11; --line2:#5c451c;
    --cp-series-op:#fbbf24; --cp-series-net:#22d3ee; --cp-series-srv:#a855f7;
  }
  :root[data-palette="p7"], .cockpit-root[data-palette="p7"]{
    --theme-accent:#88c0d0; --theme-on-accent:#0b1922; --surface:#1b2636; --line2:#3b4d66;
    --cp-series-op:#88c0d0; --cp-series-net:#b48ead; --cp-series-srv:#a3be8c;
  }
  :root[data-palette="p8"], .cockpit-root[data-palette="p8"]{
    --theme-accent:#60a5fa; --theme-on-accent:#051937; --surface:#141e30; --line2:#334155;
    --cp-series-op:#60a5fa; --cp-series-net:#34d399; --cp-series-srv:#94a3b8;
  }
  :root[data-theme="light"][data-palette="p1"], .cockpit-root[data-theme="light"][data-palette="p1"]{
    --theme-accent:#0072ce; --theme-on-accent:#ffffff; --surface:#e6eef7; --line2:#bcd0e6;
    --cp-series-op:#4f46e5; --cp-series-net:#0284c7; --cp-series-srv:#0d9488;
  }
  :root[data-theme="light"][data-palette="p2"], .cockpit-root[data-theme="light"][data-palette="p2"]{
    --theme-accent:#2563eb; --theme-on-accent:#ffffff; --surface:#e8effd; --line2:#bfdbfe;
    --cp-series-op:#2563eb; --cp-series-net:#d97706; --cp-series-srv:#059669;
  }
  :root[data-theme="light"][data-palette="p3"], .cockpit-root[data-theme="light"][data-palette="p3"]{
    --theme-accent:#6d28d9; --theme-on-accent:#ffffff; --surface:#f1ecfe; --line2:#ddd6fe;
    --cp-series-op:#7c3aed; --cp-series-net:#e11d48; --cp-series-srv:#0891b2;
  }
  :root[data-theme="light"][data-palette="p4"], .cockpit-root[data-theme="light"][data-palette="p4"]{
    --theme-accent:#0369a1; --theme-on-accent:#ffffff; --surface:#e0f2fe; --line2:#bae6fd;
    --cp-series-op:#0284c7; --cp-series-net:#ea580c; --cp-series-srv:#0d9488;
  }
  :root[data-theme="light"][data-palette="p5"], .cockpit-root[data-theme="light"][data-palette="p5"]{
    --theme-accent:#0e7490; --theme-on-accent:#ffffff; --surface:#ecfeff; --line2:#a5f3fc;
    --cp-series-op:#e11d48; --cp-series-net:#65a30d; --cp-series-srv:#0891b2;
  }
  :root[data-theme="light"][data-palette="p6"], .cockpit-root[data-theme="light"][data-palette="p6"]{
    --theme-accent:#b45309; --theme-on-accent:#ffffff; --surface:#fef3c7; --line2:#fde68a;
    --cp-series-op:#d97706; --cp-series-net:#0891b2; --cp-series-srv:#7c3aed;
  }
  :root[data-theme="light"][data-palette="p7"], .cockpit-root[data-theme="light"][data-palette="p7"]{
    --theme-accent:#0369a1; --theme-on-accent:#ffffff; --surface:#e6f0f7; --line2:#bdd3e4;
    --cp-series-op:#0369a1; --cp-series-net:#9333ea; --cp-series-srv:#15803d;
  }
  :root[data-theme="light"][data-palette="p8"], .cockpit-root[data-theme="light"][data-palette="p8"]{
    --theme-accent:#2563eb; --theme-on-accent:#ffffff; --surface:#f1f5f9; --line2:#cbd5e1;
    --cp-series-op:#2563eb; --cp-series-net:#059669; --cp-series-srv:#475569;
  }
  /* ── 치수 계단 — 글자·간격·모서리. 테마와 무관해 :root에서 공유한다.
     글자 clamp는 브라우저 기본 16px에서 최솟값이 되고, 사용자 기본 글자 설정은 rem에 반영된다.
     간격·모서리는 고정폭 레이아웃과 맞추기 위해 px를 쓴다. */
  :root{
    --fs-0:clamp(10px, .625rem, 13px);    /* 맵·영상 **위** 오버레이 전용. UI 라벨엔 쓰지 마라(하한은 --fs-1) */
    --fs-1:clamp(11px, .6875rem, 14px);   /* 라벨 하한 */
    --fs-2:clamp(12px, .75rem, 15px);     /* 보조 본문 */
    --fs-3:clamp(13px, .8125rem, 17px);   /* 본문 = body 기준 */
    --fs-4:clamp(14px, .875rem, 18px);    /* 소제목 · header h1 */
    --fs-5:clamp(16px, 1rem, 20px);       /* 화면 제목(h2) */
    --fs-6:clamp(20px, 1.25rem, 26px);    /* 큰 숫자 · 빈 상태 아이콘 */
    --sp-1:2px; --sp-2:4px; --sp-3:6px; --sp-4:8px; --sp-5:10px; --sp-6:12px; --sp-7:16px;
    --r-1:3px; --r-2:4px; --r-3:6px; --r-4:8px; --r-pill:999px;
    /* STOP(콕핏 v1 S2·S10) — 터치 목표 44px·최소 폭 96px, 왼쪽 24px 는 비운다(옆 버튼 오조작 방지) */
    --stop-min-h:44px; --stop-min-w:96px; --stop-gap:24px;
    /* 콕핏 상단 한 줄 바(콕핏 v1 SPEC §3.1·§3.5) — 줄 48px 안에 컨트롤 높이 하나·칩 높이 하나. 카드 최소 높이는
       상태 탭 요약 카드와 스킬 탭 칸(이름 + 부제 한 줄)이 같이 쓴다("박스 크기가 제각각" F8 — 값을 칸마다 새로 짓지 않는다). */
    --bar-h:48px; --control-h:32px; --chip-h:28px; --card-min-h:48px;
    /* 로봇 설정 시트·쥔 팔 팝오버 폭(콕핏 v1 SPEC §4.6) — 좁은 화면에서 팝오버는 cockpit.js placeTopPopover 가 STOP 왼쪽 안으로 줄이고,
       시트는 바 아래 전체 폭으로 편다(1.0.5 — 시트는 바 아래라 STOP 을 덮을 수 없다) */
    --sheet-w:360px;
    /* 피킹 카메라 상태 띠 — 카메라 패널 아래쪽 고정 높이 띠. 컨트롤(--control-h) 한 줄 + 위아래 여백 */
    --modebar-h:44px;
    /* 피킹 탭 자세 직접 지정 슬라이더 최소 폭 */
    --pickpose-slider-min-w:120px;

    /* ── 박스 크기 · 구역 배치 토큰 (Box Sizing & Zone Layout) ──────────────────────────────
       정본 규약: synapse/standards/STANDARD_ui_layout.md (구역 1~7 배치도 · DO/DO NOT).
       새 박스를 만들 때 폭·높이·안쪽 여백·z-index 를 **여기서 고른다** — 칸마다 새 숫자를 짓지 않는다.
       계단에 맞는 값이 없으면 새 토큰을 제안하고, 그 전엔 가장 가까운 **작은** 칸을 쓴다.
       사이드바·도크·팝오버 폭은 360px(--sheet-w)을 넘지 않는다. 그보다 넓은 것은 모달(--modal-w-*)이다. */

    /* 구역 3 — 왼쪽 내비게이션. nexus_ui css/fleet.css #sidebar 의 172/46px 와 같은 값
       (test_responsive.js 가 fleet.css 의 리터럴 46px 를 확인하므로 거기는 리터럴로 둔다) */
    --nav-w:172px; --nav-collapsed-w:46px;
    /* 구역 4 — 도크·측면 패널. --sheet-w(360px)는 위 콕핏 바 묶음에 이미 있다 — 이 계단의 상한이다 */
    --dock-w-sm:220px;    /* 좁은 우측 도크 · 콕핏 좌우 도크 존 기본 폭 */
    --dock-w-md:280px;    /* 표준 측면 패널 · 시뮬 환경 패널 · 로스터 */
    --dock-w-lg:340px;    /* 인스펙터 · 트레이스 · IoT · 콕핏 왼쪽 카메라 열 */
    /* 구역 5 — 헤더 팝오버 · 우클릭 메뉴 · 드롭다운. 높이는 뷰포트에 묶고 넘치면 안에서 스크롤 */
    --pop-w-sm:240px; --pop-w-md:320px; --pop-w-lg:360px;
    --pop-max-h:min(64vh, 480px);
    /* 구역 6 — 모달 · 전체 탭. 입력칸은 전체 폭으로 늘리지 않고 --field-w-* 중 하나 */
    --modal-w-sm:420px;   /* 확인 · 파라미터 한두 개 */
    --modal-w-md:560px;   /* 폼 · 미션 · 대상 지정 */
    --modal-w-lg:760px;   /* 두 열 인스펙터 */
    --page-max-w:1200px;  /* 설정·관리 전체 탭 본문 최대 폭 */
    --field-w-sm:180px; --field-w-md:220px; --field-w-lg:260px;
    /* 구역 7 — 영상·맵 위 HUD · 미니맵 · 차트 */
    --minimap-w:200px; --cmd-card-w:240px; --hud-h:180px;
    --chart-h-sm:68px;    /* 스파크라인 · 한 줄 추세 */
    --chart-h-md:96px;    /* 단일 시계열 차트 */
    --chart-h-lg:120px;   /* 여러 레인 차트 전용(지연 3레인) — 96px 이면 레인당 곡선이 7px 로 눌린다 */
    /* 컴포넌트 안쪽 여백 — 높이는 --chip-h · --control-h 가 정하므로 칩·버튼은 좌우만 */
    --pad-chip:0 var(--sp-4);
    --pad-btn:0 var(--sp-5);
    --pad-card:var(--sp-5) var(--sp-6);
    --pad-panel:var(--sp-6);
    --pad-modal:var(--sp-7);     /* 안쪽 여백 상한(16px) — 이보다 큰 padding 은 쓰지 않는다 */
    /* z-index 계단 — nexus_ui #cockpit(50) · #toast(60) · #paramback(80) 과 같은 층.
       body 에 붙는 position:fixed 메뉴는 콕핏 오버레이(50) 위에 서야 하므로 --z-modal 을 쓴다 */
    --z-canvas:1; --z-hud:6; --z-panel:20; --z-popover:30; --z-topbar:46;
    --z-overlay:50; --z-toast:60; --z-modal:80;
  }
  /* 터치 화면은 컨트롤을 손가락 목표(44px)로 — 줄(48px)은 그대로라 STOP(44px)과 나란히 한 줄에 들어간다 */
  @media (pointer:coarse){ :root{ --control-h:44px; } }
  /* 피킹 모드 바는 그 44px 컨트롤이 위아래 여백과 함께 들어가게 */
  @media (pointer:coarse){ :root{ --modebar-h:56px; } }
  /* ── 본문 서체 — 나눔스퀘어 라운드.
     외부 인터넷 없이 표시하도록 400·700 woff2를 vendor에 동봉한다.
     라이선스: vendor/nanumsquareround/LICENSE.md.
     이 글꼴은 숫자 폭이 같고 GSUB/GPOS가 없다. tabular-nums는 대체 글꼴을 위한 설정이다. */
  @font-face{ font-family:"NanumSquareRound"; font-style:normal; font-weight:400; font-display:swap;
    src:url("../vendor/nanumsquareround/NanumSquareRound.woff2") format("woff2"); }
  @font-face{ font-family:"NanumSquareRound"; font-style:normal; font-weight:700; font-display:swap;
    src:url("../vendor/nanumsquareround/NanumSquareRoundB.woff2") format("woff2"); }

  *{ box-sizing:border-box; }
  /* html은 100%로 둬 브라우저 기본 글자 설정과 rem 계단을 유지한다.
     본문 크기는 body에서만 정한다. */
  html{ font-size:100%; }
  html,body{ margin:0; height:100%; background:var(--bg); color:var(--ink);
    user-select:none; overflow:hidden; }
  /* font 단축을 쓰지 않는다 — 단축은 font-variant-numeric 을 normal 로 되돌려서, 한 줄 안에서
     tabular-nums 를 같이 쓰면 조용히 꺼진다. 자식 규칙도 같은 이유로 longhand 를 쓴다. */
  body{ font-family:"NanumSquareRound","Apple SD Gothic Neo","Noto Sans CJK KR",ui-sans-serif,system-ui,"Segoe UI",sans-serif;
    font-size:var(--fs-3); line-height:1.4; font-variant-numeric:tabular-nums; }
  button{ font:inherit; color:var(--ink); cursor:pointer; }
  #app{ display:flex; flex-direction:column; height:100vh; }
  /* 헤더는 **절대 두 줄이 되지 않는다**(사용자 지시 2026-09-15: "글자나 뱃지가 다 깨지면 문제").
     관제는 폰·태블릿·FHD·QHD·4K 에 150%·200% 배율까지 섞인다. `flex-wrap:wrap` 이면 그때마다
     헤더가 2~3줄로 접히면서 아래 화면을 밀어 올렸다. 이제 **안 접고**, 좁아지면 덜 중요한 것부터
     차례로 물러난다: 단축키 힌트 → 서버 주소 입력 → KPI 라벨(점+숫자만 남는다).
     기준 폭은 뷰포트 CSS px 이라 브라우저 배율도 같이 걸린다(200% = 폭 절반). */
  header{ padding:6px 12px; border-bottom:1px solid var(--line); display:flex; gap:14px;
    align-items:center; flex-wrap:nowrap; overflow:visible; min-width:0;
    position:relative; z-index:var(--z-topbar, 46); }
  header > *{ flex:0 0 auto; }                      /* 기본은 안 줄어든다 — 줄일 것만 아래에서 지정 */
  /* 폰 폭(430px 실측) — 남는 것끼리도 안 들어간다. 관제에서 덜 급한 순서로 더 접는다:
     버전 → 제목 글자 → 연결 주소. 상태 요약(KPI)·알람·설비는 끝까지 남긴다. */
  @media (max-width:760px){
    header{ gap:8px; padding:6px 8px; }
    header .uiver{ display:none; }
    header .conn{ max-width:96px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  }
  /* 후퇴 순서의 **마지막 쐐기** — 기준 폭(1500/1180/980/760px)은 뷰포트 px 이라 브라우저 '기본 글자
     크기'를 키운 사람에겐 안 걸린다. 그때 헤더가 넘치면 `header > *{flex:0 0 auto}` 때문에 아무도
     안 줄고 **맨 오른쪽(테마 토글)이 잘린다.** 제목만 줄 수 있게 열어 둔다 — 줄어드는 순서는
     단축키 힌트 → 서버 주소 → KPI 라벨 → **제목 글자** 이고, 헤더는 여전히 한 줄이다(nowrap). */
  header h1{ font-size:var(--fs-4); margin:0; color:var(--theme-accent, var(--accent)); letter-spacing:.5px; white-space:nowrap;
    flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; }
  /* 좁으면 제목 글자를 접고 ◈ 만 남긴다(0.13.37). 이 블록은 반드시 위의 기본 header h1 **뒤** 에 와야 한다 —
     @media 는 특이도를 못 올리므로 앞에 두면 같은 특이도의 기본 규칙(font-size:14px)에 그냥 덮인다.
     덮이면 index.html 의 h1 텍스트에 이미 있는 ◈ 와 ::before 의 ◈ 가 겹쳐 "◈◈ NEXUS 관제" 가 되고
     제목이 오히려 넓어진다(실측 96.1px → 108.2px, 고친 뒤 17.0px). 아래 .hint 블록이 뒤에 있는 것도 같은 이유다. */
  @media (max-width:760px){
    header h1{ font-size:0; }                       /* 글자는 접고 ◈ 만 남긴다 */
    header h1::before{ content:"◈"; font-size:15px; }
  }
  /* 단축키 힌트는 **맵 화면 안 pill**(#maphint, css/fleet.css)로 갔다(0.13.50). 맵 전용 설명이 전 화면
     헤더에 상주하던 것을 없앴고, 그만큼 헤더가 넓어져 ≤1500px 접힘 단계가 통째로 필요 없어졌다.
     0.13.44 가 넣었던 ⌨ 접힘 + title + 클릭 토스트는 **pill 이 그대로 이어받는다**(접기 ⓘ · title 전문 ·
     잘렸을 때 클릭 토스트) — 기능이 사라진 게 아니라 자리를 옮긴 것이다. */
  /* 콘솔 자기 버전 배지 — 로봇이 보고하는 nexus_ui 값과 **다를 수 있는** 값이라 눈에 띄되 조용하게 */
  header .uiver{ font-size:var(--fs-1); color:var(--dim); font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
    border:1px solid var(--line); border-radius:999px; padding:1px 7px; white-space:nowrap; }
  /* 연결 칩 + 서버 주소 팝오버(0.13.50) — 종전의 상시 입력칸(header .srv, 180px + [연결])을 칩 뒤로 넣었다.
     서버 주소는 하루 한 번 쓰는 설정인데 매 화면의 1순위 자리를 먹고 있었다(계획안 BeforeHeader 4).
     ⚠️ margin-left:auto 는 .srv 가 갖고 있던 **우측 묶음 스페이서**다 — 여기(#connwrap)로 넘기지 않으면
        연결·설비·알람·테마가 통째로 왼쪽에 붙는다.
     ⚠️ header .conn 에 max-width 를 **여기서 주면 안 된다**: 위 ≤760px 블록(max-width:96px)이 이 규칙보다
        앞에 있어 같은 특이도로 덮인다. 폭 제한은 그 블록 한 곳이 정본이다. */
  header #connwrap{ position:relative; margin-left:auto; }
  header .conn{ font-size:11px; background:var(--card); border:1px solid var(--line); border-radius:11px;
    padding:2px 9px; line-height:1.5; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  header .conn:hover{ border-color:var(--accent); }
  header .conn.ok{ color:var(--ok); } header .conn.bad{ color:var(--err); }
  /* 후퇴 1단계: 호스트 주소부터 접는다(전문은 팝오버와 title 에 남는다). 종전 ≤980 의 '.srv 통째 숨김'을
     대신한다 — 칸이 팝오버로 들어갔으니 숨길 것이 없고, 대신 칩이 짧아지면 된다. */
  @media (max-width:1180px){ header .conn .ch{ display:none; } }
  #connpop{ position:absolute; top:28px; right:0; z-index:var(--z-popover, 30); width:290px; background:var(--panel);
    border:1px solid var(--line2); border-radius:8px; padding:9px 10px;
    box-shadow:0 8px 24px color-mix(in srgb,#000 45%,transparent); }
  #connpop[hidden]{ display:none; }
  #connpop .cp-t{ font-size:11px; color:var(--dim); margin-bottom:5px; }
  #connpop .cp-h{ font-size:11px; color:var(--dim); line-height:1.5; margin-top:6px; }
  #connpop .srv{ display:flex; gap:5px; align-items:center; font-size:11px; }
  #connpop .srv label{ color:var(--dim); }
  #connpop .srv input{ flex:1; min-width:0; background:var(--card); border:1px solid var(--line); color:var(--ink);
    border-radius:4px; padding:4px 6px; font:11px/1.3 ui-monospace,monospace; }
  #connpop .srv button{ background:var(--accent); color:var(--on-accent); border:none; border-radius:4px; padding:4px 10px; font-weight:600; }
  header #themebtn{ background:var(--card); border:1px solid var(--line); color:var(--ink); border-radius:4px; padding:2px 8px; font-size:13px; line-height:1; }
  header #themebtn:hover{ border-color:var(--accent); }
  header #navtoggle{ background:var(--card); border:1px solid var(--line); color:var(--ink); border-radius:4px; padding:2px 9px; font-size:14px; line-height:1; cursor:pointer; }
  header #navtoggle:hover{ border-color:var(--accent); }

  /* ── 포커스 링 — 지금까지 네 장 어디에도 :focus-visible 이 **한 줄도 없었다**. UA 기본 링에만
     기대고 있었고 그 색·두께는 브라우저마다 다르다. --focus 로 통일한다.
     링은 요소 **바깥** 2px 에 그린다: 그 자리에 보이는 것은 부모 배경이라, accent/err 로 칠한 버튼
     (STOP·[연결]·범위 세그먼트) 위에서도 1.9:1 로 묻히지 않는다.
     ⚠️ 예외 — overflow:hidden 안에 있는 컨트롤은 바깥 링이 잘린다(header · #sidebar · .rscope).
        그때만 안쪽(-2px)으로 그리고, 칠해진 버튼은 링 색을 --on-accent 로 바꾼다.
     ⚠️ 여기서 키보드 **도달 순서**는 안 만든다. .navitem(href 없는 <a>) · .skill · .thumb 은 div/a 라
        지금도 Tab 이 안 닿는다 — tabindex 는 마크업 일이라 단계 2 다. */
  :focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
  header button:focus-visible, header input:focus-visible,
  #sidebar a:focus-visible, .rscope button:focus-visible{ outline-offset:-2px; }
  header .srv button:focus-visible, .rscope button.on:focus-visible{ outline-color:var(--on-accent); }
