/* 새 셸 화면별 완성도 층 — library. DESIGN.md(Framer) 준수 · body.shell-v2 스코프 */
/*   화면: 라이브러리(#/library) · 프로젝트 에셋(#/projects/:id/assets). 피드 규칙은 feed.css 로 옮겼다. 모든 규칙은 body.shell-v2 로 시작한다.
 *   ⚠️ 덮어쓰기 대상: shell2.css(.lib-*) · framer.css(카드 표면). 원본은 읽기 전용. */

/* ════════ 라이브러리 · 프로젝트 에셋 ════════ */
body.shell-v2 .lib-wrap { max-width: 1320px; padding: var(--sp-xl) var(--page-gutter) var(--sp-section); gap: var(--sp-lg); }
body.shell-v2 .lib-head { align-items: center; gap: var(--sp-md); }
body.shell-v2 .lib-head .hub-title { margin: 0; }

/* 검색 — 아이콘 + 알약 입력 · 포커스 링 */
body.shell-v2 .lib-search-wrap { position: relative; display: flex; align-items: center; width: min(320px, 100%); }
body.shell-v2 .lib-search-wrap > svg { position: absolute; left: 14px; color: var(--ink-48); pointer-events: none; }
body.shell-v2 .lib-search-wrap .lib-search {
  width: 100%; min-width: 0; height: 40px; padding: 0 14px 0 38px;
  background: var(--field-fill); border: 1px solid var(--field-edge); border-radius: var(--r-pill);
  color: var(--ink); font: 400 var(--fs-caption)/1 var(--font-sans); letter-spacing: var(--ls-caption);
  transition: background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
body.shell-v2 .lib-search-wrap .lib-search::placeholder { color: var(--ink-48); }
body.shell-v2 .lib-search-wrap .lib-search:hover { background: var(--field-fill-hover); border-color: var(--field-edge-hover); }
body.shell-v2 .lib-search-wrap .lib-search:focus,
body.shell-v2 .lib-search-wrap .lib-search:focus-visible { outline: none; background: var(--field-fill-hover); border-color: var(--accent); box-shadow: var(--ring-focus); }
body.shell-v2 .lib-search-wrap:focus-within > svg { color: var(--ink-80); }

/* 소유자 필터(2026-09-21) — 라이브러리가 팀 전체가 되며 생겼다. 검색과 **같은 필드 모양**을 쓴다
 *   (`--field-fill`/`--field-edge` — 그 토큰이 이 앱의 입력칸 표면이고, 여기서 따로 색을 지어내면
 *   같은 줄의 두 칸이 다른 물건처럼 보인다). 네이티브 `<select>` 라 화살표는 브라우저가 그린다. */
body.shell-v2 .lib-owner {
  height: 40px; padding: 0 12px; flex: 0 0 auto; max-width: 180px;
  background: var(--field-fill); border: 1px solid var(--field-edge); border-radius: var(--r-pill);
  color: var(--ink); font: 400 var(--fs-caption)/1 var(--font-sans); letter-spacing: var(--ls-caption);
  transition: background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
body.shell-v2 .lib-owner:hover:not(:disabled) { background: var(--field-fill-hover); border-color: var(--field-edge-hover); }
body.shell-v2 .lib-owner:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--ring-focus); }
/* 고를 것이 하나뿐이면 비활성 — 눌러도 아무 일이 없는 칸을 또렷하게 두지 않는다. */
body.shell-v2 .lib-owner:disabled { opacity: 0.5; cursor: default; }

