/* 숫자·영문 대문자 전용 글꼴(8.5 KB).
   왜 있나: 이 앱은 KE1402 · 23:50 · HL8350 이 세로로 쌓이는 화면이다. 숫자 폭이 제각각이면
   시각의 콜론이 줄마다 어긋나 표가 흔들려 보인다. `font-variant-numeric: tabular-nums` 는
   **글꼴에 그 기능이 있을 때만** 듣는데, 갤럭시/아이폰 기본 한글 글꼴에 있는지 확인할 방법이 없다.
   그래서 숫자·대문자 65자만 잘라 낸 글꼴을 직접 싣는다 — tnum 포함을 확인했다.
   한글은 건드리지 않는다(한글까지 실으면 307 KB가 되는데 얻는 건 '모양이 조금 다름'뿐).
   글꼴: Pretendard v1.3.9, SIL OFL 1.1 — 사본은 /fonts/OFL.txt. */
@font-face {
  font-family: 'oneair num';
  src: url('/fonts/oneair-num.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-display: swap;
  /* 이 글자들만 이 글꼴이 맡는다. 나머지(한글)는 아래 스택의 시스템 글꼴이 그대로 그린다. */
  unicode-range: U+0030-0039, U+0041-005A, U+003A, U+002B, U+002D, U+002E, U+002F, U+2013, U+2014;
}

/* one air — 설계 10장 디자인 브리프.
   모든 수치·색은 이 토큰 블록에만 존재한다. 아래 컴포넌트 규칙에는 px·hex를 쓰지 않는다.
   축이 셋: data-theme(light/dark = 바탕색, 사용자가 고른다) · data-density(tight = 현장용 빽빽함)
   · data-preset(무엇을 보여줄지 = 데이터). 바탕색과 밀도는 서로 모른다 —
   프리셋을 바꿔도 바탕색은 그대로다.
   컴포넌트 CSS에 프리셋·테마 분기 금지 — 차이는 전부 아래 토큰으로만 낸다(설계 10.1). */

:root {
  /* ── 타이포 (10.2) ── */
  --fs-xs: 11px;
  --fs-sm: 13px;
  --fs-md: 15px;
  --fs-lg: 17px;
  --fs-xl: 22px;
  --fs-2xl: 28px;
  --lh: 1.35;
  --fw-bold: 600;
  --fw-reg: 400;

  /* ── 간격 4의 배수 (10.3) ── */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-6: 24px;
  --sp-8: 32px;

  /* ── 모서리 (10.3) — 크기마다 쓰임이 정해져 있다. 한 화면에 세 종류가 섞이면 소음이 된다. ── */
  --r-sm: 6px;        /* 상태 배지처럼 작고 촘촘한 것 */
  --r-btn: 8px;       /* 버튼·칩·입력칸 (알약 아님) */
  --r-md: 12px;       /* 카드·시트 안의 덩어리 */
  --r-lg: 16px;       /* 바텀시트 윗모서리 */
  --r-full: 999px;    /* 진짜 동그라미(점·손잡이)에만 */
  --bw: 1px;
  --bw-focus: 2px;

  /* ── 움직임 (10.4) ── */
  --t-fast: 120ms;
  --t-base: 200ms;
  --t-slow: 320ms;
  --e-in: cubic-bezier(0.2, 0.8, 0.2, 1);
  --e-out: cubic-bezier(0.4, 0, 1, 1);

  /* ── 크기 ── */
  --hit: 44px;          /* 최소 탭 영역 (10.5) — 보이는 높이가 아니라 **누를 수 있는 높이** */
  --h-chip: 32px;       /* 칩·날짜 버튼이 보이는 높이. 탭 영역은 ::after 로 44px까지 넓힌다 */
  --h-field: 40px;      /* 검색칸 */
  --hdr-h: 44px;
  --tabs-h: 56px;
  --card-h: 64px;       /* 승객 모드 (10.1) */
  /* 밀도 토큰 — 모드 차이는 전부 여기로. 컴포넌트 CSS에 모드 분기를 두지 않는다(10.1) */
  --card-pad-y: var(--sp-2);
  --card-pad-x: var(--sp-3);
  --card-radius: var(--r-md);
  --card-border-w: var(--bw);
  --list-gap: var(--sp-2);
  --fs-time: var(--fs-lg);
  --fs-fln: var(--fs-lg);
  --fs-badge: var(--fs-md);
  --badge-pad: var(--sp-1) var(--sp-2);
  --lh-sub: var(--lh);
  --l2-wrap: nowrap;   /* 보조줄은 접지 않는다 — 줄마다 높이가 달라지면 밀도가 아니라 어수선함이 된다 */
  --l2-mt: var(--sp-1);
  --l2-gap: var(--sp-3);
  --time-w: 5.4em;   /* 고정폭. '2시간 36분 전'이 잘리지 않는 폭 */
  --status-w: 5.2em;  /* 상태 배지 칸 고정폭 — 배지 길이가 달라도 칸이 흔들리지 않게 */
  /* 표는 한 편이 두 줄이다(설계 10.10): 1줄 굵게 읽는 값, 2줄 작은 회색 보조값.
     열을 5칸으로 줄여 13px를 확보했다 — 9칸을 한 줄에 우겨넣으면 11px 아래로 내려간다(애플 최소치). */
  --row-h: 30px;      /* 1줄 */
  --subrow-h: 22px;   /* 2줄 → 한 편 52px */
  --fs-2xs: 9px;      /* 표 안의 작은 **라틴/숫자** 라벨 전용 */
  /* 한글은 한 칸에 자모가 2~3개 들어가 라틴보다 최소 크기가 커야 한다.
     9px 한글('10분 후')은 뭉개진다 — 한글이 들어가는 작은 글자는 여기를 쓴다. */
  --fs-2xs-ko: 11px;
  --ls-caps: 0.04em;  /* 라틴 대문자 라벨(DATE·FLT)만. 한글 본문에는 자간을 주지 않는다 */
  --fs-tbl: 13px;     /* 표 1줄 */
  --fs-tbl-sub: 11px; /* 표 2줄 — 애플이 말하는 절대 최소치. 더 줄이지 않는다 */
  --tbl-pad-x: var(--sp-1);
  --tbl-pad-y: var(--sp-1);
  --tbl-pad-x-tight: 3px;  /* 시트 안 표(폭이 더 좁다) */
  --fs-tbl-tight: 11px;
  --c-pick: rgba(244, 143, 177, 0.22); /* 누른 편 강조(분홍) — 캡처와 같은 표시 */
  --zero: 0px;        /* JS가 실측 높이를 넣기 전 기본값 */
  --maxw: 560px;        /* 본문 최대폭 — PC에서 카드가 끝까지 늘어나지 않게 */
  --dot-d: 6px;         /* 항공사색 점 지름 — 글자 크기를 따라가지 않는다 */
  /* 시스템 글꼴 한 벌. 숫자 전용 글꼴('oneair num')을 **빼야 하는 곳**이 있어서 토큰으로 둔다 —
     로고처럼 숫자와 글자가 한 낱말인 자리에서는 둘이 섞이면 '1'만 다른 글꼴로 보인다. */
  --font-sys: system-ui, -apple-system, BlinkMacSystemFont,
    'Apple SD Gothic Neo', 'Malgun Gothic', '맑은 고딕', 'Noto Sans KR', 'Noto Sans CJK KR',
    'Nanum Gothic', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --grip-w: 36px;
  --grip-h: 4px;
  --ptr-threshold: 64px;
  --slide: 24px;       /* 탭 전환 슬라이드 거리 (10.4) */

  /* ── 색: 승객 모드 라이트 (10.1) ── */
  --c-bg: #f6f7f9;
  --c-surface: #ffffff;
  --c-surface-2: #eceef2;
  --c-line: #dfe3e9;
  --c-line-strong: #cbd1da;   /* 표 격자처럼 '있어야 보이는' 선. 카드 테두리(--c-line)보다 한 단계 진하다 */
  --c-text: #14181f;
  --c-dim: #5f6672;           /* 5.40:1 — 야외 밝기에서 작은 글자가 산다(전 4.55:1) */
  --c-accent: #1b64da;        /* 흰 카드 5.41:1 · 바탕 5.05:1 (전 #2563eb 은 4.86:1로 아슬아슬했다) */
  --c-on-accent: #ffffff;
  --c-warn: #b45309;
  --c-bad: #dc2626;
  --c-go: #047857;
  --c-boarding: #7c3aed;
  --c-al-etc: #995aa7;   /* 외항사 공통색(밝은 바탕용) — 탑승중 보라와 색조 27도·채도 절반 차이라 나란히 놓아도 갈린다 */
  --sh-card: 0 1px 2px rgba(0, 0, 0, 0.06);
  --sh-sheet: 0 -8px 24px rgba(0, 0, 0, 0.12);
}

/* 승객 모드 + 다크(시스템/수동): 현장보다 덜 차가운 계열 (10.1) */
@media (prefers-color-scheme: dark) {
  :root[data-theme='light']:not([data-force='light']) {
    --c-bg: #101318;
    --c-surface: #191d24;
    --c-surface-2: #222730;
    --c-line: #2d333d;
    --c-line-strong: #3c434e;
    --c-text: #e9ecf1;
    --c-dim: #98a0ad;
    --c-accent: #7cb2ff;
    --c-on-accent: #101318;
    --c-warn: #fbbf24;
    --c-bad: #f87171;
    --c-go: #34d399;
    --c-boarding: #a78bfa;
    --c-al-etc: #a770b3;
    --sh-card: none;
    --sh-sheet: 0 -8px 24px rgba(0, 0, 0, 0.5);
  }
}
:root[data-theme='dark'] {
    --c-bg: #101318;
  --c-surface: #191d24;
  --c-surface-2: #222730;
  --c-line: #2d333d;
  --c-line-strong: #3c434e;
  --c-text: #e9ecf1;
  --c-dim: #98a0ad;
  --c-accent: #7cb2ff;
  --c-on-accent: #101318;
  --c-warn: #fbbf24;
  --c-bad: #f87171;
  --c-go: #34d399;
  --c-boarding: #a78bfa;
  --c-al-etc: #a770b3;   /* 외항사 공통색(어두운 바탕용) */
  --sh-card: none;
  --sh-sheet: 0 -8px 24px rgba(0, 0, 0, 0.5);
}

/* 밀도(빽빽함)는 **색과 따로** 논다. 현장용 프리셋은 한 화면에 더 많이 담아야 하지만,
   바탕색은 승객이든 현장이든 같다 — 프리셋을 바꿨다고 화면이 밝았다 어두웠다 하면 안 된다.
   밝게/어둡게는 오로지 사용자가 고른다(설계 10.1 — 프리셋은 '무엇을', 밝기는 '어떻게'). */

/* 승객 밀도. 위 :root 값은 카드 말고도 상세 시트가 같이 쓰기 때문에,
   **카드만** 줄이려면 여기서 덮는다 — :root를 건드리면 시트 글자까지 같이 작아진다.
   시각 17→15 · 편명 17→15 · 상태 15→13 · 카드 키 64→56px. 표(52px)와 리듬이 맞는다. */
:root[data-density='roomy'] {
  --card-h: 56px;
  --card-pad-y: var(--sp-1);
  --fs-time: var(--fs-md);
  --fs-fln: var(--fs-md);
  --fs-badge: var(--fs-sm);
  --badge-pad: var(--sp-1) var(--sp-2);
  --l2-gap: var(--sp-2);
  --l2-mt: var(--sp-1);
  --time-w: 5em;
}

:root[data-density='tight'] {
  --card-h: 56px;
  --card-pad-y: var(--sp-1);
  --card-radius: 0;
  --card-border-w: 0 0 var(--bw);
  --list-gap: 0;
  --fs-time: var(--fs-md);
  --fs-fln: var(--fs-md);
  --fs-badge: var(--fs-xs);
  --badge-pad: 0 var(--sp-1);
  --lh-sub: 1;
  --l2-wrap: nowrap;
  --l2-mt: 0;
  --l2-gap: var(--sp-2);
  --time-w: 5em;
  --sh-card: none;
  --sh-sheet: 0 -8px 24px rgba(0, 0, 0, 0.6);
}

/* 큰 글씨: 토큰만 키운다. 관제판은 +1(밀도 유지), 승객은 +2 (10.2) */
:root[data-big='1'] {
  --fs-xs: 13px;
  --fs-sm: 15px;
  --fs-md: 17px;
  --fs-lg: 19px;
  --fs-xl: 24px;
  --fs-2xl: 30px;
  /* 표는 크기를 고정한다 — 열을 다 보여주면서 폰 폭에 들어가야 하고, 숫자 칸은 줄바꿈이 안 된다.
     큰 글씨는 카드·시트·헤더에만 적용된다(설계 확정). */
  --fs-tbl: 13px;
  --fs-2xs: 9px;
}
:root[data-big='1'][data-density='tight'] {
  --fs-xs: 12px;
  --fs-sm: 14px;
  --fs-md: 16px;
  --fs-lg: 18px;
}

/* 좁은 폰(400px 미만 — 갤럭시 다수가 360px). 표 9열이 12px로는 안 들어간다 — 표 글자만 한 단계 줄인다.
   열을 빼거나 옆으로 미는 것보다 낫다(설계 10.10). 카드 글자는 그대로다. */
/* 표 글자는 여기서 줄이지 않는다 — 1줄 5칸이면 360px에 13px로 들어간다(실측).
   글자를 줄여 칸을 늘리던 방식은 11px 아래로 내려가 읽을 수 없었다. */
:root[data-layout='narrow'] {
  --fs-2xs: 8px;
  --sp-4: 12px;
}
/* 360px에서 날짜 네 칸이 13px 넘쳤다(실측). 옆으로 스크롤은 되지만 '모레'가 반만 보이면 덜 만든 것처럼 읽힌다. */
:root[data-layout='narrow'] .date-btn { padding-inline: var(--sp-2); }
/* 좁은 폰에서는 앱 이름을 한 단계 작게 — 공항·프리셋 이름이 먼저다. */
:root[data-layout='narrow'] .brand { font-size: var(--fs-md); }

/* PC 배치 — 토큰만 바꾼다. 컴포넌트 CSS에 화면폭 분기를 두지 않는다(10.1·10.10).
   넓은 화면에서는 표를 넓게 쓰고 글자·줄높이를 키운다. 헤더 3층은 펼친 채 고정(10.11). */
:root[data-layout='desktop'] {
  --maxw: 1200px;
  --fs-tbl: 15px;
  --fs-tbl-sub: 12px;
  --tbl-pad-x: var(--sp-3);
  --tbl-pad-y: var(--sp-2);
  --row-h: 34px;
  --subrow-h: 24px;
  --card-h: 80px;
}

/* ===== 바탕 ===== */
* { box-sizing: border-box; }

/* 버튼·입력칸의 브라우저 기본 여백(1px·6px)을 지운다 — 4의 배수 리듬(10.3)에서 벗어난 유일한 값이었다.
   여백은 각 컴포넌트가 토큰으로 다시 준다. */
button, input, select, textarea { padding: 0; font: inherit; color: inherit; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  /* 한글이 시스템 기본(세리프·깨짐)으로 떨어지지 않게 폴백을 끝까지 적는다.
     갤럭시=삼성 원(system-ui) · 아이폰=Apple SD Gothic Neo · 윈도=맑은 고딕 · 그 외=Noto Sans KR. */
  font-family: 'oneair num', var(--font-sys);
  /* 한글·영문·숫자가 섞인 줄에서 높이가 튀지 않게 줄높이를 못 박는다. */
  font-synthesis: none;
  font-size: var(--fs-md);
  line-height: var(--lh);
  padding-bottom: calc(var(--tabs-h) + env(safe-area-inset-bottom));
  touch-action: manipulation; /* 300ms 탭 지연 방지 (10.5) */
  transition: background-color var(--t-base) var(--e-in), color var(--t-base) var(--e-in);
  overscroll-behavior-y: none;
}

/* 숫자는 전부 등폭 — 시각·편명·게이트가 세로로 줄 맞게 (10.2) */
body, button, input, select, textarea { font-variant-numeric: tabular-nums; }

/* 본문 최대폭: PC에서 카드가 화면 끝까지 늘어나지 않게 가운데 정렬 */
.wrap { max-width: var(--maxw); margin-inline: auto; width: 100%; }

.ic { width: 1em; height: 1em; display: inline-block; vertical-align: -0.125em; flex: none; }

/* 모든 탭 가능한 요소에 예외 없이 (10.4) */
button { font: inherit; color: inherit; transition: transform var(--t-fast) var(--e-in), background-color var(--t-fast) var(--e-in); }
button:active { transform: scale(0.98); }
button:focus-visible { outline: var(--bw-focus) solid var(--c-accent); outline-offset: var(--bw-focus); }

/* ===== 헤더 ===== */
.hdr {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--c-surface);
  border-bottom: var(--bw) solid var(--c-line);
  padding-top: env(safe-area-inset-top);
  transition: background-color var(--t-base) var(--e-in);
}
.hdr-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--hdr-h);
  padding-inline: var(--sp-4);
  flex-wrap: nowrap;
}
/* 워드마크 — 두 단어 사이에 강조색 점 하나. 점이 세 가지 일을 한다:
   단어를 가르고, 브랜드 색을 심고, 앱 아이콘의 씨앗이 된다.
   굵기 대비나 밑줄로 가르는 안을 제친 이유: 좁은 폰에서 15px로 줄면 굵기 차이는 뭉개지지만
   점은 벡터 원이라 안 뭉개진다. 자간 -0.02em 은 라틴 소문자 워드마크라 준다(한글 아님). */
