:root {
  --sq-toolbar-height: 32px;
}

html[data-sq-toolbar] body {
  margin: 0 !important;
  padding-top: var(--sq-toolbar-height) !important;
  box-sizing: border-box !important;
}

html[data-sq-toolbar] sq-collab-toolbar {
  display: block;
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 2147483647;
  width: 100%;
  height: var(--sq-toolbar-height);
  min-height: var(--sq-toolbar-height);
}

html[data-sq-toolbar="chat"] #react-root,
html[data-sq-toolbar="docs"] #root,
html[data-sq-toolbar="project"] #root,
html[data-sq-toolbar="platform-admin"] #root,
html[data-sq-toolbar="platform-portal"] #root,
html[data-sq-toolbar="files"] #opencloud {
  height: calc(100vh - var(--sq-toolbar-height)) !important;
  min-height: calc(100vh - var(--sq-toolbar-height)) !important;
  max-height: calc(100vh - var(--sq-toolbar-height)) !important;
}

@supports (height: 100dvh) {
  html[data-sq-toolbar="chat"] #react-root,
  html[data-sq-toolbar="docs"] #root,
  html[data-sq-toolbar="project"] #root,
  html[data-sq-toolbar="platform-admin"] #root,
  html[data-sq-toolbar="platform-portal"] #root,
  html[data-sq-toolbar="files"] #opencloud {
    height: calc(100dvh - var(--sq-toolbar-height)) !important;
    min-height: calc(100dvh - var(--sq-toolbar-height)) !important;
    max-height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }
}

html[data-sq-toolbar="chat"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="chat"] #react-root {
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  width: auto !important;
  max-width: none !important;
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
  margin: 0 !important;
  overflow: hidden !important;
  transform: translateZ(0);
}

html[data-sq-toolbar="docs"] #sidebar {
  top: var(--sq-toolbar-height) !important;
  height: calc(100vh - var(--sq-toolbar-height)) !important;
  max-height: calc(100vh - var(--sq-toolbar-height)) !important;
}

@supports (height: 100dvh) {
  html[data-sq-toolbar="docs"] #sidebar {
    height: calc(100dvh - var(--sq-toolbar-height)) !important;
    max-height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }
}

html[data-sq-toolbar="files"] body {
  overflow: hidden !important;
}

html[data-sq-toolbar="files"] #opencloud #web,
html[data-sq-toolbar="files"] #opencloud #web-content {
  height: 100% !important;
  min-height: 0 !important;
  max-height: 100% !important;
}

/* [설명] Planka와 Platform Admin은 100vh 셸을 사용하므로 문서 스크롤 대신 툴바 아래 앱 영역만 스크롤합니다.
   /portal 은 같은 Platform Admin 번들·같은 #root 인데 toolbar.js 가 별도 서비스
   id(platform-portal)로 표시한다 — 여기 규칙에 빠지면 generic padding-top 만 적용돼
   문서가 툴바 높이만큼 넘치고(실측: scrollHeight 891 vs 뷰포트 859) 스크롤 시
   사이드바가 고정 툴바 밑으로 묻힌다(2026-08-25). platform-admin 과 항상 짝으로 둔다. */
html[data-sq-toolbar="project"] body,
html[data-sq-toolbar="design"] body,
html[data-sq-toolbar="platform-admin"] body,
html[data-sq-toolbar="platform-portal"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="project"] #root,
html[data-sq-toolbar="design"] #app,
html[data-sq-toolbar="platform-admin"] #root,
html[data-sq-toolbar="platform-portal"] #root {
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  width: auto !important;
  height: auto !important;
  min-height: 0 !important;
}

/* [설명] Penpot 루트는 #app 이며 캔버스가 자체 스크롤·줌을 갖는다. */
html[data-sq-toolbar="design"] #app {
  overflow: hidden !important;
}

/* [설명] Penpot 내부 레이아웃이 뷰포트 높이(100vh/100dvh)를 기준으로 잡혀서, 툴바 아래로
   고정된 #app(=viewport-툴바높이) 안에서 100vh 만큼 커지면 하단이 툴바 높이만큼 넘쳐
   잘린다(2026-08-08 실측: 아래가 숨김). #app 의 자식을 #app 높이(100%)에 맞춰 뷰포트
   기준 높이를 무력화해 하단 잘림을 없앤다. */
html[data-sq-toolbar="design"] #app > * {
  height: 100% !important;
  max-height: 100% !important;
  min-height: 0 !important;
}