/* 종류 칩 — 한 줄 레일(넘치면 가로 스크롤 · 스냅). 레일이 wrap 패딩까지 뻗어 칩이 가장자리에서 잘려 보이지 않게 한다. */
body.shell-v2 .lib-chips {
  flex-wrap: nowrap; gap: 6px; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; scrollbar-width: none;
  margin: 0 calc(-1 * var(--sp-xl)); padding: 2px var(--sp-xl); scroll-padding-inline: var(--sp-xl);
}
body.shell-v2 .lib-chips::-webkit-scrollbar { display: none; }
body.shell-v2 .lib-chips .lib-chip {
  flex: none; scroll-snap-align: start; height: 32px; padding: 0 14px; /* 34 → 32: 컨트롤 사다리(28·32·36·40·44) — 이 칩만 눈금 밖이었다(2026-09-18 감사) */
  background: transparent; color: var(--ink-48); font-size: var(--fs-caption); font-weight: 500; border-radius: var(--r-pill);
}
body.shell-v2 .lib-chips .lib-chip:hover { background: var(--surface-1); color: var(--ink-80); }
body.shell-v2 .lib-chips .lib-chip.is-active,
body.shell-v2 .lib-chips .lib-chip.is-active:hover { background: var(--surface-3); color: var(--ink); }

/* 본문 = 그리드 + 인스펙터 */
body.shell-v2 .lib-body { grid-template-columns: minmax(0, 1fr); gap: 0; } /* 인스펙터는 칼럼이 아니라 시트다(2026-09-17) */
body.shell-v2 .lib-grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--grid-gap); align-content: start; align-items: start; } /* 16:9 시트가 읽히는 폭 · align-items: 클립 칸은 높이가 제각각이라(원본 비율) 카드가 행 높이로 늘어나면 제목 아래가 빈다 */
/* 클립 칩 = 정렬 행(홈 '최근 영상' 과 같은 배치 — 2026-09-22 오너 *"홈에 있는 최근 영상 갤러리의 규칙을
 * 따르면 … 높이가 고정이고 넓이가 가변적"*). 위치·크기는 JS(`libraryClipLayout`)가 인라인으로 정하고
 * CSS 는 **그 자리에 설 수 있게만** 한다. 다른 종류는 비율이 한 가지라 위의 고정 열 격자 그대로다. */
body.shell-v2 .lib-grid > .lib-justified { grid-column: 1 / -1; position: relative; width: 100%; }
body.shell-v2 .lib-justified > .lib-card { position: absolute; top: 0; left: 0; }
/* ⚠️ 타일 높이는 행이 정한다 — 카드마다 얹던 `aspect-ratio` 를 여기서 꺼야 두 규칙이 다투지 않는다.
 *   행 높이가 상한(H_MAX_RATIO)에 걸린 타일은 제 비율과 조금 달라지고 그만큼 `cover` 가 잘라 낸다(홈과 같다). */
body.shell-v2 .lib-justified .lib-card-thumb { aspect-ratio: auto; }
/* 캡션은 **한 줄씩**이다 — 폭이 카드마다 다른데 줄 수까지 달라지면 행 높이가 어긋난다(배치는 캡션 높이를
 *   하나로 잡는다). 실측 높이는 JS 가 첫 배치 뒤 재서 쓴다. */
body.shell-v2 .lib-justified .lib-card-title,
body.shell-v2 .lib-justified .lib-card-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

body.shell-v2 .lib-grid > .hub-muted {
  grid-column: 1 / -1; padding: var(--sp-xxl) var(--sp-lg); text-align: center;
  background: var(--surface-1); border-radius: var(--r-xl); font-size: var(--fs-caption);
}
body.shell-v2 .lib-grid > .btn { grid-column: 1 / -1; justify-self: center; }