/* 워드마크 1air●live — 가운데 점이 **생방송 점**이다. 켜져 있는 동안 천천히 숨을 쉰다:
   "지금 뜨고 있는 걸 지금 보여 준다"가 이 앱의 전부라, 이름 한가운데에 그걸 박았다.
   점은 앱 아이콘의 그 점과 같은 색·같은 뜻이고, 굵기 대비나 밑줄로 가르는 안을 제친 이유는
   좁은 폰에서 글자가 줄면 굵기 차이는 뭉개져도 점은 안 뭉개지기 때문이다.
   'live'만 강조색으로 두어 눈이 먼저 가게 한다. 움직임 줄이기 설정에서는 전역 규칙이 멈춘다(10.4). */
.brand {
  display: inline-flex;
  align-items: baseline;
  /* 로고는 '1'과 'airlive'가 한 낱말이다 — 숫자 전용 글꼴을 빼서 한 벌로 그린다.
     등폭 숫자도 끈다: 표에서는 자릿수가 맞아야 하지만 로고에서는 '1' 옆이 휑해 보인다. */
  font-family: var(--font-sys);
  font-variant-numeric: normal;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.brand em { font-style: normal; color: var(--c-accent); }
.brand i {
  align-self: center;
  width: 0.3em;
  height: 0.3em;
  margin: 0 0.26em;
  border-radius: var(--r-full);
  background: var(--c-accent);
  flex: none;
  animation: live-pulse 2.6s var(--e-in) infinite;
}
@keyframes live-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.82); }
}
.spacer { flex: 1; }

