/* 43-v2-topbar-search.css — 새 셸(#1719)의 **맨 윗줄**과 **통합검색**(상민님 2026-08-20).
   ⚠ 로드 순서는 public/index.html 의 <link> 나열이 정본이다(이 파일은 40~42 v2 규칙 뒤 = 맨 뒤).

   담는 것 셋:
    ① .v2-topbar   — 맨 윗줄. 데스크톱 앱에선 창 맨 윗줄(최소화·창모드·닫기와 같은 줄)이고,
                     브라우저(`.v2-topbar--web`)에선 왼쪽 두 열(레일 + 사이드바) 위에만 선다(#2142).
    ② .v2-side-nav — 사이드바 맨 윗줄: [뒤로][앞으로] + [검색] (클로드 데스크톱 문법).
    ③ .v2-omni     — 통합검색 스포트라이트(세션·대화·프로젝트·지식·자료·바로 가기 한 결과, #4530 3차).
*/

/* ════════════════════════════════════════════════════════════════════════
   ① 맨 윗줄 — 데스크톱 앱은 **창 맨 윗줄**(창 전폭), 브라우저는 **왼쪽 두 열까지만**(#2142, 아래 ①-b).
   데스크톱: preload 가 그리던 빈 36px 띠를 셸이 가져와(web/v2/titlebar.ts) 탭 줄을 그리로 올린다.
   아래 규칙들은 창 버튼(--v2-tb-left/right)·드래그가 있는 **데스크톱 기준**으로 쓰였다 — 브라우저에선 그 둘이
   각각 0·무의미하고, 달라지는 자리 셋(열 범위 · 톤 잇기 · 안쪽 자리)만 `--web`/`.topbar-web` 으로 덮는다.
   좌·우 안쪽 여백(--v2-tb-left/right)은 OS 창 버튼이 얹히는 폭이다 — 맥은 왼쪽 신호등, 윈도우는 오른쪽 WCO.
   줄 전체가 드래그 영역이고, 실제로 누르는 것들(탭·닫기·[모든 탭])만 no-drag 로 되돌린다.
   ⚠ 탭이 줄을 꽉 채우면 창을 옮길 데가 없다 → 오른쪽 .v2-tb-grip 이 늘 빈 손잡이로 남는다(크롬과 같은 이유).
   ════════════════════════════════════════════════════════════════════════ */
.v2-topbar { display: none; }
#v2-root.has-topbar { --v2-tb-h: 42px; grid-template-rows: var(--v2-tb-h, 36px) minmax(0, 1fr); }   /* 8차: 36→42 — 슬랙의 그 두께 */
#v2-root.has-topbar > .v2-topbar {
  position: relative;        /* 검색칸이 이 줄의 **가운데**에 앉는 기준(#2016 7차) */
  display: flex; align-items: stretch;
  grid-column: 1 / -1; grid-row: 1;
  height: var(--v2-tb-h, 36px);
  padding-left: var(--v2-tb-left, 0px); padding-right: var(--v2-tb-right, 0px);
  background: var(--gray-bg-2); border-bottom: 1px solid var(--line);
  -webkit-app-region: drag; -webkit-user-select: none; user-select: none;
}
#v2-root.has-topbar > .v2-topbar > .v2-tabs {
  order: -1;                 /* 손잡이는 늘 오른쪽 — 탭 줄이 DOM 뒤에 붙어도 자리는 앞이다 */
  flex: 1 1 auto; min-width: 0; height: 100%;
  border-bottom: 0; background: none;
  /* 가운데 열에 있을 때 붙던 오른쪽 여백(타임라인 서랍 버튼 자리, 40-v2.css `#v2-root.no-aside:not(.no-tl) .v2-tabs`)은
     창 줄에서는 뜻이 없다 — 그 버튼은 가운데 열 위에 뜬다. 여기선 끌 손잡이(.v2-tb-grip)가 그 자리를 맡는다. */
  padding-right: 0;
  -webkit-app-region: no-drag;
}
/* 창을 끌 자리 — 늘 빈 채로 둔다. 폭은 '끌 수 있는 최소'에 맞춘다: 종전 128px 은 윈도우에서 마지막 탭과
   최소화 단추 사이가 휑해 보였다(상민님 2026-08-20). 창버튼 여백(--v2-tb-right)이 그 옆에 또 붙는다는 걸
   감안하면 이 손잡이는 짧아도 충분하다. */
/* 창을 끌 자리 — 늘 빈 채로 둔다. 128px 은 마지막 탭과 최소화 단추 사이가 휑했고(2026-08-20), 56px 로 줄였더니
   이번엔 잡을 데가 모자랐다(상민님 2026-08-24). 그 사이값으로 둔다 — 끌기에 충분하면서 빈 자리로 보이지 않는 폭. */
.v2-tb-grip { flex: 0 0 88px; min-width: 48px; }
/*  #1954 — 상단 탭이 빠지면서 이 줄이 비었다. 뒤로·앞으로·검색이 그 자리로 올라온다(side.ts navHost).
    ⚠ no-drag 는 **누르는 것에만** 건다. 이 칸은 `flex: 1 1 auto` 로 줄의 남은 폭을 통째로 먹으므로, 여기에
      no-drag 를 걸면 검색칸 오른쪽의 빈 자리까지 전부 '못 끄는 자리'가 된다 — 실제로 그렇게 나갔다
      (#2024 상민님 2026-08-26: "빈 부분을 잡아도 창이 안 옮겨지고 맨 오른쪽 끝만 된다"). 그 '맨 오른쪽 끝'이
      곧 아래 .v2-tb-grip 이었다. 규칙은 하나다 — **줄은 drag, 실제로 누르는 것만 no-drag.** */
#v2-root.has-topbar > .v2-topbar > .v2-side-nav {
  order: -1; flex: 1 1 auto; min-width: 0; align-items: center; gap: 2px; padding: 0 4px;
  -webkit-app-region: drag;
}
/*  누르는 것 셋만 되돌린다 — [뒤로][앞으로]와 검색칸. 그 사이 여백도, 검색칸 오른쪽에 남는 폭도 끌 수 있다. */
#v2-root.has-topbar > .v2-topbar > .v2-side-nav .v2-navb,
#v2-root.has-topbar > .v2-topbar > .v2-side-nav .v2-omnib { -webkit-app-region: no-drag; }
/*  검색칸은 창 줄의 **가운데**(슬랙의 그 자리, #2016 7차 원준: "검색 텍스트 박스가 2열 사이드바 밖으로 튀어나와서").
    종전엔 [뒤로][앞으로] 옆에 210px 로 붙어 있어 사이드바를 좁히면 열 경계를 넘었다 — 열 폭을 모르는 줄에 열에
    맞춰야 할 것을 두지 않는다. 가운데면 어느 열 폭에서도 어긋날 것이 없고, 통합검색은 어차피 온 화면의 것이다. */
