/* ============================================================
   app.css — AeroNexus 컴포넌트 스타일
   (구 index.html 인라인 <style>에서 분리 — 2026-08-24 시안 A 개편)

   여기에는 «내용물»만 둔다: 경고 카드·설정 폼·노탐/비행계획 폼·지도 팝업 내용·
   담당구역 목록 등. 화면 «골격»(헤더·네비 레일·서랍·인스펙터·팝오버)은 shell.css,
   색 토큰은 theme.css.
   ⚠ 로드 순서: theme.css → app.css → shell.css (골격이 이겨야 한다)

   ⛔ 지도 배경(#map·.leaflet-container)과 지도 위 라벨(fb-lb·ntw-lb·#hoverTip)은
      테마 토큰을 쓰지 않는다 — 지도는 이번 개편 범위에서 제외 (사용자 확정 2026-08-24)
   ============================================================ */

  *{ box-sizing:border-box; }
  #map{ position:absolute; inset:0; background:#eef1f4; }
  .leaflet-container{ background:#eef1f4; font-family:inherit; }
  /* 우상단 커스텀 +/-를 쓰므로 Leaflet 기본 좌상단 +/-는 숨긴다 */
  .leaflet-control-zoom{ display:none !important; }
  h1{ font-size:var(--fs-xl); margin:0 0 2px; } .sub{ font-size:var(--fs-sm); color:var(--muted); margin-bottom:10px; }
  /* 섹션 헤더 = 접기 토글 (RADAR·WEATHER와 동일 규약 — 캐럿은 오른쪽 끝 고정) */
  .sect{ border-top:1px solid var(--border); margin-top:12px; padding-top:12px; }
  .sect h2{ display:flex; align-items:center; gap:7px; font-size:var(--fs-lg); color:var(--ink);
    margin:0 -8px 10px; padding:6px 8px; font-weight:700; cursor:pointer; user-select:none;
    border-radius:8px; transition:background .12s; }
  .sect h2:hover{ background:var(--bg-hover); }
  .sect h2 .ttl{ flex:none; color:var(--blue); }
  /* 요약줄은 본문 폰트 — 모노는 한글 미보유라 폴백 혼합으로 자간이 들쭉날쭉해진다 (사용자 지적 2026-08-08).
     숫자만 tabular-nums로 고정폭 정렬 */
  .sect h2 .foldsum{ flex:1 1 auto; min-width:0; color:var(--muted); font-weight:500; font-size:var(--fs-sm);
    font-variant-numeric:tabular-nums; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sect h2 .caret{ margin-left:auto; flex:none; width:22px; height:22px; display:inline-flex; align-items:center; justify-content:center;
    border:1px solid var(--border); border-radius:7px; background:var(--bg-surface-elevated); color:var(--blue); font-size:var(--fs-sm); line-height:1;
    transition:transform .15s, background .12s; }
  .sect h2:hover .caret{ background:var(--blue); color:var(--text-inverse); border-color:var(--blue); }
  .sect.fold h2{ margin-bottom:0; }
  .sect.fold h2 .caret{ transform:rotate(-90deg); }
  .sect.fold .secBody{ display:none; }
  .srow{ display:flex; justify-content:space-between; gap:10px; font-size:var(--fs-md); padding:3px 0; }
  .srow span:first-child{ color:var(--muted); }
  .srow .v{ font-family:var(--font-mono); font-size:var(--fs-md); font-weight:600; text-align:right; white-space:nowrap; }
  /* 원천 상태 줄 (사용자 확정 2026-08-24 「단순화 · 오류는 느낌표 + 호버」) —
     라벨은 절대 접히지 않고 넘치면 말줄임한다. 종전에는 «인천 출발 (실시간)»이 두 줄로 접혀
     그 아래 값과 세로 정렬이 무너졌다. 설명 전문은 title(호버)로 간다. */
  .srow .k{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; cursor:help; }
  .srow.bad, .srow.bad span:first-child{ color:var(--err); }   /* 문제 있는 줄은 줄 전체가 오류색 */
  /* ⚠ 배지 — 오류 원문은 여기 title에 담긴다. «접었지» 숨긴 것이 아니다:
     배지는 항상 뜨고 줄 색도 오류색으로 남는다 (자료없음≠정상 원칙). */
  .wb{ margin-left:5px; cursor:help; font-family:var(--font-sans); font-weight:700; color:var(--err); }
  .lyr{ display:flex; align-items:center; gap:8px; font-size:var(--fs-md); padding:3px 0; cursor:pointer; }
  .lyr input{ width:auto; accent-color:var(--blue); }
  /* 단순 체크박스 목록을 2열로 (사용자 지시 2026-08-30 「한 줄에 두 개씩 나열해도 되는건 두 개씩」).
     .pcol(minmax 240px)보다 훨씬 좁게 잡는다 — 체크박스+짧은 라벨은 130px면 충분하고, 그래야
     390px 서랍에서도 2열이 실제로 잡힌다. auto-fit이라 컨테이너가 좁아지면(모바일 바텀시트 등)
     자동으로 1열로 접힌다 — 별도 미디어쿼리 없이 .pcol과 같은 방식. 슬라이더·펼침 하위영역이
     붙는 항목(강수·상층풍 등)은 폭이 줄면 안 되므로 이 그리드에 넣지 않는다. */
  .lyr2{ display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:0 10px; }
  .lyr2 .lyr{ padding:3px 0; }
  .swatch{ width:18px; height:0; border-top:2px solid; display:inline-block; }
  .swatch.dash{ border-top-style:dashed; }
  /* ── 항공기 색 고르개 (2026-08-25 사용자 요청 「표시 메뉴에 항공기 색상 선택」) ──
     상층풍 색범례(#windBar)와 **같은 형태**로 만든다 — 등폭 셀을 한 줄로 붙인 띠.
     ⚠ 선택 표시는 테두리가 아니라 «안쪽 링»(inset box-shadow)이다: 바깥 테두리를 쓰면
        셀 폭이 1px씩 밀려 띠가 흔들린다. 링 바깥쪽 어두운 선은 흰색 칸에서도 보이게 하려는 것. */
  .colbar{ display:flex; height:18px; border-radius:4px; overflow:hidden; margin-top:6px; }
  .colbar .cc{ flex:1; border:0; padding:0; margin:0; width:auto; height:100%; cursor:pointer;
    border-radius:0; transition:none; }
  .colbar .cc:hover{ box-shadow:inset 0 0 0 2px rgba(255,255,255,.65); }
  .colbar .cc[aria-checked="true"]{ box-shadow:inset 0 0 0 2px #fff, inset 0 0 0 3px rgba(0,0,0,.55); }
  .colbar .cc:focus-visible{ outline:2px solid var(--blue); outline-offset:-2px; }
  /* 사용자 지정 칸 (2026-08-25 사용자 요청 「사용자 정의색상도 고를수 있게」) —
     팔레트 맨 끝 한 칸. 아직 고르지 않았으면 «고를 수 있는 칸»임을 알리는 무지개 띠를 깔고,
     고른 뒤에는 그 색으로 채운다. 색 고르개(<input type=color>)는 이 칸 위에 투명하게 덮어
     둔다 — 버튼을 따로 두면 좁은 띠에서 누를 자리가 부족하다.
     ⚠ 안쪽 링(선택 표시)이 가리지 않게 input은 pointer-events만 받고 배경은 칠하지 않는다. */
  .colbar .cc.custom{ position:relative; }
  .colbar .cc.custom.unset{ background:linear-gradient(90deg,#c2261f,#b45309,#1a7f37,#1d5fae,#6b4fa0); }
  .colbar .cc.custom::after{ content:'+'; position:absolute; inset:0; display:flex;
    align-items:center; justify-content:center; font:600 12px/1 var(--font-sans,sans-serif);
    color:rgba(255,255,255,.92); text-shadow:0 0 2px rgba(0,0,0,.6); pointer-events:none; }
  .colbar .cc.custom[aria-checked="true"]::after{ content:''; }
  .colbar .cc.custom input[type="color"]{ position:absolute; inset:0; width:100%; height:100%;
    opacity:0; border:0; padding:0; cursor:pointer; }
  button{ width:100%; margin-top:8px; padding:8px; background:var(--blue); color:var(--text-inverse); border:0; border-radius:8px;
    font-weight:700; font-size:var(--fs-md); cursor:pointer; font-family:inherit; }
  button.sec{ background:var(--bg-sunken); color:var(--ink); border:1px solid var(--border); font-weight:500; }
  /* 설명·근거 줄. 11px는 «작아서 안 읽힌다»는 지적(2026-08-24)으로 12.5px로 올렸다 —
     여기 담기는 것이 대개 «무엇을 못 하는가»(한계·자료없음 표기)라 읽히지 않으면 의미가 없다. */
  .hint{ font-size:var(--fs-md); color:var(--muted); margin-top:6px; line-height:1.55; }
  /* ── 상승 프로파일 CCO (features/climb-profile, 2026-09-01) ──
     ⚠ 하강 프로파일(.dp-panel)은 CSS가 아예 없고 인라인 스타일로 그린다. 이쪽은 요약행·
       고도 분포 막대가 «표»라서 인라인으로 두면 같은 규칙이 여러 줄에 흩어진다 — 여기 모은다.
     ⛔ 색은 넣지 않는다: 색은 모듈(climb-profile.js COL)이 정한다. 여기는 **배치**만 한다
        (색을 두 곳에 두면 CDO·CCO의 «주황 = 수평비행» 언어가 조용히 갈린다). */
  .cp-rows{ margin-top:5px; }
  .cp-row{ display:flex; justify-content:space-between; align-items:baseline; gap:8px;
    padding:2px 0; border-bottom:1px dashed var(--border); font-size:var(--fs-md); }
  .cp-row:last-child{ border-bottom:0; }
  .cp-row .k{ color:var(--muted); white-space:nowrap; }
  .cp-row .v{ font-family:var(--font-mono); text-align:right; }
  /* 고도 분포 — PRD §15 「특정 고도의 Level-off 집중」. 성공률 대신 내는 그림이다. */
  .cp-bands{ margin-top:6px; display:flex; flex-direction:column; gap:2px; }
  .cp-band{ display:flex; align-items:center; gap:6px; font-size:var(--fs-sm); }
  .cp-band .fl{ font-family:var(--font-mono); color:var(--muted); width:44px; flex:none; }
  .cp-band .bar{ height:7px; border-radius:3px; flex:none; min-width:4px; }
  .cp-band .s{ color:var(--muted); white-space:nowrap; }
  .cp-chart{ display:block; margin-top:4px; }
  /* 유보문 — 접힘 상태는 **모듈 변수**가 갖는다(인스펙터가 innerHTML을 갈아 끼우므로) */
  .cp-notes{ margin-top:6px; }
  .cp-notes-t{ width:auto; margin:0; padding:2px 0; background:none; border:0; cursor:pointer;
    font:inherit; font-size:var(--fs-sm); color:var(--muted); text-align:left; }
  .cp-notes-t:hover{ color:var(--ink); }
  .cp-notes ul{ margin:3px 0 0; padding-left:16px; font-size:var(--fs-sm); color:var(--muted); line-height:1.5; }

  /* 레이어 줌 게이트 안내 (2026-09-01) — 「체크는 켰는데 지도에 안 나온다」를 화면이 말한다.
     ⛔ 색으로만 말하지 않는다: 글자로 「확대 필요 · 줌 7+」를 적는다. */
  .lyr .lyrZ { margin-left: auto; flex: none; font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }
  .lyr .lyrZ.on { color: var(--status-warn, #b45309); font-weight: 700; }
  .lyr.lyr-hidden > span:not(.lyrZ) { opacity: .5; }

  /* ── 유사호출부호 경고 목록 ── */
  .fcnt{ color:var(--pink); font-size:var(--fs-xs); font-weight:700; margin-left:7px; flex:none; white-space:nowrap; }
  .alrow{ position:relative; border:1px solid var(--border); border-left-width:4px; border-radius:8px; padding:6px 8px;
    margin:5px 0; cursor:pointer; transition:background .12s; }
  .alrow:hover{ background:var(--bg-sunken); }
  .alrow.on{ background:var(--status-danger-soft); border-color:currentColor; }
  .alcs{ font-family:var(--font-mono); font-size:var(--fs-md); font-weight:600; letter-spacing:.02em; color:var(--ink); }
  .alcs .d{ color:var(--err); }                      /* 두 콜사인에서 서로 다른 자릿수 */
  .alcs .sep{ color:var(--muted); font-weight:400; margin:0 4px; }
  .alfreq{ font-size:var(--fs-xs); margin-left:auto; flex:none; }
  .alfreq i{ font-style:normal; color:var(--muted); margin-right:4px; }
  .alfreq b{ font-family:var(--font-mono); font-weight:600; color:var(--ink); }
  .almeta{ display:flex; gap:6px; align-items:baseline; font-size:var(--fs-xs); color:var(--muted); margin-top:3px; }
  .albadge{ font-size:var(--fs-xs); font-weight:700; color:#fff; border-radius:5px; padding:1px 5px; flex:none; }
  .albadge.xb{ background:var(--bg-surface-elevated); color:var(--ink); border:1px dashed var(--muted); font-weight:600; }
  /* GNSS 「지역 확정」 배지 (사용자 지시 2026-08-25) — 같은 구역에서 3회 이상 관측돼 지도에
     이상구역이 그려지기 시작한 상태. 종전에는 이 순간이 아무 신호 없이 지나갔다.
     ⚠ 채움색을 쓰지 않고 테두리로 낸다 — 옆의 상태 배지(관측 중)가 경고 종류색으로 채워져 있어,
       둘 다 채우면 무엇이 상태이고 무엇이 확정인지 구분되지 않는다.
     ⚠ 색만으로 알리지 않는다: 배지 안에 「지역 확정 · N회」 글자가 언제나 함께 간다 (저장소 확정 규칙). */
  .albadge.cf{ background:transparent; color:currentColor; border:1px solid currentColor; font-weight:700; }
  /* 방금 확정된 20초 동안만 깜빡인다 (호스트가 .fresh를 붙였다 뗀다). 계속 깜빡이면 소음이 된다.
     ⚠ prefers-reduced-motion 존중 — 움직임에 민감한 이용자에게는 정지 상태로 보인다(글자는 그대로 읽힌다). */
  .albadge.cf.fresh{ animation:cfflash 1.1s ease-out 3; }
  @keyframes cfflash{ 0%,100%{ opacity:1 } 50%{ opacity:.2 } }
  @media (prefers-reduced-motion:reduce){ .albadge.cf.fresh{ animation:none; } }
  /* AI 위험도 — 풀어쓴 문구 한 줄 (사용자 확정 2026-08-06: 등급 배지 제거, "어떤 오류 가능성 몇%"로 표기) */
  .alrisk{ font-size:var(--fs-sm); font-weight:600; color:var(--text-secondary); margin-top:3px; }
  .alrisk b{ font-family:var(--font-mono); }
  .alrisk .aichip{ background:var(--chip-bg); color:var(--chip-fg); border-radius:4px; padding:0 4px;
    font-size:var(--fs-xs); font-weight:700; margin-right:5px; vertical-align:1px; }
  .xn{ color:var(--muted); }
  /* 카드 1줄: 콜사인 쌍 + 등급 배지(편명 바로 옆) / 2줄: 제목 붙은 항목들 */
  .altop{ display:flex; align-items:center; gap:7px; }
  /* 경고 끄기 ✕ (사용자 확정 2026-08-17) — 조건 지속 중에만 억제, 상황 재발 시 다시 뜬다.
     카드 우상단 **절대 배치** (사용자 확정 2026-08-17): 콜사인이 길어 첫 줄이 넘쳐도
     ✕는 항상 카드 안에 보여야 한다 — 흐름 배치(margin-left:auto)는 가로로 밀려나 반려 */
  /* ⚠ width:auto·margin:0 필수 — 전역 button{width:100%;margin-top:8px}을 되돌리지 않으면 카드 전체 폭의
     투명 버튼이 되어 ✕가 가운데 표시되고, 상단 어디를 눌러도 경고가 꺼진다 (2026-08-17 실사고) */
  .aldel{ position:absolute; top:5px; right:5px; width:auto; margin:0; flex:none; border:0; background:none;
    color:var(--muted); font-size:var(--fs-md); line-height:1; padding:2px 5px; border-radius:4px; cursor:pointer; }
  .aldel:hover{ background:var(--bg-hover); color:var(--err); }
  .altop{ padding-right:22px; }                        /* 첫 줄이 ✕ 밑으로 파고들지 않게 */
  .alkv{ display:flex; flex-wrap:wrap; gap:2px 10px; margin-top:4px; font-size:var(--fs-xs); color:var(--ink); }
  .alkv i{ font-style:normal; color:var(--muted); margin-right:4px; }
  .alkv b{ font-family:var(--font-mono); font-weight:600; }
  .alzone{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .alnum{ font-family:var(--font-mono); margin-left:auto; flex:none; }
  /* 분리간격 기준값 입력 */
  .cfg{ background:var(--bg-sunken); border:1px solid var(--border); border-radius:8px; padding:7px 9px; margin-bottom:6px; }
  .lgd2{ display:block; margin-bottom:4px; }
  .mk{ display:inline-block; width:12px; height:12px; vertical-align:-2px; margin-right:3px; }
  .mk-cs{ border:2px solid var(--blue); border-radius:50%; }
  .mk-sep{ border:2px solid var(--err); border-radius:2px;
    -webkit-mask:linear-gradient(#000 0 0) top/100% 4px no-repeat, linear-gradient(#000 0 0) bottom/100% 4px no-repeat,
      linear-gradient(#000 0 0) left/4px 100% no-repeat, linear-gradient(#000 0 0) right/4px 100% no-repeat; }
  .cfghd{ font-size:var(--fs-xs); font-weight:700; color:var(--ink); margin-top:7px; }
  .cfghd .u{ font-weight:400; color:var(--muted); }
  .cfgrow{ display:flex; gap:8px; align-items:flex-end; margin-top:3px; }
  .cfgrow label{ flex:1; font-size:var(--fs-xs); color:var(--muted); display:block; }
  .cfgrow label .u{ color:var(--muted); }
  .cfgrow input{ width:100%; margin-top:2px; padding:5px 7px; background:var(--bg-surface-elevated); border:1px solid var(--border);
    border-radius:6px; font-size:var(--fs-md); font-family:var(--font-mono); font-weight:600; color:var(--ink); }
  .cfgrow input:focus{ outline:none; border-color:var(--blue); }
  .cfgrow input:disabled{ background:var(--bg-hover); color:var(--muted); }
  .cfgrow .mbtn{ flex:none; font-size:var(--fs-sm); padding-bottom:6px; }
  .hdpick{ background:var(--accent-teal-soft); border:1px dashed var(--accent-teal); color:var(--accent-teal); border-radius:8px;
    padding:6px 9px; font-size:var(--fs-sm); margin-bottom:6px; }
  .hdturn{ font-size:var(--fs-sm); color:var(--muted); margin-top:6px; display:flex; align-items:center; gap:6px; }
  .tbtn{ cursor:pointer; font-family:var(--font-mono); font-size:var(--fs-sm); font-weight:700; padding:3px 8px;
    border:1px solid var(--border); border-radius:7px; background:var(--bg-surface-elevated); color:var(--ink); }
  .tbtn.on{ background:var(--accent-teal); border-color:var(--accent-teal); color:var(--text-inverse); }
  .hdph{ font-family:var(--font-mono); font-size:var(--fs-sm); line-height:1.5; background:var(--accent-teal-soft); border-left:3px solid var(--accent-teal);
    border-radius:0 6px 6px 0; padding:5px 8px; margin-top:5px; color:var(--ink); letter-spacing:.01em; }
  /* ── FR24 패널 (radar.html과 동일 마크업·스타일 — 한쪽을 고치면 다른 쪽도 같이) ── */
  #frBody label{ display:block; font-size:var(--fs-sm); font-weight:600; margin:8px 0 3px; }
  #frBody label .sfx{ font-weight:400; color:var(--muted); }
  #frBody input[type=password], #frBody input[type=text]{ width:100%; padding:6px 9px; background:var(--bg-sunken);
    border:1px solid var(--border); border-radius:8px; color:var(--ink); font-size:var(--fs-md); font-family:var(--font-mono); }
  #frBody input:focus{ outline:none; border-color:var(--blue); background:var(--bg-surface-elevated); }
  .mbtn{ cursor:pointer; color:var(--blue); font-weight:600; }
  .mbtn:hover{ text-decoration:underline; }
  .bxin{ display:flex; gap:4px; align-items:center; margin-top:5px; flex-wrap:wrap; }
  .bxin label{ flex:1 1 44px; margin:0; font-size:var(--fs-xs); color:var(--muted); }
  .bxin input{ width:100%; padding:4px 5px; background:var(--bg-sunken); border:1px solid var(--border);
    border-radius:6px; font-size:var(--fs-sm); font-family:var(--font-mono); color:var(--ink); }
  .credit-sum{ font-size:var(--fs-sm); margin-top:7px; padding-top:6px; border-top:1px dashed var(--border); color:var(--ink); }
  .credit-sum .sfx{ color:var(--muted); font-size:var(--fs-xs); }
  #loading{ position:absolute; inset:0; z-index:2000; display:flex; align-items:center; justify-content:center;
    background:var(--bg-space); color:var(--muted); font-size:var(--fs-lg); flex-direction:column; gap:10px; }
  .spin{ width:32px; height:32px; border:3px solid var(--border); border-top-color:var(--blue); border-radius:50%; animation:s 1s linear infinite; }
  @keyframes s{ to{ transform:rotate(360deg); } }
  /* 팝업 — 전역 button CSS가 상속되지 않도록 .pbtn은 색·폭을 직접 지정 (MAP AGENTS §7-8) */
  .leaflet-popup-content{ margin:11px 13px; font-size:var(--fs-md); line-height:1.5; }
  /* 지도 팝업 닫기 × — 모든 팝업(기상·공역·픽스·홀딩·기체) 우상단에 뚜렷하게 (사용자 요청 2026-08-17).
     Leaflet 기본 ×(회색 24px)가 흐려서 안 보인다는 지적 — 경고 카드 ✕와 같은 조형.
     선택자는 leaflet.css 원본(.leaflet-container a.…)과 동급 이상이어야 덮인다 */
  .leaflet-container a.leaflet-popup-close-button{ top:5px; right:5px; width:22px; height:22px;
    font:700 var(--fs-xl)/22px var(--font-sans); color:var(--muted); border-radius:5px; padding:0; }
  .leaflet-container a.leaflet-popup-close-button:hover{ background:var(--bg-hover); color:var(--err); }
  .leaflet-popup-content-wrapper{ cursor:grab; }
  .leaflet-popup-content-wrapper:active{ cursor:grabbing; }
  .pn{ font-weight:700; font-size:var(--fs-lg); } .pe{ color:var(--muted); font-size:var(--fs-sm); margin-bottom:6px; }
  .pko{ font-weight:600; font-size:var(--fs-md); color:var(--blue); }   /* 국문 호출부호 — 편명 옆 (radar.js가 삽입) */
  select{ width:100%; padding:6px 9px; background:var(--bg-sunken); border:1px solid var(--border); border-radius:8px; color:var(--ink); font-size:var(--fs-md); }
  .prow{ display:flex; justify-content:space-between; gap:14px; } .prow span:first-child{ color:var(--muted); }
  .pbtn{ font-size:var(--fs-sm); padding:4px 9px; margin:2px 5px 0 0; border:1px solid var(--border); border-radius:7px;
    background:var(--bg-surface-elevated); color:var(--ink); width:auto; display:inline-block; cursor:pointer; font-family:inherit; font-weight:600; }
  /* 스콱 경고 기체의 팝업 강조 — radar.js가 className 주입 (비상=빨강, 경고 카드와 같은 색) */
  .leaflet-popup.p-sq .leaflet-popup-content-wrapper{ border:2px solid var(--err);
    box-shadow:0 0 0 4px rgba(208,2,27,.15), 0 6px 22px rgba(30,41,51,.22); }
  .leaflet-popup.p-dup .leaflet-popup-content-wrapper{ border:2px solid var(--status-warn);
    box-shadow:0 0 0 4px rgba(148,98,0,.15), 0 6px 22px rgba(30,41,51,.22); }
  /* 섹터 목록 행 (교신 청취 삭제 2026-08-24 이후로는 체크박스 한 줄뿐) */
  .secrow{ display:flex; align-items:center; gap:6px; }
  .secrow .lyr{ flex:1; padding:2px 0; }
  .pane{ display:none; } .pane.on{ display:block; }
  .pcol{ display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:6px 24px; }
  .phd{ font-size:var(--fs-md); font-weight:700; letter-spacing:.03em; color:var(--muted);
    text-transform:uppercase; margin-bottom:4px; }
  .phint{ font-size:var(--fs-md); color:var(--muted); line-height:1.6; margin-bottom:7px; }
  /* 노탐 탭 비행계획 폼 + 비행브리핑 지도 라벨 (features/flight-briefing draw) */
  .fp .fprow{ display:flex; gap:6px; margin-bottom:8px; align-items:flex-start; }
  .fp .fprow>*{ flex:1; min-width:0; }
  .fp .lab{ display:block; font-size:var(--fs-xs); font-weight:700; letter-spacing:.05em; color:var(--muted); text-transform:uppercase; margin:0 0 3px; }
  .fp .lab i{ font-style:normal; font-weight:400; letter-spacing:0; text-transform:none; }
  .fp input, .fp textarea{ width:100%; box-sizing:border-box; background:var(--bg-sunken); border:1px solid var(--border); border-radius:6px;
    padding:6px 8px; font:var(--fs-md) var(--font-mono); color:var(--ink); line-height:1.35; margin:0; }
  .fp textarea{ resize:vertical; min-height:52px; }
  .fp input:focus, .fp textarea:focus{ outline:2px solid var(--blue); outline-offset:-1px; }
  /* 항공 식별자 칸은 **화면에서도 대문자**로 (2026-08-25) — ICAO·픽스·항로는 대문자가 원문 표기다.
     값 자체도 host가 대문자로 되돌린다(fpUpper) — CSS만 걸면 화면과 .value가 갈라진다. */
  #fpDep, #fpArr, #fpVia, #fpCs, #fpType, .fp .fpghost{ text-transform:uppercase; }
  /* 예시(placeholder)를 **입력값처럼 보이지 않게** (2026-08-25 사용자 지적: 속도 칸의 예시 450을
     넣은 값으로 읽어 「속도 미입력」 경고와 어긋나 보였다). 흐리게 + 기울여 값과 구분한다. */
  .fp input::placeholder, .fp textarea::placeholder{ color:var(--muted); opacity:.55; font-style:italic; text-transform:none; }
  .fp .unit{ position:relative; }
  .fp .unit em{ position:absolute; right:8px; bottom:8px; font:var(--fs-sm) var(--font-sans); font-style:normal; color:var(--muted); pointer-events:none; }
  .fp .unit input{ padding-right:30px; }
  /* 출도착 공항 콤보 (2026-08-25 — datalist 대체, index.html fpAptCombo). 한 항목 = 한 줄, 글자 작게(--fs-sm).
     body에 fixed로 띄운다(서랍 overflow에 잘리지 않게). 열(ICAO·IATA)은 고정폭이라 세로로 줄이 맞는다 */
  .fpapt{ position:fixed; z-index:3000; overflow:auto; background:var(--bg-surface-float); color:var(--text-primary);
    border:1px solid var(--border); border-radius:7px; box-shadow:0 8px 24px rgba(30,41,51,.25); padding:3px; box-sizing:border-box; }
  .fpapt-i{ display:flex; gap:8px; align-items:baseline; padding:3px 8px; font:var(--fs-sm) var(--font-mono); line-height:1.4;
    border-radius:4px; cursor:pointer; white-space:nowrap; }
  .fpapt-i b{ width:38px; flex:none; font-weight:700; }
  .fpapt-i span{ width:30px; flex:none; color:var(--muted); }
  .fpapt-i .k{ width:auto; flex:1 1 auto; min-width:0; color:var(--text-primary); font-family:var(--font-sans); overflow:hidden; text-overflow:ellipsis; }
  .fpapt-i em{ flex:none; font:var(--fs-xs) var(--font-sans); font-style:normal; color:var(--muted); }
  .fpapt-i:hover, .fpapt-i.on{ background:var(--bg-sunken); }
  .fp .fpbtn button{ margin:0; padding:7px 10px; font-size:var(--fs-md); }
  .fp .fpbtn button.pri{ flex:2; background:var(--blue); color:var(--text-inverse); border:1px solid var(--blue); font-weight:700; border-radius:7px; cursor:pointer; }
  .fp .fpsep{ border-top:1px solid var(--border); margin:2px 0 8px; }
  /* 경로 고스트 자동완성 (2026-08-25 — docs/검토-비행계획-입력보조.md §5-2)
     textarea 뒤에 **같은 글꼴·같은 여백의 거울**을 깔고, 친 글자는 감춘 채 제안분만 흐리게 비춘다.
     ⚠ 두 요소의 padding·font·line-height가 어긋나면 글자가 어긋나 겹쳐 보인다 — 그래서 위
       `.fp input, .fp textarea` 규칙과 **같은 값**을 여기 한 곳에 다시 묶어 둔다. 바꿀 때 같이 바꿀 것. */
  .fp .fpvia{ position:relative; }
  .fp .fpvia textarea{ position:relative; background:transparent; }
  .fp .fpghost{ position:absolute; inset:0; box-sizing:border-box; border:1px solid transparent; border-radius:6px;
    padding:6px 8px; font:var(--fs-md) var(--font-mono); line-height:1.35; white-space:pre-wrap;
    overflow-wrap:break-word; overflow:hidden; pointer-events:none; background:var(--bg-sunken); color:transparent; }
  .fp .fpghost b{ font-weight:400; color:var(--muted); opacity:.72; }
  /* 입력 검증줄 — 「검색을 누르기 전에」 성립 여부를 말해 준다 (FlightBriefing.checkRoute) */
  .fp .fpchk{ font-family:var(--font-sans); font-size:var(--fs-sm); line-height:1.55; margin:-4px 0 8px; }
  .fp .fpchk .e{ color:var(--err); font-weight:600; }
  .fp .fpchk .w{ color:#b45309; }
  .fp .fpchk .i, .fp .fpchk .k{ color:var(--muted); }
  /* 대안 토큰 (↓ 또는 제안 옆) — 편수를 같이 적어 최빈만 맹종하지 않게 한다 */
  .fp .fpalt{ display:flex; flex-wrap:wrap; gap:4px; margin:-4px 0 8px; align-items:center; }
  .fp .fpalt button{ margin:0; padding:2px 7px; font:var(--fs-sm) var(--font-mono); border-radius:5px;
    border:1px solid var(--border); background:var(--bg-sunken); color:var(--ink); cursor:pointer; }
  .fp .fpalt button:hover{ border-color:var(--blue); }
  .fp .fpalt .k{ font:var(--fs-xs) var(--font-sans); color:var(--muted); }
  /* ── 접어 둔 「직접 입력」 (2026-09-03 — 고도·속도·기종·경로를 기본으로 숨긴다) ──────────
     ⛔ 지우지 않고 접는 이유는 index.html의 #fpAdv 주석에 있다(소형기 용도가 같은 폼을 쓴다). */
  .fp #fpAdv{ margin:-2px 0 8px; }
  .fp #fpAdv>summary.fpadv{ cursor:pointer; font-size:var(--fs-sm); color:var(--muted);
    padding:3px 0; list-style:none; user-select:none; }
  .fp #fpAdv>summary.fpadv::before{ content:'▸ '; }
  .fp #fpAdv[open]>summary.fpadv::before{ content:'▾ '; }
  .fp #fpAdv>summary.fpadv::-webkit-details-marker{ display:none; }
  .fp #fpAdv>summary.fpadv:hover{ color:var(--ink); }
  .fp #fpAdv[open]{ padding:6px 0 0; border-top:1px dashed var(--border); }
  /* 시각 기준 — EOBT(계획) / 실제 출발 (사용자 확정 2026-09-03) */
  .fp .fpbasis{ gap:12px; margin:-4px 0 8px; align-items:center; }
  .fp .fpbasis label{ flex:0 0 auto; display:flex; align-items:center; gap:4px;
    font-size:var(--fs-sm); color:var(--muted); cursor:pointer; }
  .fp .fpbasis input{ margin:0; width:auto; }
  .fpst{ font-family:var(--font-mono); font-size:var(--fs-sm); color:var(--muted); margin:-2px 0 8px; line-height:1.4; }
  /* ── 경로 브리핑 블록 (2026-08-25) — 조회 탭 두 하위탭(항공편·비행계획)이 같은 서식을 쓴다.
     왜 필요했나: 브리핑 본문은 `.acbox`/`.prow`인데 **`.acbox`에는 규칙이 없어** body 기본 12px로
     떴다. 바로 위 검증줄(.fpchk)·상태줄(.fpst)이 11px이라 «갑자기 커지고 달라진» 덩어리로 보였다
     (사용자 지적 2026-08-25). ⛔ `.prow` 자체를 건드리지 않는다 — 기체 인스펙터(#acBody)와 지도
     팝업이 같은 클래스를 쓰고, 거기서는 지금 크기가 맞다. */
  .brf{ font-size:var(--fs-sm); line-height:1.55; }
  .brf .hint{ font-size:var(--fs-sm); margin-top:5px; }
  .brf .phd{ font-size:var(--fs-sm); }
  .brf .acbox{ display:flex; flex-direction:column; gap:1px; margin:2px 0 4px; }
  .brf .prow{ gap:10px; align-items:baseline; padding:1px 0; }
  /* 라벨 칸을 고정한다 — 안 하면 값이 길 때(경로 36지점) 「경로」가 «경/로» 두 줄로 쪼개진다 */
  .brf .prow>span:first-child{ flex:0 0 58px; white-space:nowrap; }
  /* 긴 값은 왼쪽 정렬이 읽힌다. 인라인 style="text-align:right"를 이기려면 !important가 필요하다
     (그 인라인은 인스펙터의 짧은 값에 맞춘 것이고, 여기서는 문단이 된다) */
  /* 브리핑 구조 (2026-08-25 2차 — 사용자 지적 「가독성 떨어짐, 그룹화하거나 표를 쓰거나」)
     ① 결론 배지 ② 한 줄 요약 ③ 표 ④ 알릴 것 없는 구간은 접기.
     ⛔ 접는 것이지 버리는 것이 아니다 — 접힌 개수와 요약은 겉에 남는다. */
  .brf .chips{ display:flex; flex-wrap:wrap; gap:4px; margin:1px 0 7px; }
  .brf .chips .c{ font-size:var(--fs-xs); font-weight:700; padding:2px 8px; border-radius:999px;
    border:1px solid var(--border); background:var(--bg-sunken); color:var(--muted); white-space:nowrap; }
  .brf .chips .c.err{ color:var(--err); border-color:var(--err); }
  .brf .chips .c.warn{ color:#b45309; border-color:#d9a441; }
  .brf .chips .c.ok{ color:#177245; border-color:#8fbf9f; }
  .brf .sum{ font-weight:700; line-height:1.5; }
  .brf .sub{ color:var(--muted); margin:1px 0 4px; }
  /* 절 머리 — 얇은 구분선 + 오른쪽에 그 절의 «몇 건인지» */
  .brf .sec{ display:flex; align-items:baseline; gap:6px; margin:9px 0 3px; padding-top:7px;
    border-top:1px solid var(--border-subtle); font-size:var(--fs-xs); font-weight:700;
    letter-spacing:.05em; text-transform:uppercase; color:var(--muted); }
  .brf .sec i{ font-style:normal; font-weight:500; letter-spacing:0; text-transform:none;
    font-size:var(--fs-sm); color:var(--muted); }
  .brf table{ width:100%; border-collapse:collapse; table-layout:fixed; }
  .brf td{ padding:3px 0; vertical-align:top; border-top:1px solid var(--border-subtle); overflow-wrap:anywhere; }
  .brf tr:first-child td{ border-top:0; }
  .brf td.no{ width:74px; font-family:var(--font-mono); white-space:nowrap; }
  .brf td.rt{ width:104px; text-align:right; color:var(--muted); }
  .brf .k{ color:var(--muted); }
  .brf details{ margin:2px 0; }
  .brf summary{ cursor:pointer; color:var(--muted); list-style:none; }
  .brf summary::-webkit-details-marker{ display:none; }
  .brf summary::before{ content:'\25B8\00A0'; }
  .brf details[open]>summary::before{ content:'\25BE\00A0'; }
  .brf .warn{ color:#b45309; margin-top:3px; }
  .brf .prow>span:last-child{ flex:1 1 auto; min-width:0; text-align:left !important; overflow-wrap:anywhere; }
  .leaflet-tooltip.fb-lb{ background:rgba(20,26,34,.82); border:0; color:#eaf1f8; font-size:var(--fs-xs); padding:1px 5px; box-shadow:none; }
  .leaflet-tooltip.fb-lb::before{ display:none; }
  /* 노탐 확인 라벨 (features/notam-watch) — 배경 없이 흰 테두리만 (사용자 확정 2026-08-24: 검은 상자가 구역을 가렸다) */
  .leaflet-tooltip.ntw-lb{ background:transparent; border:0; box-shadow:none; color:#5b21b6; font-weight:700;
    font-size:var(--fs-xs); padding:0 2px; text-shadow:0 0 3px #fff,0 0 3px #fff,0 0 3px #fff,0 0 3px #fff; }
  .leaflet-tooltip.ntw-lb::before{ display:none; }
  #acBody .pn{ font-size:var(--fs-xl); font-weight:800; }
  /* ⚠ !important — features/gnss-sky가 행마다 font-size를 인라인으로 박는다(11.5px).
     인스펙터 안에서 절마다 글자 크기가 달라 보이던 원인이라 여기서 본문 크기로 되돌린다. */
  #acBody .prow{ padding:2px 0; font-size:var(--fs-md) !important; }
  #acBody .pbtn{ font-size:var(--fs-sm); }
  /* 노탐 자동 확인 옵션 (features/notam-watch 수동 버튼 옆 — 2026-08-25) —
     켜면 경로 표시 중인 기체의 노탐을 매번 누르지 않아도 같이 보여준다 */
  .ntmAutoRow{ display:flex; align-items:center; gap:5px; margin:5px 5px 0 0; font-size:var(--fs-sm);
    color:var(--muted); cursor:pointer; user-select:none; }
  .ntmAutoRow input{ margin:0; cursor:pointer; }

  /* ══ 글꼴 통일 (사용자 지시 2026-08-25 「팝업 메뉴마다 글꼴이 모두 다름」) ══════════
     규칙 3줄로 요약된다.
       ① 화면의 모든 글자는 var(--font-sans) — 한 얼굴이다.
       ② var(--font-mono)는 «세로로 맞춰 읽는 숫자»에만 쓴다(시각·고도·속도·좌표·노탐번호).
          한글 문장에는 쓰지 않는다 — 모노에는 한글이 없어 낱자가 다른 글꼴로 떨어진다.
       ③ 크기는 --fs-xs/sm/md/lg/xl/hero 6단만 쓴다 (theme.css).
     ============================================================================ */
  /* leaflet.css가 팝업·툴팁·컨트롤에 Helvetica를 박아 둔다 — 본문 글꼴로 되돌린다.
     (.leaflet-container만 inherit이던 종전 규칙으로는 컨트롤·툴팁이 빠져나갔다) */
  .leaflet-popup-content, .leaflet-tooltip, .leaflet-control,
  .leaflet-control-attribution, .leaflet-control-scale-line{ font-family:var(--font-sans); }
  /* 한글이 섞이는 칸은 모노에서 빼낸다 — 모듈이 행 전체를 모노로 깔아도 여기가 이긴다.
       .fpst  = 노탐 상태줄 「CDR 1 · 계획 없음 · 저장소 408건」
       .fbc   = 운항현황판 목적지 칸 「오사카/간사이 KIX」 */
  .fpst, .fbc{ font-family:var(--font-sans); }
  /* 모노를 쓰는 칸은 숫자 폭을 고정해 세로로 맞춘다 (통일의 나머지 절반) */
  .srow .v, .metric-inline, .alnum, .alcs, .fbrow, .fp input, .fp textarea,
  .cfgrow input, .tbtn, #windRead{ font-variant-numeric:tabular-nums; }

  /* 기능 모듈(features/*.js)이 인라인으로 박는 px 크기를 6단 계단으로 되돌린다.
     ⛔ 모듈 JS는 고치지 않는다(정본과의 괴리를 늘리지 않는다) — theme.css의 [style*=...] 색 보정과
        같은 방식으로 여기서 덮는다. 모듈이 토큰을 쓰게 되면 이 블록은 통째로 지운다.
     대상은 «패널 안»뿐이다 — 지도 위 라벨·툴팁은 제 크기를 유지해야 한다. */
  #sheet [style*="font-size:13px"], #acBody [style*="font-size:13px"],
  #alertWrap [style*="font-size:13px"]{ font-size:var(--fs-lg) !important; }
  #sheet [style*="font-size:12.5px"], #acBody [style*="font-size:12.5px"],
  #alertWrap [style*="font-size:12.5px"], #sheet [style*="font-size:12px"],
  #acBody [style*="font-size:12px"], #alertWrap [style*="font-size:12px"]{ font-size:var(--fs-md) !important; }
  #sheet [style*="font-size:11.5px"], #acBody [style*="font-size:11.5px"],
  #alertWrap [style*="font-size:11.5px"], #sheet [style*="font-size:11px"],
  #acBody [style*="font-size:11px"], #alertWrap [style*="font-size:11px"]{ font-size:var(--fs-sm) !important; }
  #sheet [style*="font-size:10.5px"], #acBody [style*="font-size:10.5px"],
  #alertWrap [style*="font-size:10.5px"], #sheet [style*="font-size:10px"],
  #acBody [style*="font-size:10px"], #alertWrap [style*="font-size:10px"],
  #sheet [style*="font-size:9px"], #acBody [style*="font-size:9px"]{ font-size:var(--fs-xs) !important; }

  /* ══ 도움말 아이콘 + 호버 툴팁 (사용자 지시 2026-08-25
        「도움말이나 설명은 가능하면 아이콘으로 표시해서 마우스호버하면 나오게」) ══
     설명 문단을 화면에서 걷어내되 **버리지는 않는다** — data-tip에 그대로 담아
     아이콘 위에 얹는다. 클릭으로도 열린다(모바일에는 호버가 없다).
     ⛔ 안전 단서(「관제 분리 판정을 대체하지 않습니다」 류)는 아이콘 뒤로 넣더라도
        아이콘 자체가 눈에 띄어야 한다 — 그래서 테두리 있는 원형으로 둔다. */
  .hlp{ display:inline-flex; align-items:center; justify-content:center; flex:none;
    width:16px; height:16px; margin:0 0 0 5px; padding:0; vertical-align:-3px;
    border:1px solid var(--border-medium); border-radius:50%; background:transparent;
    color:var(--text-tertiary); font:700 var(--fs-xs)/1 var(--font-sans);
    /* 아이콘이 놓이는 자리(.phd·.fp .lab·.acsecHd)는 대문자 변환·자간을 걸어 둔다 — 상속을 끊는다 */
    text-transform:none; letter-spacing:0;
    cursor:help; user-select:none; }
  .lyr .hlp{ margin-left:0; }        /* .lyr는 flex gap 8px — 여기에 margin까지 더하면 멀어진다 */
  .hlp::before{ content:'?'; }
  .hlp:hover, .hlp:focus, .hlp.on{ background:var(--blue); color:var(--text-inverse);
    border-color:var(--blue); outline:none; }
  .hlp.warn{ border-color:var(--status-warn); color:var(--status-warn); }
  .hlp.warn::before{ content:'!'; }
  .hlp.warn:hover, .hlp.warn:focus, .hlp.warn.on{ background:var(--status-warn); color:#fff; }
  /* 툴팁 상자 — body 직속 + position:fixed. 서랍·인스펙터는 overflow:auto라
     그 안에 그리면 잘린다(스크롤 컨테이너의 숙명). 좌표는 JS가 화면 안으로 밀어 넣는다. */
  #tipBox{ position:fixed; z-index:3000; display:none; max-width:min(300px, calc(100vw - 24px));
    padding:8px 10px; border:1px solid var(--border-medium); border-radius:var(--radius-md,10px);
    background:var(--bg-surface-elevated); color:var(--text-secondary);
    font-size:var(--fs-sm); line-height:1.55; box-shadow:var(--shadow-md);
    pointer-events:none; }
  #tipBox b{ color:var(--ink); }

  /* 구역 밖 흐리게 — 담당구역 패널 안의 토글 (사용자 확정 2026-08-10, 떠 있는 버튼 제거) */
  #fadeBtn{ width:100%; margin-top:8px; padding:6px 10px; font-size:var(--fs-sm); font-weight:600;
    background:var(--bg-surface-elevated); color:var(--muted); border:1px solid var(--border); border-radius:8px;
    cursor:pointer; font-family:inherit; }
  #fadeBtn.on{ background:var(--blue); color:var(--text-inverse); border-color:var(--blue); }
  .credit{ position:absolute; bottom:calc(6px + var(--sa-b,0px)); left:calc(12px + var(--sa-l,0px)); z-index:1000; font-size:var(--fs-xs); color:var(--muted);
    background:var(--bg-surface-glass); padding:1px 5px; border-radius:4px; }
  /* 서비스 저작권 — .credit(지도·데이터 출처)과 반대쪽 구석, 같은 높이 (#rcBar는 재생 중일 때
     한 단 위(52px)로 올라가 이 줄을 가리지 않는다 — shell.css #rcBar 주석 참조). */
  .copyright{ position:absolute; bottom:calc(6px + var(--sa-b,0px)); right:calc(12px + var(--sa-r,0px)); z-index:1000; font-size:var(--fs-xs); color:var(--muted);
    background:var(--bg-surface-glass); padding:1px 5px; border-radius:4px; }
  /* 노선분류 색상 범례(지도 위, 우하단) — .credit과 반대쪽 구석, 저작권 줄 위로 한 단 띄운다.
     내용은 index.html의 renderRcLegend()가 채운다(색값 정본은 radar.js Radar.rcLegend). */
  .rcMapLegend{ position:absolute; bottom:calc(26px + var(--sa-b,0px)); right:calc(12px + var(--sa-r,0px)); z-index:1000;
    display:flex; flex-wrap:wrap; gap:3px 10px; max-width:220px; justify-content:flex-end;
    font-size:var(--fs-xs); color:var(--text-secondary); background:var(--bg-surface-glass);
    padding:5px 8px; border-radius:6px; border:1px solid var(--border); box-shadow:var(--shadow-sm,0 1px 3px rgba(0,0,0,.15));
    pointer-events:none; }
  #hoverTip{ position:absolute; z-index:1500; pointer-events:none; display:none; background:#0b3d91; color:#fff;
    font-size:var(--fs-md); font-weight:700; padding:3px 8px; border-radius:6px; box-shadow:0 2px 8px rgba(0,0,0,.3);
    white-space:nowrap; transform:translate(10px,-50%); }
  #hoverTip small{ font-weight:400; opacity:.8; }
  /* 기체 고도 바람 배지 — 기체 클릭 시 **그 기체 고도**의 바람을 기체 좌표 우하단에 표시.
     (우하단 고정 박스 → 커서 추적 판독 → 팝업 행, 전부 반려 이력 2026-08-11: 고정 박스는 존재를 모르고,
      커서 판독은 기체 고도가 반영되지 않고, 팝업 행은 눈에 안 띈다. 팝업은 위로 열리므로 아래 오프셋이면 안 겹친다) */
  #windRead{ position:absolute; z-index:1500; display:none;
    background:var(--bg-surface-float); border:1px solid var(--border); border-radius:7px;
    padding:3px 26px 3px 9px; font-family:var(--font-mono); font-size:var(--fs-sm); font-weight:600; color:var(--ink);
    pointer-events:none; font-variant-numeric:tabular-nums; box-shadow:0 2px 8px rgba(0,0,0,.18);
    white-space:nowrap; transform:translate(14px,16px); }
  #windRead small{ font-weight:600; color:var(--muted); margin-right:5px; }
  /* 바람 배지 닫기 ✕ (사용자 요청 2026-08-17 — 팝업 × 통일의 연장). 배지 컨테이너는 pointer-events:none
     (지도 클릭 통과)이라 ✕만 auto로 예외. ⚠ width·margin 명시 필수 — 전역 button{width:100%} 상속 방지 */
  #windRead .acwX{ position:absolute; top:50%; right:4px; transform:translateY(-50%); pointer-events:auto;
    width:18px; height:18px; margin:0; padding:0; border:0; background:none; color:var(--muted);
    font-size:var(--fs-md); line-height:18px; border-radius:4px; cursor:pointer; }
  #windRead .acwX:hover{ background:var(--bg-hover); color:var(--err); }
  #sectorPop{ margin-top:4px; border:1px solid var(--border); border-radius:8px; background:var(--bg-sunken);
    padding:6px 9px; max-height:220px; overflow:auto; }
  #sectorPop .grp{ font-size:var(--fs-xs); font-weight:700; color:var(--muted); margin:6px 0 2px; letter-spacing:.04em; }
  #zoneAllRow{ display:flex; align-items:center; gap:7px; padding:5px 8px; margin-bottom:5px;
    border:1px solid var(--border); border-radius:7px; font-size:var(--fs-md); font-weight:700;
    color:var(--muted); cursor:pointer; user-select:none; }
  #zoneAllRow .zdot{ width:8px; height:8px; border-radius:50%; background:var(--border); flex:none; }
  #zoneAllRow.on{ color:var(--blue); border-color:var(--blue); background:var(--bg-hover); cursor:default; }
  #zoneAllRow.on .zdot{ background:var(--blue); }
  #zoneAllRow:not(.on):hover{ background:var(--bg-sunken); color:var(--ink); }
  #quiet{ margin-top:10px; padding:7px 10px; border:1px solid var(--border); border-left:3px solid var(--live);
    border-radius:8px; font-size:var(--fs-md); color:var(--muted); background:var(--status-live-soft); }
  .agrp{ margin-top:10px; }
  .agrp .ahd{ font-size:var(--fs-md); font-weight:700; display:flex; align-items:center; margin-bottom:2px; }
  /* 비상 스콱 = 확인 전 주의 끌기 (은은한 점멸 — ACK 도입 전 임시) */
  @keyframes sqpulse{ 0%,100%{ background:var(--bg-surface-elevated); } 50%{ background:var(--status-danger-soft); } }
  .alrow.em{ animation:sqpulse 1.6s ease-in-out infinite; }
  /* --- 「공항」 탭 보드 글자 상향 (2026-08-24 리뷰 P3) ------------------------------
     fltboard 주입 스타일은 지도 팝업 전제라 10~11px — 서랍에서는 2026-08-24 확정
     「글자가 너무 작다」 기준(본문 12.5px)에 맞춘다. 팝업 쪽은 그대로(모듈 불수정).
     시각 열 88px = 「12:34→13:05」(변경시각 병기)가 12.5px 모노에서 안 접히는 폭. */
  /* 열 폭 (사용자 확정 2026-08-25 「목록의 너비도 적절하게」) — 종전 도착지 열이 1fr이라 서랍
     폭(470px)에서 남는 자리를 **전부** 먹어, 「홍콩 HKG」 뒤에 100px 넘는 빈칸이 생기고 상태·게이트가
     저 멀리 떨어져 한 행이 눈으로 안 이어졌다. fit-content(178px) = «내용만큼, 최대 178px»이라
     도착지 뒤에 상태가 바로 붙고(그래서 .fbs는 이 탭에서만 좌측정렬), 남는 자리는 게이트 앞
     한 곳으로 모인다. 긴 지명(「아디스아바바/볼레」)은 178px에서 …로 잘린다. */
  /* 목록은 **표(table)**다 (사용자 확정 2026-08-25 「목록 간격도 가운데 공백 없이 일정하게」).
     ⚠ 왜 grid를 버렸나: 행 하나하나가 별개의 grid 컨테이너라 내용 기준 열폭(fit-content)이
     **행마다 따로** 계산된다 — 실측으로 같은 열이 113px·156px로 갈려 상태·게이트가 행마다
     들쭉날쭉했다. 반대로 고정폭 + 1fr로 두면 1fr 열이 남는 자리를 통째로 먹어 **행 한가운데
     빈칸**이 생긴다(종전 판의 「홍콩 HKG …… 출발」). 표는 둘 다 아니다 — 열폭을 **행 전체가
     공유**하면서 내용만큼만 차지하고, 남는 자리는 표 오른쪽 한 곳에 모인다.
     그래서 모듈이 행들을 .fbtbl로 감싸 준다(팝업은 종전 grid 그대로 — 좁아서 남는 자리가 없다). */
  /* ⛔ 가로 스크롤 금지 (사용자 확정 2026-08-25 「가로 스크롤은 없도록 너비 조정」) — 종전 width:auto +
     모든 칸 nowrap이라 열 폭 합(시각 88·편명 90·도착지 236·상태·게이트 + 칸 간격 48)이 서랍 폭을 넘으면
     .fbbody가 옆으로 스크롤됐다(ICN 82편 실측). 표를 100%로 두고 **도착지 칸(.fbc)만 max-width:0**으로
     «남는 폭»을 받게 한다(table auto 레이아웃의 관용구 — 그 칸의 최소폭이 0이 돼 나머지 열은 내용만큼,
     도착지는 남는 자리만큼 차지하고 넘치면 …). 가운데 공백은 안 생긴다 — 유일한 신축 열이 도착지 하나라
     남는 폭이 전부 거기로 가고 상태·게이트는 그 바로 뒤에 붙는다. 전체 지명은 행 title로 남는다. */
  .pane[data-pane="apt"] .fbbody{ overflow-x:hidden; }
  .pane[data-pane="apt"] .fbtbl{ display:table; width:100%; max-width:100%; border-collapse:collapse; }
  .pane[data-pane="apt"] .fbrow{ display:table-row; font-size:var(--fs-md); padding:0; }
  .pane[data-pane="apt"] .fbrow > span{ display:table-cell; padding:2.5px 12px 2.5px 0;
    border-bottom:1px dotted var(--border-subtle); white-space:nowrap; vertical-align:baseline; }
  .pane[data-pane="apt"] .fbrow > span:last-child{ padding-right:0; }
  .pane[data-pane="apt"] .fbs{ text-align:left; }
  .pane[data-pane="apt"] .fbg{ text-align:left; }
  /* 출도착 칸 = 유일한 신축 열. max-width:0이 없으면 nowrap 내용폭이 열의 최소폭이 돼 표가 서랍을 밀어낸다.
     (종전 .fbod max-width:236px 고정 캡은 폐지 — 칸 폭이 곧 상한이다) */
  .pane[data-pane="apt"] .fbc{ max-width:0; overflow:hidden; text-overflow:ellipsis; }
  /* 남는 폭은 **전부** 출도착 열로 (2026-08-25 후속 「출도착 컬럼이 너무 작음. 최대한 꽉차게」) —
     max-width:0만으로는 auto 레이아웃이 남는 폭을 열별 «최대내용폭 비례»로 나눠 시각·편명 뒤에 빈칸이
     생기고 출도착은 130px에 그쳤다(실측). 한 열에 width:100%를 주면 나머지 열은 내용폭으로 눌리고
     이 열이 나머지를 다 가진다(table의 고전 관용구). 머리글 칸까지 잡히도록 nth-child로 건다. */
  .pane[data-pane="apt"] .fbrow > span:nth-child(3){ width:100%; }
  .pane[data-pane="apt"] .fbod{ display:block; max-width:none; overflow:hidden; text-overflow:ellipsis; }
  .pane[data-pane="apt"] .fbrow small{ font-size:var(--fs-xs); }
  .pane[data-pane="apt"] .fbsum{ font-size:var(--fs-md); }
  .pane[data-pane="apt"] .fbmsg{ font-size:var(--fs-md); }
  .pane[data-pane="apt"] .fbs, .pane[data-pane="apt"] .fbg{ font-size:var(--fs-sm); }
  /* 📡(fbnow) = 지금 뜬 항적 — 누르면 지도 클릭과 같은 처리(선택 + 실제항적 + 예상경로)로 이어진다.
     onRow를 주면 모듈이 모든 행을 클릭 대상으로 만들므로, 누를 것과 아닌 것을 눈으로 갈라 준다
     (2026-08-25 — 안 그러면 눌러도 안 되는 행이 눌리는 행처럼 보인다) */
  .pane[data-pane="apt"] .fbrow.fbnow .fbid{ color:var(--blue); }
  .pane[data-pane="apt"] .fbrow.fbnow:hover{ background:var(--bg-hover); }
  /* 항적 없는 행도 누를 수 있다 (2026-08-25 — 비행계획 기반 «예측» 시각·경로, aptPickRow → FlightFind).
     📡 행과는 색(fbid 파랑)으로 갈리고, 눌리는 행이라는 표시(커서·hover)는 둘 다 준다. */
  .pane[data-pane="apt"] .fbrow:not(.fbnow){ cursor:pointer; }
  .pane[data-pane="apt"] .fbrow:not(.fbnow):hover{ background:var(--bg-hover); filter:saturate(.6); }
  /* 「공항」 탭 = 위(공항 선택)·아래(조작줄) 고정 + **가운데 목록만** 스크롤
     (사용자 확정 2026-08-25 「스크롤 하단에 BOTTOM 이 있는 메뉴는 하단이 항상 보이고
      가운데 목록만 스크롤 생기도록」). 종전에는 서랍(#sheet) 전체가 한 덩어리로 스크롤돼,
      100편짜리 목록에서는 공항 선택칸과 항적 버튼이 **둘 다** 화면 밖으로 나갔다.
     구조: #sheet(스크롤 끔) → .pane(세로 flex) → .fbbody(여기서만 스크롤).
     ⚠ min-height:0이 빠지면 flex 자식이 내용만큼 늘어나 스크롤이 생기지 않는다(flex 기본 min-content).
     다른 탭에는 영향이 없다 — body[data-tab="apt"]로 이 탭에서만 #sheet를 바꾼다. */
  body[data-tab="apt"] #sheet{ display:flex; flex-direction:column; overflow:hidden; }
  body[data-tab="apt"] .pane[data-pane="apt"].on{ display:flex; flex-direction:column;
    flex:1 1 auto; min-height:0; }
  .pane[data-pane="apt"] .fbbody{ flex:1 1 auto; min-height:0; overflow-y:auto; }
  /* 요약줄은 위에, 조작줄은 아래에 «붙여» 둔다 — 목록이 그 밑으로 흐른다.
     배경은 반드시 **불투명**이어야 한다(반투명이면 지나가는 행 글자가 비쳐 읽을 수 없다) */
  .pane[data-pane="apt"] .fbsum{ position:sticky; top:0; z-index:2; margin:0 0 3px;
    padding:2px 0 4px; background:var(--bg-surface-elevated); }
  .pane[data-pane="apt"] .fbact{ position:sticky; bottom:0; z-index:2; margin-top:0 !important;
    padding:6px 0 2px; background:var(--bg-surface-elevated);
    border-top:1px solid var(--border-subtle); }
  /* 바텀시트(모바일)에서는 서랍 폭을 넓힐 수가 없다 — 대신 고정열을 줄여 도착지 자리를 만든다
     (2026-08-25 「공항탭 너비 조정」의 좁은 화면 몫. 시각 82px = 「09:35→09:20」이 11.5px 모노에서
     안 접히는 폭, 편명 72px = 「📡I98809화물」) */
  @media (max-width: 560px){
    .pane[data-pane="apt"] .fbrow{ font-size:var(--fs-sm); }
    .pane[data-pane="apt"] .fbrow > span{ padding-right:8px; }
    .pane[data-pane="apt"] .fbs, .pane[data-pane="apt"] .fbg{ font-size:var(--fs-sm); }
    /* 출도착 열 (2026-08-25 6.1~6.5인치 최적화): 폰 시트 폭 393이면 고정열(시각 84·편명 72·상태 72·게이트 28·
       간격 32)을 빼고 ~100px, 360이면 ~68px만 남는다. «내 공항» 쪽(.fbme — 출발 탭이면 ICN, 모듈이 표시)은
       지금 고른 공항이라 한글 괄호가 중복 정보다 → 접는다: 「ICN→HKG(홍콩)」 ≈ 95px. */
    .pane[data-pane="apt"] .fbme small{ display:none; }
  }
  /* 360px대(Galaxy S24 등)는 상대 공항 괄호까지 접어 「ICN→HKG」만 — 전체 이름은 행 title에 남는다.
     경계 380 = iPhone 15(393)는 제외 — 거기선 출도착 열이 141px(실측)라 「ICN→CXR(나트랑)」이 들어간다 */
  @media (max-width: 380px){
    .pane[data-pane="apt"] .fbod small{ display:none; }
  }