/* 칩은 테두리를 두르지 않는다 — 한 화면에 테두리가 열 개면 그게 소음이다.
   안 고른 것은 옅은 바탕, 고른 것은 강조색으로 **채운다**(설계 10.1 — 위계는 굵기→크기→색 순). */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  position: relative;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  min-height: var(--h-chip);
  justify-content: center;
  white-space: nowrap;
  padding-inline: var(--sp-3);
  border: 0;
  border-radius: var(--r-btn);
  background: var(--c-surface-2);
  color: var(--c-text);
}
/* 보이는 높이는 32px, 누를 수 있는 높이는 44px — 손가락은 눈보다 굵다(10.5).
   보이는 칩을 44px로 키우면 헤더가 화면의 3분의 1을 먹는다. 그래서 **넓히는 건 손가락 쪽만** 한다:
   보이지 않는 영역을 위아래로 덧대고, 옆 칩을 덮지 않게 뒤로 보낸다. */
.chip, .date-btn, .al-chip { position: relative; }
.chip::after, .date-btn::after, .al-chip::after {
  content: '';
  position: absolute;
  inset: calc((var(--h-chip) - var(--hit)) / 2) 0;
  z-index: -1;
}
.chip[aria-pressed='true'], .chip.on { background: var(--c-accent); color: var(--c-on-accent); }
/* 프리셋 이름이 길면(케이터링 · 정비) 헤더 한 줄을 넘긴다 → 칩 안에서 말줄임 */
.chip .lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#airportChip, #btnPreset { min-width: 0; flex-shrink: 1; }
#btnPreset { max-width: 34vw; }
#airportChip { max-width: 26vw; }
.brand { flex: none; }
.chip:active, .icon-btn:active { background: var(--c-surface-2); }
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-lg);
  min-width: var(--hit);
  min-height: var(--hit);
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
}
.chip:disabled, .icon-btn:disabled { opacity: 0.4; }

/* ===== 요약 띠 ===== */
.summary-bar { background: var(--c-surface); border-bottom: var(--bw) solid var(--c-line); }
.summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--c-dim);
}
.summary .age { margin-left: auto; white-space: nowrap; }
.summary .age.stale { color: var(--c-warn); }

/* 오류 띠 — 전체 화면 에러 페이지 금지 (10.6) */
.errbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--c-warn);
  background: var(--c-surface-2);
  border-bottom: var(--bw) solid var(--c-line);
}
.errbar button {
  margin-left: auto;
  min-height: var(--hit);
  padding-inline: var(--sp-3);
  border: var(--bw) solid var(--c-warn);
  border-radius: var(--r-btn);
  background: transparent;
  color: var(--c-warn);
  font-size: var(--fs-xs);
}

/* ===== 날짜 세그먼트 ===== */
.dates-bar { background: var(--c-surface); border-bottom: var(--bw) solid var(--c-line); }
.dates {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  padding: var(--sp-2) var(--sp-4);
  scrollbar-width: none;
}
.dates::-webkit-scrollbar { display: none; }
.date-btn {
  white-space: nowrap;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  min-height: var(--h-chip);
  padding-inline: var(--sp-3);
  border: 0;
  border-radius: var(--r-btn);
  background: transparent;
  color: var(--c-dim);
}
.date-btn[aria-current='true'] {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-on-accent);
  font-weight: var(--fw-bold);
}

/* ===== 당겨서 새로고침 (10.5) ===== */
.ptr {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: var(--ptr-threshold);
  margin-top: calc(var(--ptr-threshold) * -1);
  font-size: var(--fs-xs);
  color: var(--c-dim);
  transition: transform var(--t-base) var(--e-in);
}
.ptr.dragging { transition: none; }
.ptr .ic { transition: transform var(--t-base) var(--e-in); }
.ptr.ready .ic { transform: rotate(180deg); }
.ptr.spinning .ic { animation: spin 900ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ===== 목록 ===== */
/* 좌우 여백 없음 — 목록이 화면 끝까지 간다(설계 확정). 위아래 숨만 남긴다. */
.body { padding: var(--sp-1) 0 var(--sp-8); display: grid; gap: var(--list-gap); }
.body.switching { opacity: 0; transform: translateX(var(--slide)); }
.body {
  transition: opacity var(--t-base) var(--e-in), transform var(--t-base) var(--e-in);
}

/* ===== 편 카드 (템플릿 한 벌) ===== */
.card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--sp-3);
  align-items: center;
  width: 100%;
  min-height: var(--card-h);
  text-align: left;
  position: relative;
  background: var(--c-surface);
  border: 0;
  border-radius: 0;   /* 목록이 화면 끝까지 간다 — 모서리를 둥글리면 잘린 것처럼 보인다 */
  padding: var(--card-pad-y) var(--card-pad-x);
}
/* 줄을 가르는 선은 **양옆에서 들여쓴다**. 끝까지 긋는 선은 화면을 층층이 잘라 답답해 보인다.
   테두리로 사방을 두르는 대신 이 선 하나만 쓴다(그림자도 없앴다 — 목록 항목은 떠 있지 않다). */
.card::after {
  content: '';
  position: absolute;
  left: var(--card-pad-x);
  right: var(--card-pad-x);
  bottom: 0;
  height: var(--bw);
  background: var(--c-line);
}
.card:last-child::after { display: none; }
.card:active { background: var(--c-surface-2); }
/* 지난 편도 또렷하게 둔다 — 흐리면 현장에서 못 읽는다(설계 확정). 시간 글자만 한 톤 낮춘다. */
.card.is-past .t-main { color: var(--c-dim); }
/* 지금 시각에 가까운 편은 왼쪽 띠로 표시한다 — 테두리를 두르면 옆 줄과 어긋나 보인다. */
.card.is-near { box-shadow: inset var(--bw-focus) 0 0 0 var(--c-accent); }
.card.is-changed { animation: flash 600ms var(--e-in); }
@keyframes flash {
  0%, 60% { background: color-mix(in srgb, var(--c-accent) 8%, var(--c-surface)); }
  100% { background: var(--c-surface); }
}