/* 카드 */
body.shell-v2 .lib-card {
  min-width: 0; gap: 8px; padding: 6px 6px 10px; border-radius: var(--r-lg);
  transition: background var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
body.shell-v2 .lib-card:focus-visible { outline: none; box-shadow: var(--ring-focus); }
body.shell-v2 .lib-card.is-selected { background: var(--surface-2); border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
/* 캐릭터·배경 시트는 여러 컷을 가로로 붙인 16:9 라 정사각 cover 가 가운데만 잘랐다(오너 피드백 2026-09-17 — 홈과 같은 처리) — 16:9 칸에 전체를 담는다 */
body.shell-v2 .lib-card-thumb { position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-md); background: var(--surface-2); overflow: hidden; }
body.shell-v2 .lib-card--audio .lib-card-thumb { aspect-ratio: 16 / 10; }
body.shell-v2 .lib-card-thumb img { object-fit: contain; transition: transform 0.25s var(--ease); }
/* 영상 클립 타일 — 정지 이미지가 없어 <video> 가 0.6초 프레임을 그린다(videoThumbLoader).
 * ★ 칸이 **원본 비율**을 받는다(libraryPage 가 loadedmetadata 에서 aspect-ratio 를 얹는다) — 2026-09-21 오너:
 *   *"세로 영상일 때는 세로 영상 크기에 맞게 … 검은 여백 없게"*. 16:9 칸 + contain 이 세로 클립의 좌우를 검게 남겼다.
 * ⚠️ 기본값은 **세로**다(9:16). 이 제품의 클립은 대부분 세로라(clipGrid.js 와 같은 전제) 흔한 쪽은 메타데이터가
 *   와도 칸이 움직이지 않는다 — 16:9 를 기본으로 두면 거의 모든 타일이 뒤늦게 뛴다.
 * ⚠️ cover 인 이유: 칸 = 원본 비율이므로 잘릴 것이 없다(여백도 없다). 극단 비율만 clipThumbAspect 가 가두고,
 *   그때는 잘라 내는 쪽이 검은 여백보다 낫다. contain 으로 되돌리면 가둔 타일에 여백이 되살아난다. */
body.shell-v2 .lib-card--clip .lib-card-thumb { aspect-ratio: 9 / 16; }
body.shell-v2 .lib-card-video { width: 100%; height: 100%; object-fit: cover; background: #000; pointer-events: none; }
body.shell-v2 .lib-card:hover .lib-card-thumb img { transform: scale(1.03); }
body.shell-v2 .lib-card-title { padding: 0 4px; font-size: var(--fs-caption); font-weight: 500; letter-spacing: var(--ls-caption); color: var(--ink); }
body.shell-v2 .lib-card-meta { padding: 0 4px; margin-top: -4px; font-size: 12px; color: var(--ink-48); }

/* 이미지 없는 항목 — 종류 아이콘 + 이니셜 */
body.shell-v2 .lib-card-empty { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--ink-48); }
body.shell-v2 .lib-card-empty-ico { position: absolute; top: 10px; left: 10px; }
body.shell-v2 .lib-card-initial {
  width: 30%; aspect-ratio: 1 / 1; display: grid; place-items: center; border-radius: var(--r-md);
  background: var(--surface-3); color: var(--ink-80); font-size: 20px; font-weight: 600;
}
/* 오디오 — 종류 아이콘 + 장식 파형 */
body.shell-v2 .lib-card-audio { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-between; padding: 12px; }
body.shell-v2 .lib-card-audio-ico { width: 32px; height: 32px; display: grid; place-items: center; border-radius: var(--r-pill); background: var(--surface-3); color: var(--ink-80); }
body.shell-v2 .lib-card-wave { display: flex; align-items: center; gap: 3px; height: 38%; }
body.shell-v2 .lib-card-wave i { flex: 1; min-width: 2px; height: var(--h, 40%); border-radius: 2px; background: var(--ink-48); opacity: 0.45; }
body.shell-v2 .lib-card:hover .lib-card-wave i, body.shell-v2 .lib-card.is-selected .lib-card-wave i { opacity: 0.8; }

/* 인스펙터 */
/* 인스펙터 = 시트(2026-09-17 오너 · kobra Sheet 규격을 Framer 다크 토큰으로) — 항목을 누를 때만 뜬다.
 *   넓은 화면: 오른쪽 변에 붙은 640px 패널(모양은 edge-attached.css) · 트레이와 같은 500ms cubic-bezier(.32,.72,0,1) 로 화면 밖에서 밀려 들어온다 · 닫힘 300ms.
 *   ≤810px: 아래 미디어쿼리의 바텀시트. 동작(대화상자·Escape·Tab 가두기·스크롤 잠금)은 librarySheet.js. */
body.shell-v2 .lib-inspector, body.shell-v2 .lib-scrim { display: none; }
body.shell-v2 .lib-wrap.lib-has-sel .lib-inspector {
  display: flex; flex-direction: column; position: fixed; z-index: 910;
  top: var(--sp-sm); bottom: var(--sp-sm); right: var(--sp-sm); width: 640px; max-width: calc(100% - 2 * var(--sp-sm)); min-height: 0; max-height: none; /* 폭 440 → 640(오너 2026-09-17 — 미리보기를 크게) */
  padding: 0; overflow: hidden; border-radius: var(--r-xl); word-break: keep-all; /* 떠 있는 패널 반경 = --r-xl(framer.css 패널 규칙 · kobra 16 은 토큰 밖) */
  background: var(--surface-1); box-shadow: 0 0 0 1px var(--hairline), var(--shadow-float);
  /* 등장 모션 = 트레이와 같다(2026-09-18 오너 "드로어는 더 빠르고 갑작스럽다 — 트레이 기준으로"): 페이드 없이 화면 밖(100%)에서 500ms 로 밀려 들어온다.
   *   전에는 16px·300ms·페이드라 '제자리에서 켜지는' 느낌이었다. 닫힘도 트레이처럼 300ms 로 화면 밖까지. */
  transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
  @starting-style { transform: translateX(100%); }
}
body.shell-v2 .lib-wrap.lib-has-sel .lib-scrim {
  display: block; position: fixed; inset: 0; z-index: 909;
  background: color-mix(in srgb, var(--canvas) 48%, transparent);
  transition: opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1); /* = 트레이 ::backdrop */
  @starting-style { opacity: 0; }
}
body.shell-v2 .lib-wrap.lib-sheet-leaving .lib-inspector { transform: translateX(calc(100% + var(--sp-sm))); transition-duration: 0.3s; }
body.shell-v2 .lib-wrap.lib-sheet-leaving .lib-scrim { opacity: 0; transition-duration: 0.3s; }
body.shell-v2 .lib-ins { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0; }
/* 간격 점검(2026-09-17 — DESIGN.md 'AIDRA 적용 간격'): 네 변 --modal-pad 20 으로 통일 · 머리→내용 --sp-md · 닫기는 머리 글 두 줄의 가운데 */
body.shell-v2 .lib-ins-head { display: flex; flex-direction: column; gap: 2px; padding: var(--modal-pad) calc(var(--modal-pad) + 32px + var(--sp-sm)) var(--sp-md) var(--modal-pad); }
body.shell-v2 .lib-ins-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0; padding: 0 var(--modal-pad) var(--modal-pad); overflow-y: auto; overscroll-behavior: contain; }
body.shell-v2 .lib-ins-desc { margin: 0; font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--ink-48); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body.shell-v2 .lib-ins-close {
  position: absolute; top: calc(var(--modal-pad) + 4px); right: var(--modal-pad); width: 32px; height: 32px; padding: 0; margin: 0;
  display: inline-grid; place-items: center; border: 0; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.05); color: var(--ink-48); cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