#v2-root.has-topbar > .v2-topbar > .v2-side-nav .v2-omnib {
  width: clamp(260px, 34vw, 520px); max-width: 100%; height: 28px; margin: 0 0 0 4px; flex: 0 1 auto;
}
#v2-root.has-topbar > .v2-topbar > .v2-side-nav .v2-nav-core { flex: 0 1 auto; }
/* 탭이 줄 맨 위에 닿으므로 켜진 탭의 파란 밑줄은 **아래쪽**에 긋는다 — 위에 그으면 창 모서리와 붙어 선이 잘려 보인다. */
#v2-root.has-topbar > .v2-topbar .v2-tab.on { box-shadow: inset 0 -2px 0 var(--blue); }
/* 데스크톱 앱은 맨 윗줄이 이미 탭 줄이다 — 가운데 열 위에 또 한 줄이 생기지 않게 [모든 탭] 도 같은 줄에서 산다.
   자리는 줄 맨 왼쪽이라(tabs.ts) 창 버튼과 안 겹친다. 맥에선 그 왼쪽이 신호등 자리이므로 --v2-tb-left 가 이미 비켜 준다. */
#v2-root.has-topbar > .v2-topbar .v2-tab-menu { background: none; border-left-color: var(--line); -webkit-app-region: no-drag; }
/* 좁은 폭(≤900px)에서도 **창 줄은 그대로 있다**(#1954 3차 상민님: "창모드든 아니든 타이틀바는 똑같게").
   종전엔 이 폭에서 창 줄을 감추고 모바일 바(☰·제목·타임라인)가 드래그까지 대신 맡았는데, 그러면 같은 자리가
   두 얼굴을 갖는다 — 넓을 땐 뒤로·앞으로·검색, 좁을 땐 세션명. 이제 ☰ 는 창 줄 맨 왼쪽에 살고(main.ts 가 옮긴다)
   모바일 바에는 남길 것이 [타임라인] 하나뿐이라, 그 바는 **버튼이 있을 때만** 선다. */
@media (max-width: 900px) {
  #v2-root.has-topbar { display: flex; flex-direction: column; }
  #v2-root.has-topbar > .v2-topbar { display: flex; flex: none; }
  /* 창 줄이 살아 있으므로 모바일 바는 드래그를 대신 맡지 않는다 — 창버튼 여백도 창 줄이 이미 비켜 준다. */
  #v2-root.has-topbar > .v2-mbar { padding-left: 4px; padding-right: 4px; }
  /*  좁은 폭은 서랍이 담당한다 — 데스크톱 접기 클래스는 여기서 무시한다(안 그러면 서랍까지 안 보인다). */
  #v2-root.has-topbar.side-off > .v2-side { visibility: visible; overflow: auto; }
  /* 좁은 폭 — 가운데 묶음 그대로, 검색칸 폭만 줄인다. */
  #v2-root.has-topbar > .v2-topbar > .v2-side-nav .v2-omnib { max-width: none; width: clamp(150px, 44vw, 520px); }
  /* 끌 자리는 좁은 화면에서 아깝지만 **0 이 되면 창을 아예 못 옮긴다**. 종전엔 여기서 손잡이를 통째로 감췄는데
     ('창버튼 여백 --v2-tb-right 로 끌면 된다'는 계산) 그건 윈도우(WCO 가 오른쪽) 얘기고 **맥은 신호등이 왼쪽이라
     --v2-tb-right 가 0** 이다. 바로 위에서 검색칸의 210px 상한까지 풀리므로 맥 좁은 창엔 끌 자리가 한 점도 안
     남았다. 게다가 이 폭은 **창 최소폭에서 바로 닿는다** — 웹 창 minWidth 가 900px 이라(APP_WINDOW_MIN,
     desktop/main/web-shell.mjs) 끝까지 줄이면 이 블록이 켜진다. 감추지 말고 **줄이기만** 한다. */
  #v2-root.has-topbar > .v2-topbar > .v2-tb-grip { flex: 0 0 48px; }
}
/* ☰ 는 창 줄 맨 왼쪽 — 폭과 무관하게 늘 같은 자리다(#1954 3차). 맥 신호등·윈도우 WCO 여백 안쪽에 앉는다. */
#v2-root.has-topbar > .v2-topbar > .v2-mbar-menu {
  order: -2; flex: none; width: 28px; height: 28px; align-self: center; margin: 0 4px 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 8px; background: none; color: var(--muted-head); cursor: pointer; -webkit-app-region: no-drag;
}
#v2-root.has-topbar > .v2-topbar > .v2-mbar-menu:hover { background: var(--bg); color: var(--ink); }
/*  ⚠ 획 스타일(fill:none·stroke)은 40-v2.css 의 **모바일 미디어 블록 안**에만 있다 — ☰ 가 그 바를 떠나
    창 줄로 오면서 그 규칙 밖으로 나가, 넓은 폭에서 아이콘이 stroke:none·fill:black 이 되어 안 보였다(#1954 3차 실측).
    여기서 폭과 무관하게 다시 준다. */
#v2-root.has-topbar > .v2-topbar > .v2-mbar-menu .v2-mbar-ic {
  width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round;
}
/* 모바일 바는 [타임라인] 하나만 남는다 — 그 버튼이 숨으면 바 자체가 설 이유가 없다. */
#v2-root.has-topbar > .v2-mbar:not(:has(.v2-mbar-btn:not([hidden]))) { display: none; }

/* ── ①-b 브라우저에서는 이 줄이 **왼쪽 두 열(레일 + 사이드바)까지만** 선다 ─────────────────────────
   (#2142 상민님 2026-08-27: "맨 좌측 패널 ~ 좌측 사이드바 영역만 차지하고 그 오른쪽은 높이 안 차지하게")
   데스크톱 앱에서 이 줄이 창을 가로지르는 데는 이유가 있다 — 그건 **OS 타이틀바**다. 최소화·닫기가 얹히고
   남는 자리가 곧 창을 끄는 손잡이라, 줄이 창 끝까지 가야 한다. 브라우저엔 얹힐 창 버튼도 끌 창도 없다.
   그러니 가로지를 이유가 없고, 가로지르면 본문·우패널이 아무것도 안 얻으면서 42px 을 잃는다(8차가 그랬다).
   ⚠ 열은 하나씩 못 박는다 — 두 줄짜리 그리드에서 자동배치는 남은 것들을 **윗줄부터** 채우므로, 레일·사이드바만
     아랫줄로 내리면 본문이 42px 짜리 윗줄에 앉는다. 열 번호는 `.rail-mode` 여섯 벌 기준(47-v2-rail.css) —
     레일1 · 사이드바2 · 손잡이3 · 본문4 · 손잡이5 · 우패널6. 팝아웃(`.solo`)엔 애초에 이 줄이 없다.
   ⚠ 좁은 폭(≤900px)은 그리드가 아니라 flex 한 줄 셸이고 레일도 떠 있는 서랍이라 이 규칙이 통째로 어긋난다
     → `min-width: 901px` 로 잠근다(그 폭에선 종전대로 줄이 화면을 가로지른다). */