.c-time {
  text-align: center;
  /* 고정폭이어야 카드마다 편명이 같은 자리에서 시작한다.
     '1시간 23분 후' 같은 긴 글자 때문에 폭이 늘면 줄이 통째로 밀린다(실측 7px). */
  width: var(--time-w);
  flex: none;
}
.t-main { display: block; font-size: var(--fs-time); font-weight: var(--fw-bold); }
/* 바뀐 시각과 '몇 분 후'는 **한 줄에** 둔다 — 줄을 하나 더 쓰면 그 카드만 키가 커진다.
   모든 카드의 높이가 같아야 목록이 오밀조밀해 보인다. */
.t-sub {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: var(--sp-1);
  min-width: 0;
  line-height: var(--lh-sub);
}
.t-old { font-size: var(--fs-2xs); color: var(--c-dim); text-decoration: line-through; flex: none; }
.t-rel {
  display: inline-block;
  font-size: var(--fs-2xs-ko);
  color: var(--c-dim);
  font-style: normal;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.c-main { min-width: 0; }
.c-l1 { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: nowrap; min-width: 0; }
.c-l1 .al { overflow: hidden; text-overflow: ellipsis; }
.fln { font-size: var(--fs-fln); font-weight: var(--fw-bold); white-space: nowrap; }
/* 항공사명은 잘리지 않는다 — 자리가 없으면 편명 아래로 내려간다("아시아…"는 못 읽는다). */
.al { font-size: var(--fs-sm); font-weight: var(--fw-reg); color: var(--c-dim); white-space: nowrap; }
.c-l2 {
  display: flex;
  gap: var(--l2-gap);
  flex-wrap: var(--l2-wrap);
  margin-top: var(--l2-mt);
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-reg);
  color: var(--c-dim);
  /* 한 줄 고정. 앞의 값은 온전히 두고 **넘치는 꼬리만** 잘린다 —
     칸마다 …으로 접으면 '공동… ← … 게…' 처럼 전부 못 읽게 된다.
     모든 줄의 높이가 같아야 목록이 '오밀조밀'해 보인다(밀집 목록의 1차 원칙).
     잘린 자리는 오른쪽 끝을 흐려 알린다 — 자세한 값은 눌러서 보는 상세에 다 있다. */
  overflow: hidden;
  mask-image: linear-gradient(to right, #000 calc(100% - var(--sp-4)), transparent); /* 예외: 마스크는 색이 아니라 투명도만 쓴다 */
}
.c-l2 > * { flex: none; }
/* 카드 안 뱃지(선행편 지연)는 자리가 없으면 두 줄로 접는다.
   한 줄을 고집하면 테두리가 카드 밖으로 삐져나가 잘린 것처럼 보인다(실기 확인). */
/* 보조줄 안의 배지(선행편 지연)는 세로 패딩을 빼서 줄 키를 늘리지 않는다 —
   이 배지가 붙은 편만 카드가 7px 높아져 목록이 들쭉날쭉했다(실측). */
.c-l2 .badge { white-space: nowrap; padding-block: 0; }
.bit { white-space: nowrap; }
.bit i { font-style: normal; opacity: 0.75; margin-right: var(--sp-1); }
.bit b { font-weight: var(--fw-bold); color: var(--c-text); }
.bit.strong b { font-size: var(--fs-md); }
.route u { text-decoration: none; opacity: 0.7; }

/* 상태 칸은 **고정폭 + 오른쪽 정렬**. 내용 폭에 맡기면 '착륙'과 '탑승구 변경'의 길이 차이만큼
   칸의 시작점이 줄마다 흔들린다(실측 49px) — 세로로 훑을 때 그게 제일 어수선하다. */
.c-status { display: flex; align-items: center; justify-content: flex-end; width: var(--status-w); flex: none; }
/* 배지는 테두리 대신 **제 색을 옅게 깔아** 구분한다. 테두리를 두르면 카드 안에 상자가 또 생긴다.
   글자는 진한 원색, 바탕은 같은 색 12% — 색맹이어도 글자를 읽으면 되고, 대비는 글자로 지킨다. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-badge);
  font-weight: var(--fw-bold);
  white-space: nowrap;
  padding: var(--badge-pad);
  border-radius: var(--r-sm);
  border: 0;
  background: color-mix(in srgb, currentColor 12%, transparent);
  color: var(--c-dim);
}
.badge.tone-go { color: var(--c-go); }
.badge.tone-warn { color: var(--c-warn); }
.badge.tone-bad { color: var(--c-bad); }
.badge.tone-board { color: var(--c-boarding); }
.badge.tone-done { color: var(--c-dim); }
.badge.tone-plain { color: var(--c-dim); background: var(--c-surface-2); }


/* ===== 상태 화면 (10.6) ===== */
.skel { display: grid; gap: var(--sp-2); padding: var(--sp-2) var(--sp-4); }
.skel-row {
  height: var(--card-h);
  border-radius: var(--r-md);
  background: linear-gradient(90deg, var(--c-surface) 25%, var(--c-surface-2) 50%, var(--c-surface) 75%);
  background-size: 400% 100%;
  animation: shimmer 1400ms linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }
.skel-note { text-align: center; font-size: var(--fs-sm); color: var(--c-dim); padding-top: var(--sp-2); }

/* 검색: 지금 목록 밖에서 찾은 편 (설계 3.4 · /api/search).
   지금 화면 결과가 먼저, 그 아래 다른 공항·날짜·구분. 색·크기는 토큰만 쓴다. */
.more { margin-top: var(--sp-6); }
.more-h {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  color: var(--c-dim);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.more-h::after { content: ''; flex: 1; height: var(--bw); background: var(--c-line); }
.more-h em { font-style: normal; color: var(--c-accent); }
.more-note { margin: 0; padding: var(--sp-3) 0; font-size: var(--fs-sm); color: var(--c-dim); }
.more-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.more-row {
  width: 100%;
  min-height: var(--hit);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-surface);
  color: var(--c-text);
  font-size: var(--fs-sm);
  text-align: left;
}
.more-row:active { background: var(--c-surface-2); }
.more-ap {
  flex: none;
  min-width: 3.4em;
  font-size: var(--fs-xs);
  color: var(--c-on-accent);
  background: var(--c-accent);
  border-radius: var(--r-btn);
  padding: var(--sp-1) var(--sp-2);
  text-align: center;
}
.more-mid { min-width: 0; display: flex; align-items: baseline; gap: var(--sp-2); flex: 1; }
.more-fln { font-variant-numeric: tabular-nums; }
.more-rt { color: var(--c-dim); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.more-t { flex: none; font-variant-numeric: tabular-nums; }
.more-d { flex: none; font-size: var(--fs-xs); color: var(--c-dim); }
.more-row .badge { flex: none; }

/* 보기 설정 — 밝기 세그먼트 · 큰 글씨 스위치 (설계 3.8) */
.setrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--hit);
  font-size: var(--fs-sm);
}
.seg { display: inline-flex; border: var(--bw) solid var(--c-line); border-radius: var(--r-btn); overflow: hidden; }
.seg-btn {
  min-height: var(--hit);
  padding-inline: var(--sp-3);
  border: 0;
  background: var(--c-surface);
  color: var(--c-dim);
  font-size: var(--fs-xs);
}
.seg-btn.on { background: var(--c-accent); color: var(--c-on-accent); font-weight: var(--fw-bold); }
.seg-btn[disabled] { opacity: 0.45; }
.sw {
  width: calc(var(--hit) + var(--sp-2));
  height: var(--sp-6);
  flex: none;
  padding: 0 var(--sp-1);
  display: flex;
  align-items: center;
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-surface-2);
  transition: background-color var(--t-fast) var(--e-in);
}
.sw .sw-knob {
  width: var(--sp-4);
  height: var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-dim);
  transition: transform var(--t-fast) var(--e-in), background-color var(--t-fast) var(--e-in);
}
.sw.on { background: var(--c-accent); border-color: var(--c-accent); }
.sw.on .sw-knob { transform: translateX(var(--sp-6)); background: var(--c-on-accent); }