body.shell-v2 .lib-ins-close:hover { background: rgba(255, 255, 255, 0.10); color: var(--ink); }
body.shell-v2 .lib-ins-close:focus-visible { outline: none; box-shadow: var(--ring-focus); }
body.shell-v2 .lib-inspector:focus { outline: none; }
body.shell-v2 .lib-ins-preview { position: relative; flex: none; min-height: 0; margin-bottom: var(--sp-xs); aspect-ratio: 4 / 3; background: var(--surface-2); border-radius: var(--r-md); }
body.shell-v2 .lib-ins-preview img { width: 100%; height: 100%; object-fit: contain; }
/* 클립 미리 보기 — 칸이 원본 비율(`--ar`, libraryInspector 가 loadedmetadata 에서 얹는다 · 기본 세로)을 받는다.
 * ⚠️ 폭을 100% 로 두면 세로 클립이 시트 높이를 훌쩍 넘는다(600px 폭 × 16/9 = 1067px). 그래서 **높이 상한에서
 *   폭을 거꾸로 푼다** — `min(100%, 상한 × 비율)`. 가로 클립은 100% 쪽이 이겨 지금과 같다. */
body.shell-v2 .lib-ins-preview--video { --ar: 0.5625; aspect-ratio: var(--ar); width: min(100%, calc(58vh * var(--ar))); align-self: center; }
body.shell-v2 .lib-ins-video { width: 100%; height: 100%; object-fit: contain; background: #000; border-radius: inherit; } /* 타일과 달리 contain — 재생기라 가둔 극단 비율에서 잘라 내는 것보다 여백이 낫다 */
body.shell-v2 .lib-ins-preview--audio, body.shell-v2 .lib-ins-preview--empty { aspect-ratio: auto; min-height: 140px; flex-direction: column; gap: var(--sp-sm); padding: var(--sp-md); color: var(--ink-48); }
body.shell-v2 .lib-ins-preview-ico { width: 48px; height: 48px; display: grid; place-items: center; border-radius: var(--r-pill); background: var(--surface-3); color: var(--ink-80); }
/* 이미지가 있는 미리보기 — 고정 비율 상자에 contain 으로 넣으면 좌우(또는 위아래) 띠가 생긴다. 상자를 이미지 크기에 맞추고 바탕을 비운다. */
body.shell-v2 .lib-ins-preview:has(> img) { aspect-ratio: auto; max-height: none; background: transparent; }
/* 미리보기는 크게 본다(오너 2026-09-17 — 폭 440 → 640 과 같은 결정 · 상한 560/60dvh). 큰 미리보기가 주 동작을 폴드 아래로 밀던 문제는
 *   상한을 깎아서가 아니라 **가져오기·열기를 스크롤 밖 고정 발(.lib-ins-foot)로 옮겨서** 풀었다 — 미리보기가 아무리 커도 발은 늘 보인다.
 *   (2026-09-18 한때 360/40dvh 로 깎았다가 되돌렸다: 그 근거였던 '글자 하나짜리 670px' 는 목 모드의 SVG 이니셜 <img> 였고, 실데이터는 진짜 그림이다.) */
body.shell-v2 .lib-ins-preview > img { display: block; width: auto; height: auto; max-width: 100%; max-height: min(560px, 60dvh); margin: 0 auto; object-fit: contain; border-radius: var(--r-md); }
body.shell-v2 .lib-ins-preview-note { font-size: var(--fs-fine); color: var(--ink-48); }
body.shell-v2 .lib-ins-preview audio { width: 100%; height: 40px; }
body.shell-v2 .lib-ins-title { margin: 0; font-size: var(--fs-title-3); font-weight: 700; line-height: 1.35; letter-spacing: -0.2px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 속성 줄 — 위아래 같은 여백(--sp-sm)에 줄 사이 헤어라인. 전에는 선 위 12 · 아래 8 로 어긋났다 */
body.shell-v2 .lib-kv { grid-template-columns: 64px minmax(0, 1fr); gap: var(--sp-sm); padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline-soft); font-size: var(--fs-fine); line-height: var(--lh-caption); }
body.shell-v2 .lib-kv-k { color: var(--ink-48); }
body.shell-v2 .lib-kv-v { color: var(--ink-80); }
body.shell-v2 .lib-ins-body > .hub-muted { margin: 0; padding: var(--sp-sm) 0; font-size: var(--fs-fine); line-height: var(--lh-caption); }
/* 가져오기 묶음은 시트 발(.lib-ins-foot) 안에 산다 — 경계선·윗여백은 발이 소유한다(선이 두 개 그어지지 않게).
 *   🔴 발은 칠하지 않는다(2026-09-19 오너 "하단 영역은 리퀴드 글라스가 아니고 테두리도 안 보인다"). 전엔 불투명 --canvas 였는데
 *      자식의 배경은 패널의 안쪽 광연(inset 1px --lg-edge-overlay)을 덮어 발 구간만 윤곽이 사라졌고, 유리 위에 검정 띠가 떴다.
 *      본문은 제 칸(.lib-ins-body)에서 스크롤하므로 발 아래로 글자가 지나갈 일이 없다 — 불투명으로 가릴 이유가 없다.
 *      블러를 따로 걸지도 않는다(부모가 backdrop-filter 라 자식 블러는 샘플할 게 없다). 구분선은 알파(--hairline → --lg-divider). */
body.shell-v2 .lib-ins-foot {
  flex: none; padding: var(--sp-md) var(--modal-pad) var(--modal-pad);
  background: transparent; border-top: 1px solid var(--hairline);
}
body.shell-v2 .lib-ins-import { gap: var(--toolbar-gap); margin-top: 0; padding-top: 0; border-top: 0; }
body.shell-v2 .lib-ins-import > .hub-muted { margin: 0; font-size: var(--fs-fine); }
body.shell-v2 .lib-ins-sub { text-transform: none; letter-spacing: var(--ls-caption); font-size: var(--fs-caption); font-weight: 500; color: var(--ink); }
body.shell-v2 .lib-ins-import .lib-ins-select, body.shell-v2 .lib-ins-import .lib-ins-ep {
  width: 100%; height: 40px; padding: 0 var(--row-pad-inline); border: 1px solid var(--field-edge); border-radius: var(--r-md);
  background-color: var(--field-fill); color: var(--ink); font: 400 var(--fs-caption)/1 var(--font-sans);
}
body.shell-v2 .lib-ins-import .lib-ins-select:focus-visible, body.shell-v2 .lib-ins-import .lib-ins-ep:focus-visible { outline: none; box-shadow: var(--ring-focus); }
body.shell-v2 .lib-ins-hint { margin: 0; font-size: var(--fs-fine); color: var(--ink-48); text-align: center; }
/* 버튼 높이를 셀렉트(40)와 맞춘다 — md 버튼(36)이 바로 위 셀렉트보다 낮아 층이 어긋났다 · 보조 버튼은 가져오기 묶음과 --sp-sm 만큼 떨어진다 */
body.shell-v2 .lib-inspector .lib-ins-body .btn--block, body.shell-v2 .lib-inspector .lib-ins-foot .btn--block { min-height: 40px; }
body.shell-v2 .lib-inspector .lib-ins-open { margin-top: var(--sp-sm); flex: none; }

@media (prefers-reduced-motion: reduce) {
  body.shell-v2 .lib-card-thumb img { transition: none; }
  body.shell-v2 .lib-card:hover .lib-card-thumb img { transform: none; }
}

/* 태블릿 */
@media (max-width: 1199px) {
  body.shell-v2 .lib-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}

/* 모바일 — 그리드 2열 · 인스펙터는 바텀시트(항목을 고를 때만) */
@media (max-width: 810px) {
  body.shell-v2 .lib-wrap { padding: var(--sp-lg) var(--sp-md) var(--sp-section); gap: var(--sp-md); }
  body.shell-v2 .lib-head { flex-direction: column; align-items: stretch; gap: 12px; }
  body.shell-v2 .lib-search-wrap { width: 100%; }
  body.shell-v2 .lib-search-wrap .lib-search { height: 44px; font-size: 16px; } /* 16px = iOS 입력 확대 방지 */
  body.shell-v2 .lib-chips { margin: 0 calc(-1 * var(--sp-md)); padding: 2px var(--sp-md); scroll-padding-inline: var(--sp-md); gap: 8px; }
  body.shell-v2 .lib-chips .lib-chip { height: 44px; padding: 0 16px; }
  body.shell-v2 .lib-chips .lib-chip:not(.is-active) { background: var(--surface-1); }
  body.shell-v2 .lib-body { grid-template-columns: minmax(0, 1fr); gap: 0; }
  body.shell-v2 .lib-grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-xs); } /* 16:9 는 2열이면 너무 작다 */
  body.shell-v2 .lib-card { padding: 4px 4px 10px; }
  body.shell-v2 .lib-wrap.lib-has-sel .lib-inspector {
    left: 0; right: 0; bottom: 0; top: auto; width: auto; max-width: none;
    max-height: 85dvh; padding: 8px 0 env(safe-area-inset-bottom);
    border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: var(--shadow-float); transition: none;
    /* 🔴 fill-mode 는 both 가 아니라 backwards 다 — both 면 끝난 뒤에도 항등 transform 을 붙잡아
     *    이 시트가 backdrop root 가 되고, liquid-glass-overlays.css 가 여기 건 블러가 조용히 죽는다(2026-09-15 ⌘K 실측과 같은 부류).
     *    keyframes 의 to 가 `transform:none; opacity:1` 로 기본값과 같아 backwards 로 바꿔도 보이는 결과는 동일하다. */
    animation: lib-sheet-up 0.5s cubic-bezier(0.32, 0.72, 0, 1) backwards; /* = 트레이 등장(화면 밖에서 500ms) */
  }
  body.shell-v2 .lib-wrap.lib-has-sel .lib-inspector::before {
    content: ''; display: block; flex: none; width: 36px; height: 4px; margin: 2px auto 6px; border-radius: var(--r-pill); background: var(--surface-3);
  }
  body.shell-v2 .lib-wrap.lib-has-sel .lib-scrim { background: color-mix(in srgb, var(--canvas) 72%, transparent); }
  body.shell-v2 .lib-wrap.lib-sheet-leaving .lib-inspector { transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); }
  body.shell-v2 .lib-ins-head { padding: var(--sp-xs) calc(var(--sp-md) + 44px + var(--sp-xs)) var(--sp-sm) var(--sp-md); }
  body.shell-v2 .lib-ins-body { padding: 0 var(--sp-md) var(--sp-lg); }
  /* 바텀시트에서도 발은 스크롤 밖이다 — 좌우 여백은 본문과 같게, 아래는 홈 인디케이터 영역까지. */
  body.shell-v2 .lib-ins-foot { padding: var(--sp-sm) var(--sp-md) var(--sp-md); }
  body.shell-v2 .lib-inspector .lib-ins-foot .btn--block { min-height: 44px; } /* 좁은 화면의 주 동작 — 390px 실측 40px(44 미달) */
  body.shell-v2 .lib-ins-close { top: 18px; right: var(--sp-sm); width: 44px; height: 44px; }
  body.shell-v2 .lib-ins-preview { aspect-ratio: 4 / 3; max-height: 38dvh; }
  /* ⚠️ 위 줄이 `--video` 의 원본 비율을 덮는다(뒤에 오는 같은 특이도) — 바텀시트에서도 칸이 원본 비율을 받게 다시 적는다.
   *   높이 예산은 바텀시트의 38dvh 그대로이고, 폭을 그 높이에서 거꾸로 푼다(넓은 화면의 58vh 와 같은 방식). */
  body.shell-v2 .lib-ins-preview--video { aspect-ratio: var(--ar); max-height: none; width: min(100%, calc(38dvh * var(--ar))); }
  body.shell-v2 .lib-ins-preview--audio, body.shell-v2 .lib-ins-preview--empty { aspect-ratio: auto; min-height: 120px; }
  body.shell-v2 .lib-ins-import .lib-ins-select, body.shell-v2 .lib-ins-import .lib-ins-ep { height: 44px; font-size: 16px; }
  body.shell-v2 .lib-inspector .btn--block { min-height: 44px; }
}
/* 시트가 떠 있는 동안 뒤 페이지 스크롤 잠금(librarySheet.js 가 body 에 lib-sheet-open 을 붙였다 뗀다) */
body.shell-v2.lib-sheet-open, body.shell-v2.lib-sheet-open .shell-main { overflow: hidden; }
body.shell-v2.lib-sheet-open .lib-scrim { touch-action: none; }
@keyframes lib-sheet-up { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { body.shell-v2 .lib-wrap.lib-has-sel .lib-inspector, body.shell-v2 .lib-wrap.lib-has-sel .lib-scrim { animation: none; transition: none; } }

/* 격자 아래 한 줄 — 지금 보이는 것이 전부가 아닐 때만 선다(클립 스캔 상한). */
body.shell-v2 .lib-grid-note { grid-column: 1 / -1; padding-top: var(--sp-xs); font-size: var(--fs-fine); }