/* [설명] Planka 보드의 가로 스크롤 소유자는 리스트 컨테이너가 아니라 루트다.
   Planka CSS 의 `#app ._lists_` 는 inline-flex·min-width:100% 로 넓어지기만 하고
   overflow 를 갖지 않아서, 원본에서는 문서(html/body)가 그 넘침을 스크롤한다.
   툴바가 body 스크롤을 막고 #root 를 고정하면 넘침 소유자가 #root 로 옮겨오는데,
   여기서 overflow 를 hidden 으로 두면 리스트 폭이 뷰포트를 넘는 좁은 화면(모바일)에서
   가로 스크롤이 통째로 죽는다 — 2026-08-13 실측: #root cw=1536 sw=3032 인데 사용자
   스크롤 불가, 툴바를 끄면 문서 스크롤(html sw=3032)로 정상 이동. 데스크톱은 리스트가
   뷰포트에 다 들어가 넘치지 않으므로 증상이 보이지 않는다.

   세로도 같은 이유로 열어야 한다(2026-08-14 정정). 앞서 "세로는 리스트 내부
   (_cardsInnerWrapper)가 자체 스크롤하므로 루트에서 다시 열지 않는다"고 적었으나
   틀렸다 — 보드 셸 `#app ._wrapper_amg4a_31` 은 `height: 100%` 에 `margin-top: 174px`
   (헤더 높이)를 더해 잡으므로 **항상 루트 높이를 174px 초과**한다. 원본 Planka 는 그
   넘침을 문서 스크롤이 받아내는데, 툴바가 body 스크롤을 막고 #root 를 고정한 뒤
   overflow-y 까지 hidden 으로 두면 그 174px 가 갈 곳이 없어 하단이 통째로 잘린다.
   2026-08-14 실측(루트 높이를 줄여 작은 화면을 재현): 루트 600/500/400 모두 **174px
   잘림** — 마지막 카드가 루트 밖 291px. auto 로 열면 세 경우 모두 잘림 0 이고 마지막
   카드까지 닿는다. Planka 헤더는 position:fixed 라 루트가 스크롤해도 top=32 를 지키므로
   "화면이 두 번 밀리는" 일은 없다(실측).
   `#root > * { min-height: 0 }` 로 보드 셸만 줄이는 안은 하위 `._lists_` 가 따라 줄지
   않아 넘침이 그대로 남았다(실측: 마지막 카드 루트 밖 291px 유지) — 그래서 쓰지 않는다. */
html[data-sq-toolbar="project"] #root {
  overflow-x: auto !important;
  overflow-y: auto !important;
}

html[data-sq-toolbar="platform-admin"] #root,
html[data-sq-toolbar="platform-portal"] #root {
  overflow: hidden !important;
}

/* [설명] Platform Admin 셸은 자기 높이를 100vh 로 잡는다. #root 는 툴바 아래로 고정돼
   32px 짧은데 그 안에서 100vh 가 살아 있으면 내용이 위로 밀려 상단 로고·헤더 아이콘이
   툴바에 가리고 사이드바 접기까지 어긋난다(2026-08-09 실측).
   직계 자식만 겨냥하면 안 된다 — UI 개편으로 `.radix-themes` 래퍼가 하나 끼면서
   `#root > .solution-shell` 이 빗나가 같은 증상이 되살아났다. 래퍼가 몇 겹이 되든
   버티도록 직계 자식과 셸을 함께 100% 로 눌러 뷰포트 기준 높이를 무력화한다. */
html[data-sq-toolbar="platform-admin"] #root > *,
html[data-sq-toolbar="platform-admin"] #root .solution-shell,
html[data-sq-toolbar="platform-portal"] #root > *,
html[data-sq-toolbar="platform-portal"] #root .solution-shell {
  width: 100% !important;
  height: 100% !important;
  max-height: 100% !important;
  min-height: 0 !important;
}

/* [설명] /admin 아래엔 앱셸(.solution-shell)을 쓰는 관리 화면 말고도, collab-shell 설치
   안내(/admin/install) 같은 로그인 불필요 랜딩이 platform-admin 번들로 서빙된다. 이런
   페이지는 앱셸 없이 일반 문서 흐름으로 길어지는데, 위의 #root 고정·overflow:hidden 과
   #root>* 높이 클램프가 앱셸을 가정하고 걸려 내용이 툴바 아래에서 잘리고 세로 스크롤이
   사라진다(2026-08-09 실측: /admin/install scrollHeight 1420 vs #root 827, 아래 593px 숨김).
   앱셸이 없는 #root 에 한해 세로 스크롤을 허용하고 자식 높이 클램프를 풀어 문서가 자연
   높이로 늘어나며 #root 가 스크롤하게 한다. 앱셸 화면은 :has 로 제외돼 그대로 유지된다. */