/* 온보딩 2단계 — 첫 실행에만 한 번 (설계 7장 M6) */
.onb {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: var(--sp-4);
  background: var(--c-bg);
  overflow: auto;
}
.onb-card {
  width: 100%;
  max-width: var(--maxw);
  display: grid;
  gap: var(--sp-4);
}
.onb-head { display: grid; gap: var(--sp-1); }
.onb-step { font-size: var(--fs-xs); color: var(--c-accent); font-weight: var(--fw-bold); }
.onb-head h2 { margin: 0; font-size: var(--fs-xl); }
.onb-head p { margin: 0; font-size: var(--fs-sm); color: var(--c-dim); }
.onb-list { max-height: 56vh; overflow: auto; -webkit-overflow-scrolling: touch; }
.onb-acts { display: flex; gap: var(--sp-2); align-items: center; }
.onb-skip {
  min-height: var(--hit);
  padding-inline: var(--sp-4);
  border: 0;
  background: none;
  color: var(--c-dim);
  font-size: var(--fs-sm);
}
.onb-next {
  margin-left: auto;
  min-height: var(--hit);
  padding-inline: var(--sp-6);
  border: 0;
  border-radius: var(--r-btn);
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
}

/* 공동운항 줄 — 승객 모드는 접어 두고, 찍고 들어온 편명만 강조 */
.cs-more {
  min-height: var(--hit);
  padding: 0 var(--sp-2);
  border: 0;
  background: none;
  color: var(--c-accent);
  font-size: var(--fs-sm);
}
.cs-hit { color: var(--c-accent); text-decoration: underline; }
.more-op { font-size: var(--fs-xs); color: var(--c-dim); white-space: nowrap; }

/* 항공사 필터 첫 줄 — 왼쪽 '전체', 둘째 줄 왼쪽 '공동운항' */

.empty {
  display: grid;
  justify-items: center;
  gap: var(--sp-3);
  padding: var(--sp-8) var(--sp-4);
  text-align: center;
  color: var(--c-dim);
  font-size: var(--fs-sm);
}
.empty .ic { font-size: var(--fs-2xl); opacity: 0.5; }
.empty button {
  min-height: var(--hit);
  padding-inline: var(--sp-4);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-surface);
  color: var(--c-accent);
  font-size: var(--fs-sm);
}

/* ===== 하단 탭 ===== */
.tabs-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  background: var(--c-surface);
  border-top: var(--bw) solid var(--c-line);
  padding-bottom: env(safe-area-inset-bottom);
  transition: background-color var(--t-base) var(--e-in);
}
.tabs { display: flex; }
.tab-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  font-size: var(--fs-xs);
  min-height: var(--tabs-h);
  border: 0;
  background: transparent;
  color: var(--c-dim);
}
.tab-btn .ic { font-size: var(--fs-lg); }
.tab-btn[aria-current='true'] { color: var(--c-accent); font-weight: var(--fw-bold); }

/* ===== 바텀시트 (10.5) ===== */
body.sheet-open { overflow: hidden; }
.sheet-host { position: fixed; inset: 0; z-index: 10; }
.sheet-dim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  transition: opacity var(--t-slow) var(--e-in);
}
.sheet-host.in .sheet-dim { opacity: 1; }
.sheet {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 100%;
  max-width: var(--maxw);
  transform: translate(-50%, 100%);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  border-top-left-radius: var(--r-lg);
  border-top-right-radius: var(--r-lg);
  box-shadow: var(--sh-sheet);
  padding-bottom: env(safe-area-inset-bottom);
  transition: transform var(--t-slow) var(--e-in);
  will-change: transform;
}
.sheet-host.in .sheet { transform: translate(-50%, 0); }
.sheet.dragging { transition: none; }
.sheet-grip-zone {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--hit);
  border: 0;
  background: transparent;
  width: 100%;
  touch-action: none;
}
.sheet-grip { display: block; width: var(--grip-w); height: var(--grip-h); border-radius: var(--r-full); background: var(--c-line); }
.sheet-head { padding: 0 var(--sp-4) var(--sp-2); }
.sheet-title { margin: 0; font-size: var(--fs-md); font-weight: var(--fw-bold); }
.sheet-body {
  overflow-y: auto;
  overscroll-behavior: contain; /* iOS 사파리 바운스 충돌 방지 (10.5) */
  padding: 0 var(--sp-3) var(--sp-6);
  -webkit-overflow-scrolling: touch;
}
.sheet-note { margin: 0 var(--sp-1) var(--sp-2); font-size: var(--fs-xs); color: var(--c-dim); }

.pick { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.pick-row {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
  text-align: left;
  min-height: var(--hit);
  padding: var(--sp-3);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-bg);
  color: var(--c-text);
}
.pick-row:active { background: var(--c-surface-2); }
.pick-row.on { border-color: var(--c-accent); color: var(--c-accent); font-weight: var(--fw-bold); }
.pick-main { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.pick-main u { text-decoration: none; color: var(--c-dim); font-size: var(--fs-xs); }
.pick-sub { color: var(--c-dim); font-size: var(--fs-xs); white-space: nowrap; }
.pick-desc { display: block; color: var(--c-dim); font-weight: var(--fw-reg); font-size: var(--fs-xs); }
.dot { width: var(--dot-d); height: var(--dot-d); border-radius: var(--r-full); background: currentColor; flex: none; }

/* ── 항공사색 ──
   국내 항공사는 각자 브랜드색, 외항사는 100곳이 넘어 색이 서로 뭉개지므로 전부 한 색(--c-al-etc).
   JS가 줄·카드·칩에 --al-d(어두운 바탕용)/--al-l(밝은 바탕용) 두 칸을 얹고, 고르는 일은 여기서 한다 —
   한 색으로 두 바탕에서 다 읽히는 값은 없다(한 색의 최대 대비 4.21:1).
   색을 안 얹은 항공사는 var()의 기본값이 받아 자동으로 보라가 된다. */
.fln-c, .dot { color: var(--al-l, var(--c-al-etc)); }
.sheet-clear {
  width: 100%;
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  min-height: var(--hit);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--c-dim);
}

/* ===== 움직임 줄이기 (10.4) ===== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity !important;
    transition-duration: var(--t-fast) !important;
  }
  button:active { transform: none; }
  .body.switching { transform: none; }
}


/* 건너뛰기 링크 — 평소엔 화면 밖에 있다가 탭으로 오면 나타난다.
   display:none 으로 숨기면 키보드로도 못 닿는다(그러면 있으나 마나다). */
.skip {
  position: absolute;
  left: var(--sp-3);
  top: calc(var(--sp-3) * -6);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  min-height: var(--hit);
  padding: 0 var(--sp-3);
  border-radius: var(--r-btn);
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  text-decoration: none;
  transition: top var(--t-fast) var(--e-in);
}
.skip:focus { top: var(--sp-3); }

/* ===== 헤더 3층 (10.11) ===== */
/* 헤더는 네 층이지만 **한 덩어리로 보여야 한다** — 층마다 선을 그으면 화면이 넷으로 잘린다.
   층 사이는 여백으로만 나눈다(설계 10.1 — 선 대신 여백). */
.hdr-1 {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--hdr-h);
  padding: 0 var(--sp-3);
  flex-wrap: nowrap;
}
/* 견본과 같게 — 돋보기·입력칸·지우기가 테두리 하나 안에 든 한 덩어리 */
.search-box {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--h-field);
  padding-inline: var(--sp-3);
  border: 0;
  border-radius: var(--r-btn);
  background: var(--c-surface-2);
}
/* 눌렀을 때만 테두리가 나타난다 — 평소엔 바탕색만으로 '여기 쓸 수 있다'가 읽힌다 */
.search-box:focus-within { box-shadow: inset 0 0 0 var(--bw-focus) var(--c-accent); }
.search-box input {
  flex: 1;
  min-width: 0;
  min-height: var(--h-field);
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--c-text);
  background: none;
  border: 0;
  outline: none;
}
.search-box input::placeholder { color: var(--c-dim); }
.search-ic { display: inline-flex; color: var(--c-dim); font-size: var(--fs-md); flex: none; }
/* 지우기 단추: 보이는 크기는 24px(검색칸 안에서 튀지 않게)지만, **누를 수 있는 넓이는 44px**로 덧댄다.
   보이는 대로만 두면 손가락으로는 못 누른다(10.5). */