@media (min-width: 901px) {
  #v2-root.has-topbar.topbar-web > .v2-topbar { grid-column: 1 / 3; grid-row: 1; }
  #v2-root.has-topbar.topbar-web > .v2-rail { grid-column: 1; grid-row: 2; }
  #v2-root.has-topbar.topbar-web > .v2-side { grid-column: 2; grid-row: 2; }
  #v2-root.has-topbar.topbar-web > .v2-side + .v2-split-x { grid-column: 3; grid-row: 1 / -1; }
  #v2-root.has-topbar.topbar-web > .v2-main { grid-column: 4; grid-row: 1 / -1; }
  #v2-root.has-topbar.topbar-web > .v2-main + .v2-split-x { grid-column: 5; grid-row: 1 / -1; }
  #v2-root.has-topbar.topbar-web > .v2-aside { grid-column: 6; grid-row: 1 / -1; }
  /*  줄이 왼쪽 두 열 위에만 남으므로 **그 두 열의 톤을 그대로 위로 잇는다** — 레일 위는 레일 색(--canvas),
      사이드바 위는 사이드바 색(--gray-bg-2, 이 줄의 원래 배경), 둘 사이 세로선(레일 border-right)도 이어 긋는다.
      그래야 이 줄이 왼쪽 판에 '얹힌 띠'가 아니라 **그 판의 머리**로 읽힌다(8차 전, 줄이 사이드바 안에 있던 때의 모습).
      아래 경계선은 지운다 — 같은 색끼리 만나는 자리에 그으면 왼쪽 판을 가로지르는 금이 된다.
      ⚠ 두 톤은 **배경 그라디언트**로 칠한다. ::before 덮개로 칠했더니 그것이 positioned 라 ☰·[뒤로]보다 위에 그려져
        레일 칸의 단추들이 통째로 가려졌다(실측). 배경은 언제나 내용 아래다 — 톤은 배경으로만 칠한다.
      ⚠ 레일을 걷으면 --v2-rail-w 가 0 이라 앞 두 구간이 폭 0 으로 접히고 사이드바 색만 남는다(자동). */
  #v2-root.has-topbar.topbar-web > .v2-topbar {
    border-bottom: 0;
    border-right: 1px solid var(--line);   /* 사이드바 오른쪽 테두리(.stu-panel)의 연장 */
    background: linear-gradient(to right,
      var(--canvas) 0 calc(var(--v2-rail-w, 0px) - 1px),
      var(--line) calc(var(--v2-rail-w, 0px) - 1px) var(--v2-rail-w, 0px),
      var(--gray-bg-2) var(--v2-rail-w, 0px) 100%);
  }
  /*  안의 것도 제 열을 지킨다 — ☰ 는 레일 칸, [뒤로][앞으로][검색] 은 사이드바 칸.
      묶음을 줄 가운데 두던 8차 셈법(양쪽 빈 칸 .v2-nav-sp)은 창 전폭일 때의 것이다. 줄이 두 열로 줄면 그 셈이
      [뒤로]·[앞으로]를 레일/사이드바 경계에 걸치게 놓는다(실측 x=44~102, 경계는 76). 사이드바 칸을 폭으로 못 박고
      남는 레일 자리를 ☰ 쪽에 남기면(margin-left:auto) 아래 목록·머리줄과 좌우 여백까지 그대로 맞는다.
      끌 손잡이는 여기서 지운다 — 끌 창이 없으니 자리만 먹고, 그 8px 이 검색칸을 열 밖으로 민다. */
  #v2-root.has-topbar.topbar-web > .v2-topbar > .v2-tb-grip { display: none; }
  #v2-root.has-topbar.topbar-web > .v2-topbar > .v2-side-nav {
    flex: 0 1 var(--v2-side-w); margin-left: auto;
    padding: 0 18px 0 8px;   /* ② 사이드바 줄과 같은 좌우 여백 — 검색칸 오른쪽 끝이 아래 머리줄 글리프와 맞는다 */
  }
  /*  가운데를 만들던 빈 칸은 여기선 할 일이 없다. 남겨 두면 폭 0 인 채로 양옆 gap(2px×2)만 먹어 검색칸 오른쪽 끝이
      머리줄 글리프에서 3px 어긋난다(실측 371 vs 374). */
  #v2-root.has-topbar.topbar-web > .v2-topbar > .v2-side-nav > .v2-nav-sp { display: none; }
  /*  ☰ 는 레일 칸 **가운데** — 바로 아래 워크스페이스 타일·구역 아이콘이 전부 그 자리에 선다(레일은 가운데 정렬 열이다).
      창 전폭이던 8차엔 '줄의 맨 왼쪽'이 곧 화면 맨 왼쪽이라 6px 이 맞았지만, 줄이 레일 칸 위로 들어온 지금은
      6px 이 그 열의 중심에서 18px 어긋난다. 레일을 걷으면(폭 0) 계산값이 음수가 되므로 6px 로 받친다. */
  #v2-root.has-topbar.topbar-web > .v2-topbar > .v2-mbar-menu {
    margin: 0 0 0 max(6px, calc((var(--v2-rail-w, 0px) - 28px) / 2));
  }
}

/* ════════════════════════════════════════════════════════════════════════
   ② 사이드바 맨 윗줄 — [뒤로][앞으로] + [검색]
   내용(프로젝트·세션)보다 위, 워크스페이스 문패보다도 위. '움직이는 손잡이'라 목록의 일부가 아니다.
   ════════════════════════════════════════════════════════════════════════ */
/*  #2016 7차 — 셋(토글·뒤로·앞으로)은 한 굵기(16px · 1.7)로 왼쪽에 모으고, 검색칸의 오른쪽 끝은 **아래 머리줄의 마지막
    아이콘 글리프**와 맞춘다(오른쪽 18px = 머리줄 4px 패딩 + 28px 단추 안 글리프 여백 — 실측 371→366). 위 여백 10px 로 줄이 숨 쉰다. */