html[data-sq-toolbar="platform-admin"] #root:not(:has(.solution-shell)),
html[data-sq-toolbar="platform-portal"] #root:not(:has(.solution-shell)) {
  overflow-y: auto !important;
}
html[data-sq-toolbar="platform-admin"] #root:not(:has(.solution-shell)) > *,
html[data-sq-toolbar="platform-portal"] #root:not(:has(.solution-shell)) > * {
  height: auto !important;
  max-height: none !important;
  min-height: 0 !important;
}

/* [설명] ChartDB 편집기는 데스크톱에서 100vh, 모바일에서 100dvh를 직접 점유합니다.
   generic body padding 위에 그대로 두면 문서가 툴바 높이만큼 더 길어져 하단 canvas 도구가
   잘립니다. #root를 툴바 아래 가용 영역으로 고정하고 전체 화면 직계 자식만 100%로 눌러
   편집기는 정확히 맞추되, 소스·템플릿 같은 문서형 화면은 #root가 계속 스크롤하게 합니다. */
html[data-sq-toolbar="chartdb"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="chartdb"] #root {
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  width: auto !important;
  height: auto !important;
  min-height: 0 !important;
  overflow: auto !important;
}

html[data-sq-toolbar="chartdb"] #root > .h-screen,
html[data-sq-toolbar="chartdb"] #root > .h-dvh {
  height: 100% !important;
  min-height: 0 !important;
}

html[data-sq-toolbar="chartdb"] #root > .min-h-screen {
  min-height: 100% !important;
}

/* [설명] 모바일 toast viewport의 top-0은 툴바 뒤에 가려집니다. 데스크톱은 기존 bottom
   배치를 유지하고 좁은 화면에서만 실제 가용 높이로 내립니다. */
@media (max-width: 639px) {
  html[data-sq-toolbar="chartdb"] [data-radix-toast-viewport] {
    top: var(--sq-toolbar-height) !important;
    max-height: calc(100vh - var(--sq-toolbar-height)) !important;
    max-height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }
}

/* [설명] Gitea 는 body 가 flex column·height 100vh·border-box 라 툴바 padding-top 만으로
   레이아웃이 완성된다. 예전의 .full.height min-height 강제는 footer(37px)를 body 밖으로
   밀어 문서 스크롤을 만들었다 — 로그인 화면 실측: scrollHeight 1116 vs 뷰포트 1079
   (2026-08-07). 규칙을 제거하면 flex 배분으로 스크롤 0·footer 하단 고정이 된다. */

html[data-sq-toolbar="storybook"] #root {
  height: calc(100vh - var(--sq-toolbar-height)) !important;
  min-height: calc(100vh - var(--sq-toolbar-height)) !important;
}

html[data-sq-toolbar="sdk"] body {
  padding-top: 0 !important;
}

html[data-sq-toolbar="sdk"] .page > header.header {
  inset-block-start: var(--sq-toolbar-height) !important;
}

html[data-sq-toolbar="sdk"] .sidebar-pane {
  inset-block-start: calc(var(--sl-nav-height) + var(--sq-toolbar-height)) !important;
}

html[data-sq-toolbar="sdk"] .main-frame {
  padding-top:
    calc(
      var(--sl-nav-height) + var(--sl-mobile-toc-height) + var(--sq-toolbar-height)
    ) !important;
}

html[data-sq-toolbar="sdk"] .right-sidebar {
  height: calc(100vh - var(--sq-toolbar-height)) !important;
  padding-top: calc(var(--sl-nav-height) + var(--sq-toolbar-height)) !important;
}

html[data-sq-toolbar="sdk"] mobile-starlight-toc > nav {
  top: calc(var(--sl-nav-height) + var(--sq-toolbar-height) - 1px) !important;
}

html[data-sq-toolbar="sdk"] starlight-menu-button button {
  top:
    calc(
      var(--sq-toolbar-height) +
        (var(--sl-nav-height) - var(--sl-menu-button-size)) / 2
    ) !important;
}

html[data-sq-toolbar="sdk"] .sl-skip-link {
  top: calc(12px + var(--sq-toolbar-height)) !important;
}