.search-box .icon-btn {
  position: relative;
  min-width: var(--sp-6);
  min-height: var(--sp-6);
  font-size: var(--fs-md);
  flex: none;
}
.search-box .icon-btn::after {
  content: '';
  position: absolute;
  inset: calc((var(--sp-6) - var(--hit)) / 2);
  z-index: -1;
}

/* 3층: 날짜 */
.hdr-3 > .wrap { padding: var(--sp-2) var(--sp-4); }
.algroup { display: grid; gap: var(--sp-1); margin-bottom: var(--sp-2); }
.algroup:last-of-type { margin-bottom: 0; }
.algroup > b {
  font-size: var(--fs-xs);
  font-weight: var(--fw-reg);
  color: var(--c-dim);
}
.al-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  white-space: nowrap;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  min-height: var(--h-chip);
  padding-inline: var(--sp-2);
  border: 0;
  border-radius: var(--r-btn);
  background: var(--c-surface-2);
  color: var(--c-text);
}
.al-chip.on { background: var(--c-accent); color: var(--c-on-accent); }
/* '전체'·'공동운항'은 글자만 있는 단추다 — 가운데로 모아야 두 개가 세로로 줄이 맞는다. */
.al-chip.wide { justify-content: center; text-align: center; }
.al-chip.on .dot, .al-chip.on .al-count { color: inherit; }
.al-chip .dot { width: var(--dot-d); height: var(--dot-d); }
.al-count { color: var(--c-dim); font-size: var(--fs-2xs); font-weight: var(--fw-reg); }

/* 스크롤 내리면 1층만 남긴다 */

/* 접힐 때 배경색이 튀지 않게 — 높이 변화는 어쩔 수 없지만 색은 부드럽게 */
.hdr { transition: background-color var(--t-base) var(--e-in); }

/* 헤더 2·3·4층 — 늘 펼쳐 둔다(접기 없음). */
.hdr-2, .hdr-3, .hdr-4 { padding: 0 var(--sp-3) var(--sp-2); }