.v2-side-nav { display: flex; align-items: center; gap: 2px; padding: 10px 18px 4px 8px; }
/* 8차 — [‹][›][검색] 한 묶음과 그 양쪽 빈 칸. 창 줄에선 묶음이 줄 가운데 선다(위 has-topbar 규칙이 flex 를 조인다). */
.v2-nav-sp { flex: 1 1 0; min-width: 0; }
.v2-nav-core { display: flex; align-items: center; gap: 2px; flex: 1 1 auto; min-width: 0; }
/*  8차의 `.v2-topbar--web > .v2-tb-grip { flex: 0 0 8px }`(끌 손잡이를 장식으로 줄이던 줄)은 걷었다 —
    넓은 폭에선 위 ①-b 가 손잡이를 아예 지우고, 좁은 폭(≤900px)에선 `#v2-root.has-topbar …` 쪽이 이겨 48px 이 된다.
    어느 폭에서도 닿지 않는 규칙이었다. */
#v2-root.has-topbar > .v2-topbar > .v2-mbar-menu { margin-left: 6px; }
.v2-navb { display: inline-grid; place-items: center; width: 28px; height: 28px; flex: none; padding: 0;
  border: 0; border-radius: 8px; background: none; color: var(--muted-head); cursor: pointer; }
.v2-navb:hover:not(:disabled) { background: var(--bg); color: var(--ink); }
.v2-navb:disabled { color: var(--muted-2); cursor: default; }
.v2-navb-ic { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
/* 검색은 **칸처럼 생긴 버튼**이다 — 진짜 입력칸을 두면 사이드바 20초 재렌더가 입력·한글 조합을 끊는다. */
.v2-omnib { display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0; height: 28px; margin-left: 6px; padding: 0 8px 0 10px;
  border: 1px solid var(--line-net); border-radius: 8px; background: var(--bg);
  font: inherit; font-size: 12.5px; color: var(--muted); cursor: pointer; text-align: left; }
.v2-omnib:hover { border-color: var(--blue); color: var(--ink-sub); }
.v2-omnib-ic { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; }
.v2-omnib-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-omnib-k { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; letter-spacing: .02em;
  padding: 1px 5px; border: 1px solid var(--line); border-radius: 5px; color: var(--muted-2); background: var(--canvas); }

/* ════════════════════════════════════════════════════════════════════════
   ③ 통합검색(스포트라이트) — 목록 + 미리보기 두 칸(#4530 안 A, 원준 2026-10-04 «A안으로 가자»).
   ════════════════════════════════════════════════════════════════════════
   왜 두 칸인가 — 목록 한 줄(이름 + 발췌 한 조각)로는 «이게 내가 찾던 것인가» 를 못 가려 열어 봐야 했고, 열면 검색 창이 닫혀
    다시 찾아야 했다(지금 화면 진단: 결과 8줄 · 줄 높이 52~78px 들쭉날쭉 · 세션은 여섯째 줄부터 · 손잡이 9개가 한 줄).
   · 왼쪽 = 결과 목록. 모든 줄이 같은 높이(50px) 한 줄 제목 + 한 줄 «어디에 있는 것인가».
   · 오른쪽 = 고른 결과의 안(web/v2/omni-preview.ts — 종류마다 다른 레이아웃).
   · 위 = 입력칸 / 탭(전체·세션·프로젝트·지식·자료 + 숫자) · 기간 · 정렬. 아래 = 키 안내 · 상태 한 줄.
   · 폰(≤640) = 목록이 화면 전체, 줄을 누르면 미리보기가 아래에서 판으로 올라온다.
   크기 — 폭 980px(좁은 창에선 스스로 준다) · 높이는 고정(min(680px, 창 안)) — 결과 수에 따라 카드가 출렁이면 미리보기 칸이 같이 흔들린다.
   겹침 순서 1550(#4530): 런치패드(900)·[나] 창·확인 창(.ov-back 1450) 위, 기간 메뉴(ctx-menu 1600)·토스트(2000) 아래.
   창 맨 윗줄의 «끌기» 영역(데스크톱 42px)이 덮개를 이기지 않게 no-drag. */
.v2-omni { position: fixed; inset: 0; z-index: 1550; display: flex; justify-content: center; align-items: flex-start;
  padding: clamp(18px, 8vh, 96px) 16px 24px; background: rgba(var(--shadow-ink), .34); -webkit-app-region: no-drag; }
.v2-omni-card { width: 980px; max-width: 100%; height: min(680px, 100%); display: flex; flex-direction: column; position: relative;
  background: var(--surface); border: 1px solid var(--line-net); border-radius: 14px; overflow: hidden;
  box-shadow: 0 28px 70px rgba(var(--shadow-ink), .28), 0 2px 6px rgba(var(--shadow-ink), .08); }
.v2-omni-top { display: flex; align-items: center; gap: 10px; height: 56px; padding: 0 14px 0 18px; border-bottom: 1px solid var(--line); flex: none; }
.v2-omni-lens { width: 20px; height: 20px; flex: none; fill: none; stroke: var(--muted); stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
.v2-omni-in { flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 17px; font-weight: 500; color: var(--ink); }
.v2-omni-in::placeholder { font-weight: 400; color: var(--muted-2); }
.v2-omni-in:focus { outline: none; }
.v2-omni-esc { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; padding: 2px 6px;
  border: 1px solid var(--line); border-radius: 5px; color: var(--muted-2); background: var(--bg-tint-2); }
.v2-omni-close { flex: none; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 4px 0 8px;
  border: 0; border-radius: 7px; background: none; font: inherit; font-size: 12px; color: var(--muted); cursor: pointer; }
.v2-omni-close:hover { background: var(--bg-tint-2); color: var(--ink-sub); }
.v2-omni-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.v2-omni-close-t { display: none; }
/* 찾는 중 — 카드 맨 위 가는 줄. 앞 결과는 흐리게 두고 새 결과가 자리 잡으면 한 번에 바꾼다(목록이 비었다 차는 깜빡임 없음). */
.v2-omni-bar { height: 2px; flex: none; background: transparent; position: relative; overflow: hidden; margin-top: -2px; }
.v2-omni-bar.on::after { content: ''; position: absolute; inset: 0 auto 0 0; width: 30%; background: var(--blue);
  animation: v2-omni-bar 1.1s ease-in-out infinite; }
@keyframes v2-omni-bar { 0% { transform: translateX(-100%); } 100% { transform: translateX(340%); } }
@media (prefers-reduced-motion: reduce) { .v2-omni-bar.on::after { animation: none; width: 100%; opacity: .5; } }

/* 탭 줄 — 왼쪽 종류(전체·세션·프로젝트·지식·자료 + 숫자), 오른쪽 기간·정렬. 켜진 탭 하나가 «지금 무엇을 보고 있나» 를 말한다. */
.v2-omni-filters { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 12px; border-bottom: 1px solid var(--line); flex: none; }
.v2-omni-tabs { display: flex; align-items: center; gap: 2px; min-width: 0; }
.v2-omni-tab { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border: 0; border-radius: 8px; background: none;
  font: inherit; font-size: 13px; color: var(--ink-sub); cursor: pointer; white-space: nowrap; }
.v2-omni-tab:hover { background: var(--bg-tint-2); }
.v2-omni-tab.on { background: var(--bg-punch); color: var(--blue); font-weight: 600; }
/*  자료는 눌렀을 때만 찾는다(느리고 많다) — 점선 테두리로 «아직 안 찾은 것» 임을 말한다. */
.v2-omni-tab.aux:not(.on) { border: 1px dashed var(--line-net); color: var(--muted-2); height: 28px; margin-left: 4px; }
.v2-omni-tabn { font-style: normal; font-size: 11.5px; font-weight: 500; color: var(--muted-3); font-variant-numeric: tabular-nums; }
.v2-omni-tab.on .v2-omni-tabn { color: var(--blue); }
.v2-omni-tabn[hidden] { display: none; }
.v2-omni-tools { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; flex: none; }
.v2-omni-opt { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface); font: inherit; font-size: 12px; color: var(--ink-sub); cursor: pointer; white-space: nowrap; }
.v2-omni-opt:hover { border-color: var(--line-net-2); background: var(--bg-tint); }
.v2-omni-opt.on { border-color: var(--blue); color: var(--blue); background: var(--bg-punch); font-weight: 600; }
.v2-omni-opt-ic { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
.v2-omni-opt-ic:last-child { width: 11px; height: 11px; opacity: .7; }
.v2-omni-tab:focus-visible, .v2-omni-opt:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

/* 몸통 — 목록 | 미리보기 */
.v2-omni-body { flex: 1; min-height: 0; display: flex; position: relative; }
.v2-omni-col { flex: 0 0 41%; min-width: 300px; max-width: 420px; display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
.v2-omni-list { flex: 1; min-height: 0; overflow: auto; padding: 4px 8px 8px; }
.v2-omni-list.stale { opacity: .55; transition: opacity .12s; }
.v2-omni-gh { padding: 12px 10px 4px; font-size: 11.5px; font-weight: 700; color: var(--muted-head); }
/* 빈 칸 맨 위의 «최근 검색» — 한 줄의 칩(#4530, 원준 2026-10-05 «최근 검색 기록이 차지하는 부분이 너무 많다»). 종전엔 검색어마다 한 줄이라
   목록을 다 차지했다. 넘치면 옆으로 민다(막대는 숨긴다) — 고른 칩은 scrollIntoView 가 데려온다. */
.v2-omni-recent { display: flex; align-items: center; gap: 6px; padding: 10px 28px 2px 10px; overflow-x: auto; scrollbar-width: none;
  /* 오른쪽 끝은 흐려서 «더 있다» 를 알린다(끝까지 밀면 오른쪽 여백 덕에 마지막 칩은 또렷하다). */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent); }
.v2-omni-recent::-webkit-scrollbar { display: none; }
.v2-omni-recent-l { flex: none; margin-right: 4px; font-size: 11.5px; font-weight: 700; color: var(--muted-head); }
.v2-omni-chip { flex: none; display: inline-flex; align-items: center; gap: 5px; max-width: 180px; height: 28px; padding: 0 10px 0 8px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--ink-sub); font-size: 12.5px; cursor: pointer; }
.v2-omni-chip:hover { border-color: var(--line-net-2); background: var(--bg-tint); }
.v2-omni-chip.on { border-color: var(--blue); background: var(--bg-sel); color: var(--ink); }
.v2-omni-chip-ic { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; opacity: .75; }
.v2-omni-chip-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-omni-row { display: flex; align-items: center; gap: 11px; height: 50px; padding: 0 10px; border-radius: 9px; cursor: pointer; }
.v2-omni-row.on { background: var(--bg-sel); box-shadow: inset 0 0 0 1px var(--line-note); }
/*  종류는 그림의 색이 말한다(앱 아이콘 색 토큰) — 세션 파랑 · 프로젝트 보라 · 지식 초록 · 자료 갈색 · 바로 가기 회색. */
.v2-omni-ic { display: inline-grid; place-items: center; width: 28px; height: 28px; flex: none; border-radius: 8px; background: var(--bg-tint-2); color: var(--muted-head); }
.v2-omni-ic.k-sess { color: var(--gi-c-chat); } .v2-omni-ic.k-proj { color: var(--gi-c-proj); }
.v2-omni-ic.k-know { color: var(--gi-c-wiki); } .v2-omni-ic.k-src { color: var(--gi-c-src); }
.v2-omni-row.on .v2-omni-ic { background: var(--surface); }
.v2-omni-kic { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
.v2-omni-tt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.v2-omni-tl { display: flex; align-items: center; gap: 6px; min-width: 0; }
.v2-omni-t { font-size: 14px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.v2-omni-row.sim .v2-omni-t { font-weight: 500; }
.v2-omni-s { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-omni-head { flex: none; font-size: 10.5px; font-weight: 700; color: var(--muted); background: var(--bg-tint-2); border-radius: 4px; padding: 1px 5px; white-space: nowrap; }
.v2-omni-st { flex: none; font-size: 10.5px; font-weight: 700; color: var(--muted-head); border: 1px solid var(--line-net); border-radius: 999px; padding: 0 6px; white-space: nowrap; }
.v2-omni-sub { font-weight: 600; color: var(--muted-head); }
.v2-omni-ctx { color: var(--ink-sub); }
/*  어디에 있는 것인가(세션의 프로젝트 · 자료의 출처) — 뒤에 맞은 글이 이어지므로 긴 이름은 줄여 자리를 남긴다. */
.v2-omni-where { display: inline-block; max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; color: var(--ink-sub); }
.v2-omni-where.solo { display: inline; max-width: none; }
/*  덜 맞는 결과 — 왜 그런지 한마디(«‘물소’ 없음» · «‘귤나무 정원’ 으로 찾음»)가 둘째 줄 맨 앞에 선다. 제목은 한 단계 가볍게. */
.v2-omni-why { font-weight: 600; color: var(--muted-head); background: var(--bg-tint-2); border-radius: 4px; padding: 0 5px; }
.v2-omni-row.weak .v2-omni-t { font-weight: 500; color: var(--ink-sub); }
.v2-omni-edit { color: var(--muted-head); }
/* 일치 부분 — 형광펜 밑줄(글자색·굵기는 그대로). ⚠ <mark> 의 브라우저 기본값(노랑 바탕·검정 글자)은 다크모드를 뚫고 나오므로 덮어쓴다. */
.v2-omni-hl { background: transparent; color: inherit; border-radius: 2px; box-shadow: inset 0 -.42em 0 var(--md-mark-bg); }
/* key(지식 이름 · 프로젝트 번호) — 사람이 옮겨 적는 이름이라 고정폭으로. 정확히 맞았으면 테두리로 그렇다고 말한다. */
.v2-omni-key { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-head);
  background: var(--gray-bg-2); border: 1px solid transparent; border-radius: 4px; padding: 0 4px; }
.v2-omni-key.exact { border-color: var(--blue); color: var(--ink-sub); }
.v2-omni-meta { flex: none; display: flex; flex-direction: column; align-items: flex-end; }
.v2-omni-when { flex: none; font-size: 11.5px; color: var(--muted-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
/*  종류 이름은 그림이 말한다 — 눈에는 숨기고 화면 읽기 프로그램에만 읽힌다. */
.v2-omni-badge { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/*  결과가 없다 · 찾는 중 — 목록 **위**에 선다(목록 아래에 두면 칸 맨 밑에 붙어 보였다, 실화면). */
.v2-omni-none { flex: none; padding: 22px 18px 10px; color: var(--muted); font-size: 13px; }
.v2-omni-none b { display: block; font-size: 14px; color: var(--ink-sub); margin-bottom: 4px; }
.v2-omni-none p { margin: 0; line-height: 1.6; }
.v2-omni-none[hidden] { display: none; }
.v2-omni-none-go { margin-top: 10px; height: 30px; padding: 0 12px; border: 1px solid var(--line-net); border-radius: 8px; background: var(--surface);
  font: inherit; font-size: 12.5px; color: var(--blue); cursor: pointer; }
.v2-omni-none-go:hover { border-color: var(--blue); }
.v2-omni-none-go:focus-visible, .v2-omni-more:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.v2-omni-more { flex: none; margin: 0 10px 10px; height: 30px; border: 1px solid var(--line-net); border-radius: 8px; background: var(--surface);
  font: inherit; font-size: 12px; color: var(--ink-sub); cursor: pointer; }
.v2-omni-more:hover { border-color: var(--blue); }
.v2-omni-more[hidden] { display: none; }

/* 아래 줄 — 왼쪽 키 안내, 오른쪽 상태(색인 중 · 가져오지 못함). */
.v2-omni-foot { flex: none; display: flex; align-items: center; gap: 14px; min-height: 36px; padding: 6px 14px; border-top: 1px solid var(--line);
  background: var(--bg-tint); font-size: 11.5px; color: var(--muted); }
.v2-omni-hints { display: flex; align-items: center; gap: 14px; flex: none; white-space: nowrap; }
.v2-omni-hints kbd, .v2-opv-kbd { font: 600 10.5px/1 var(--mono, ui-monospace, monospace); color: var(--muted); background: var(--surface);
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 2px 5px; margin-right: 3px; }
.v2-omni-note { margin-left: auto; min-width: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.v2-omni-note[hidden] { display: none; }

/* ── 미리보기 칸(web/v2/omni-preview.ts) ── 머리(종류·제목) / 스크롤되는 안 / 단추 */
.v2-omni-pvw { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--bg); }
.v2-omni-grab, .v2-omni-sheetbg { display: none; }
.v2-opv { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.v2-opv.empty { justify-content: center; align-items: center; }
.v2-opv-h { flex: none; padding: 18px 22px 0; }
.v2-opv-kline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.v2-opv-kind { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; color: var(--ink-sub); background: var(--bg-tint-2); border-radius: 6px; padding: 2px 8px; }
.v2-opv-kic { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
.v2-opv-tag { font-size: 11px; font-weight: 700; color: var(--muted); background: var(--bg-tint-2); border-radius: 5px; padding: 2px 6px; }
.v2-opv-pill { font-size: 11px; font-weight: 700; border-radius: 999px; padding: 1px 8px; border: 1px solid var(--line-net); color: var(--muted-head); }
.v2-opv-pill.done { color: var(--ok); border-color: var(--ok-line-2); background: var(--ok-bg); }
.v2-opv-pill.doing { color: var(--blue); border-color: var(--line-note); background: var(--bg-punch); }
.v2-opv-state { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--ink-sub); }
.v2-opv-t { margin: 8px 0 0; font-size: 18px; line-height: 1.4; font-weight: 700; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.v2-opv-b { flex: 1; min-height: 0; overflow: auto; padding: 10px 22px 16px; display: flex; flex-direction: column; gap: 8px; }
.v2-opv-facts { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12.5px; color: var(--muted); }
.v2-opv-fact { display: inline-flex; align-items: center; gap: 5px; min-width: 0; border: 0; background: none; padding: 0; font: inherit; color: inherit; }
.v2-opv-fact span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.v2-opv-fact.link { cursor: pointer; color: var(--blue); }
.v2-opv-fact.link:hover span { text-decoration: underline; }
.v2-opv-ic { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--ic-stroke); stroke-linecap: round; stroke-linejoin: round; }
.v2-opv-sec { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 12px; font-weight: 700; color: var(--muted-head); }
.v2-opv-sec em { font-style: normal; font-weight: 500; color: var(--muted-3); }
.v2-opv-when { font-weight: 500; color: var(--muted-3); }
.v2-opv-nav { margin-left: auto; display: inline-flex; gap: 4px; }
.v2-opv-navb { width: 24px; height: 22px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--ink-sub); font: inherit; font-size: 14px; line-height: 1; cursor: pointer; }
.v2-opv-navb:hover { border-color: var(--blue); color: var(--blue); }
.v2-opv-first { margin: 2px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--muted); }
.v2-opv-first b { font-weight: 700; color: var(--muted-head); }
.v2-opv-sum { margin: 2px 0 0; font-size: 13px; line-height: 1.65; color: var(--ink-sub); }
/* 세션 — 대화 모양. 맞은 말은 카드로 돋우고, 앞뒤 말은 흐리게. */
.v2-opv-conv { display: flex; flex-direction: column; gap: 6px; }
.v2-opv-msg { display: flex; gap: 10px; align-items: flex-start; padding: 8px 12px; border-radius: 10px; font-size: 13.5px; line-height: 1.6; color: var(--ink-sub); }
.v2-opv-msg p { margin: 0; overflow-wrap: anywhere; }
.v2-opv-msg.dim { color: var(--muted); }
/*  앞뒤 말은 세 줄까지만 — 길면 맞은 말이 화면 아래로 밀린다(폰 캡처로 확인). */
.v2-opv-msg.dim p { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.v2-opv-msg.hit { background: var(--surface); border: 1px solid var(--line-note); color: var(--ink); box-shadow: 0 1px 2px rgba(var(--shadow-ink), .05); }
.v2-opv-msg.plain { background: var(--surface); border: 1px solid var(--line); color: var(--ink); }
.v2-opv-who { flex: none; margin-top: 2px; font-size: 10.5px; font-weight: 700; border-radius: 5px; padding: 1px 6px; }
.v2-opv-who.user { background: var(--bg-punch); color: var(--blue); }
.v2-opv-who.ai { background: var(--bg-tint-2); color: var(--muted); }
.v2-opv-files { display: flex; flex-wrap: wrap; gap: 6px; }
.v2-opv-files code { font: 12px/1.4 var(--mono, ui-monospace, monospace); background: var(--bg-tint-2); color: var(--ink-sub); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; }
.v2-opv-files code.hit { border-color: var(--line-note); background: var(--surface); }
/* 본문에서 맞은 곳 — 그 줄이 속한 제목(절) 아래에, 맞은 줄은 진하게 · 이웃 줄은 흐리게. */
.v2-opv-blocks { display: flex; flex-direction: column; gap: 8px; }
.v2-opv-block { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px; }
.v2-opv-crumb { font-size: 11.5px; font-weight: 700; color: var(--muted-head); margin-bottom: 3px; }
.v2-opv-line { margin: 0; font-size: 13px; line-height: 1.65; color: var(--muted); overflow-wrap: anywhere; }
.v2-opv-line.hit { color: var(--ink); }
.v2-opv-toc { margin: 0; padding: 0; list-style: none; columns: 2; column-gap: 18px; font-size: 12.5px; color: var(--ink-sub); }
.v2-opv-toc li { break-inside: avoid; padding: 2px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-opv-toc li.l1 { padding-left: 12px; color: var(--muted); }
/* 태스크 진행 — 끝남(초록) · 하는 중(파랑) · 남은 것(바탕). */
.v2-opv-prog { display: flex; height: 6px; border-radius: 3px; overflow: hidden; background: var(--line-row); }
.v2-opv-prog i { display: block; height: 100%; }
.v2-opv-prog i.done { background: var(--ok-fill); } .v2-opv-prog i.doing { background: var(--blue-fill); }
.v2-opv-rows { display: flex; flex-direction: column; }
.v2-opv-trow { display: flex; align-items: center; gap: 9px; min-height: 30px; padding: 3px 8px; border: 0; border-radius: 7px; background: none;
  font: inherit; font-size: 13px; color: var(--ink-sub); text-align: left; width: 100%; }
button.v2-opv-trow { cursor: pointer; } button.v2-opv-trow:hover { background: var(--bg-tint-2); }
.v2-opv-trow .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-opv-trow .s { flex: none; font-size: 11.5px; color: var(--muted-3); white-space: nowrap; }
.v2-opv-sdot { width: 8px; height: 8px; border-radius: 50%; flex: none; border: 1.5px solid var(--muted-3-line); }
.v2-opv-sdot.done { background: var(--ok-fill); border-color: var(--ok-fill); } .v2-opv-sdot.doing { background: var(--blue-fill); border-color: var(--blue-fill); }
.v2-opv-link { display: block; width: 100%; border: 0; background: none; padding: 4px 8px; border-radius: 7px; font: inherit; font-size: 13px; color: var(--blue);
  text-align: left; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-opv-link:hover { background: var(--bg-tint-2); }
.v2-opv-note { margin: 0; font-size: 12px; color: var(--muted-3); }
.v2-opv-empty { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.6; }
.v2-opv-empty.big { padding: 0 28px; text-align: center; }
.v2-opv-skel { display: flex; flex-direction: column; gap: 10px; padding-top: 6px; }
.v2-opv-skel i { display: block; height: 12px; border-radius: 6px; background: var(--line-row); }
.v2-opv-act { flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 22px 14px; border-top: 1px solid var(--line); background: var(--bg); }
.v2-opv-btn { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border: 1px solid var(--line-net); border-radius: 8px; background: var(--surface);
  font: inherit; font-size: 13px; color: var(--ink); cursor: pointer; text-decoration: none; white-space: nowrap; }
.v2-opv-btn:hover { border-color: var(--blue); }
.v2-opv-btn.pri { background: var(--blue-fill); border-color: var(--blue-fill); color: var(--on-fill); }
.v2-opv-btn.pri:hover { background: var(--blue-fill-deep); border-color: var(--blue-fill-deep); }
.v2-opv-btn.pri .v2-opv-kbd { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .3); color: var(--on-fill); }
.v2-opv-btn .v2-opv-kbd { margin: 0 0 0 2px; }
.v2-opv-btn:focus-visible, .v2-opv-navb:focus-visible, .v2-opv-link:focus-visible, button.v2-opv-trow:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

@media (max-width: 900px) {
  .v2-omni { padding: clamp(12px, 5vh, 56px) 10px 14px; }
  .v2-omni-col { flex-basis: 44%; min-width: 260px; }
  .v2-omni-hints span:nth-child(n+4) { display: none; }
}

/*  폰(≤640) — 카드를 화면 전체로, 높이는 **키보드 위까지**(visualViewport 높이 → --omni-vh, omni.ts). 바깥 여백이 사라지므로
    닫기는 위 오른쪽 «닫기» 단추로. 목록이 화면 전체를 쓰고, 줄을 누르면 미리보기가 아래에서 판으로 올라온다([열기]로 들어간다).
    탭 줄은 한 줄 가로 스크롤 — 기간·정렬은 그 줄 끝에 선다. 키 안내는 폰에 없다. */
@media (max-width: 640px) {
  .v2-omni { padding: 0; align-items: stretch; background: var(--surface); }
  .v2-omni-card { width: 100%; max-width: none; height: var(--omni-vh, 100dvh); max-height: none; margin-top: var(--omni-vt, 0px);
    border: 0; border-radius: 0; box-shadow: none; }
  .v2-omni-top { height: 52px; padding: 0 8px 0 14px; gap: 8px; }
  .v2-omni-in { font-size: 17px; }   /* 16px 아래면 iOS 가 칸을 확대한다 */
  .v2-omni-close { height: 36px; padding: 0 10px; font-size: 15px; color: var(--blue); }
  .v2-omni-close-t { display: inline; }
  .v2-omni-close .v2-omni-esc { display: none; }
  .v2-omni-filters { height: 46px; padding: 0 10px; overflow-x: auto; scrollbar-width: none; }
  .v2-omni-filters::-webkit-scrollbar { display: none; }
  .v2-omni-tabs { flex: none; gap: 4px; }
  /*  탭 다섯이 390px 한 화면에 다 보이게 — 안 여백과 숫자 간격을 줄인다(«자료» 가 잘려 있었다, 실화면). */
  .v2-omni-tab { height: 32px; border: 1px solid var(--line); border-radius: 999px; padding: 0 9px; gap: 4px; font-size: 12.5px; }
  .v2-omni-tabn { font-size: 11px; }
  .v2-omni-tab.on { border-color: var(--line-note); }
  .v2-omni-tab.aux:not(.on) { height: 32px; margin-left: 0; }
  .v2-omni-tools { margin-left: 6px; }
  .v2-omni-opt { height: 32px; border-radius: 999px; }
  .v2-omni-chip { height: 32px; font-size: 13.5px; }   /* 손가락으로 누르는 크기 */
  .v2-omni-col { flex: 1 1 auto; min-width: 0; max-width: none; border-right: 0; }
  .v2-omni-row { height: 56px; }
  .v2-omni-t { font-size: 15px; }
  .v2-omni-head { display: none; }
  .v2-omni-hints { display: none; }
  .v2-omni-foot { min-height: 0; padding: 6px 12px; }
  .v2-omni-foot:has(.v2-omni-note[hidden]) { display: none; }
  .v2-omni-note { margin-left: 0; text-align: left; }
  /* 미리보기 판 — 평소엔 아래에 내려가 있다가 줄을 누르면 올라온다. 뒤 목록은 어둡게, 누르면 내려간다. */
  .v2-omni-sheetbg { display: block; position: absolute; inset: 0; background: rgba(var(--shadow-ink), .30); opacity: 0; pointer-events: none; transition: opacity .16s; }
  .v2-omni-pvw { position: absolute; left: 0; right: 0; bottom: 0; max-height: 82%; min-height: 46%; border-radius: 16px 16px 0 0; background: var(--surface);
    border-top: 1px solid var(--line); box-shadow: 0 -12px 40px rgba(var(--shadow-ink), .22); transform: translateY(102%); transition: transform .18s ease-out; visibility: hidden; }
  .v2-omni-card.sheet .v2-omni-pvw { transform: none; visibility: visible; }
  .v2-omni-card.sheet .v2-omni-sheetbg { opacity: 1; pointer-events: auto; }
  /*  손잡이 — 누르거나 아래로 끌면 판이 내려간다(끄는 동안 화면이 따라 밀리지 않게 touch-action: none). */
  .v2-omni-grab { display: block; flex: none; width: 100%; height: 28px; border: 0; background: none; position: relative; cursor: pointer; touch-action: none; }
  .v2-omni-grab::after { content: ''; position: absolute; left: 50%; top: 10px; width: 40px; height: 5px; margin-left: -20px; border-radius: 3px; background: var(--line-net); }
  .v2-opv-h { padding: 0 18px 0; }
  .v2-opv-b { padding: 10px 18px 14px; }
  .v2-opv-act { padding: 10px 18px calc(14px + env(safe-area-inset-bottom, 0px)); }
  .v2-opv-btn { flex: 1; justify-content: center; height: 42px; font-size: 15px; }
  .v2-opv-btn .v2-opv-kbd { display: none; }
  .v2-opv-toc { columns: 1; }
  @media (prefers-reduced-motion: reduce) { .v2-omni-pvw, .v2-omni-sheetbg { transition: none; } }
}

/* ── ①-c #3830 맥락 관리에서는 이 줄이 **창을 가로지른다**(슬랙) ────────────────────
   ①-b 는 브라우저에서 이 줄을 왼쪽 두 열 위로 줄였다 — 그 근거는 "오른쪽은 아무것도 안 얻으면서 42px 을 잃는다"
   였고, 사이드바가 있는 화면에서는 맞다. 사이드바를 접는 화면(app-ctx)에서는 그 셈이 뒤집힌다: 줄이 두 열 위에만
   남으면 레일 폭 76px 짜리 토막이 되어 [‹][›][검색] 이 들어갈 자리가 없다.
   그래서 이 화면에서만 ①-b 를 되돌린다 — 줄은 전폭, 톤은 단색, 묶음은 가운데(빈 칸 .v2-nav-sp 복원).
   ⚠ ①-b 의 규칙을 **지우지 않는다**(check-css-drops: 셀렉터 삭제 금지). 같은 자리에 클래스 하나를 더해 이긴다. */
@media (min-width: 901px) {
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-topbar {
    grid-column: 1 / -1; grid-row: 1;
    border-right: 0; border-bottom: 1px solid var(--line);
    background: var(--gray-bg-2);
  }
  /*  줄이 윗줄을 통째로 먹으므로 아래 열들은 **둘째 행**으로 내려온다(안 내리면 본문이 42px 줄에 얹힌다). */
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-rail,
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-side,
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-side + .v2-split-x,
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-main,
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-main + .v2-split-x,
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-aside { grid-row: 2; }
  /*  [‹][›][검색] 은 다시 줄 **가운데**로 — 사이드바 열이 없으니 그 열에 맞출 것도 없다(#2016 8차의 그 배치). */
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-topbar > .v2-side-nav { flex: 1 1 auto; margin-left: 0; padding: 0 8px; }
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-topbar > .v2-side-nav > .v2-nav-sp { display: block; }
  #v2-root.has-topbar.topbar-web.app-ctx > .v2-topbar > .v2-side-nav .v2-nav-core { flex: 0 1 auto; }
  /*  ☰ 는 레일 칸 가운데 그대로. 레일을 걷으면(폭 0) 6px 로 받친다 — ①-b 와 같은 셈. */
}

/* ── ①-d #4533 사이드바를 닫았을 때도 이 줄은 **창을 가로지른다** — ①-c(맥락 관리)와 같은 배치 ─────────────────
   사이드바 열이 0 이면 ①-b 의 줄은 레일 폭(76px)짜리 토막이 되고, 레일까지 걷으면 **폭 0** 이 되어 ☰ 째로 사라진다 —
   닫힌 사이드바를 되찾는 유일한 길이 없어진다. 그래서 ①-c 와 똑같이 편다. 셀렉터만 다르고 값은 ①-c 그대로다. */
@media (min-width: 901px) {
  #v2-root.has-topbar.topbar-web.side-closed > .v2-topbar {
    grid-column: 1 / -1; grid-row: 1;
    border-right: 0; border-bottom: 1px solid var(--line);
    background: var(--gray-bg-2);
  }
  #v2-root.has-topbar.topbar-web.side-closed > .v2-rail,
  #v2-root.has-topbar.topbar-web.side-closed > .v2-side,
  #v2-root.has-topbar.topbar-web.side-closed > .v2-side + .v2-split-x,
  #v2-root.has-topbar.topbar-web.side-closed > .v2-main,
  #v2-root.has-topbar.topbar-web.side-closed > .v2-main + .v2-split-x,
  #v2-root.has-topbar.topbar-web.side-closed > .v2-aside { grid-row: 2; }
  #v2-root.has-topbar.topbar-web.side-closed > .v2-topbar > .v2-side-nav { flex: 1 1 auto; margin-left: 0; padding: 0 8px; }
  #v2-root.has-topbar.topbar-web.side-closed > .v2-topbar > .v2-side-nav > .v2-nav-sp { display: block; }
  #v2-root.has-topbar.topbar-web.side-closed > .v2-topbar > .v2-side-nav .v2-nav-core { flex: 0 1 auto; }
}