/* [설명] Scalar는 자체 컨테이너를 뷰포트에 고정하므로 본문 패딩 대신 고정 영역 자체를 툴바 아래로 내립니다. */
html[data-sq-toolbar="api"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="api"] #scalar-container {
  --full-height: calc(100vh - var(--sq-toolbar-height));
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  height: auto !important;
  min-height: 0 !important;
  overflow-x: hidden !important;
  overflow-y: auto !important;
}

/* [설명] Scalar가 내부에서 100dvh를 다시 선언하므로 실제 레이아웃 변수와 최소 높이도 툴바를 제외한 값으로 맞춥니다. */
html[data-sq-toolbar="api"] #scalar-container .references-layout {
  --full-height: calc(100vh - var(--sq-toolbar-height));
  min-height: calc(100vh - var(--sq-toolbar-height)) !important;
}

/* [설명] Grafana와 Langfuse는 앱 루트가 뷰포트 높이를 직접 점유하므로 툴바 아래의 고정 영역으로 제한합니다. */
html[data-sq-toolbar="service-board"] body,
html[data-sq-toolbar="agent-board"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="service-board"] #reactRoot,
html[data-sq-toolbar="agent-board"] #__next {
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  width: auto !important;
  height: auto !important;
  min-height: 0 !important;
  overflow: auto !important;
}

html[data-sq-toolbar="sdk"] {
  scroll-padding-top:
    calc(
      1.5rem + var(--sl-nav-height) + var(--sl-mobile-toc-height) +
        var(--sq-toolbar-height)
    ) !important;
}

@supports (min-height: 100dvh) {
  html[data-sq-toolbar="storybook"] #root {
    min-height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }

  html[data-sq-toolbar="storybook"] #root {
    height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }

  html[data-sq-toolbar="sdk"] .right-sidebar {
    height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }

  html[data-sq-toolbar="api"] #scalar-container {
    --full-height: calc(100dvh - var(--sq-toolbar-height));
  }

  html[data-sq-toolbar="api"] #scalar-container .references-layout {
    --full-height: calc(100dvh - var(--sq-toolbar-height));
    min-height: calc(100dvh - var(--sq-toolbar-height)) !important;
  }

}

/* [설명] 영상 편집기 셸은 ChartDB 와 같이 h-screen w-screen overflow-hidden 을 직접 점유합니다.
   generic body padding 위에 그대로 두면 문서가 툴바 높이만큼 길어져 하단 타임라인이 잘립니다.
   그래서 앱 루트를 툴바 아래 가용 영역으로 고정합니다.

   대상을 툴바의 인접 형제(`sq-collab-toolbar + div`)로 잡던 규칙을 버립니다. 그 인접
   관계는 편집기에서 유지되지 않습니다 — 2026-09-10 실측(운영 이미지 그대로 로컬 재현):
   toolbar.js 는 t=192ms 에 앱 루트 바로 앞에 툴바를 넣어 그 순간에는 인접이 맞지만,
   React 가 t=341ms 와 t=678ms 에 앱 루트를 **폐기하고 새로 만들어** body 에 다시 답니다
   (편집기는 MobileGate 뒤 완전 클라이언트 렌더라 마운트가 여러 번 일어납니다). 그 결과
   툴바의 다음 형제는 `script#_R_` 가 되고 인접 선택자는 아무것도 고르지 못했습니다.
   같은 노드가 아니므로 마운트 시점에 표식을 달아 두는 방법도 함께 무효입니다.
   `/projects` 는 앱 루트가 서버 렌더라 인접이 살아남아 지금까지 정상으로 보였습니다.

   그래서 toolbar.js 가 쓰는 앱 루트 정의(`body > div:not([hidden])` 의 **첫** 요소)를
   CSS 로 그대로 옮깁니다. 뒤의 `:not(div:not([hidden]) ~ *)` 가 "앞에 보이는 div 형제가
   없다" 즉 "첫 번째"를 뜻합니다. Next 가 넣는 빈 `div[hidden]` 과 나중에 body 끝에 붙는
   다이얼로그 포털 레이어는 이 조건에서 걸러집니다. */
html[data-sq-toolbar="opencut"] body {
  padding-top: 0 !important;
  overflow: hidden !important;
}

html[data-sq-toolbar="opencut"] body > div:not([hidden]):not(div:not([hidden]) ~ *) {
  position: fixed !important;
  inset: var(--sq-toolbar-height) 0 0 !important;
  width: auto !important;
  height: auto !important;
  min-height: 0 !important;
  overflow: auto !important;
}