/* 3층 날짜 — 가운데 정렬, 넘치면 옆으로 */
.hdr-3.dates {
  display: flex;
  justify-content: safe center;
  gap: var(--sp-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.hdr-3.dates::-webkit-scrollbar { display: none; }

/* 4층 항공사 필터 — **두 줄 고정**, 옆으로 스크롤. 접지 않는다.
   칩을 **열 방향으로** 흘려 넣는다: 한 열에 두 개씩 쌓이고 오른쪽으로 이어진다.
   이 방식이라야 두 줄을 통째로 차지하는 칸(왼쪽 고정 단추 · 국/외 이름표)을 끼울 수 있다. */
.alscroll {
  display: grid;
  grid-template-rows: auto auto;
  grid-auto-flow: column;
  grid-auto-columns: max-content;
  align-items: center;
  gap: var(--sp-1);
  overflow-x: auto;
  scrollbar-width: none;
  mask-image: linear-gradient(to right, #000 calc(100% - var(--sp-6)), transparent); /* 예외: 마스크는 색이 아니라 투명도만 쓴다 — #000은 '가리지 않음'을 뜻한다 */
}
.alscroll::-webkit-scrollbar { display: none; }

/* '전체'·'공동운항'은 항공사가 아니라 **무엇을 셀지 정하는 단추**다.
   예전엔 각 줄 맨 앞에 하나씩 있어서 옆 칩들이 그 단추에 딸린 것처럼 읽혔다.
   둘을 한 덩어리로 묶어 왼쪽에 붙여 두고, 오른쪽에 선을 그어 항공사와 갈라 놓는다. */
.alfix {
  grid-row: 1 / 3;
  position: sticky;
  left: 0;
  z-index: 1;
  display: grid;
  gap: var(--sp-1);
  padding-right: var(--sp-2);
  margin-right: var(--sp-1);
  border-right: var(--bw) solid var(--c-line);
  background: var(--c-surface);
}

/* 한국/외국 이름표 — 두 줄을 통째로 세로로 가로지르는 좁은 띠.
   **글자를 세로로 세운다**: 가로로 쓰면 두 글자가 칩 하나 폭을 먹어 항공사가 그만큼 밀려난다.
   칩처럼 보이면 눌러야 하는 것으로 오해하므로 바탕은 깔지 않고, 왼쪽 세로선으로만 경계를 낸다. */
.algrp {
  grid-row: 1 / 3;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 세로쓰기. 한글은 세로로 세워도 글자가 눕지 않는다(upright). */
  writing-mode: vertical-rl;
  text-orientation: upright;
  padding-block: var(--sp-1);
  padding-inline: var(--sp-1);
  margin-left: var(--sp-2);
  border-left: var(--bw) solid var(--c-line);
  color: var(--c-dim);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;   /* 세로로 세우면 글자가 붙어 보인다 */
  white-space: nowrap;
}
/* 맨 앞 이름표는 왼쪽 선이 .alfix 의 오른쪽 선과 겹친다 — 하나만 남긴다. */
.alfix + .algrp { border-left: 0; margin-left: 0; }

/* ===== 요약 칩 = 목록 첫 줄 sticky ===== */
.listbar {
  position: sticky;
  top: var(--hdr-1-h, var(--hdr-h));
  z-index: 2;
  background: var(--c-bg);
  border-bottom: var(--bw) solid var(--c-line);
}
.sumchips {
  display: flex;
  align-items: center;
  justify-content: safe center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-2);
  overflow-x: auto;
  scrollbar-width: none;
  font-size: var(--fs-xs);
  color: var(--c-dim);
  /* 옆으로 더 있다는 것을 오른쪽 끝을 흐려 보여준다 — 잘린 것처럼 보이지 않게. */
  mask-image: linear-gradient(to right, #000 calc(100% - var(--sp-6)), transparent); /* 예외: 마스크는 색이 아니라 투명도만 쓴다 — #000은 '가리지 않음'을 뜻한다 */
}
.sumchips::-webkit-scrollbar { display: none; }
/* 지금 보는 구분 — 견본처럼 요약 줄 맨 앞에 크게. 목록 바로 위에서 "무엇을 보고 있나"를 말해 준다. */
.sumtitle {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--c-text);
  white-space: nowrap;
  padding-inline: var(--sp-1);
  flex: none;
}

/* 요약 숫자는 상자에 담지 않는다 — 라벨은 옅게, 숫자만 진하게. 굵기로 위계를 만든다. */
.sumchip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  white-space: nowrap;
  padding: 0 var(--sp-1);
}
.sumchip b { color: var(--c-text); font-weight: var(--fw-bold); }
.sumchip.warn b { color: var(--c-warn); }
.sumchip.bad b { color: var(--c-bad); }
.sumchip.age { margin-left: auto; }
.sumchip.age.stale { color: var(--c-warn); }

/* ===== 표 형식 (10.10) — 진짜 <table>. 열 폭이 내용 기준으로 자동 정렬된다 ===== */
/* 좌우 여백을 준다 — 화면 양끝에 딱 붙으면 머리글이 잘린 것처럼 읽힌다. */
.tbl {
  margin-inline: var(--sp-3);
  width: calc(100% - var(--sp-3) * 2);
  border-collapse: collapse;
  table-layout: auto;         /* 열 폭을 내용이 정한다 */
  font-size: var(--fs-tbl);
  font-variant-numeric: tabular-nums;
}
.tbl th, .tbl td {
  padding: var(--tbl-pad-y) var(--tbl-pad-x);
  text-align: center;   /* 시안과 같게 — 칸마다 가운데. 숫자가 등폭이라 세로로 줄이 맞는다 */
  white-space: nowrap;        /* 숫자·코드는 줄바꿈 금지 — 세로로 줄이 맞아야 읽힌다 */
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 상태만은 말이 길어질 수 있다('탑승구 변경'·'출발지연'). 그 한 칸 때문에 표가 옆으로 넘치면
   가로 스크롤이 생긴다 — 설계 10.10은 그걸 금지한다. 넘치느니 그 줄만 두 줄로 접는다.
   word-break: keep-all → 한글은 낱말 단위로만 끊는다('탑승구 변/경'이 되지 않게). */
.tbl td.st { white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
.tbl th { white-space: nowrap; }   /* 머리글은 짧다 — 접으면 'P-DLY'가 'P-'/'DLY'로 쪼개진다 */
/* 글자 칸(앞뒤 편·지상시간·도시명)은 자리가 없으면 접는다. 숫자·코드 칸만 한 줄을 지킨다. */
.tbl td.dim { white-space: normal; word-break: keep-all; }
/* 두 줄 칸 — 위에 본값, 아래 작은 글씨(기번 아래 기종). 열을 하나 더 만들면 폰 폭을 넘는다. */
/* 한글이 두 줄로 접히면 1.15에서는 윗줄 받침과 아랫줄 초성이 닿는다. */
.tbl td.two { line-height: 1.25; }
.tbl td.two .sub { display: block; font-style: normal; font-size: var(--fs-2xs); color: var(--c-dim); }
.tbl td.two .sub.solo { font-size: var(--fs-tbl); }   /* 윗줄이 비면 그 값이 본값이다 */
/* 같은 줄 옆에 붙는 작은 값(+4). 아랫줄로 내리면 그 편만 키가 커져 줄이 들쭉날쭉해진다. */
.tail { font-style: normal; font-size: var(--fs-2xs); font-weight: var(--fw-reg); color: var(--c-dim); margin-left: 0.2em; }
/* 머리글은 테두리로 감싼 한 덩어리 — 견본과 같게. 양 끝만 둥글린다. */
/* 머리글은 상자가 아니라 **라벨**이다. 테두리를 두르지 않고, 라틴 대문자라 자간을 벌려
   작게 써도 또렷하게 만든다(한글에는 자간을 주지 않는다 — DATE·FLT는 전부 라틴이다). */
.tbl thead th {
  position: sticky;
  top: calc(var(--hdr-1-h, var(--hdr-h)) + var(--listbar-h, var(--zero)));
  z-index: 1;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  color: var(--c-dim);
  background: var(--c-surface-2);
  border-bottom: var(--bw) solid var(--c-line-strong);
  padding-block: var(--sp-1);
}
/* 좌우 여백이 생겼으니 머리글 덩어리의 모서리가 실제로 보인다. */
.tbl thead th:first-child { border-start-start-radius: var(--r-btn); }
.tbl thead th:last-child { border-start-end-radius: var(--r-btn); }
/* 세로 격자선을 없앴다 — 숫자가 등폭이라 선 없이도 세로로 줄이 맞는다.
   선을 다 그으면 표가 아니라 모눈종이가 된다(밀집 표의 1차 원칙: 선 대신 여백). */
.tbl tbody tr { background: var(--c-surface); }
.tbl tbody .tsub { border-bottom: var(--bw) solid var(--c-line); }
/* 보조줄이 없는 편(값이 하나도 없을 때)은 1줄이 마지막이니 거기에 선을 긋는다. */
.tbl tbody .trow:not(:has(+ .tsub)) { border-bottom: var(--bw) solid var(--c-line); }
.tbl tbody tr:active { background: var(--c-surface-2); }
.tsub.is-past > td { color: var(--c-dim); }
/* 한 편 = 두 줄(설계 10.10). 1줄은 굵게 읽는 값, 2줄은 작은 회색 보조값.
   모든 편의 키가 같아야 스크롤할 때 줄이 안 튄다 — <tr>에는 min-height가 안 먹어서 칸(td)에 건다.
   가르는 선은 **2줄 아래에만** 긋는다. 1줄 아래에 그으면 한 편이 두 편으로 보인다. */
.tbl tbody .trow > td { height: var(--row-h); font-weight: var(--fw-bold); }
.tbl tbody .tsub > td { height: var(--subrow-h); padding-top: 0; }
.trow, .tsub { cursor: pointer; }

/* 2줄: 한 줄 고정. 넘치면 꼬리만 흐리게 — 자세한 값은 눌러서 보는 상세에 다 있다.
   ★ 2줄 내용을 칸 안에 그냥 넣으면 **그 칸이 "이만큼 필요하다"고 주장해 표 전체가 넓어진다**
     (실측: 336px 표가 391px이 되어 화면이 옆으로 밀렸다). overflow:hidden 으로는 안 막힌다.
     그래서 내용을 **자리를 차지하지 않는 층(absolute)** 으로 띄운다 — 칸은 빈 칸으로 남고
     열 너비는 1줄이 정한 그대로다. */
.tsub > td {
  position: relative;
  padding-inline: 0;
}
.subline {
  position: absolute;
  inset: 0 var(--sp-3);
  display: flex;
  align-items: center;
  /* safe center — 들어가면 가운데, 넘치면 **왼쪽부터** 보여 준다.
     그냥 center 로 두면 넘칠 때 앞쪽도 같이 잘려 시각의 첫 자리가 사라진다(08:00 → 8:00). */
  justify-content: safe center;
  font-size: var(--fs-tbl-sub);
  font-weight: var(--fw-reg);
  color: var(--c-dim);
  white-space: nowrap;
  overflow: hidden;
  mask-image: linear-gradient(to right, #000 calc(100% - var(--sp-4)), transparent); /* 예외: 마스크는 색이 아니라 투명도만 쓴다 */
}
/* 보조값 한 덩어리. 덩어리 사이는 가운뎃점 대신 여백으로 나눈다(선 대신 여백). */
.sg { display: inline-flex; align-items: baseline; gap: var(--sp-1); margin-inline: var(--sp-2); }

/* 화살표 — 꼬리를 뗀 홑화살괄호(›‹). 꼬리 있는 →는 글자 사이에 누우면 줄이 어지러워 보이고,
   작은 글씨에서 꼬리가 먼저 뭉개진다. 획이 하나뿐이라 11px에서도 또렷하다.
   글자보다 한 단계 키워 방향이 먼저 읽히게 하고, 색은 한 톤 낮춰 값보다 앞서지 않게 한다. */
.ar {
  font-style: normal;
  font-size: 1.5em;
  font-weight: var(--fw-bold);   /* 획이 하나뿐이라 가늘면 사라진다 — 굵기로 살린다 */
  line-height: 1;
  color: var(--c-dim);
  /* 홑화살괄호는 글자 가운데보다 살짝 높이 앉는다 — 눈으로 맞춘 값 */
  vertical-align: -0.05em;
  margin-inline: 0.14em;
  flex: none;
}
/* 덩어리 안에서는 gap 이 이미 사이를 벌린다 — 여백을 두 번 주지 않는다. */
.sg .ar { margin-inline: 0; }
.sg:first-child { margin-left: 0; }
.sg i { font-style: normal; opacity: 0.55; }
.sg b { font-weight: var(--fw-reg); }
.sg .chg { color: var(--c-warn); font-weight: var(--fw-bold); }
/* 연결편 — 이 줄의 주인공은 '이 편'이고 연결편은 딸린 값이다. 한 단계 작고 옅게 둔다.
   숫자·라틴이라 11px 아래로 내려가도 뭉개지지 않는다(한글이었으면 못 줄인다). */
.chain-sub { font-style: normal; font-size: var(--fs-2xs); opacity: 0.85; }
.trow.is-past td.num:nth-child(-n+1) { color: var(--c-dim); }
.trow.is-near td:first-child { box-shadow: inset var(--bw-focus) 0 0 0 var(--c-accent); }
.trow.is-changed { animation: flash 600ms var(--e-in); }
.trow.is-cur { background: var(--c-pick); }
.daysep-row td { padding: 0; background: var(--c-bg); border: 0; }

/* 셀 색 — 상태 색은 status.json의 tone과 짝 */
td.num { font-weight: var(--fw-bold); color: var(--c-text); }
td.dim { color: var(--c-dim); }
td.chg { color: var(--c-warn); font-weight: var(--fw-bold); }
td.yday { color: var(--c-accent); }
td.st { font-weight: var(--fw-bold); }
td.st.tone-go { color: var(--c-go); }
td.st.tone-warn { color: var(--c-warn); }
td.st.tone-bad { color: var(--c-bad); }
td.st.tone-board { color: var(--c-boarding); }
td.st.tone-done, td.st.tone-plain { color: var(--c-dim); font-weight: var(--fw-reg); }

/* 시트 안의 상세 표 */
.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-3); font-size: var(--fs-sm); }
.kv dt { color: var(--c-dim); }
.kv dd { margin: 0; font-weight: var(--fw-bold); }
.sheet-sub { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); color: var(--c-dim); }

/* ===== 내 편 핀 (설계 3.6) ===== */
.pins { display: grid; gap: var(--sp-1); padding: var(--sp-2) var(--sp-4) 0; }
.pins:empty { display: none; }
.pinrow {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--hit);
  text-align: left;
  font-size: var(--fs-sm);
  padding: var(--sp-2) var(--sp-3);
  border: var(--bw) solid var(--c-accent);
  border-radius: var(--r-md);
  background: var(--c-surface);
  color: var(--c-text);
}
.pinrow .ic { color: var(--c-accent); }
.pinrow b { font-weight: var(--fw-bold); }
.pinrow .when { color: var(--c-dim); margin-left: auto; white-space: nowrap; }
.pinrow .chg { color: var(--c-warn); font-weight: var(--fw-bold); }

/* ===== 날짜 구분 띠 (설계 10.10 · A-1) ===== */
.daysep {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-dim);
  background: var(--c-bg);
  border-bottom: var(--bw) solid var(--c-line);
}
.daysep::before, .daysep::after { content: ''; flex: 1; height: var(--bw); background: var(--c-line); }
.daysep.yday { color: var(--c-accent); }

/* ===== 상세 시트 ===== */
.sheet-acts { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.sheet-acts button {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-height: var(--hit);
  font-size: var(--fs-sm);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-bg);
  color: var(--c-text);
}
.sheet-acts button.on { border-color: var(--c-accent); color: var(--c-accent); font-weight: var(--fw-bold); }
.kv dd.dim { color: var(--c-dim); font-weight: var(--fw-reg); }
.kv dd .moved { color: var(--c-warn); font-size: var(--fs-xs); margin-left: var(--sp-2); font-weight: var(--fw-reg); }

.sec-title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-6) 0 var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
}
.sec-title span { color: var(--c-dim); font-weight: var(--fw-reg); }
.legchips { display: flex; gap: var(--sp-2); overflow-x: auto; scrollbar-width: none; margin-bottom: var(--sp-2); }
.legchips::-webkit-scrollbar { display: none; }
.legchip {
  white-space: nowrap;
  font-size: var(--fs-xs);
  min-height: var(--hit);
  padding-inline: var(--sp-3);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-bg);
  color: var(--c-dim);
}
.legchip.on { border-color: var(--c-accent); color: var(--c-accent); font-weight: var(--fw-bold); }

.legs { display: grid; gap: var(--sp-1); }
.leg {
  display: grid;
  grid-template-columns: 3.4em 4.6em 1fr auto;
  gap: var(--sp-2);
  align-items: center;
  width: 100%;
  min-height: var(--hit);
  text-align: left;
  font-size: var(--fs-sm);
  padding: var(--sp-2);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-bg);
  color: var(--c-text);
}
.leg.on { border-color: var(--c-accent); }
.leg .lg-when { color: var(--c-dim); font-size: var(--fs-xs); }
.leg .lg-fln { font-weight: var(--fw-bold); }
.leg .lg-route { color: var(--c-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leg .lg-st { font-size: var(--fs-xs); white-space: nowrap; }

/* 연결편 표 — 시트 안이라 폭이 더 좁다. 본 목록과 같은 열을 유지하되 더 조인다. */
.legtbl { --tbl-pad-x: var(--tbl-pad-x-tight); margin: var(--sp-1) 0 0; width: 100%; }
.legtbl thead th { position: static; }
#legTitle { color: var(--c-accent); font-size: var(--fs-lg); }

/* 항공사색 — 어두운 바탕에서는 밝은 쪽 값을 쓴다(위 '항공사색' 주석 참고) */
@media (prefers-color-scheme: dark) {
  :root[data-theme='light']:not([data-force='light']) .fln-c,
  :root[data-theme='light']:not([data-force='light']) .dot { color: var(--al-d, var(--c-al-etc)); }
}
:root[data-theme='dark'] .fln-c,
:root[data-theme='dark'] .dot { color: var(--al-d, var(--c-al-etc)); }

/* ===== 딱지 모드 (개발용) =====
   일반 사용자에게는 이 규칙이 닿을 요소 자체가 없다 — ddakji.js 가 켜졌을 때만 만들어진다.
   화면에 딱지를 붙여 "여기를 이렇게 고쳐 달라"를 그대로 옮기는 장치다. */
.dk-btn {
  position: fixed;
  right: var(--sp-3);
  bottom: calc(var(--tabs-h) + var(--sp-4));
  z-index: 9;
  width: var(--hit);
  height: var(--hit);
  border: 0;
  border-radius: var(--r-full);
  background: var(--c-surface-2);
  color: var(--c-dim);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  box-shadow: var(--sh-sheet);
  /* 끌어서 옮기는 단추 — 브라우저 기본 스크롤·길게눌러 선택이 끼어들지 않게 */
  touch-action: none;
  user-select: none;
}
.dk-btn.on { background: var(--c-accent); color: var(--c-on-accent); }
/* 딱지 붙이는 중에는 화면 전체가 '고르는 판'이다 — 눌린 것이 열리지 않게 손 모양으로 알린다. */
.dk-picking .body, .dk-picking .hdr, .dk-picking .listbar { cursor: crosshair; }

.dk-pin {
  position: absolute;
  z-index: 8;
  width: var(--sp-6);
  height: var(--sp-6);
  margin: calc(var(--sp-6) / -2) 0 0 calc(var(--sp-6) / -2);
  border-radius: var(--r-full);
  background: var(--c-bad);
  color: #ffffff; /* 예외: 딱지는 어느 테마에서도 같은 빨강 바탕이라 글자색이 고정이다 */
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  font-style: normal;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.dk-wrap {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: rgba(0, 0, 0, 0.4); /* 예외: 덮개는 테마와 무관하게 어둡게 깔린다 */
  display: flex;
  align-items: flex-end;
}
/* display 를 준 요소는 hidden 이 안 먹는다 — 안 보이는 덮개가 화면 전체를 막는다. */
.dk-wrap[hidden] { display: none; }
.dk-panel {
  width: 100%;
  max-height: 80vh;
  overflow-y: auto;
  padding: var(--sp-3);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--c-surface);
  color: var(--c-text);
}
.dk-head { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-md); }
.dk-where { color: var(--c-dim); font-size: var(--fs-xs); }
.dk-x { margin-left: auto; min-width: var(--hit); min-height: var(--hit); border: 0; background: none; color: var(--c-dim); }
.dk-empty { color: var(--c-dim); font-size: var(--fs-sm); }
.dk-list { list-style: none; margin: var(--sp-3) 0; padding: 0; display: grid; gap: var(--sp-2); }
.dk-row {
  display: grid;
  grid-template-columns: var(--sp-6) 1fr var(--hit);
  gap: var(--sp-2);
  align-items: center;
  padding-bottom: var(--sp-2);
  border-bottom: var(--bw) solid var(--c-line);
}
.dk-no {
  width: var(--sp-6);
  height: var(--sp-6);
  border-radius: var(--r-full);
  background: var(--c-bad);
  color: #ffffff; /* 예외: 위 .dk-pin 과 같은 이유 */
  font-size: var(--fs-xs);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dk-what { display: grid; font-size: var(--fs-sm); min-width: 0; grid-area: 1 / 2; }
.dk-memo { grid-area: 2 / 1 / 3 / 4; }
.dk-del { grid-area: 1 / 3; }
.dk-what em { font-style: normal; color: var(--c-dim); }
.dk-what i { font-style: normal; font-size: var(--fs-2xs); color: var(--c-dim); }
.dk-memo {
  min-height: var(--hit);
  padding-inline: var(--sp-2);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-bg);
  color: var(--c-text);
  font-size: var(--fs-sm);
}
.dk-del { min-width: var(--hit); min-height: var(--hit); border: 0; background: none; color: var(--c-dim); }
.dk-acts { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.dk-acts button {
  flex: 1 1 auto;
  white-space: nowrap;
  min-height: var(--hit);
  padding-inline: var(--sp-3);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-bg);
  color: var(--c-text);
  font-size: var(--fs-sm);
}
.dk-acts .dk-go { border-color: var(--c-accent); background: var(--c-accent); color: var(--c-on-accent); }
.dk-out {
  width: 100%;
  min-height: 40vh;
  margin-top: var(--sp-2);
  padding: var(--sp-2);
  border: var(--bw) solid var(--c-line);
  border-radius: var(--r-btn);
  background: var(--c-bg);
  color: var(--c-text);
  font-size: var(--fs-sm);
}
