/* ==========================================================================
   Homepage — canonical stylesheet

   01. Theme / global tokens
   02. Base / typography / scrollbar / SVG
   03. Desktop / taskbar / windows
   04. Content apps (gallery / diary / movie / guestbook)
   05. Popovers / previews / start menu
   06. Settings application
   07. Theme surfaces / interaction states
   08. Responsive rules

   NOTE: 같은 selector/property의 사망 선언(dead override)은 제거했습니다.
   Cascade 의미가 달라질 수 있는 서로 다른 selector 간 선언은 그대로 유지합니다.
   ========================================================================== */
:root {
  --taskbar-h: 50px;

  /* 영역별 기본 투명도(0~1). 과거 표면 계층(surface-*-alpha)의 대표값을 그대로 이어받음.
     system-*-alpha는 그 영역의 배경/테두리 전체에 단일 값으로 적용됨(요소별 깊이감 차이 없음). */
  --surface-alpha: .60;
  --surface-strong-alpha: .75;
  --surface-solid-alpha: .95;

  --focus-color: #2b97ff;
  --focus-rgb: 43, 151, 255;
  --focus-font-color: #fff;
  --focus-font-rgb: 255, 255, 255;

  --desktop-background-image: none;
  --desktop-background-position-landscape: 50% 50%;
  --desktop-background-position-portrait: 50% 50%;
  --desktop-shortcut-font-color: #000;
  --desktop-shortcut-hover-color: #fff;
  --desktop-shortcut-hover-rgb: 255, 255, 255;
  --desktop-shortcut-hover-alpha: .6;
  --desktop-shortcut-hover-font-color: #000;
  --desktop-shortcut-hover-shadow-color: #2b97ff;
  --desktop-shortcut-hover-shadow-rgb: 43, 151, 255;
  --desktop-shortcut-hover-shadow-alpha: .16;

  --z-background: 0;
  --z-content: 10;
  --z-window: 100;
  --z-popup: 200;
  --z-preview: 300;
  --z-toast: 400;
  --z-dialog: 500;
  --z-debug: 1000;
}

/* transition: all은 "이 요소에 바뀔 수 있는 모든 CSS 속성(width/height/
   left/top/transform/filter/backdrop-filter까지 포함)을 매 프레임 감시하다
   바뀌면 애니메이션해라"는 뜻이라, 페이지에 있는 모든 엘리먼트 각각에서
   실제로 필요도 없는 감시 비용을 계속 문다 — DOM이 늘어날수록(실제 게시글이
   쌓인 운영 서버가 게시글 몇 개 없는 로컬 테스트보다 훨씬 큼) 그 비용도
   같이 늘어 창 드래그처럼 매 프레임 스타일이 바뀌는 상호작용에서 체감
   버벅임으로 드러난다. 이 프로젝트에서 실제로 쓰는 hover 전환은 전부
   배경/글자/테두리색·그림자·투명도뿐이라(width/height/transform을 hover로
   쓰는 곳은 없음, 각자 자기 selector에서 따로 transition을 선언해 이 전역
   규칙보다 우선함) 그 다섯 속성만 감시하도록 좁힌다. */
* {
  transition: background-color .2s ease, color .2s ease, border-color .2s ease, box-shadow .2s ease, opacity .2s ease;
}

/* pointermove로 매 프레임 left/top/width/height를 갱신하는 동안
   전역 transition이 매번 0.2s ease로 뒤쫓아가며 커서보다 느리게 보이는 문제를 막음. */
.window.dragging,
.window.resizing {
  transition: none !important;
}

/* 초기 설정 마법사(homepage.html #setupWizardOverlay) — user.css의
   .user-guest-overlay를 그대로 재사용하되(배경/블러/중앙정렬 다 그쪽 몫),
   거긴 특정 창 하나(.user-modal-root)만 덮는 position:absolute라 여기선
   데스크톱 전체(작업표시줄 포함)를 덮도록 fixed로 다시 잡는다. 창/팝업/
   토스트(--z-debug: 1000)보다도 위에 있어야 어떤 상태에서도 항상 최상단에서
   보인다. */
.setup-wizard-overlay {
  position: fixed !important;
  z-index: calc(var(--z-debug) + 10);
}
.setup-wizard-overlay[hidden] {
  display: none !important;
}

html {
  background-color: transparent;
}
html,
body {
  height: 100%;
  overflow: hidden;
}
body {
  background: transparent !important;
}

/* 창이 뜨기 전(비동기 로딩) 동안 로딩 커서 — guardWindowOpen(homepage.ui.js). */
body.is-window-opening,
body.is-window-opening * {
  cursor: progress !important;
}

input {
  border: 0;
}

.desktop {
  background: transparent !important;
  position: relative;
  height: calc(100vh - var(--taskbar-h));
  overflow: hidden;
}

/* ==========================================================================
   바탕화면 바로가기(desktop shortcuts) — top/left/right/bottom 4영역
   각 영역(.desktop-region)은 padding/margin/gap 없이 아이콘이 필요로 하는
   만큼만 공간을 차지한다(flex: 0 0 auto). 영역이 공간을 차지하는 순서(우선순위)는
   JS(homepage.js의 getDesktopAreaOrder)가 계산해 .desktop-shortcuts와
   .desktop-region-remainder에 is-column/is-row(-reverse) 클래스를 중첩으로
   부여하는 방식으로 구현한다 — 먼저 배치되는 영역이 자기 축 전체를 차지하고,
   다음 영역은 "남은 사각형"(.desktop-region-remainder) 안에서만 배치된다.
   ========================================================================== */
.desktop-shortcuts {
  position: absolute;
  inset: 0;
  display: flex;
  padding: 3px;
}
.desktop-shortcuts.is-column,
.desktop-region-remainder.is-column {
  flex-direction: column;
}
.desktop-shortcuts.is-column-reverse,
.desktop-region-remainder.is-column-reverse {
  flex-direction: column-reverse;
}
.desktop-shortcuts.is-row,
.desktop-region-remainder.is-row {
  flex-direction: row;
}
.desktop-shortcuts.is-row-reverse,
.desktop-region-remainder.is-row-reverse {
  flex-direction: row-reverse;
}

.desktop-region {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  pointer-events: auto;
}
.desktop-region:empty {
  display: none;
}
.desktop-region--top,
.desktop-region--bottom {
  flex-direction: row;
}
.desktop-region--left,
.desktop-region--right {
  flex-direction: column;
}
.desktop-region--top.is-fill-reverse,
.desktop-region--bottom.is-fill-reverse {
  flex-direction: row-reverse;
}
.desktop-region--left.is-fill-reverse,
.desktop-region--right.is-fill-reverse {
  flex-direction: column-reverse;
}

.desktop-region-remainder {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  pointer-events: none;
}

.desktop-shortcut {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 60px;
  height: 60px;
  padding: 8px 4px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  text-align: center;
  justify-content: center;
}

/* 바탕화면 아이콘 전용 hover(설정 > 화면 디자인 편집기 > 바탕화면 > Hover에서 지정) */
.desktop-shortcut:not(.is-clicked):hover,
.desktop-shortcut:not(.is-clicked):focus,
.desktop-shortcut:not(.is-clicked):focus-within {
  background: rgba(var(--desktop-shortcut-hover-rgb), var(--desktop-shortcut-hover-alpha)) !important;
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%),
  0 5px 14px rgba(var(--desktop-shortcut-hover-shadow-rgb), var(--desktop-shortcut-hover-shadow-alpha)) !important;
}
.desktop-shortcut:not(.is-clicked):hover span,
.desktop-shortcut:not(.is-clicked):focus span,
.desktop-shortcut:not(.is-clicked):focus-within span {
  color: var(--desktop-shortcut-hover-font-color) !important;
}
/* svg 자체뿐 아니라 내부 path/g까지 같이 잡아야 한다 — body,body*{color:...}
   (아래 "--font-color Manage")가 특이도는 낮아도(0,0,1) svg 자식들을 직접
   지정하므로, svg 하나에만 색을 주면 상속이 아니라 그 body* 규칙이 자식에서
   그대로 이겨버린다(바로가기 아이콘이 테마 폰트색을 따르던 버그의 원인). */
.desktop-shortcut:not(.is-clicked):hover svg,
.desktop-shortcut:not(.is-clicked):focus svg,
.desktop-shortcut:not(.is-clicked):focus-within svg,
.desktop-shortcut:not(.is-clicked):hover svg *,
.desktop-shortcut:not(.is-clicked):focus svg *,
.desktop-shortcut:not(.is-clicked):focus-within svg * {
  color: var(--desktop-shortcut-hover-font-color) !important;
  stroke: var(--desktop-shortcut-hover-font-color) !important;
}

/* 임의의 배경사진 위에 놓이므로 테마 폰트색 대신 sound-popover와 같은 방식으로
   흰 글자 + 그림자로 고정해 가독성을 보장한다. */
.desktop-shortcut span {
  color: var(--desktop-shortcut-font-color);
  margin-top: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.desktop-shortcut svg,
.desktop-shortcut svg * {
  color: var(--desktop-shortcut-font-color);
  stroke: var(--desktop-shortcut-font-color)!important;
}

/* ==========================================================================
   z-index Manage
   ========================================================================== */
/* 배경 */
.desktop-background {
  z-index: var(--z-background);
}

/* 일반 콘텐츠 내부 */
.desktop,
.music-content,
.menu-admin-header,
.diary-weekdays,
.preview-close,
.guest-form {
  z-index: var(--z-content);
}

/* 일반 모달 */
.window {
  z-index: var(--z-window);
}

/* 모달 위 편집 레이어 */
.settings-editor-layer {
  z-index: calc(var(--z-window) + 10);
}

/* 작업표시줄 위 팝업 */
.popover,
.search-suggest {
  z-index: var(--z-popup);
}

/* 작업표시줄 미리보기는 팝업보다 위 */
.preview-card,
.window.preview-peek {
  z-index: var(--z-preview);
}

/* 시스템 메시지 */
.system-message-stack,
.taskbar,
.display-theme-anchor {
  z-index: var(--z-toast);
}

/* 화면 정중앙 확인 알람: 무엇보다 위 */
.confirm-dialog-overlay {
  z-index: var(--z-dialog);
}

/* 창 가장자리 리사이즈 핸들 — .confirm-dialog-overlay.is-window-scoped(위
   z-dialog)도 같은 .window의 자식이라, 창 안에 뜬 팝업이 핸들을 덮어 리사이즈가
   막히면 안 된다. 팝업이 떠 있어도 가장자리 드래그로 창 크기를 바꿀 수 있게
   z-dialog보다 위에 둔다(핸들은 커서용 투명 스트립이라 시각적으로는 무영향). */
.resize-handle {
  z-index: calc(var(--z-dialog) + 1);
}

/* ==========================================================================
   --font-color Manage
   기본값은 System C(윈도우 컨텐츠영역) 폰트색. 작업표시줄/윈도우바는 각자 tier로 재정의.
   ========================================================================== */
body, body * {
  color: var(--system-c-font-color);
}
.taskbar-scope, .taskbar-scope *,
.calendar-title {
  color: var(--system-a-font-color);
}
.window-bar, .window-bar * {
  color: var(--system-b-font-color);
}

.grid-cell-meta, .grid-cell-meta *,
.entry-meta, .entry-meta *,
.post-meta,.post-meta *,
.settings-panel-head span,
.settings-header-text span {
  color: var(--system-c-desc-color) !important;
}

/* System C: Title 폰트 (게시글/카드/섹션 제목류) */
h1, h2, h3,
.grid-cell-title,
.post-title,
.movie-card-title,
.settings-panel-head strong,
.settings-header-text strong,
.settings-editor-head strong,
.menu-admin-title,
.settings-music-title,
.music-title,
.diary-date-select {
  color: var(--system-c-title-color) !important;
}

.star-btn {
  color: var(--focus-color) !important;
}

.user-primary-button,.settings-form-actions .primary,
button:focus-visible:not(.settings-music-summary):not(.user-link-button):not(.profile-stat):not(.app-btn):not(.task-square):not(.status-btn):not(.clock):not(.shortcut):not(.gallery-power-button):not(.settings-header-breadcrumb):not(.window-address-button):not(.youtube-detail-player-toggle) {
  color: var(--focus-font-color) !important;
}

/* ==========================================================================
   --font-size Manage
   홈페이지(/homepage)에서 로드되는 모든 CSS(이 파일 + web/static/css/modals/*.css,
   user.css 포함)의 font-size 단일 진입점. 새 font-size는 component 규칙에 직접
   선언하지 말고 이 구역 하단의 px 값별 묶음에 selector를 추가할 것 — 자세한
   내용은 AGENTS.md Frontend 섹션 참고.
   예외: gallery.css는 독립 `/gallery` 페이지에서 단독 로드되어 이 구역이 적용되지
   않으므로 대상이 아니다(그 파일 상단 주석 참고).
   ========================================================================== */
/* 제목 */
  .title,
  .character-info-name,
  .start-menu-search input /*작업표시줄,시작메뉴: 검색*/,
  .diary-date-select,
  .profile-name, .profile-name-input,
  .calendar-title,
  .window-content-head,
  .calendar-head *,
  .settings-panel-head strong,
  .settings-header-text strong,
  .post-markdown-body h3, .post-markdown-body h3 *,
  .post-editor-content h3, .post-editor-content h3 *
  {
    font-size: 14px!important;
  }
/* 본문 */
  body, body *,
  .window-content *,
  .grid-cell-title /*window.grid.title*/,
  .settings-nav-btn,
  .suggest-item,
  .guest-form textarea,
  .mini-day,
  .activity-title
  {
    font-size: 12px;
  }
/* 작은글 */
  .clock,
  .grid-cell-meta /*window.grid.title*/,
  .post-meta /*게시글.meta*/,
  .post-admin-toolbar select,
  .preview-empty,
  .modal-template-loading, .modal-template-error,
  .settings-card-label,
  .settings-info-value,
  .settings-music-title,
  .settings-editor-head strong,
  .post-editor-title-input, .post-editor-visibility-select, .post-editor-format-btn, .window-post-visibility,
  .post-editor-content, .post-editor-message,
  .window-address-input, .window-address-message,
  .confirm-dialog-message,
  .settings-info-label,
  .mini-week span,
  .settings-theme-groups .theme-group-head-text strong,
  .settings-theme-groups .theme-row-label,
  .post-visibility-option,
  .entry-reply-input-wrap textarea,
  .diary-weekdays span,
  .diary-day,
  .close-all,
  .settings-empty,
  .menu-admin-title,
  .user-admin-name strong,
  .settings-form-field input[type=text], .settings-form-field input[type=url], .settings-form-field select,
  .settings-main-message,
  .suggest-item small,
  .settings-theme-groups .theme-alpha-value,
  .desktop-shortcut span,
  .shortcut:not(.start-search-post) strong,
  .entry-meta,
  .entry-reply-toggle,
  .entry-reply-submit-btn,
  .preview-label,
  .settings-panel-head span,
  .settings-header-text span,
  .menu-admin-row,
  .admin-action-button,
  .settings-log-item, .settings-log-item strong,
  .settings-form-field>span,
  .settings-check-row label,
  .settings-form-actions button,
  .specific-user-item strong,
  .settings-inline-message,
  .settings-theme-groups .theme-subsection-label,
  .settings-theme-groups .bg-region-tab,
  .menu-admin-header,
  .settings-pill,
  .user-admin-header,
  .user-admin-name span,
  .specific-user-item span, .specific-user-item time,
  .settings-theme-groups .bg-region-hint,
  .menu-hub-card strong, .menu-hub-card span,
  .menu-order-name strong, .desktop-shortcut-name, .desktop-shortcut-group-title,
  .desktop-shortcut-group-body:empty::before,
  .field-required-message,
  .post-image-viewer-position,
  .post-image-lightbox-position,
  .post-thumb-image-badge,
  .post-thumb-live2d-badge,
  .live2d-badge,
  .profile-login-id,
  .character-info-message,
  .window-post-search-count
  {
    font-size: 11px!important;
  }
/* ICON */
  .star-btn
  {
    font-size: 30px!important;
  }
  .window-actions > .window-minimize, .window-actions > .window-close {
    font-size: 15px!important;
  }
/* 아래는 컴포넌트별 개별 font-size(전역 !important 규칙에 의해 덮이지 않는 요소들).
   px 값별로 묶어 두었으니 크기를 바꾸려면 값을 옮겨 적지 말고 해당 selector를
   다른 묶음으로 옮기면 됨. */
/* 22px */
  .server-stats-visitor-count
  {
    font-size: 22px;
  }
/* 20px */
  .preview-close
  {
    font-size: 20px;
  }
/* 18px */
  .desktop-area-sort-handle, .post-image-viewer-nav, .post-image-lightbox-nav
  {
    font-size: 18px;
  }
/* 16px */
  .settings-header-toggle, .desktop-shortcut-handle
  {
    font-size: 16px;
  }
/* 15px */
  .post-image-remove-btn
  {
    font-size: 15px;
  }
/* 13px */
  .settings-header-breadcrumb
  {
    font-size: 13px;
  }
/* 11.5px */
  .post-mention
  {
    font-size: 11.5px;
  }
/* 10px (홈페이지 계열 전체 진입점 — user.css의 로그인·프로필·활동 화면 크기 포함) */
  .server-stats-visitor-count small, .settings-toggle-text,
  .user-loading-state p, .auth-label,
  .user-primary-button, .user-link-button,
  .profile-stat strong,
  .profile-actions .user-primary-button, .profile-edit-actions .user-primary-button,
  .small-btn
  {
    font-size: 10px;
  }
/* 9px (user.css 포함) */
  .server-stats-chart-axis, .server-stats-disk-meta, .server-stats-updated,
  .user-auth-message, .profile-login-id, .profile-stat small, .profile-edit-message
  {
    font-size: 9px;
  }
/* ==========================================================================
   --border-color-color Manage
   기본값은 System C(윈도우 컨텐츠영역). 작업표시줄/윈도우바는 각자 tier로 재정의.
   ========================================================================== */
* {
  border-color: rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;
}
.start-menu-search.input-text-box,
.taskbar-scope, .taskbar-scope * {
  border-color: rgba(var(--system-a-rgb), var(--system-a-alpha)) !important;
}
.window-bar, .window-bar * {
  border-color: rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
}
/* ==========================================================================
   스크롤 Manage
   width/track는 common.css와 동일하므로 재선언하지 않음. thumb 색상만 테마색으로 교체.
   ========================================================================== */
*::-webkit-scrollbar-thumb {
  background: rgba(var(--focus-rgb),.75);
  border-radius: 10px;
}
/* ==========================================================================
   window.grid
   ========================================================================== */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(max(240px, calc((100% - 48px) / 5)), 100%), 1fr));
  gap: 12px;
}

/* 그림/영화/캐릭터/유튜브 모달: 포스트(캐릭터) 수가 한 줄 최대 열 수보다 적어도
   카드 폭을 유지하고 남는 공간은 빈 칸으로 둔다 (auto-fit는 빈 트랙을 접어
   카드가 늘어남). */
.window[data-root="gallery"] [data-gallery-grid],
[data-movie-grid],
[data-character-grid], [data-youtube-grid] {
  grid-template-columns: repeat(auto-fill, minmax(min(max(240px, calc((100% - 48px) / 5)), 100%), 1fr));
}

/* 좁은 화면(모바일 등, 다른 곳과 같은 640px 기준)만 최소 카드 폭을 150px로
   낮춘다 — 기본 240px 그대로면 창 폭(모바일은 화면 전체, 패딩 빼고
   350~380px대)에 한 줄에 카드 1장만 들어간다. 데스크톱은 이 미디어쿼리
   밖이라 기본 240px를 유지한다. */
@media (max-width: 640px) {
  .window[data-root="gallery"] [data-gallery-grid],
  [data-movie-grid],
  [data-character-grid], [data-youtube-grid] {
    grid-template-columns: repeat(auto-fill, minmax(min(max(150px, calc((100% - 12px) / 5)), 100%), 1fr));
    gap: 3px;
  }
}

.grid-cell {
  border: 2px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  border-radius: 9px;
  cursor: pointer;
  padding: 7px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  user-select: none;
  -webkit-user-drag: none;
}

.grid-cell img {
  -webkit-user-drag: none;
}
.window[data-root="gallery"] .grid-cell {
  min-width: 0;
  padding: 7px;
  border-radius: 9px;
  cursor: pointer;
  background: transparent;
  transition: .15s;
}

/* 그림/영화 후기 등 .grid-cell 공용 hover — 기존 .normal-button:hover와 같은
   System C hover 배경/글자/그림자 변수를 그대로 재사용한다. 제목(.grid-cell-title/
   .post-title/.movie-card-title)은 자체적으로 !important 색을 고정해 두므로,
   상속만으로는 hover 글자색이 먹히지 않는다 — 더 높은 특이도의 !important 규칙으로
   명시적으로 덮어써야 한다. 아이콘(.post-visibility-icon)도 stroke:currentColor라
   같은 이유로 명시한다. 메타(.grid-cell-meta 및 그 안의 span/svg, 영화 후기의
   .movie-card-meta.grid-cell-meta 포함)는 반대로 hover 중에도 System C 설명색
   (--system-c-desc-color, 아래 --font-color Manage 규칙)을 유지해야 하므로 여기서
   재정의하지 않는다.
   .grid-cell.is-selected의 outline(선택 표시)은 별개 속성이라 그대로 유지된다. */
.grid-cell:hover {
  /* hover 배경은 콘텐츠 배경을 교체하지 않고 그 위에 오버레이로 얹는다 —
     --system-c-hover-alpha가 100 미만이어도 콘텐츠 위에 강조색이 겹쳐 보이도록
     (.normal-button:hover와 같은 방식). */
  background:
    linear-gradient(rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha)), rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha))),
    rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  color: var(--system-c-hover-font-color) !important;
  border-color: rgba(var(--system-c-hover-border-rgb), var(--system-c-hover-border-alpha)) !important;
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%),
    0 5px 14px rgba(var(--system-c-hover-shadow-rgb), var(--system-c-hover-shadow-alpha)) !important;
}
.grid-cell:hover .grid-cell-title,
.grid-cell:hover .post-title,
.grid-cell:hover .movie-card-title,
.grid-cell:hover .post-visibility-icon {
  color: var(--system-c-hover-font-color) !important;
}

.grid-cell-meta {
  margin-top: 4px;

}

.window[data-root="gallery"] .grid-cell-meta,
.window[data-root="youtube"] .grid-cell-meta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.window[data-root="gallery"] .grid-cell-meta span,
.window[data-root="youtube"] .grid-cell-meta span {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

/* 그리드↔리스트 전환("⋯ → 리스트로 전환") — 카드 마크업은 그대로 두고
   .grid-cell을 [썸네일 | 본문] 2열로 오버라이드한다. 제목/메타(영화는 별점
   포함)는 .grid-cell-body로 묶여 있고(그리드 뷰에선 display:contents로 투명),
   리스트 뷰에서만 세로 flex 컬럼이 된다. 썸네일과 본문 블록은 하단 정렬. */
/* 컨테이너 자체를 한 열로 바꾼다 — !important는 위 갤러리 전용
   `.window[data-root="gallery"] [data-gallery-grid]`(특이도가 이 클래스
   선택자보다 높음) 등 grid-template-columns를 정하는 기존 규칙들을 3개
   모달 공통으로 확실히 덮기 위함이다. */
.grid.is-list-view {
  grid-template-columns: 1fr !important;
}
.grid-cell-body {
  display: contents;
}
.grid.is-list-view .grid-cell {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: end;
  column-gap: 12px;
  padding: 6px 10px;
}
.grid.is-list-view .grid-cell > .grid-cell-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
/* 썸네일은 높이만 64px로 고정하고 폭은 각 메뉴 그리드 카드의 기본 비율
   (.post-thumb 16/9, .movie-poster 2/3, 캐릭터 아바타 1/1)을 그대로 따른다. */
.grid.is-list-view .grid-cell > .post-thumb-wrap,
.grid.is-list-view .grid-cell > .character-card-avatar-wrap {
  grid-column: 1;
  align-self: end;
  width: fit-content;
  height: 64px;
  padding: 0;
}
/* <img>/aspect-ratio가 있는 썸네일: 높이만 채우고 폭은 비율대로. */
.grid.is-list-view .grid-cell .post-thumb,
.grid.is-list-view .grid-cell .movie-poster,
.grid.is-list-view .grid-cell .image-area {
  width: auto;
  height: 100%;
  object-fit: cover;
}
/* 캐릭터 아바타는 배경이미지 div(고유 비율 없음) — 정사각으로 고정. */
.grid.is-list-view .grid-cell .character-card-avatar {
  width: 64px;
  height: 64px;
}
/* 제목/설명 줄 바짝. */
.grid.is-list-view .grid-cell > .grid-cell-body > .post-title-row {
  margin: 0;
  line-height: 1.2;
}
.grid.is-list-view .grid-cell > .grid-cell-body > .grid-cell-meta,
.grid.is-list-view .grid-cell > .grid-cell-body > .movie-card-rating {
  margin: 0;
}

/* ==========================================================================
   SVG Manage
   ========================================================================== */
svg, svg:not([fill="currentColor"]) {
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.medium-svg {
  width: 17px;
  height: 17px;
}

.big-svg {
  width: 22px;
  height: 22px;
}

.input-text-box svg {
  flex: 0 0 auto;
}

/* ==========================================================================
   ETC
   ========================================================================== */

.taskbar { /* 작업표시줄 */
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--taskbar-h);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, .06);
  backdrop-filter: blur(20px) saturate(1.12);
  -webkit-backdrop-filter: blur(20px) saturate(1.12);
  border-top-color: rgba(var(--system-a-rgb), var(--system-a-alpha)) !important;
}

/* 좁은 화면은 작업표시줄 공간을 상시 예약하지 않는다. 하단 스와이프로
   .is-mobile-visible이 붙는 동안만 전체화면 모달 위에 오버레이한다. */
@media (max-width: 640px) {
  .desktop {
    height: 100vh;
    height: 100dvh;
  }

  .taskbar {
    transform: translateY(100%);
    transition: transform .2s ease;
  }

  .taskbar.is-mobile-visible {
    transform: translateY(0);
  }

  .taskbar,
  .shortcut-popover,
  .search-suggest,
  .sound-popover,
  .calendar-popover,
  .preview-card {
    z-index: calc(var(--z-dialog) - 1) !important;
  }
}

@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
  .taskbar {
    transition: none;
  }
}

/* 작업표시줄 좌측(시작+검색) / 우측(볼륨+시계) 묶음 — gap만 다름 */
.start-group, .status {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}
.start-group { gap: 4px; }
.status { gap: 1px; }

/* 작업표시줄 아이콘 버튼 공통 골격. 배경/글자/hover는 .sys-a-btn-a(§버튼)가 담당. */
.task-square, .app-btn, .status-btn, .gallery-power-button {
  border: 0;
  border-radius: 7px;
  display: grid;
  place-items: center;
  cursor: pointer;
  padding: 0;
}

.status-btn, .task-square, .app-btn {
  width: calc(var(--taskbar-h)*.9);
  height: calc(var(--taskbar-h)*.9);
}

.task-square, .app-btn {
  position: relative;
  flex: 0 0 auto;
}

.star-btn {
  line-height: 1;
  text-align: center;
}

.star-btn:after {
  content: "";
  position: absolute;
  left: 9px;
  right: 9px;
  bottom: 2px;
  height: 2px;
  border-radius: 99px;
  opacity: 0;
}

.input-text-box {
  position: relative;
  display: flex;
  align-items: center;
  padding: 0 12px;
  border-radius: 25px;
  backdrop-filter: blur(18px) saturate(1.12);
  -webkit-backdrop-filter: blur(18px) saturate(1.12);
  cursor: text;
  flex: 0 0 auto;
  border: 1px solid rgb(0 0 0 / 30%) !important;
}

.input-text-box input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
}

.search-suggest {
  position: fixed;
  display: none;
  overflow: auto;
}

.search-suggest.open {
  display: block;
}

.suggest-item {
  width: 100%;
  border: 0;
  border-radius: 7px;
  text-align: left;
  cursor: pointer;
}

.suggest-item small {
  display: block;
}

.suggest-item mark {
  border-radius: 2px;
  padding: 0 1px;
}

.apps-viewport {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 100%;
  overflow: hidden;
}

.apps {
  height: 100%;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0 3px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  touch-action: pan-x;
}

.apps::-webkit-scrollbar {
  display: none;
}

.app-wrap {
  position: relative;
  flex: 0 0 auto;
}

.app-btn, .window[data-root="user"] * {
  user-select: none;
  -webkit-user-drag: none;
}

.app-btn:after {
  content: "";
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 2px;
  height: 2px;
  border-radius: 99px;
  opacity: 0;
  transform: scaleX(0);
  transition: opacity .14s,transform .14s,left .14s,right .14s;
}

.app-btn.active:after {
  opacity: 1;
  transform: scaleX(1);
}

.app-btn.active.focused:after {
  left: 9px;
  right: 9px;
}

.app-btn.active.minimized:after {
  left: 18px;
  right: 18px;
}

.icon-click {
  animation: task-icon-bounce .24s ease;
}

@keyframes task-icon-bounce{
  0%{transform:translateY(0)}
  38%{transform:translateY(-4px)}
  68%{transform:translateY(1px)}
  100%{transform:translateY(0)}
}

.clock {
  border: 0;
  border-radius: 7px;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 8px;
  white-space: nowrap;
  cursor: pointer;
}
.clock-datetime {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
}
/* 알림은 로그인해야 쓸 수 있어 비로그인 방문자에겐 감춘다(homepage.js). */
.clock-bell[hidden] {
  display: none;
}
/* 시계 버튼 안 날짜 오른쪽 종 아이콘 + 읽지 않은 알림 수 뱃지. */
.clock-bell {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
}
.clock-bell svg {
  width: 15px;
  height: 15px;
}
.clock-bell-count {
  position: absolute;
  top: -6px;
  right: -8px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  box-sizing: border-box;
  border-radius: 8px;
  background: var(--focus-color);
  color: var(--focus-font-color);
  /* 작업표시줄 색과 같은 링으로 종 아이콘에서 뱃지를 오려내듯 분리한다 —
     테마 focus색이 종 색과 비슷해도 형태가 또렷하게 보인다. */
  box-shadow: 0 0 0 2px rgba(var(--system-a-rgb), var(--system-a-alpha));
  font-size: 9px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}
.clock-bell-count[hidden] {
  display: none;
}
/* windows */

.window {
  position: fixed;
  display: none;
  flex-direction: column;
  overflow: hidden;
  min-width: 260px;
  min-height: 180px;
  width: 560px;
  height: 420px;
  border-radius: 12px;
  box-shadow: 0 6px 14px -2px rgb(0 0 0 / 0.2);
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
  border: 2px solid;
}

.window.open {
  display: flex;
}

.window.post-detail-window {
  min-width: min(1000px, calc(100vw - 4px));
  min-height: min(700px, calc(100dvh - var(--taskbar-h) - 4px));
}

.window.comment-window {
  min-height: 220px;
}

.window.minimized,.window.preview-hidden {
  display: none !important;
}

/* 비활성 창은 화면에 그대로 남기되 CSS 애니메이션의 프레임 소비를 멈춘다.
   music/youtube는 JS 수명주기에서 is-suspended 자체를 붙이지 않는다. */
.window.is-suspended *,
.window.is-suspended *::before,
.window.is-suspended *::after {
  animation-play-state: paused !important;
}

.window.preview-peek {
  display: flex !important;
}

.window.maximized {
  top: 0 !important;
  left: 0 !important;
  width: 100vw !important;
  height: calc(100vh - var(--taskbar-h)) !important;
  /* 모바일 브라우저의 100vh는 주소창이 접힌 "최대" 높이로 고정돼 있어,
     주소창이 떠 있는 실제 화면(더 작은 동적 뷰포트)보다 커진다 — 창
     하단이 그만큼 실제 화면 밖으로 밀려나 작업표시줄(고정 bottom:0)에
     가려 보인다. dvh(동적 뷰포트, 지원 브라우저에서 위 100vh를 덮어씀)로
     실제 보이는 높이만큼만 잡는다. */
  height: calc(100dvh - var(--taskbar-h)) !important;
  border-radius: 0 !important;
}

/* 창을 화면 가장자리/모서리로 끄는 동안 스냅될 영역을 미리 보여주는 오버레이
   (homepage.ui.js가 하나만 만들어 위치·크기·표시 여부를 계속 바꿔 쓴다).
   pointer-events:none이라 실제 드래그를 절대 가로채지 않고, z-index는 매번
   드래그 중인 창보다 1 낮게 다시 맞춰져 그 창 뒤에서만 보인다. */
.window-snap-preview {
  position: fixed;
  pointer-events: none;
  border-radius: 12px;
  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
  border: 2px solid rgba(var(--system-c-hover-shadow-rgb), var(--system-c-hover-shadow-alpha));
  box-shadow: 0 5px 14px -2px rgba(var(--system-c-hover-shadow-rgb), var(--system-c-hover-shadow-alpha));
}

.window-snap-preview[hidden] {
  display: none;
}

.window-bar {
  flex: 0 0 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px 0 12px;
  user-select: none;
}

.window-title-group {
  min-width: 0;
  flex: 1;
  display: flex;
  align-items: center;
  gap: 5px;
}

.window-title-icon {
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  display: inline-flex;
  color: inherit;
}

.window-title-icon img,
.window-title-icon svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.window-title {
  min-width: 0;
  flex: 1;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* line-height 기본값(브라우저 "normal", 폰트마다 1.15~1.2배)이 아이콘의
     1em 정사각 박스보다 커서, .window-title-group의 align-items:center가 둘을
     "박스" 기준으로는 맞춰도 글자 자체의 광학 중심은 살짝 어긋나 보인다 —
     1로 낮춰 줄박스를 아이콘 박스 높이에 붙인다. */
  line-height: 1;
}

.window-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.window-minimize,.window-close {
  width: 23px;
  height: 23px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
}

.window-minimize {
  line-height: 1;
  padding-top: 4px;
}

.window-content {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* 좌우 패딩만 변수로 빼둔다 — 아래 다이어리 캘린더처럼 이 패딩을 상쇄해
     창 폭 끝까지 채우는 요소가 데스크톱/모바일(아래 미디어쿼리에서 값만
     바뀜) 양쪽에서 항상 정확히 같은 값을 참조하게 하기 위함. */
  --window-content-padding-x: 14px;
  padding: 14px var(--window-content-padding-x);
  /* 네이티브 스크롤바 대신 아래 .window-content-scrollbar(다이어리 캘린더와
     같은 오버레이 방식)를 쓴다 — 콘텐츠 폭을 차지하지 않는다. */
  scrollbar-width: none;
  box-shadow: inset 0 10px 10px -18px rgba(var(--system-b-content-shadow-rgb), var(--system-b-content-shadow-alpha));
}

/* 모바일(창이 자동 최대화되는 폭, 다른 곳과 같은 640px 기준) — 어차피 화면
   전체를 쓰는 만큼 양옆 여백부터 줄여 실제 컨텐츠 폭을 넓힌다. 위아래는
   그대로(스크롤로 해결되니 급하지 않음). */
@media (max-width: 640px) {
  .window.maximized {
    height: 100vh !important;
    height: 100dvh !important;
  }

  .window.guestbook-window {
    max-width: none;
  }

  .window-content {
    --window-content-padding-x: 8px;
    padding-left: var(--window-content-padding-x);
    padding-right: var(--window-content-padding-x);
  }
}

.window-content::-webkit-scrollbar {
  display: none;
}

/* ==========================================================================
   window-content 오버레이 스크롤바 — 다이어리 캘린더(.diary-scroll-shell)와
   같은 패턴을 모든 창의 본문 스크롤에 공용으로 적용한 것(homepage.ui.js의
   bindWindowOverlayScrollbar). window-content는 창마다 한 번만 만들어지고
   이후 내용만 갈아 끼우므로, 이 dock은 그 형제로 한 번만 붙고 JS가
   ResizeObserver/MutationObserver로 위치·크기를 다시 잰다. 평소엔 투명하다가
   휠 스크롤 중/드래그 중에만 보인다(is-active) — 스크롤할 게 아예 없으면
   hidden으로 완전히 빠진다. */
.window-content-scrollbar {
  position: absolute;
  right: 2px;
  width: 12px;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s;
  touch-action: none;
}

.window-content-scrollbar[hidden] {
  display: none;
}

.window-content-scrollbar.is-active {
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}

.window-content-scrollbar-thumb {
  margin-left: 5px;
  width: 7px;
  min-height: 28px;
  border-radius: 10px;
  background: rgba(var(--focus-rgb), .75);
  cursor: grab;
}

.window-content-scrollbar.is-dragging .window-content-scrollbar-thumb {
  cursor: grabbing;
}

/* ==========================================================================
   주소 표시줄 + 관리자 선택 메뉴
   ========================================================================== */
.window-toolbar {
  --area-input-rgb: var(--system-b-input-rgb);
  --area-input-alpha: var(--system-b-input-alpha);
  --area-input-font-color: var(--system-b-input-font-color);
  --area-input-border-rgb: var(--system-b-input-border-rgb);
  --area-input-border-alpha: var(--system-b-input-border-alpha);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 4px;
  background: rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
  color: var(--system-b-font-color) !important;
}

.window-toolbar * {
  color: var(--system-b-font-color);
}

.window-toolbar input:hover,
.window-toolbar input:focus,
.window-toolbar select:hover,
.window-toolbar select:focus {
  background: rgba(var(--system-b-input-hover-rgb), var(--system-b-input-hover-alpha)) !important;
  color: var(--system-b-input-hover-font-color) !important;
}

/* 창 주소 줄 — window-bar 바로 아래 고정 행. 새 글 작성/수정 창
   (openPostEditorWindow가 세팅하는 data-post-editing)에는 보이지 않는다. */
.window[data-post-editing="1"] [data-window-address-bar] {
  display: none;
}
.window-address-controls {
  flex: 0 0 auto;
  display: flex;
  gap: 2px;
}
.window-address-button {
  width: 26px;
  height: 26px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent !important;
  color: var(--system-b-font-color) !important;
  box-shadow: none !important;
  cursor: pointer;
  outline: none;
}
.window-address-button:disabled {
  opacity: .35;
  cursor: default;
}
.window-address-button svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.window-address-field {
  --window-address-icon-column: 32px;
  flex: 1;
  min-width: 0;
  height: 26px;
  box-sizing: border-box;
  position: relative;
  display: grid;
  grid-template-columns: var(--window-address-icon-column) minmax(0, 1fr) auto;
  align-items: center;
  border-radius: 15px;
  border: 1px solid;
  border-color: rgba(var(--system-b-input-border-rgb), var(--system-b-input-border-alpha)) !important;
  background: rgba(var(--system-b-input-rgb), var(--system-b-input-alpha));
}
.window-address-lock {
  width: var(--window-address-icon-column);
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.window-address-lock svg,
.window-address-suggest-query-icon svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.window-address-lock-icon {
  display: flex;
  align-items: center;
  justify-content: center;
}
.window-address-lock-icon img {
  width: 13px;
  height: 13px;
  object-fit: contain;
}
.window-address-search-icon {
  display: none;
}
.window-address-field.is-suggest-open .window-address-lock-icon {
  display: none;
}
.window-address-field.is-suggest-open .window-address-search-icon {
  display: block;
}
/* 주소창 입력 + 자동완성 검색어 입력은 스타일이 같다. */
.window-address-input,
.window-address-suggest-query-input {
  min-width: 0;
  width: 100%;
  height: 26px;
  padding: 0 10px 0 0;
  box-sizing: border-box;
  border-radius: 0;
  border: 0 !important;
  outline: none;
  background: transparent !important;
  color: var(--system-b-input-font-color) !important;
}
.window-toolbar .window-address-input:hover,
.window-toolbar .window-address-input:focus,
.window-toolbar .window-address-suggest-query-input:hover,
.window-toolbar .window-address-suggest-query-input:focus {
  border: 0 !important;
  outline: none;
  background: transparent !important;
  color: var(--system-b-input-font-color) !important;
}
.window-address-suggest {
  position: absolute;
  z-index: 20;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0px;
  max-height: min(430px, 65vh);
  padding: 0;
  overflow: auto;
  border-radius: 15px 15px 10px 10px;
  /* .window-address-field(주소창 입력)과 같은 System B 입력 테두리 테마 —
     자동완성이 그 아래로 이어지는 모양이라 테두리도 이어져야 한다. */
  border: 1px solid rgba(var(--system-b-input-border-rgb), var(--system-b-input-border-alpha)) !important;
  background: linear-gradient(rgba(var(--system-b-input-rgb), var(--system-b-input-alpha)), rgba(var(--system-b-input-rgb), var(--system-b-input-alpha))), rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
  cursor: default;
}
.window-address-suggest[hidden] {
  display: none;
}
.window-address-suggest,
.window-address-suggest * {
  color: var(--system-b-font-color) !important;
}
.window-address-suggest .window-address-suggest-item {
  width: 100%;
  min-height: 30px;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: var(--window-address-icon-column) minmax(0, 1fr);
  align-items: center;
  gap: 0;
  padding: 3px 10px 3px 0;
  border: 0 !important;
  border-radius: 0;
  background: rgba(var(--system-b-input-rgb), var(--system-b-input-alpha)) !important;
  color: var(--system-b-input-font-color) !important;
  text-align: left;
}
.window-address-suggest-query {
  position: sticky;
  z-index: 1;
  top: 0;
  flex: 0 0 auto;
  min-width: 0;
  height: 26px;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: var(--window-address-icon-column) minmax(0, 1fr);
  align-items: center;
  padding: 0;
  background: rgba(var(--system-b-input-rgb), var(--system-b-input-alpha)) !important;
  color: var(--system-b-input-font-color) !important;
}
.window-address-suggest-query-icon {
  width: var(--window-address-icon-column);
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.window-address-suggest .window-address-suggest-item *,
.window-address-suggest .window-address-suggest-item mark {
  color: var(--system-b-input-font-color) !important;
}
.window-address-suggest .window-address-suggest-item:hover,
.window-address-suggest .window-address-suggest-item[aria-selected="true"] {
  background: rgba(var(--system-b-input-hover-rgb), var(--system-b-input-hover-alpha)) !important;
  color: var(--system-b-input-hover-font-color) !important;
  outline: none;
  box-shadow: none !important;
}
.window-address-suggest .window-address-suggest-item:hover *,
.window-address-suggest .window-address-suggest-item[aria-selected="true"] * {
  color: var(--system-b-input-hover-font-color) !important;
}
.window-address-suggest-icon,
.window-address-suggest-icon svg,
.window-address-suggest-icon img {
  width: 12px;
  height: 12px;
}
.window-address-suggest-icon {
  width: var(--window-address-icon-column);
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.window-address-suggest-icon svg {
  fill: none;
  color: inherit !important;
  stroke: currentColor !important;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.window-address-suggest-icon img {
  object-fit: contain;
}
.window-address-suggest-text {
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: center;
}
.window-address-suggest-meta {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.window-address-suggest mark {
  padding: 0;
  background: transparent !important;
  color: inherit !important;
  font-weight: 700;
}
.window-address-message {
  flex: 0 0 100%;
  margin: 0;
}
.window-address-field > .window-post-like {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 9px;
  border: 0 !important;
  border-radius: 15px;
  background: transparent !important;
  color: var(--system-b-input-font-color) !important;
  white-space: nowrap;
}

/* 주소창 내부의 입력값·검색 결과·좋아요·아이콘은 입력 테마가 아니라
   윈도우바(System B) 컨텐츠 폰트색을 공통으로 따른다. */
.window-address-field,
.window-address-field * {
  color: var(--system-b-input-font-color) !important;
}
.window-address-field svg {
  stroke: currentColor !important;
}
/* 주소줄 오른쪽 끝 "⋯" 버튼 + 드롭다운 — margin-left:auto로 같은 줄의
   뒤로가기/새로고침/주소창보다 항상 오른쪽 끝에 붙는다. 드롭다운 자체는
   .post-admin-menu 위치/배경/그림자 스타일을 그대로 물려쓴다(아래
   window-more-dropdown 클래스 추가). */
.window-more-menu {
  position: relative;
  margin-left: auto;
  flex: 0 0 auto;
}

/* 검색 입력창/게시물 관리 패널 공용 껍데기 — .window-more-menu(position:relative)
   기준으로 아래 .post-admin-menu와 똑같이 뜨는 절대위치 팝업이다(요청: 주소줄
   레이아웃에 끼어들지 않고 post-admin-menu처럼 떠 보여야 함). [hidden]에
   !important가 필요한 이유는 아래 .post-admin-menu[hidden]과 같다. */
.window-more-panel,
.post-admin-menu,
.post-visibility-dropdown {
  position: absolute;
  padding: 4px;
  border: 1px solid rgba(var(--system-b-input-border-rgb), var(--system-b-input-border-alpha));
  border-radius: 6px;
  background: linear-gradient(rgba(var(--system-b-input-rgb), var(--system-b-input-alpha)), rgba(var(--system-b-input-rgb), var(--system-b-input-alpha))), rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
  color: var(--system-b-input-font-color) !important;
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
  box-shadow: 0 8px 20px -4px rgba(0, 0, 0, .18);
}
.window-more-panel,
.post-admin-menu {
  top: calc(100% + 5px);
}
.window-more-panel {
  right: 34px;
  z-index: 6;
}
.window-more-search-panel {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 240px;
  height: 34px;
  box-sizing: border-box;
}
/* 세로 메뉴형 패널(게시물 관리 툴바 / ⋯ 드롭다운 / 공개범위 서브메뉴) 공통. */
.post-admin-toolbar.window-more-panel,
.post-admin-menu,
.post-visibility-dropdown {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.post-admin-toolbar.window-more-panel,
.post-admin-menu {
  min-width: 125px;
}
.post-admin-menu {
  right: 0;
  z-index: 7;
}
.window-more-panel[hidden],
.post-admin-menu[hidden],
.post-visibility-dropdown[hidden] {
  display: none !important;
}
.post-admin-menu-item {
  width: 100%;
  height: 26px;
  padding: 0 8px;
  border: 0;
  border-radius: 6px;
  background: transparent !important;
  text-align: left;
}
.window-more-panel *,
.post-admin-menu.window-more-dropdown * {
  color: var(--system-b-input-font-color) !important;
}

/* 선택된 상태를 강조하는 토글 버튼(예: 라이브2D 트래킹 패널) 공용 —
   다이어리의 활성 도구 아이콘(.diary-tool-icon.is-active: 배경을 포커스색으로
   채움)과 같은 느낌으로 맞춘다. */
.small-btn.is-active {
  background: var(--focus-color) !important;
  border-color: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}

/* danger 버튼은 Focus 색을 쓴다(하드코딩 빨강 제거). */
.small-btn.danger {
  border-color: var(--focus-color) !important;
  color: var(--focus-color) !important;
}

.small-btn.danger:hover,
.small-btn.danger:focus-visible {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}

.small-btn:disabled {
  opacity: .4;
  cursor: default;
}

.post-visibility-editor {
  position: relative;
  display: inline-flex;
}

.post-visibility-dropdown {
  top: 0;
  right: 100%;
  left: auto;
  z-index: 7;
  min-width: max-content;
}

.post-visibility-option {
  width: 100%;
  height: 24px;
  padding: 0 8px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  text-align: left;
  cursor: pointer;
}

.grid-cell.is-selectable {
  position: relative;
}

.grid-cell-select {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 15px;
  height: 15px;
  border-radius: 4px;
  border: 1px solid;
  background: rgba(255, 255, 255, .85);
  /* .post-thumb-wrap도 position:relative라 둘 다 z-index:auto인 채로는 DOM
     순서상 뒤에 오는 .post-thumb-wrap이 이 체크박스 위에 그려졌다(포지션드
     요소는 z-index:auto여도 비포지션드 요소보다 위, 같은 그룹 안에선 DOM
     순서로 쌓임). z-index를 줘서 명시적으로 위로 끌어올린다. */
  z-index: 1;
}

.grid-cell.is-selected {
  outline: 2px solid var(--focus-color);
  outline-offset: -2px;
}

.grid-cell.is-selected .grid-cell-select {
  background: var(--focus-color);
  border-color: var(--focus-color);
}

.post-title-row {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 7px;
}

.post-title-row .post-title,
.post-title-row .movie-card-title {
  margin-top: 0;
  min-width: 0;
}

.post-visibility-icon {
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--system-c-desc-color);
}

/* 그리드 카드(그림/영화 후기) meta의 댓글 수 앞 아이콘 — 항상 .grid-cell-meta
   안에 있으므로 색은 그 부모의 !important 규칙(설명색, hover 중에도 유지)에 맡기고
   여기서는 크기·정렬만 잡는다. */
.grid-cell-comment {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.grid-cell-comment-icon {
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.resize-handle {
  position: absolute;
}

.resize-handle.n,.resize-handle.s {
  left: 12px;
  right: 12px;
  height: 8px;
}

.resize-handle.n {
  top: -3px;
  cursor: ns-resize;
}

.resize-handle.s {
  bottom: -3px;
  cursor: ns-resize;
}

.resize-handle.e,.resize-handle.w {
  top: 12px;
  bottom: 12px;
  width: 8px;
}

.resize-handle.e {
  right: -3px;
  cursor: ew-resize;
}

.resize-handle.w {
  left: -3px;
  cursor: ew-resize;
}

.resize-handle.nw,.resize-handle.ne,.resize-handle.sw,.resize-handle.se {
  width: 14px;
  height: 14px;
}

.resize-handle.nw {
  left: -3px;
  top: -3px;
  cursor: nwse-resize;
}

.resize-handle.ne {
  right: -3px;
  top: -3px;
  cursor: nesw-resize;
}

.resize-handle.sw {
  left: -3px;
  bottom: -3px;
  cursor: nesw-resize;
}

.resize-handle.se {
  right: -3px;
  bottom: -3px;
  cursor: nwse-resize;
}

.window.maximized .resize-handle {
  display: none;
}
.blog-post {
  box-sizing: border-box;
  max-width: 720px;
  margin: auto;
  padding: 10px;
  border-radius: 10px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha));
}

.blog-post h2 {
  margin: 0 0 5px;
}

.blog-post p {
  line-height: 1.85;
}

.blog-post + .gallery-comments {
  max-width: 720px;
  margin: 10px auto 0;
}

/* 댓글 달기 대상인 게시글 전체 하단을 흐려 댓글 컴포즈로 자연스럽게 잇는다.
   타임라인처럼 댓글이 없는 post-markdown-body에는 적용하지 않는다. */
.post-body-fade {
  padding-bottom: 30px;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
}

.comments {
  /* 댓글폼→댓글목록/댓글↔댓글/댓글↔답글 간격을 전부 3px로 통일한다(요청) —
     margin-top이 폼과의 간격, gap이 최상위 스레드끼리의 간격을 맡는다. */
  margin-top: 3px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.comments-unsupported {
  display: none;
}

.comments h3 {
  margin: 0 0 10px;
}

.comment {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 15px;
  padding: 8px;
  border-radius: 33px 10px 10px 33px;
  margin-bottom: 2px;
  box-shadow: 0 0 5px -2px rgba(0, 0, 0, .14)
}

.comment p {
  margin: 4px 0 0;
  line-height: 1.5;
  /* textarea에 입력한 줄바꿈(엔터)이 기본 white-space:normal에 의해 렌더링에서
     사라지던 문제 — 그림/영화/캐릭터/방명록 댓글이 모두 이 .comment 컴포넌트를
     공유하므로 여기 한 곳만 고치면 전부 반영된다. */
  white-space: pre-wrap;
  word-break: break-word;
}

/* ==========================================================================
   댓글(그림/영화/다이어리/방명록 공용 — 방명록도 같은 .comment 컴포넌트를
   그대로 쓴다): 아바타(좌) + 작성자/날짜/수정/삭제/답글(우) + 답글쓰레드
   ========================================================================== */

.entry-avatar {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background-color: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha));
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  overflow: hidden;
  border: 0px solid;
}

.entry-avatar svg {
  width: 28px;
  height: 28px;
}

.entry-body {
  flex: 1;
  min-width: 0;
}

.entry-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.entry-head > strong {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 댓글 작성자 아바타/닉네임 — 클릭하면 프로필 팝오버(setupMentionProfiles). */
.entry-avatar.is-profile-ref,
.entry-author.is-profile-ref {
  cursor: pointer;
}
.entry-author.is-profile-ref:hover {
  text-decoration: underline;
}

.entry-meta {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}

.entry-reply-toggle {
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

.entry-reply-toggle:hover,
.entry-reply-toggle:focus-visible {
  color: var(--system-c-hover-font-color) !important;
}

.entry-reply-form {
  margin-top: 6px;
}

.entry-reply-form[hidden] {
  display: none !important;
}

/* .comment는 display:flex를 지정하므로(위), 작성 폼/답글 폼처럼 .comment를
   그대로 쓰면서 hidden 속성으로 토글하는 요소는 이 규칙 없이는 hidden이
   무시된다(작성자 스타일시트가 UA 기본 [hidden] 규칙을 이긴다). */
.comment[hidden] {
  display: none !important;
}

/* 답글/수정 등록 버튼도 guest-form과 같은 이유로 절대배치 겹침 대신 textarea
   아래 별도 flex 행으로 분리한다 — 글이 길어지면(autoGrowTextarea) textarea
   자체가 커지고 버튼은 항상 그 아래에 그대로 있다. */
.entry-reply-input-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* min-height는 늘어나기 전 기본 크기의 바닥값, overflow-y:hidden은
   autoGrowTextarea가 height를 잴 때 스크롤바가 잠깐 끼어드는 걸 막는다 —
   실제 스크롤은 이 textarea 안이 아니라(생기지 않는다) 그 바깥 창에서
   생긴다. */
.entry-reply-input-wrap textarea {
  width: 100%;
  min-height: 50px;
  resize: none;
  overflow-y: hidden;
  /* border-box여야 autoGrowTextarea가 재는 scrollHeight(패딩 포함)를 그대로
     height에 넣어도 border/padding이 두 번 더해지지 않는다 — 아니면 실제
     필요한 높이보다 살짝 모자라 안에 스크롤이 도로 생긴다. */
  box-sizing: border-box;
  border-radius: 8px;
  padding: 0px;
  margin: 4px 0px 0px;
  border: 0px solid !important;
}

/* 위 border:0으로 테두리 자체는 이미 안 보이지만, .input-text-box:hover/focus의
   전역 box-shadow(테두리 안쪽 glow)는 별도 속성이라 따로 꺼야 한다 —
   :hover/:focus 의사클래스가 있어야 전역 규칙(.input-text-box:hover 등)보다
   우선한다. */
.entry-reply-input-wrap textarea:hover,
.entry-reply-input-wrap textarea:focus,
.entry-reply-input-wrap textarea:focus-within {
  box-shadow: none !important;
}

/* 답글 등록(버튼 1개)은 .entry-reply-submit-btn이 wrap의 직계 자식이라 여기서
   바로 우측 정렬한다. 수정 폼(버튼 2개)은 .entry-reply-actions가 그 자리를
   대신하는 직계 자식이다. */
.entry-reply-input-wrap > .entry-reply-submit-btn,
.entry-reply-actions {
  align-self: flex-end;
}

.entry-reply-submit-btn {
  height: 21px;
  padding: 0 8px;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}

.entry-reply-actions {
  display: flex;
  gap: 6px;
  margin-bottom: 5px;
}

.entry-replies {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.entry-replies:not(:empty) {
  margin-top: 3px;
}

/* 답글(1depth 초과)은 배경/그림자 없이, 우측 padding도 없애 날짜·좋아요·답글이
   상위 댓글과 동일한 우측 라인에 정렬되도록 함. 트리선 없이 프로필 사진 너비만큼만 들여쓴다. */
.entry-replies [data-entry] {
  position: relative;
  background: transparent !important;
  box-shadow: none !important;
  padding-right: 0 !important;
  padding-left: 0 !important;
}

/* 그림/일기 댓글(.comment-thread)은 guestbook(.entry-body 안에 중첩된
   .entry-replies)과 달리, 답글 목록이 부모 article과 형제로 분리되어 있어
   flex 중첩으로 저절로 들여써지지 않는다. 아바타 폭(40px)+간격(8px)만큼
   padding-left를 줘서 기존과 같은 시각적 들여쓰기를 재현하고, 이 padding이
   재귀적으로 중첩된 .entry-replies마다 쌓여 depth별 누적 들여쓰기가 된다.
   답글은 부모 카드 밖의 독립 항목이므로 배경/그림자는 .comment 기본값을
   그대로 유지한다(guestbook의 [data-entry] 스트리핑과 다른 지점). */
.comment-thread > .entry-replies {
  padding-left: 48px;
}

/* ==========================================================================
   댓글 컴포즈 바 — 모달 하단 테두리에 고정(요청). .gallery-comments의 마지막
   자식이라 그 위(.comments 목록 + 게시글 본문)만 스크롤되고 이 바는 그
   스크롤 컨테이너(.window-content) 바닥에 붙어 항상 보인다. 최상위 댓글/
   답글 모두 이 입력창 하나로 쓴다(homepage.ui.js의 setReplyTarget).
   ========================================================================== */
.comment-compose {
  /* 기본은 sticky(문서 흐름 안, homepage.ui.js가 도킹 대상을 못 찾았을 때의
     폴백 — 예: 같은 창에 이미 다른 댓글 섹션이 도킹된 movie 후기). 실제로는
     bindGalleryComments의 dockComposeBar가 이 엘리먼트를 창(.window)의
     직계 자식으로 옮기고 .comment-compose-docked를 붙여 아래 규칙으로
     완전히 고정한다(요청: "모달 하단에 완전히 붙어서"). */
  position: sticky;
  bottom: 0;
  margin-top: 10px;
}

/* [hidden]인데도 위 sticky/flex 규칙(작성자 스타일)이 네이티브 [hidden]의
   display:none을 이겨버려(.comment[hidden]과 같은 이유) 댓글 작성 권한이
   없을 때(form.hidden=true) 이 바가 계속 보이던 버그가 있었다. */
.comment-compose[hidden] {
  display: none !important;
}

/* dockComposeBar가 창 직계 자식으로 옮긴 뒤 붙이는 클래스 — 창(.window,
   position:fixed) 기준으로 절대 위치를 잡아 window-content 스크롤·리사이즈와
   무관하게 항상 같은 자리(창 하단)에 남는다. left/width/bottom은 JS(syncDock)가
   실측해서 매번 정확히 맞춘다. */
.comment-compose-docked {
  position: absolute;
  margin-top: 0;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  box-shadow: 0 -4px 14px -4px rgba(var(--system-c-font-rgb), .18);
  border: 1px solid rgba(var(--system-c-rgb), var(--system-c-alpha));
  border-radius: 14px 14px 0 0;
  padding: 10px 12px;
}

.comment-compose-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-sizing: border-box;
  border-radius: 14px;
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
}

.comment-compose-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.comment-compose-resize {
  flex: 0 0 auto;
  height: 22px;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
}

/* "Reply to 게시글명"과 "Reply to (프사)닉네임 내용"을 같은 자리에서
   전환한다. 답글 내용이 길면 한 줄 말줄임으로 유지한다. */
.comment-compose-reply {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1 1 auto;
  min-width: 0;
  height: 26px;
  padding: 4px 8px 4px 0;
  box-sizing: border-box;
  border-radius: 8px;
  font-size: 12px;
}

/* .entry-avatar와 취소 버튼의 display 선언이 네이티브 [hidden]보다 강하므로
   게시글 대상 상태에서는 자식별 hidden을 명시적으로 보장한다. */
.comment-compose-reply > [hidden] {
  display: none !important;
}

.comment-compose-reply-label,
.comment-compose-reply-name {
  flex: 0 0 auto;
}

.comment-compose-reply-label {
  color: var(--system-c-desc-color);
}

/* .entry-avatar와 함께 걸려있는 복합 선택자로 특이도를 확실히 올린다
   (그냥 .comment-compose-reply-avatar만 쓰면 .entry-avatar와 특이도가
   같아서 소스 순서에만 기대야 했다). */
.entry-avatar.comment-compose-reply-avatar {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
}

.comment-compose-reply-avatar svg {
  width: 10px;
  height: 10px;
}

.comment-compose-reply-content {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--system-c-desc-color);
}

.comment-compose-reply-cancel {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

/* entry-avatar(내 프로필 사진)와 입력창 — 사진 상단과 입력창 첫 줄이
   맞도록 align-items:flex-start(요청). 입력창 높이는 homepage.ui.js의
   growCompose가 scrollHeight 기준으로 직접 조절한다. */
.comment-compose-body {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.comment-compose-body > .entry-avatar {
  width: 36px;
  height: 36px;
}

.comment-compose-body > .entry-avatar svg {
  width: 20px;
  height: 20px;
}

.comment-compose-input {
  flex: 1;
  min-width: 0;
  min-height: 50px;
  box-sizing: border-box;
  resize: none;
  border-radius: 8px;
  padding: 8px 10px;
  font: inherit;
  overflow-y: hidden;
  border: 0 !important;
  box-shadow: none !important;
  background: rgba(var(--system-c-input-rgb), var(--system-c-input-alpha)) !important;
  color: var(--system-c-input-font-color) !important;
}

/* 요청: 기본/hover/클릭(focus) 전부 테두리·box-shadow 없음 — 전역
   input/textarea:hover,:focus 규칙(homepage.css, border-color+box-shadow
   글로우를 !important로 켬)을 여기서 명시적으로 다시 꺼야 한다. */
.comment-compose-input:hover,
.comment-compose-input:focus,
.comment-compose-input:focus-within {
  border: 0 !important;
  outline: none !important;
  box-shadow: none !important;
}

/* 등록 버튼은 테두리 밖, 우측 정렬(요청 — 아이콘/입력창을 감싼 패널
   바깥쪽 아래). */
.comment-compose-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: 6px;
}

.comment-compose-footer .small-btn {
  height: 27px;
  padding: 0 16px;
}
/* diary */

.window[data-root="diary"] .window-content {
  padding-bottom: 0;
}

.diary-layout {
  width: 100%;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  /* 우측 FAB(diary-fab-dock)/좌하단 도구(diary-tool-dock)/스티커 툴팁을
     이 레이아웃 기준 절대 위치로 띄우기 위한 포지셔닝 컨텍스트. */
  position: relative;
}

.diary-date-selects {
  display: flex;
  align-items: center;
  gap: 6px;
}

.diary-date-select {
  height: 28px;
  padding: 0 8px;
  border: 1px solid;
  border-color: transparent !important;
  border-radius: 7px;
  font-weight: 750;
  background: transparent !important;
}

.diary-nav {
  display: flex;
  align-items: center;
  gap: 2px;
}

.diary-nav button {
  min-width: 25px;
  width: auto;
  height: 25px;
  padding: 0 7px;
  border: 0;
  background: transparent !important;
  border-radius: 6px;
  cursor: pointer;
}

/* 요일 머리글/달력 그리드만 .window-content 좌우 패딩을 음수 마진으로
   상쇄해 창 폭 끝까지 채운다(요청: "다이어리 캘린더는 여백 없이 창을
   가득 채우도록") — 위 연/월 선택·이동 버튼(.diary-head)은 그대로 패딩
   안쪽에 둔다. --window-content-padding-x는 .window-content가 정의하고
   모바일에서 8px로 바뀌므로(homepage.css 상단) 그 값을 그대로 물려받아
   항상 정확히 맞아떨어진다. */
.diary-weekdays,
.diary-scroll-shell {
  min-width: 0;
  margin-left: calc(var(--window-content-padding-x) * -1);
  margin-right: calc(var(--window-content-padding-x) * -1);
}

.diary-weekdays {
  display: grid;
  grid-template-columns: repeat(7,minmax(0,1fr));
  background: transparent;
  box-shadow: 0 3px 3px -2px rgba(0, 0, 0, .2);
}

.diary-weekdays span {
  text-align: center;
  padding: 7px 0;
}

.diary-scroll-shell {
  flex: 1;
  min-height: 0;
  position: relative;
}

.diary-scroll {
  width: 100%;
  min-width: 0;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}

.diary-scroll::-webkit-scrollbar {
  display: none;
}

.diary-scrollbar {
  position: absolute;
  top: 0;
  right: 2px;
  bottom: 0;
  width: 12px;
  z-index: 850;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s;
  touch-action: none;
}

.diary-scroll-shell.is-wheel-scrolling .diary-scrollbar {
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}

.diary-scrollbar-thumb {
  margin-left: 5px;
  width: 7px;
  min-height: 28px;
  border-radius: 10px;
  background: rgba(var(--focus-rgb),.75);
  cursor: grab;
}

.diary-scroll-shell.is-scrollbar-dragging .diary-scrollbar-thumb {
  cursor: grabbing;
}

.diary-grid {
  width: 100%;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(7,minmax(0,1fr));
  position: relative;
  /* 드래그로 날짜 범위를 고를 때(attachDragDateSelect) 브라우저 기본
     텍스트/이미지 선택이 함께 끼어들지 않도록 — 달력엔 어차피 사용자가
     따로 선택할 텍스트가 없다. */
  user-select: none;
  /* 내부 날짜뱃지와 꾸미기 스테이지의 z-index를 이 그리드 안에 가둔다. */
  z-index: 0;
}

/* 4:3로 고정 — 날짜 칸 자체는 빈 칸이고, 실제 꾸민 내용은 스티커(.diary-sticker)가
   같은 그리드 위에 겹쳐서 보여준다(아래). 날짜 숫자는 별도
   뱃지(.diary-day-num)로 배치하되 스티커보다 아래에 둔다. */
/* 평소엔(새로 만들기로 날짜를 고르는 중이 아니면) 완전히 비활성 — hover도
   클릭도 반응하지 않는다(pointer-events:none). 실제로 상호작용이 필요한 건
   .diary-grid.is-date-selecting일 때뿐이라 그때만 되살린다(아래). */
.diary-day {
  aspect-ratio: 4 / 3;
  padding: 6px;
  text-align: left;
  cursor: default;
  pointer-events: none;
  position: relative;
  background: transparent;
}

.diary-grid.is-date-selecting .diary-day {
  cursor: pointer;
  pointer-events: auto;
}

/* 날짜 범위를 여러 주에 걸쳐 세로로 드래그해서 고르는 제스처(attachDragDateSelect)라,
   터치에서 이 속성이 없으면 브라우저 기본 세로 스크롤이 같은 손가락 움직임을
   가로채 버려 한 주를 넘어가는 범위를 못 고른다. 날짜 선택 중일 때만 막고
   (평소 달력 스크롤은 그대로 터치로 되게) 좁힌다. */
.diary-grid.is-date-selecting {
  touch-action: none;
}

/* 새로 만들기로 날짜를 고르는 중엔 스티커(기존 게시글)를 클릭 대상에서
   완전히 빼서(pointer-events:none) 그 밑에 깔린 날짜 칸이 드래그를 그대로
   받게 한다 — 안 그러면 이미 게시글이 있는 날짜 위에서 드래그를 시작/통과할
   때 스티커의 <img>가 이벤트를 가로채 브라우저 기본 이미지 드래그가 뜨고
   (attachDragDateSelect의 cellSelector:'.diary-day' 매칭도 실패해) 그 날짜가
   선택 범위에서 빠지는 문제가 있었다. */
.diary-grid.is-date-selecting .diary-sticker {
  pointer-events: none;
}

/* 날짜 셀은 .normal-button 공통 규칙이 입히는 인풋 테마(배경/글자/테두리)
   대신 컨텐츠 테마를 쓴다. */
.diary-grid .diary-day.normal-button.light-border {
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  color: var(--system-c-font-color) !important;
  border-color: rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
}

/* 선택된 연/월과 다른 달의 날짜 칸은 사용자가 휠을 굴리거나 스크롤바를
   드래그하는 동안에만 흐리게 표시한다. 입력이 끝나면 셀은 전부 원래
   불투명도로 돌아간다. */
.diary-day.is-outside-selected-month {
  opacity: 1;
}

.diary-scroll-shell.is-diary-scrolling .diary-day.is-outside-selected-month {
  opacity: .5;
}

/* 오늘 셀은 더 이상 테두리(outline)로 표시하지 않는다 — 날짜 숫자 색만으로
   충분하다는 요청. 색상 변경은 아래 .diary-day-num.today가 그대로 담당한다. */

/* 선택 강조 배경은 위 .diary-grid .diary-day.normal-button.light-border(컨텐츠
   테마) 규칙과 특이도를 맞춰야 이긴다 — 같은 4-클래스로 선언하고 뒤에 둔다. */
.diary-grid .diary-day.normal-button.is-selected {
  background: rgba(var(--focus-rgb), .28) !important;
}
.diary-day.is-selected {
  outline: 2px solid var(--focus-color);
  outline-offset: -2px;
}

/* 날짜 숫자 뱃지 — .diary-grid의 형제 아이템으로 grid-row/grid-column을
   명시해 그 날짜 칸 위에 정확히 얹는다. 배경 없이 System C 폰트색만으로
   표시하고, pointer-events:none이라 클릭/hover는 아래로 그대로 전달된다
   (날짜 숫자 자체는 클릭 대상이 아니다). */
.diary-day-num {
  position: relative;
  align-self: start;
  justify-self: start;
  margin: 3px;
  padding: 1px 4px;
  font-size: 10px;
  line-height: 1.4;
  color: var(--system-c-font-color);
  pointer-events: none;
  z-index: 0;
}

.diary-day-num.today {
  color: var(--focus-color);
  font-weight: 700;
}

/* 캘린더꾸미기(beginDecorateMode) 중엔 실제 날짜 칸 위를 세그먼트(선택한 날짜가
   이어진 한 주 구간) 단위의 편집 스테이지(.diary-decorate-segment)가 통째로
   덮으므로, 밑에 깔린 날짜 칸 자체는 그냥 클릭 반응만 꺼둔다. */
.diary-day.is-decorating {
  cursor: default;
}

/* 캘린더꾸미기 중엔 지금 편집 중인 세그먼트(.is-decorating 날짜 칸/숫자)만
   또렷하게 남기고 나머지 달력(다른 주의 날짜 칸·숫자)은 반투명하게 낮춰
   편집 대상에 시선이 가게 한다(요청) — diary.js가
   beginDecorateMode/cleanupDom에서 .diary-grid에 is-decorate-mode를
   붙였다 뗀다. */
.diary-grid.is-decorate-mode .diary-day:not(.is-decorating),
.diary-grid.is-decorate-mode .diary-day-num:not(.is-decorating) {
  opacity: .4;
}

/* 이미 등록된 스티커는 새 꾸미기 결과와 겹침을 확인하는 배경 미리보기로
   그대로 보여주되, 선택·클릭·hover 대상에서는 완전히 제외한다. */
.diary-grid.is-decorate-mode .diary-sticker {
  opacity: 1;
  pointer-events: none;
}

/* 세그먼트(패딩 영역, .diary-decorate-segment)는 실제 날짜 칸 영역
   (.diary-decorate-segment-core)보다 세로 기준 10%만큼 사방으로 더 넓게
   잡아(padding) 레이어를 자유롭게 옮기거나 펜으로 그릴 여유를 주고, 포인터
   캡처(드래그 등)는 이 넓은 padded 영역 전체가 받는다. 등록 시 실제로
   저장되는 스티커 캔버스도 이 padded 영역 크기 그대로다(buildStickers) —
   그래서 눈에 보이는 배경/그림자도 core가 아니라 이 padded 영역 전체에
   준다(요청: 등록 후 스티커가 보일 최대 영역을 입력 중에도 그대로 확인할
   수 있어야 함). 테두리 대신 box-shadow로 편집 범위를 구분하고, 배경은
   인풋 테마를 쓰되 완전 불투명이 아니라서 그 아래 실제 날짜 칸 테두리가
   은은하게 비쳐 보인다. */
.diary-decorate-segment {
  position: absolute;
  z-index: 400;
  box-sizing: border-box;
  /* 이미지 레이어는 이 영역 바깥까지 확대/이동할 수 있어야 하므로(저장 시엔
     세그먼트 캔버스 크기 그대로 자동으로 잘려 보이지 않는다) 편집 중엔
     가려버리지 않고 그대로 보여준다. */
  overflow: visible;
  touch-action: none;
  /* 아래의 기존 스티커가 클릭 불가 미리보기 레이어로 비쳐 보이게 한다. */
  background: rgba(var(--system-c-input-rgb), .18) !important;
  box-shadow: 0 3px 10px -2px rgba(0, 0, 0, .28);
  border-radius: 6px;
}

/* 좌표 정규화(normPoint)의 기준이자 레이어가 실제로 배치되는 영역(=날짜
   칸 크기) — 그 자체는 안 보이는 히트/좌표 기준일 뿐이다(배경/그림자는
   위 .diary-decorate-segment가 이미 그린다). */
.diary-decorate-segment-core {
  position: absolute;
  overflow: visible;
}

/* .diary-decorate-segment(패딩 포함 최대 영역) 사각형 자체는 구멍처럼
   비워두고(box-shadow는 자기 테두리 안쪽엔 안 퍼짐) 그 바깥 전체를 거대한
   spread의 box-shadow로 덮는 스포트라이트 기법 — 세그먼트 안(패딩 포함,
   요청대로 "diary-decorate-segment 영역 안")은 그대로, 세그먼트를 완전히
   벗어난 부분(다른 주/다른 게시글)만 이 그림자에 덮여 흐리게 보인다.
   createSegmentStage가 coreEl이 아니라 paddedEl(segment)의 자식으로
   붙인다 — 구멍 크기가 core가 아니라 segment 전체와 일치해야 하므로.
   .diary-scroll의 overflow:auto가 9999px 그림자를 화면에 보이는 만큼으로만
   잘라준다. */
.diary-decorate-dim-mask {
  position: absolute;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(var(--system-c-content-rgb), .65);
}

/* 등록 건 하나(스티커)가 그 날짜 칸들 위에 정확히 겹쳐 보이는 그리드 아이템 —
   .diary-grid의 형제로 grid-row/grid-column을 명시해 배치한다(같은 좌표를
   여러 스티커가 겹쳐 차지할 수 있다). 스티커의 불투명한(실제로 꾸민) 부분을
   클릭해야 게시글이 열리고(투명한 여백·날짜 칸 클릭은 아무 일도 하지 않는다),
   그 불투명한 부분을 hover하면 제목 툴팁으로 클릭 대상을 알려준다.
   "맨위에 표시" 게시글은 작성일과 무관하게 일반 게시글보다 높은 z-index를
   받는다 — 완전히 겹치는 배치는 자동으로 어긋내지 않는다. */
.diary-sticker {
  position: relative;
  min-width: 0;
  cursor: pointer;
  overflow: visible;
  transition: none;
}

/* Grid 아이템은 날짜 열 크기를 그대로 유지하고, 저장 PNG의 10% 여백은
   이 내부 캔버스만 절대 배치로 넓혀 행 크기나 스크롤 폭에 관여하지 않게 한다. */
.diary-sticker-canvas {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 6px;
  overflow: hidden;
}

.window-edit-cancel {
  height: 24px;
  padding: 0 7px;
  border: 1px solid;
  border-radius: 6px;
}

/* 주소줄 "⋯ → 이 페이지 내에서 검색"으로 여는 팝업(.window-more-search-panel)
   안의 아이콘/입력창 — 팝업 자체(배경/테두리/그림자)는 .window-more-panel이
   그리므로 여기선 내용물만 다룬다. */
.window-bar-search-icon {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}

.window-bar-search-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  border: none;
  background: transparent;
  padding: 0;
  font: inherit;
  color: inherit;
}

.window-toolbar .window-bar-search-input:hover,
.window-toolbar .window-bar-search-input:focus {
  background: transparent !important;
  outline: none;
}

.window-bar-search-input::placeholder {
  color: rgba(var(--system-b-font-rgb), .5) !important;
}

.window-more-panel-close {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent !important;
  color: inherit !important;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.search-highlight {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
  border-radius: 2px;
}

/* 상세보기 "이 페이지 내에서 검색"이 위/아래 화살표로 가리키는 지금 위치의
   결과 — 다른 결과와 같은 강조색 위에 테두리만 하나 더 둘러 구분한다. */
.search-highlight.is-current-match {
  outline: 2px solid var(--focus-font-color);
  outline-offset: 1px;
}

/* 상세보기 검색 패널은 입력창 옆에 n/총수 카운터 + 위아래 이동 버튼이 더
   붙어 목록 검색 패널(240px)보다 넓어야 한다. */
.window-post-search-panel {
  width: 320px;
}
.window-post-search-count {
  flex: 0 0 auto;
  min-width: 32px;
  text-align: center;
  opacity: .75;
  white-space: nowrap;
}
.window-more-panel-nav {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent !important;
  cursor: pointer;
}
.window-more-panel-nav svg {
  width: 12px;
  height: 12px;
}
.window-more-panel-nav:disabled {
  opacity: .35;
  cursor: default;
}

.diary-display-on-top {
  flex: 0 0 auto;
  height: 33px;
  padding: 0 10px;
  border: 1px solid;
  border-radius: 7px;
}

.diary-display-on-top[aria-pressed="true"] {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}

.diary-sticker.is-hover-active {
  filter: drop-shadow(0 1px 3px rgba(var(--system-c-font-rgb), .5));
}

.diary-sticker.is-selected {
  outline: 2px solid var(--focus-color);
  outline-offset: -2px;
}

.diary-sticker-bg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

.diary-sticker-gif {
  position: absolute;
  pointer-events: none;
}

/* 스티커 hover 시 게시글 제목을 보여주는 커스텀 툴팁 — 모달의 overflow에
   잘리지 않도록 body 직속 fixed 요소로 띄운다. 위치(left/top)는 diary.js가
   포인터의 화면 좌표로 계산하고, 생김새만 .preview-label을 재사용한다. */
.diary-sticker-tooltip.preview-label {
  position: fixed;
  bottom: auto;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  color: var(--system-c-font-color) !important;
  z-index: 800;
  pointer-events: none;
}

.diary-sticker-tooltip[hidden] {
  display: none;
}

/* 모든 윈도우가 공유하는 포인터 추적 툴팁 — body 직속이라 창 밖에서도 보인다. */
.window-tooltip {
  position: fixed;
  z-index: calc(var(--z-debug) + 1);
  max-width: min(320px, calc(100vw - 16px));
  padding: 5px 7px;
  border-radius: 6px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  pointer-events: none;
  color: var(--system-c-font-color) !important;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  box-shadow: 0 4px 12px -2px rgba(0, 0, 0, .18);
}

.window-tooltip[hidden] {
  display: none;
}

/* 터치 기기에서는 탭이 hover로 해석되며 툴팁이 클릭 대상을
   가리므로, 거친 포인터/호버 없는 환경에서 커스텀 툴팁을 모두 끄다. */
@media (hover: none), (pointer: coarse) {
  .window-tooltip,
  .diary-sticker-tooltip.preview-label {
    display: none !important;
  }
}

/* ==========================================================================
   새로 만들기(+) FAB — 창 우측단에 절대 위치로 떠 있다. 다이어리 전용이 아니라
   postable 메뉴(그림/영화 등, setupPostAdminToolbar가 postFabDockHTML로 삽입)와
   공유하는 클래스다. 다이어리에서는 평소 동그란 (+) 버튼(diary-fab) 하나뿐이고,
   날짜를 고르기 시작하거나 캘린더 꾸미기 단계에 들어가면 그 자리에서
   diary-fab-actions(다음/취소)로 바뀐다(diary.js가 hidden 속성만 토글 — 둘 다
   항상 DOM에 있는 정적 엘리먼트). 그림/영화는 diary-fab-actions 없이 diary-fab
   버튼 하나만 쓴다.
   ========================================================================== */
.diary-fab-dock {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: 700;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

/* 다이어리는 diary-fab-dock을 .diary-layout(높이 100%, 그 자체가 .window-content
   padding:14px 안쪽에서 시작) 밑에 두므로, 실제로는 14(window-content padding)
   + 14(diary-fab-dock 자신의 inset) = 28px만큼 창 가장자리에서 들어와 보인다.
   그림/영화는 setupPostAdminToolbar가 .window-content에 fab-dock을 바로
   붙이므로(중간에 그런 래퍼가 없음) 14px만 들어가 다이어리보다 가장자리에
   더 붙어 보였다 — 다이어리와 같은 위치로 보이도록 여기서 28px로 맞춘다. */
[data-post-fab-dock] {
  right: 28px;
  bottom: 28px;
}

.diary-fab-dock[hidden] {
  display: none;
}

/* 동그라미는 focus-color, 그 안의 +는 focus-font-color. */
.diary-fab {
  width: 46px;
  height: 46px;
  border: 0;
  border-radius: 50%;
  background: var(--focus-color);
  color: var(--focus-font-color);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 4px 10px -2px rgba(0, 0, 0, .2);
}

.diary-fab svg {
  color: var(--focus-font-color) !important;
  stroke: var(--focus-font-color) !important;
}

.diary-fab[hidden] {
  display: none;
}

/* 날짜 선택 중(is-date-selecting)엔 (+) 자리 그대로 (X)로 바뀌어 "선택
   취소"를 뜻한다 — 새로 만들기(focus-color)와 구분되게 인풋 테마로 칠한다. */
.diary-fab.is-input-theme {
  background: rgba(var(--system-c-input-rgb), var(--system-c-input-alpha));
  color: var(--system-c-input-font-color);
  border: 1px solid rgba(var(--system-c-input-border-rgb), var(--system-c-input-border-alpha));
}

.diary-fab.is-input-theme svg {
  color: var(--system-c-input-font-color) !important;
  stroke: var(--system-c-input-font-color) !important;
}

.diary-fab-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}

.diary-fab-actions[hidden] {
  display: none;
}

.diary-fab-actions button[hidden] {
  display: none;
}

/* 선택 취소 — 캘린더꾸미기 중(beginDecorateMode)에만 diary.js가 grid의
   자식으로 만들어 붙인다. 선택된 날짜의 마지막 세그먼트(.diary-decorate-segment)
   영역 밖, 그 우측하단에 오도록 매번 위치를 계산해서 얹는다(요청). 세그먼트의
   dim-mask(z-index:9000, 세그먼트 자신의 쌓임 맥락 안)보다 위에 그려지도록
   세그먼트(z-index:400)보다 큰 z-index를 준다. */
.diary-decorate-cancel {
  position: absolute;
  z-index: 500;
  background: rgba(var(--system-c-input-rgb), var(--system-c-input-alpha));
  color: var(--system-c-input-font-color);
  border: 1px solid rgba(var(--system-c-input-border-rgb), var(--system-c-input-border-alpha));
  border-radius: 7px;
  padding: 5px 12px;
  font-size: 13px;
  cursor: pointer;
  box-shadow: 0 4px 10px -2px rgba(0, 0, 0, .2);
}

/* ==========================================================================
   캘린더꾸미기 도구(선택/이미지/텍스트/선택삭제) — 다이어리 창
   좌측 하단에 절대 위치로 떠 있는 아이콘 줄. 꾸미는 동안에만 보인다.
   ========================================================================== */
.diary-tool-dock {
  position: absolute;
  left: 12px;
  bottom: 12px;
  z-index: 700;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px;
  border-radius: 12px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  box-shadow: 0 6px 16px -3px rgba(0, 0, 0, .2);
}

.diary-tool-dock[hidden] {
  display: none;
}

.diary-tool-icon {
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--system-c-font-color);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.diary-tool-icon.is-active {
  background: var(--focus-color);
  color: var(--focus-font-color);
}

.diary-tool-icon.danger {
  color: var(--focus-color);
}

.diary-tool-icon:disabled {
  opacity: .35;
  cursor: default;
}

.diary-text-controls {
  display: flex;
  align-items: center;
  gap: 4px;
}

.diary-text-controls[hidden] {
  display: none;
}

.diary-text-bold {
  font-weight: 700;
}

.diary-text-size {
  width: 52px;
  height: 26px;
  border: 1px solid;
  border-radius: 6px;
}

.diary-text-color {
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid;
  border-radius: 6px;
  cursor: pointer;
  background: transparent;
}

/* ==========================================================================
   다이어리 게시글작성 창 — 날짜선택·캘린더꾸미기는 이제 메인 달력 화면에서
   끝내고 오므로(diary.js beginDecorateMode), 이 창은 그림 게시글 에디터와
   똑같은 한 화면 폼(제목 옆 공개범위, 그 옆 등록 버튼 — UI.PostEditor.formHTML)
   이다. 별도 "확인" 단계 없이 바로 등록한다. 방금 꾸민 내용의 미리보기는
   이 창 안이 아니라 메인 달력 위에 그대로 남아 있다(beginDecorateMode의
   freezeForPreview) — 이 창이 닫힐 때(저장이든 취소든) 정리된다.
   ========================================================================== */

/* 레이어 하나는 위치/크기/회전을 갖는 래퍼(.diary-layer, transform:rotate가
   여기 걸린다)와 그 안을 꽉 채우는 실제 내용(.diary-layer-content)으로
   나뉜다 — 선택 시 핸들(.diary-layer-handle-*)도 이 래퍼의 자식이라 래퍼의
   회전을 그대로 물려받아 항상 레이어의 실제 모서리/윗변에 붙어 보인다. */
.diary-layer {
  position: absolute;
  box-sizing: border-box;
  margin: 0;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.diary-layer-content {
  display: block;
  width: 100%;
  height: 100%;
}

.diary-layer-image .diary-layer-content {
  object-fit: cover;
  border-radius: 3px;
}

.diary-layer-text .diary-layer-content {
  overflow: hidden;
  line-height: 1.25;
  white-space: pre-wrap;
  word-break: break-word;
}

.diary-layer-text-input {
  box-sizing: border-box;
  padding: 0;
  border: 0;
  outline: 0;
  resize: none;
  background: transparent;
  font-family: inherit;
  user-select: text;
  cursor: text;
}

.diary-layer-pen .diary-layer-content {
  background: transparent;
}

.diary-layer.is-selected {
  outline: 2px dashed var(--focus-color);
  outline-offset: 1px;
}

/* 크기조절(오른쪽 아래 모서리, 종횡비 유지하며 중심 기준 확대/축소)과
   회전(윗변 중앙, 레이어 중심 기준 각도) 핸들 — 선택된 레이어에만 렌더링된다. */
.diary-layer-handle {
  position: absolute;
  width: 10px;
  height: 10px;
  background: var(--focus-color);
  border: 1px solid #fff;
  z-index: 10;
  pointer-events: auto;
}

.diary-layer-handle-resize {
  right: -5px;
  bottom: -5px;
  border-radius: 2px;
  cursor: nwse-resize;
}

.diary-layer-handle-rotate {
  top: -20px;
  left: 50%;
  margin-left: -5px;
  border-radius: 50%;
  cursor: grab;
}

.light-border {
  border: 1px solid rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;
}
/* guestbook */

.guestbook-window {
  width: 500px;
  max-width: none;
  height: 430px;
}

.guestbook-window .gallery-comments {
  box-sizing: border-box;
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
}

.guestbook-window .comment-compose {
  max-width: 720px;
}

/* 등록 버튼을 textarea 안쪽 패딩 여백에 절대배치로 겹쳐 그리던 방식은 글이
   길어져 스크롤이 생기면 버튼과 시각적으로 충돌했다 — textarea를 위, 버튼을
   그 아래 별도 flex 행으로 분리해 서로의 영역을 절대 침범하지 않게 한다. */
.guest-form {
  position: sticky;
  top: 0;
  padding: 12px 0 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.guest-form textarea {
  width: 100%;
  min-height: 92px;
  resize: none;
  border: 1px solid;
  border-radius: 9px;
  padding: 10px;
  outline: 0;
}

.preview-card {
  position: fixed;
  width: 238px;
  max-height: 360px;
  display: none;
  padding: 7px;
  border-radius: 10px;
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 8px 20px -4px rgba(0,0,0,.14);
  overflow: auto;
}

.preview-card.show {
  display: block;
}

.preview-empty {
  min-height: 44px;
  display: grid;
  place-items: center;
  padding: 10px;
  text-align: center;
}

.preview-item {
  position: relative;
  height: 112px;
  border-radius: 7px;
  overflow: hidden;
  margin-bottom: 6px;
  cursor: pointer;
}

.preview-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.preview-thumb {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: top left;
  pointer-events: none;
}

.preview-close {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
  line-height: 1;
  font-family: Arial, sans-serif;
}

.preview-close::before {
  content: "×";
  display: block;
  line-height: 1;
  transform: translateY(-.25px);
}

.preview-label {
  position: absolute;
  left: 7px;
  bottom: 5px;
  max-width: 180px;
  padding: 3px 6px;
  border-radius: 4px;
  background: rgba(var(--system-b-rgb), var(--system-b-alpha));
  color: var(--system-b-font-color);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.close-all {
  position: sticky;
  top: 0;
  z-index: 2;
  display: block;
  width: auto;
  height: 28px;
  margin: 0 0 6px auto;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.popover {
  position: fixed;
  display: none;
}

.popover.open {
  display: block;
}

/* 유리 팝업 공통 면 — 시작메뉴/볼륨 팝오버(.popover)와 시계 플라이아웃 카드가 공유.
   .calendar-popover(컨테이너)는 아래에서 border/shadow/backdrop 을 전부 끈다. */
.popover,
.clock-flyout-calendar,
.clock-flyout-notifications {
  border: 1px solid;
  border-radius: 11px;
  box-shadow: 0 9px 22px -4px rgba(0, 0, 0, .13);
}
.popover,
.search-suggest,
.clock-flyout-calendar,
.clock-flyout-notifications {
  backdrop-filter: blur(22px) saturate(1.16);
  -webkit-backdrop-filter: blur(22px) saturate(1.16);
}

.shortcut-popover {
  left: 8px;
}

.shortcut-grid {
  display: grid;
  padding-top: 15px;
  justify-items: center;
}

.shortcut {
  border: 0;
  border-radius: 7px;
  text-align: center;
  cursor: pointer;
  width: 70px;
}

.shortcut strong {
  display: block;
}

/* 앱 바로가기 라벨만 바탕화면 바로가기(.desktop-shortcut span)와 같은 400 굵기로
   맞춘다 — 검색 결과(.start-search-post)의 strong은 기존 600 굵기를 그대로 유지. */
.shortcut:not(.start-search-post) strong {
  font-weight: 400;
}

.shortcut span {
  display: none;
}

.calendar-popover {
  right: 8px;
  border: 0 !important;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.calendar-popover.open {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 8px;
  height: calc(100vh - var(--taskbar-h) - 18px);
  height: calc(100dvh - var(--taskbar-h) - 18px);
}

/* 알림 카드가 없는 비로그인 상태에는 플라이아웃을 화면 높이만큼 늘리지 않는다.
   그러면 fixed bottom 기준으로 달력 카드 자체가 항상 작업표시줄 위에 붙는다. */
.calendar-popover.open:has(.clock-flyout-notifications[hidden]) {
  height: auto;
}

.clock-flyout-calendar,
.clock-flyout-notifications {
  width: 324px;
  padding: 12px;
}

.clock-flyout-calendar {
  flex: 0 0 auto;
}

.calendar-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.calendar-head button {
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
  font-weight: bold;
}

.calendar-title {
  font-weight: 700;
}

.mini-week,.mini-grid {
  display: grid;
  grid-template-columns: repeat(7,1fr);
}

.mini-week span {
  text-align: center;
}

.mini-day {
  position: relative;
  justify-self: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}

.mini-day.today {
  font-weight: 700;
}

.mini-day.has:after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
}

/* 시계 플라이아웃: 달력 위의 남은 화면 높이를 채우는 독립 알림 카드.
   표면/폰트/테두리는 .taskbar-scope 규칙으로 이미 System A를 따르고,
   각 항목만 System A 폰트색에서 파생한 콘텐츠 톤으로 한 단계 뗀다. */
.clock-flyout-notifications {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

.clock-flyout-notifications[hidden] {
  display: none;
}

.clock-flyout-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-weight: 700;
  margin-bottom: 8px;
}
.notification-settings-toggle {
  width: 24px;
  height: 24px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}
.notification-settings-toggle svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.notification-settings-toggle[hidden] { display: none !important; }

/* 톱니바퀴 왼쪽 "모두 지우기" — 제목 다음, 오른쪽 정렬 그룹의 첫 항목. */
.notification-clear-all {
  margin-left: auto;
  padding: 3px 7px;
  border: 0;
  border-radius: 7px;
  font-weight: 400;
  cursor: pointer;
}
.notification-clear-all[hidden] { display: none !important; }

.notification-list {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  /* 창 본문과 같은 오버레이 스크롤바(homepage.js의 bindWindowOverlayScrollbar)를
     쓰므로 네이티브 스크롤바는 숨긴다. */
  scrollbar-width: none;
}
.notification-list::-webkit-scrollbar { display: none; }
.notification-list[hidden] { display: none !important; }

.notification-settings {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
  font-weight: 400;
}
.notification-settings[hidden] { display: none !important; }
.notification-settings-back {
  align-self: flex-start;
  height: 24px;
  padding: 0 6px 0 2px;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}
.notification-settings-group {
  margin: 0;
  padding: 10px;
  border: 1px solid rgba(var(--system-a-font-rgb), .16);
  border-radius: 7px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.notification-settings-group legend {
  padding: 0 4px;
  font-weight: 700;
  opacity: .8;
}
.notification-settings label {
  display: flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
}
.notification-settings-filtered {
  margin-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.notification-settings-filtered[hidden] { display: none !important; }
.notification-settings-menus {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.notification-empty {
  text-align: center;
  padding: 20px 8px;
  opacity: .7;
}

.notification-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 9px 10px;
  border-radius: 7px;
  cursor: pointer;
}

.notification-item.has-thumb {
  grid-template-columns: auto 1fr auto;
}

.notification-item-thumb {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  flex: none;
}

.notification-item:hover {
  border-color: var(--focus-color) !important;
}

.notification-item.is-unread {
  border-color: rgba(var(--focus-rgb), .5) !important;
}

/* 읽은 알림은 블럭 전체를 반투명하게. hover 시 복원. */
.notification-item:not(.is-unread) {
  opacity: .55;
}
.notification-item:not(.is-unread):hover {
  opacity: 1;
}

.notification-item-title {
  font-weight: 700;
}

/* 안읽은 알림 제목도 System A 입력 폰트색을 따른다(.sys-a-btn-b * 규칙과 특이도를
   맞춰 덮는다) — 굵기와 왼쪽 테두리(.is-unread)만으로 안읽음을 표시. */
.notification-item.is-unread .notification-item-title {
  color: var(--system-a-input-font-color) !important;
}

.notification-item-body {
  margin-top: 3px;
  font-size: .9em;
  opacity: .75;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.notification-item-delete {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  line-height: 1;
  flex: none;
}

.clock {
  position: relative;
}

.sound-popover {
  right: 75px;
}

.timeline {
  margin-top: 8px;
  height: 4px;
  border-radius: 99px;
  overflow: hidden;
}

.timeline span {
  display: block;
  width: 42%;
  height: 100%;
  background: var(--focus-color);
}

/*@media(max-width:760px){.input-text-box{width:145px}*/
  .window{min-width:230px}

  .guestbook-window{max-width:calc(100vw - 18px)}
/* ==========================================================================
   Start menu gallery button
   ========================================================================== */

/* Windows 시작메뉴 하단 바(계정/전원)처럼 줄 전체가 System A 입력 톤 배경 한
   장이고, 그 위에 아이콘 버튼들이 투명하게 얹힌다(버튼 하나하나를 박스로
   감싸지 않음) — .shortcut-popover의 padding:14px를 좌우/아래로 상쇄해
   패널 가장자리까지 배경이 번지게 하고, 둥근 아래 모서리는 popover 자체의
   overflow 클리핑에 맡긴다(따로 border-radius 안 줘도 됨). */
.shortcut-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 9px;
  margin: 10px -14px -14px;
  padding: 8px 20px;
  background: rgba(var(--system-a-input-rgb), var(--system-a-input-alpha));
  border-top: 1px solid rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha));
}

.gallery-power-button {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  padding: 4px 0;
}

/* 시작메뉴 스페이스 위젯(전원버튼 왼쪽) — 로그인 여부와 무관하게 지금 스페이스
   소유자 아바타+타이틀+닉네임@아이디를 보여주고, 스페이스가 2개 이상이면
   활성화돼 openSpaceSwitcherPopover로 전환 목록을 연다. border-radius는
   sys-a-btn-a hover 시 밝아지는 배경의 모서리용(버튼 자체는 평소 투명).
   좌우 padding은 없음 — 가장자리 여백은 .shortcut-footer의 좌우 padding이
   맡아서 아바타/전원 아이콘 둘 다 같은 기준으로 정렬된다. */
.shortcut-space-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  text-align: left;
  border-radius: 7px;
}
.shortcut-space-info[hidden] {
  display: none;
}
.shortcut-space-info:disabled {
  cursor: default;
  opacity: .85;
}
.shortcut-space-avatar {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background-position: center;
  background-size: cover;
  background-color: rgba(var(--system-a-rgb), .2);
}
.shortcut-space-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}
.shortcut-space-text strong,
.shortcut-space-text small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shortcut-space-text small {
  opacity: .75;
  font-size: .82em;
}

/* 스페이스 전환 목록(위 위젯 클릭 시) — .folder-popover와 같은 팝오버 베이스,
   그리드 대신 세로 리스트만 다르다. */
.space-switcher-popover {
  width: min(300px, calc(100vw - 16px));
  padding: 10px;
}
.space-switcher-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 320px;
  overflow-y: auto;
}
.space-switcher-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  text-align: left;
}
.space-switcher-row.is-current {
  cursor: default;
}
.space-switcher-avatar {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-position: center;
  background-size: cover;
  background-color: rgba(var(--system-a-rgb), .2);
  display: grid;
  place-items: center;
}
.space-switcher-avatar svg {
  width: 18px;
  height: 18px;
}
.space-switcher-text {
  min-width: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}
.space-switcher-text strong,
.space-switcher-text small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.space-switcher-text small {
  opacity: .75;
  font-size: .82em;
}
.space-switcher-current-badge {
  flex: 0 0 auto;
  font-size: .78em;
  opacity: .75;
}

/* ==========================================================================
   Layering / aligned taskbar popups
   ========================================================================== */

.preview-card {
  bottom: calc(var(--taskbar-h) + 5px) !important;
}

.search-suggest {
  bottom: calc(var(--taskbar-h) + 5px) !important;
}

.shortcut-popover,
.calendar-popover,
.sound-popover {
  bottom: calc(var(--taskbar-h) + 5px);
}

.shortcut-popover {
  max-height: min(520px, calc(100vh - var(--taskbar-h) - 18px));
  /* 세로만 넘칠 때 스크롤하면 되고, 가로는 그리드 폭 계산이 서브픽셀로
     빠듯해도(4열*70px 고정폭 아이콘 + gap) 절대 가로 스크롤바가 보이면
     안 되므로 x축은 아예 막는다. */
  overflow-x: hidden;
  overflow-y: auto;
}

.shortcut-grid-flat {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
/* 앱별 HTML 템플릿 로딩 상태 */

.modal-template-loading,
.modal-template-error {
  height: 100%;
  min-height: 120px;
  display: grid;
  place-items: center;
}

/* ==========================================================================
   Settings application
   ========================================================================== */

.settings-app {
  height: 100%;
  min-height: 0;
}

.settings-view {
  display: none;
  height: 100%;
  min-height: 0;
}

.settings-view.is-active {
  display: flex;
  flex-direction: column;
}

/* 고정 앱 셸: 왼쪽 내비게이션은 항상 표시되고, 오른쪽 콘텐츠만 선택한 메뉴에 따라
   바뀐다(화면 전환 시 창 크기 변경 없음). 좁은 창에서는 내비게이션이 overlay
   drawer로 바뀌므로(아래 is-nav-small 관련 규칙), 그 드로어가 콘텐츠 위에 겹쳐
   그려지도록 position:relative로 기준 컨테이닝 블록을 만들어 둔다. */
.settings-shell {
  position: relative;
  display: flex;
  height: 100%;
  min-height: 0;
}

.settings-nav {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-content: start;
  overflow-y: auto;
}

.settings-nav-btn {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  text-align: left;
  cursor: pointer;
}

/* 넓은 창: ☰로 내비게이션 자체를 접어 콘텐츠에 공간을 더 준다. */
.settings-shell.is-nav-collapsed .settings-nav {
  display: none;
}

/* 좁은 창: 내비게이션은 기본적으로 숨겨져 있다가, ☰를 누르면 콘텐츠를 밀지 않고
   그 위에 겹쳐지는 overlay drawer로 나타난다. */
.settings-nav-backdrop {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 4;
  margin: 0;
  border: 0;
  padding: 0;
  background: rgba(0,0,0,.32);
  cursor: pointer;
}
.settings-shell.is-nav-small .settings-nav {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 5;
  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
  transform: translateX(-100%);
  transition: transform .18s ease;
}
.settings-shell.is-nav-small.is-nav-drawer-open .settings-nav {
  transform: translateX(0);
}
.settings-shell.is-nav-small.is-nav-drawer-open .settings-nav-backdrop {
  display: block;
}

.settings-content {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* 모든 화면이 공유하는 고정 헤더(제목/설명 + ☰ 버튼 + 오른쪽 수정·적용 버튼)와,
   그 아래 화면 전환 영역. 헤더는 항상 고정이고 스크롤은 화면별 .settings-panel-body
   에서만 일어난다(아래 참고) — 화면에 저장 버튼이 없으면 .settings-header-actions
   안에 그 화면 키를 가진 그룹이 없으므로 자연히 아무 버튼도 보이지 않는다
   (updateHeader가 매 화면 전환마다 .is-active를 다시 정함). 메뉴 관리 하위 화면
   으로 돌아가는 동작은 별도 뒤로가기 버튼 대신, 제목 줄 앞의 "메뉴 관리 /"
   breadcrumb(.settings-header-breadcrumb) 클릭으로 대신한다. */
.settings-panel-header {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
}

.settings-header-toggle {
  flex: 0 0 auto;
  cursor: pointer;
}

.settings-header-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* 제목 줄: 메뉴 관리 하위 화면에서는 얇은 글씨의 "메뉴 관리 /" breadcrumb 버튼과
   현재 하위 화면 제목(굵은 글씨, 기존 <strong>)이 한 줄에 나란히 보인다. 그 외
   화면은 breadcrumb이 hidden이라 상위 화면 제목만 보인다. */
.settings-header-title-row {
  display: flex;
  align-items: baseline;
  gap: 4px;
  min-width: 0;
}

.settings-header-breadcrumb {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  font-weight: 400;
  color: var(--system-c-desc-color);
}

/* 마우스 hover는 시각 효과 없이 기본 색상·장식을 그대로 유지하고(요청: 호버 효과
   제거), 키보드 포커스(:focus-visible)에서만 클릭 가능함을 알리는 색상+밑줄을
   보여준다. 클릭으로 상위 메뉴 허브에 돌아가는 동작 자체는 변경하지 않는다. */
.settings-header-breadcrumb:focus-visible {
  color: var(--focus-color);
  text-decoration: underline;
}

.settings-header-title-row strong {
  min-width: 0;
}

.settings-header-text strong {
  display: block;
}

.settings-header-text span {
  display: block;
}

.settings-header-actions {
  flex: 0 0 auto;
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
}

.settings-header-action-group {
  display: none;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.settings-header-action-group.is-active {
  display: flex;
}

.settings-views {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.settings-content .settings-view {
  flex: 1;
}

/* 화면별 본문: 이 안(.settings-panel-body)만 스크롤된다 — 적용·수정 버튼과
   메시지는 더 이상 화면마다 만들지 않고 공통 헤더(.settings-header-actions)에
   고정으로 존재한다. */
.settings-panel-body {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.settings-home-grid {
  display: grid;
  align-content: start;
}

.settings-pc-preview {
  position: relative;
  border-radius: 9px;
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(0,0,0,.07);
}

.settings-pc-screen {
  position: relative;
  border-radius: 5px;
  overflow: hidden;
}

.settings-card-label {
  display: block;
  margin-top: 7px;
  font-weight: 700;
}

/* 환경설정 홈의 관리자 전용 서버 현황 대시보드(settings.js syncServerStats/
   loadServerStats). 라이브러리 없이 순수 CSS로 그리는 막대 차트(트래픽)와
   채움 바(디스크 사용량) — 각 막대/채움의 실제 크기는 JS가 인라인 style로 준다. */
.settings-server-stats {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(120,120,120,.18);
}

.server-stats-content {
  margin-top: 8px;
}

.server-stats-row {
  display: grid;
  grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);
  gap: 12px;
  align-items: start;
}

.server-stats-traffic,
.server-stats-disk,
.server-stats-visitors {
  min-width: 0;
  border: 1px solid rgba(120,120,120,.18);
  border-radius: 9px;
  padding: 8px;
  height: 100%;
}

.server-stats-chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 60px;
  margin-top: 6px;
}

.server-stats-bar {
  flex: 1;
  min-width: 2px;
  height: 2px;
  background: var(--focus-color);
  border-radius: 2px 2px 0 0;
  opacity: .8;
}

.server-stats-chart-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 3px;
  color: var(--system-c-desc-color);
}

.server-stats-disk-bar {
  margin-top: 8px;
  height: 8px;
  border-radius: 4px;
  background: rgba(120,120,120,.18);
  overflow: hidden;
  display: flex;
}

.server-stats-disk-fill {
  height: 100%;
  width: 0;
  flex: 0 0 auto;
  background: var(--focus-color);
}

/* 서비스(프로젝트+업로드+DB)/그 외 두 구간으로 나눠 그릴 때의 색 — 서비스는
   기존 단색 막대와 같은 focus-color, 그 외는 중립 회색으로 구분한다. */
.server-stats-disk-fill.is-other {
  background: rgba(120,120,120,.55);
}

.server-stats-disk-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 5px;
  color: var(--system-c-desc-color);
}

.server-stats-disk-legend-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

.server-stats-disk-legend-swatch {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  flex: 0 0 auto;
  background: var(--focus-color);
}

.server-stats-disk-legend-swatch.is-other {
  background: rgba(120,120,120,.55);
}

/* "디스크 사용량" 라벨 줄에 청소 아이콘을 오른쪽 끝에 띄운다 — 다른
   settings-info-label(폼 라벨 등)은 그냥 텍스트라 flex로 바뀌어도 시각적
   차이가 없지만, 혹시 몰라 이 카드 안으로만 스코프한다. */
.server-stats-disk .settings-info-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.server-stats-disk-cleanup-btn {
  padding: 2px;
  color: var(--system-c-desc-color);
  cursor: pointer;
}

.server-stats-disk-cleanup-btn svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.server-stats-disk-cleanup-btn:hover {
  color: var(--focus-color);
}

/* 디스크 사용량 관리 화면(홈 / 디스크 사용량 관리) */
.disk-cleanup-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  margin-bottom: 10px;
}

.disk-cleanup-select-all {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.disk-cleanup-summary {
  color: var(--system-c-desc-color);
  flex: 1;
  min-width: 0;
}

.disk-cleanup-message {
  margin: 0 0 10px;
  min-height: 14px;
  color: var(--system-c-desc-color);
}

.disk-cleanup-message.is-error {
  color: var(--focus-color);
}

.disk-cleanup-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 10px;
}

.disk-cleanup-item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  border-radius: 8px;
  cursor: pointer;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
}

.disk-cleanup-item:has(.disk-cleanup-checkbox:checked) {
  outline: 2px solid var(--focus-color);
  outline-offset: -2px;
}

.disk-cleanup-checkbox {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 1;
  width: 16px;
  height: 16px;
  margin: 0;
}

.disk-cleanup-thumb {
  width: 100%;
  aspect-ratio: 1/1;
  object-fit: cover;
  border-radius: 6px;
}

.disk-cleanup-thumb-generic {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--system-c-desc-color);
  background: rgba(120,120,120,.18);
  font-size: 11px;
}

.disk-cleanup-item-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.disk-cleanup-item-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.disk-cleanup-item-meta {
  color: var(--system-c-desc-color);
}

.server-stats-disk-meta {
  margin-top: 5px;
  color: var(--system-c-desc-color);
}

.server-stats-visitor-count {
  margin-top: 6px;
  font-weight: 700;
  color: var(--system-c-title-color);
}

.server-stats-visitor-count small {
  margin-left: 3px;
  font-weight: 400;
  color: var(--system-c-desc-color);
}

.server-stats-updated {
  margin-top: 8px;
  color: var(--system-c-desc-color);
  text-align: right;
}

@media (max-width: 640px) {
  .server-stats-row {
    grid-template-columns: 1fr;
  }
}

.settings-info-list {
  display: grid;
  align-content: start;
}

.settings-info-row {
  width: 100%;
  display: grid;
  align-items: center;
  gap: 8px;
  border: 1px solid rgba(120,120,120,.18);
  border-radius: 9px;
  background: rgba(255,255,255,.52);
  text-align: left;
}

.settings-info-row:not(button) {
  grid-template-columns: 100px minmax(0,1fr);
}
button.settings-info-row {
  cursor: pointer;
}

.settings-info-value,
.settings-music-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.settings-music-thumb {
  width: 48px;
  height: 27px;
  flex: 0 0 auto;
  border-radius: 4px;
  background: center/cover no-repeat;
}

.settings-panel-head {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
}

.settings-panel-head strong {
  display: block;
  font-weight: 700;
}

.settings-panel-head span {
  display: block;
  margin-top: 3px;
}

.settings-empty {
  grid-column: 1/-1;
  padding: 22px 10px;
  text-align: center;
}

.desktop-area-sort-list {
  display: grid;
  gap: 5px;
}

.desktop-area-sort-item {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid rgba(0,0,0,.13);
  border-radius: 7px;
  background: rgba(255,255,255,.48);
  cursor: grab;
  touch-action: none;
  transition: border-color .15s,background .15s,opacity .15s,transform .15s;
}
.desktop-area-direction-toggle {
  justify-self: end;
}

.desktop-area-sort-item:active { cursor: grabbing; }
.desktop-area-sort-item.is-drag-source { display: none; }
.desktop-area-sort-placeholder {
  height: 3px;
  margin: 1px 4px;
  border-radius: 999px;
  background: var(--focus-color);
  box-shadow: 0 0 0 1px rgba(var(--focus-rgb),.18), 0 0 7px rgba(var(--focus-rgb),.55);
  transition: none !important;
}
.desktop-area-sort-placeholder.is-horizontal {
  align-self: stretch;
  height: auto;
  width: 4px;
  min-height: 30px;
  margin: 0 3px;
}
.desktop-area-sort-ghost {
  position: fixed;
  z-index: calc(var(--z-debug) + 1);
  margin: 0;
  pointer-events: none;
  cursor: grabbing;
  opacity: .94;
  transform: rotate(.5deg) scale(1.015);
  transition: none !important;
}
.desktop-area-sort-handle,
.desktop-shortcut-handle { color: #888; touch-action: none; user-select: none; }
.desktop-area-sort-item strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.desktop-area-sort-item small { color: #888; }

/* ==========================================================================
   메뉴 관리: 첫 화면(4개 버튼) + breadcrumb + 하위 화면 4종
   ========================================================================== */
.menu-hub, .menu-sub-view {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
.menu-hub.is-active, .menu-sub-view.is-active {
  display: flex;
}

.menu-hub-list {
  display: grid;
  gap: 8px;
  margin-top: 4px;
}
.menu-hub-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 10px 12px;
  border: 1px solid rgba(0,0,0,.13);
  border-radius: 9px;
  background: rgba(255,255,255,.48);
  text-align: left;
  cursor: pointer;
}
.menu-hub-card span { color: var(--system-c-desc-color); }

.menu-order-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.menu-order-icon {
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: 5px;
  background: #f0f0f0;
  overflow: hidden;
}
.menu-order-icon img,
.menu-admin-icon img { width: 100%; height: 100%; object-fit: cover; }

.menu-desktop-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  min-height: 0;
  overflow: auto;
}

/* 바탕화면 바로가기 관리: 영역(top/left/right/bottom, 우선순위 손잡이+배치 방향
   토글 보유)과 "미표시"(둘 다 없음) 총 5개의 접이식 그룹을 하나의 목록으로
   렌더링한다. 펼침 = 이름이 보이는 세로 목록, 접힘 = 아이콘만 보이는 가로 목록이며,
   두 상태 모두 항목을 드래그해 순서 변경/영역 이동이 가능하다(그룹 헤더 클릭으로
   토글). 영역 행 자체도 손잡이(.desktop-area-sort-handle)를 드래그해 우선순위를
   바꿀 수 있다 — 소속 메뉴 항목의 손잡이(.desktop-shortcut-handle)와는 다른
   요소이므로 두 드래그가 서로 간섭하지 않는다. */
.desktop-shortcut-group {
  border: 1px solid rgba(0,0,0,.13);
  border-radius: 9px;
  background: rgba(255,255,255,.3);
  overflow: hidden;
  flex: 0 0 auto;
}
.desktop-shortcut-group.is-selected {
  outline: 2px solid var(--focus-color);
  outline-offset: -2px;
}
.desktop-shortcut-group.is-drag-source { display: none; }
.desktop-shortcut-group-head-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
}
.desktop-shortcut-group-head-row .desktop-area-sort-handle {
  cursor: grab;
}
.desktop-shortcut-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}
.desktop-shortcut-group-title {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.desktop-shortcut-group-title small { color: #888; font-weight: 400; }
.desktop-shortcut-group-caret { color: #888; }

.desktop-shortcut-group-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 0 8px 8px;
}
.desktop-shortcut-group-body.is-collapsed {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: stretch;
}
.desktop-shortcut-group-body.is-drag-target {
  outline: 2px dashed var(--focus-color);
  outline-offset: -2px;
  border-radius: 6px;
}
.desktop-shortcut-group-body:empty {
  min-height: 34px;
}
.desktop-shortcut-group-body:empty::before {
  content: '항목을 여기로 드래그하세요';
  display: flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  color: #999;
}

.desktop-shortcut-item {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid rgba(0,0,0,.13);
  border-radius: 7px;
  background: rgba(255,255,255,.48);
  cursor: grab;
  touch-action: none;
  transition: border-color .15s,background .15s,opacity .15s,transform .15s;
}
.desktop-shortcut-item:active { cursor: grabbing; }
.desktop-shortcut-item.is-drag-source { display: none; }
.desktop-shortcut-group-body.is-collapsed .desktop-shortcut-item {
  padding: 5px;
}
.desktop-shortcut-group-body.is-collapsed .desktop-shortcut-name,
.desktop-shortcut-group-body.is-collapsed .desktop-shortcut-handle {
  display: none;
}
.desktop-shortcut-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.desktop-region.is-area-priority-selected {
  border-radius: 8px;
  background: rgba(var(--desktop-shortcut-hover-rgb), var(--desktop-shortcut-hover-alpha)) !important;
  color: var(--desktop-shortcut-hover-font-color) !important;
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%), 0 5px 14px -2px rgba(var(--desktop-shortcut-hover-shadow-rgb), var(--desktop-shortcut-hover-shadow-alpha)) !important;
}

.menu-admin-list,.user-admin-list,.settings-log-list {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

.menu-admin-header,.menu-admin-row {
  display: grid;
  grid-template-columns: 36px minmax(80px,.8fr) minmax(110px,1.4fr) 70px 96px 105px 30px;
  gap: 6px;
  align-items: center;
}

.menu-admin-header {
  position: sticky;
  top: 0;
  padding: 7px;
  background: #f6f6f6;
  border-bottom: 1px solid #ddd;
}

.menu-admin-row {
  min-height: 48px;
  padding: 6px 7px;
  border-bottom: 1px solid #eee;
}

.menu-admin-row:hover {
  background: rgba(255,255,255,.55);
}

.menu-admin-icon {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: #f0f0f0;
  overflow: hidden;
}

.menu-admin-title {
  font-weight: 700;
}

.menu-admin-desc {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.menu-admin-check {
  text-align: center;
}

.menu-admin-edit {
  width: 27px;
  height: 27px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

.menu-admin-edit:hover {
  background: #eee;
}

.settings-pill {
  display: inline-block;
  max-width: 100%;
  padding: 3px 5px;
  border-radius: 999px;
  background: #eee;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.user-admin-header,.user-admin-row {
  display: grid;
  grid-template-columns: 38px minmax(150px,1fr) 65px 86px 86px 70px;
  gap: 7px;
  align-items: center;
}

.user-admin-header {
  padding: 7px;
  background: #f6f6f6;
  border-bottom: 1px solid #ddd;
}

.user-admin-row {
  min-height: 52px;
  padding: 6px 7px;
  border-bottom: 1px solid #eee;
}

/* 사용자 그룹 목록 — menu-admin-row와 같은 스타일이지만 열 구성이 달라(이름/
   설명/인원/수정/삭제 5열) 별도 그리드로 둔다. */
.user-group-list {
  border: 1px solid #eee;
  border-radius: 7px;
  overflow: auto;
}

.user-group-header,.user-group-row {
  display: grid;
  grid-template-columns: minmax(80px,.8fr) minmax(110px,1.4fr) 70px 30px 70px;
  gap: 6px;
  align-items: center;
}

.user-group-header {
  position: sticky;
  top: 0;
  padding: 7px;
  background: #f6f6f6;
  border-bottom: 1px solid #ddd;
}

.user-group-row {
  min-height: 48px;
  padding: 6px 7px;
  border-bottom: 1px solid #eee;
}

.user-group-row:hover {
  background: rgba(255,255,255,.55);
}

.user-admin-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #ddd center/cover no-repeat;
}

.user-admin-name strong {
  display: block;
}

.user-admin-name span {
  display: block;
  margin-top: 2px;
}

.admin-action-button {
  height: 27px;
  border: 1px solid #ddd;
  border-radius: 6px;
  background: #fff;
  cursor: pointer;
}

.settings-log-item {
  display: grid;
  grid-template-columns: 125px 90px 110px 1fr;
  gap: 8px;
  padding: 8px;
  border-bottom: 1px solid #eee;
}

.settings-log-item p {
  margin: 0;
}

.settings-log-ip {
  font-family: monospace;
  font-size: 11px;
  opacity: .72;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 서버 로그 — 표준 log 패키지가 그대로 찍은 텍스트 줄이라 구조화된 표 대신
   콘솔처럼 보여준다(어두운 배경은 테마와 무관하게 항상 고정 — 터미널 출력과
   같은 느낌을 유지하려는 의도적 선택). */
.settings-server-log {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: 10px 12px;
  overflow: auto;
  border-radius: 8px;
  background: #1a1a1a;
  color: #d8d8d8;
  font-family: monospace;
  font-size: 11px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-all;
}

.settings-editor-layer {
  position: absolute;
  inset: 0;
  display: none;
  place-items: center;
  padding: 16px;
  background: rgba(0,0,0,.18);
  backdrop-filter: blur(3px);
}

.settings-editor-layer.is-open {
  display: grid;
}

.settings-editor-dialog {
  width: min(420px,100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(255,255,255,.75);
  border-radius: 11px;
  background: rgba(255,255,255,.95);
  box-shadow: 0 10px 28px -6px rgba(0,0,0,.14);
  overflow: hidden;
}

.settings-editor-head {
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 10px 0 13px;
  border-bottom: 1px solid #eee;
}

.settings-editor-head button {
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

.settings-editor-head button:hover {
  background: #eee;
}

.settings-editor-body {
  overflow: auto;
  padding: 12px;
}

.settings-edit-form {
  display: grid;
  gap: 10px;
}

.settings-form-field {
  display: grid;
  gap: 5px;
}

.settings-form-field>span {
  font-weight: 700
}

.settings-form-field input[type=text],.settings-form-field input[type=url],.settings-form-field select {
  width: 100%;
  height: 33px;
  padding: 0 9px;
  border: 1px solid;
  border-radius: 7px;
  outline: 0;
}

/* .post-editor(gallery/movie/character 등 각 편집기 마크업의 최상위 래퍼)가
   .window-content 높이를 그대로 채워야, 그 안의 .post-editor-form/-body가 쓰는
   flex:1;min-height:0 체인이 실제로 의미를 갖는다(퍼센트/flex 크기는 조상에게
   정해진 높이가 있어야 계산된다) — 이게 없으면 편집기가 내용이 없을 때
   쪼그라들고(아래 채움), 내용이 길어지면 .window-content 전체가 스크롤된다
   (아래 -content만 스크롤). detail 보기(openPostWindow, fitPostWindowHeight로
   내용에 맞춰 창 자체 높이를 재는 화면)는 이 클래스를 안 쓰므로 영향 없다.
   height:100%는 조상 높이가 아직 auto(fitPostWindowHeight가 재는 중)일 땐 그냥
   auto로 계산되므로(스펙상 퍼센트 높이는 조상이 확정 높이일 때만 적용) 그
   측정 로직과도 충돌하지 않는다. */
.post-editor {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.post-editor-form {
  border-radius: 10px;
  box-sizing: border-box;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 10px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
}

.post-editor-head {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid;
}

/* 제목 input을 감싸는 래퍼 — .post-editor-head가 수평 flex 행이라, 필수값 안내
   (.field-required-message)가 input의 형제로 들어가면 같은 줄에 나란히 끼어버린다.
   이 래퍼가 대신 flex item이 되어(원래 input이 갖던 flex/min-width를 그대로 옮김)
   `data-message-host`로 표시해두면 homepage.ui.js의 showRequiredFieldMessage가
   메시지를 형제로 놓는 대신 이 래퍼 "내부"(input 다음)에 넣어 진짜로 input 아래에
   쌓이게 한다. position:relative + 아래 [data-message-host] > .field-required-message의
   absolute는 그 메시지가 래퍼의 문서 흐름 높이에 관여하지 않게 해, 메시지가
   뜨고 지고 해도 .post-editor-head의 align-items:center 정렬(공개범위 select/
   등록 버튼)이 흔들리지 않게 한다. */
.post-editor-title-wrap {
  flex: 1;
  min-width: 120px;
  position: relative;
}

.post-editor-title-input {
  width: 100%;
  height: 33px;
  padding: 0 9px;
  border: 0;
  border-radius: 7px;
  outline: 0;
}

/* 브라우저 기본 필수값 말풍선 대신 쓰는 공용 인라인 안내(homepage.ui.js
   validateRequiredFields/showRequiredFieldMessage) — 어떤 필드 아래에 붙든
   같은 모습이면 충분해 폼별로 따로 만들지 않는다. */
.field-required-message {
  margin: 4px 0 0;
  line-height: 1.3;
  color: var(--focus-color);
}

/* data-message-host 안(post-editor-title-wrap 등)에 붙는 경우만 절대배치로
   흐름에서 뺀다 — 위 주석 참고. 로그인/가입처럼 세로로 쌓인 폼(형제로 붙는
   경우)은 이 규칙 대상이 아니라 계속 문서 흐름에 남아 다음 필드를 밀어낸다. */
[data-message-host] > .field-required-message {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 2px;
}

.post-editor-visibility-select {
  flex: 0 0 auto;
  height: 33px;
  padding: 0 8px;
  border: 0;
  border-radius: 7px;
  outline: 0;
}

.post-editor-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.post-editor-toolbar {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.post-editor-format-btn {
  height: 24px;
  padding: 0 8px;
  border: 1px solid;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

.post-editor-format-btn.is-bold { font-weight: 700; }
.post-editor-format-btn.is-italic { font-style: italic; }
.post-editor-format-btn.is-strike { text-decoration: line-through; }
.post-editor-format-btn.is-code { font-family: monospace; }

/* "민감한 이미지" 체크 — 체크한 채로 이미지를 삽입한 순간의 상태만 반영되고,
   그 다음 삽입부터는 다시 체크 상태를 따로 봐야 한다(토글 자체는 유지됨). */
.post-editor-sensitive-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  margin-left: auto;
  cursor: pointer;
}

/* 민감한 이미지 — 블러 처리 + 안내문/표시 버튼 오버레이. 이미지 자체는
   filter:blur만 걸고(레이아웃 그대로 유지), 오버레이는 부모에 절대배치
   형제로 끼워 넣는다(homepage.ui.js applySensitiveOverlay 참고). */
.sensitive-image-blurred {
  filter: blur(20px) saturate(1.1);
}
.sensitive-image-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px;
  text-align: center;
  background: rgba(0, 0, 0, .45);
  border-radius: inherit;
  z-index: 1;
}
.sensitive-image-overlay-text {
  color: #fff;
  font-size: 12px;
  line-height: 1.4;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

/* 지금 캐럿/선택 위치에 적용돼 있는 서식(gallery.js syncToolbarState)을 눌린
   상태로 보여준다 — is-bold 등(버튼 글자 자체의 항상-표시 스타일)과는 별개다. */
.post-editor-format-btn.is-active {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
  border-color: var(--focus-color) !important;
}

/* 본문은 <textarea>가 아니라 contenteditable — 서식 버튼이 document.execCommand로
   실제 <strong>/<em>/<blockquote>/<ul>/<ol>/<a>/<code>/<img> DOM을 만들어, 별도
   미리보기 화면 없이 입력과 동시에 이 영역 자체가 최종 렌더링과 같은 모습을 보인다
   (gallery.js insertImageNode/serializeEditorToMarkdown 참고). */
.post-editor-content {
  flex: 1;
  min-height: 0;
  width: 100%;
  border: 0px solid !important;
  border-radius: 7px;
  padding: 9px;
  line-height: 1.6;
  overflow: auto;
  /* window-content와 같은 이유로 네이티브 스크롤바를 숨긴다(postEditor.js
     bind()가 대신 window-content와 같은 오버레이 스크롤바를 붙인다) — 안
     숨기면 스크롤이 생길 때마다 네이티브 스크롤바 트랙 폭(15~17px)만큼
     입력 가능한 폭이 줄어 보인다("작성 영역이 좁아짐"). */
  scrollbar-width: none;
  outline: 0;
  transition: border-color .15s, background .15s;
}

.post-editor-content::-webkit-scrollbar {
  display: none;
}

.post-editor-title-input,
.post-editor-visibility-select,
.post-editor-content {
  background: rgba(var(--system-c-input-rgb), var(--system-c-input-alpha)) !important;
  color: var(--system-c-input-font-color) !important;
  border-color: rgba(var(--system-c-input-border-rgb), var(--system-c-input-border-alpha)) !important;
}

.post-editor-content:empty::before {
  content: attr(data-placeholder);
  color: var(--system-c-desc-color);
  pointer-events: none;
}

/* 드래그해 온 이미지가 이 영역 위에 있을 때의 시각 피드백(gallery.js가 토글). */
.post-editor-content.is-drag-over {
  border-color: var(--focus-color) !important;
  background: rgba(var(--focus-rgb), .06);
}

.post-editor-message {
  flex: 0 0 auto;
  min-height: 14px;
  margin: 0;
}

.post-editor-message.is-error {
  color: var(--focus-color);
}

/* 새 글 [등록] 시점에만 뜨는 썸네일 출처 이미지 선택 목록 —
   .image-layout-dialog-options와 같은 패턴, 텍스트 버튼 대신 작은 미리보기 그리드.
   기본 .confirm-dialog(320px)로는 4열 그리드가 너무 좁아 살짝 넓힌다. */
.thumbnail-source-dialog {
  max-width: 420px;
}

/* 공개범위 "일부 사용자 공개" 대상(그룹+사용자) 선택 다이얼로그 —
   .specific-user-list 두 벌(그룹/사용자)이 나란히 들어가 기본
   .confirm-dialog(320px)로는 좁다. */
.visibility-grantee-dialog {
  max-width: 420px;
  text-align: left;
}

/* 메뉴/공유기록 아이콘 피커(UI.buildIconPicker) — PNG 업로드 / SVG 붙여넣기 탭. */
.icon-picker-dialog {
  max-width: 420px;
  text-align: left;
}

.icon-picker-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 10px;
}

.icon-picker-tabs button {
  flex: 1;
  height: 30px;
  border: 0px solid rgba(120, 120, 120, .3);
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

.icon-picker-tabs button.is-active {
  border-color: var(--focus-color) !important;
  color: var(--focus-color);
  border-bottom: 3px solid;
}

.icon-picker-textarea {
  width: 100%;
  resize: vertical;
  font-family: monospace;
  font-size: 12px;
}

.icon-picker-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-top: 8px;
  border: 1px solid rgba(120, 120, 120, .3);
  border-radius: 4px;
}

.icon-picker-preview svg {
  width: 24px;
  height: 24px;
  fill: currentColor;
}

.thumbnail-source-dialog-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 10px 0;
  max-height: 240px;
  overflow-y: auto;
}

.thumbnail-source-dialog-item {
  width: 100%;
  aspect-ratio: 1;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  background: transparent;
}

.thumbnail-source-dialog-item:hover,
.thumbnail-source-dialog-item:focus-visible {
  border-color: var(--focus-color) !important;
}

.thumbnail-source-dialog-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* 게시글 썸네일 16:9 크롭 다이얼로그 — 기존 .confirm-dialog을 재사용하되
   이미지 박스가 들어갈 만큼 폭만 넓힌다. */
.image-crop-dialog {
  width: min(720px, calc(100% - 28px));
  max-width: 720px;
  box-sizing: border-box;
}

.image-crop-box {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  cursor: grab;
  touch-action: none;
  background: transparent;
}

.image-crop-box img {
  position: absolute;
  max-width: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* 캐릭터 아바타 등 원형으로 표시될 크롭 영역 — 자르기 자체는 그대로 정사각
   Blob(캔버스)으로 나가고, 여기선 미리보기 박스만 원으로 마스킹해 보여준다. */
.image-crop-box.is-circle {
  aspect-ratio: 1 / 1;
  border-radius: 50%;
}

.image-crop-box.is-portrait {
  width: min(280px, 100%);
  margin-inline: auto;
}

.image-crop-zoom {
  appearance: none;
  width: 100%;
  height: 12px;
  margin: 10px 0;
  background: transparent;
  accent-color: var(--focus-color);
}

.image-crop-zoom::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 999px;
  background: var(--focus-color);
}

.image-crop-zoom::-webkit-slider-thumb {
  appearance: none;
  width: 10px;
  height: 10px;
  margin-top: -4px;
  border: 0;
  border-radius: 50%;
  background: var(--focus-color);
}

.image-crop-zoom::-moz-range-track,
.image-crop-zoom::-moz-range-progress {
  height: 2px;
  border-radius: 999px;
  background: var(--focus-color);
}

.image-crop-zoom::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 50%;
  background: var(--focus-color);
}

/* 게시글 마크다운 본문 스타일 — 편집 영역(.post-editor-content)과 실제 게시글
   보기(.post-markdown-body, UI.openPost) 양쪽에서 공용으로 써서 편집 결과와 실제
   렌더링 결과가 항상 같은 모습으로 보이게 한다. */
.post-markdown-body h3,
.post-markdown-body h4,
.post-markdown-body h5,
.post-editor-content h3,
.post-editor-content h4,
.post-editor-content h5 {
  /* 브라우저 기본 h1~h6는 font-weight:bold라 execCommand의 queryCommandState('bold')가
     명시적 <strong>/<b> 없이도 제목 안에서 항상 true를 반환해 Bold 버튼이 잘못
     활성화되고, 그 상태에서 Bold를 끄면 진짜 <strong>을 지우는 게 아니라 계산값만
     되돌리는 별도 override span이 생겨 저장 시 사라진다(gallery.js syncToolbarState/
     serializeInlineNode 참고). 제목의 기본 굵기를 여기서 normal로 리셋해 "제목이라
     계산상 굵어 보이는 것"과 "명시적으로 굵게 표시한 것"을 완전히 분리한다 — 제목의
     시각적 구분은 이미 h1,h2,h3 규칙(위쪽, --system-c-title-color)과 아래 font-size
     13px!important 규칙이 맡고 있어 굵기에 의존하지 않는다. 이 규칙 아래에서 만든
     명시적 <strong>/<b>(예: `# **굵은 제목**`)는 각 태그 자체의 굵은 기본 스타일이
     남아있어 여전히 굵게 보인다.
  */
  font-weight: normal;
  margin: .8em 0 .3em;
}

.post-markdown-body blockquote,
.post-editor-content blockquote {
  margin: .6em 0;
  padding: 2px 12px;
  border-left: 3px solid rgba(var(--focus-rgb), .6)!important;
  color: var(--system-c-desc-color);
}

.post-markdown-body ul,
.post-markdown-body ol,
.post-editor-content ul,
.post-editor-content ol {
  margin: .4em 0;
  padding-left: 22px;
}

.post-markdown-body li,
.post-editor-content li {
  margin: .2em 0;
}

.post-markdown-body code,
.post-editor-content code {
  font-family: monospace;
  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
  border-radius: 4px;
  padding: 1px 5px;
}

.post-markdown-body a,
.post-editor-content a {
  color: var(--focus-color);
  text-decoration: underline;
}

/* @멘션 — 렌더된 글과 편집 중인 칩이 같은 톤을 쓴다. 렌더된 칩은 클릭하면
   body 직속 프로필 카드가 열리므로 윈도우 overflow에 잘리지 않는다. */
.post-mention,
.post-mention-chip,
.mention-pending {
  color: var(--focus-color);
  font-weight: 700;
}
.post-mention {
  padding: 0px 6px 2px;
  border-radius: 10px;
  border: 1px solid var(--focus-color) !important;
  margin: 4px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha));
  cursor: pointer;
}
.post-mention.is-self {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}
.mention-profile-popover {
  position: fixed;
  z-index: calc(var(--z-debug) + 2);
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 210px;
  max-width: min(280px, calc(100vw - 16px));
  padding: 10px;
  border-radius: 8px;
  color: var(--system-c-font-color) !important;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  box-shadow: 0 6px 18px -4px rgba(0, 0, 0, .24);
}
.mention-profile-popover[hidden] {
  display: none !important;
}
.mention-profile-avatar {
  flex: 0 0 42px;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background-position: center;
  background-size: cover;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha));
}
.mention-profile-avatar svg {
  width: 24px;
  height: 24px;
}
.mention-profile-summary {
  min-width: 0;
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}
.mention-profile-summary strong {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.post-editor-content a.post-mention-chip {
  text-decoration: none;
}

/* @멘션 검색 드롭다운 — document.body에 붙어(postEditor.js) 캐럿 span의
   getBoundingClientRect() 좌표를 그대로 쓰므로 position:fixed다(스크롤
   컨테이너 안에서도 항상 캐럿 바로 아래에 온다). system C content 테마
   (.movie-search-dropdown/.movie-search-result-item과 동일한 배경/테두리
   변수 조합)를 그대로 따른다. */
.mention-dropdown {
  position: fixed;
  z-index: 20;
  min-width: 180px;
  max-height: 220px;
  overflow-y: auto;
  scrollbar-width: none;
  border-radius: 8px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
}
.mention-dropdown::-webkit-scrollbar {
  display: none;
}
.mention-dropdown-item {
  display: flex;
  width: 100%;
  gap: 8px;
  align-items: center;
  padding: 6px 8px;
  text-align: left;
  cursor: pointer;
  background: transparent !important;
  border: none;
  color: var(--system-c-font-color) !important;
}
.mention-dropdown-item:hover,
.mention-dropdown-item.is-active {
  background: rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;
}
.mention-dropdown-avatar {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  background-color: rgba(var(--system-c-rgb), var(--system-c-alpha));
}
.mention-dropdown-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mention-match {
  color: var(--focus-color);
  font-weight: 700;
}

/* 실제 게시글과 편집기가 항상 같은 모습이 되도록 원본 크기와 무관하게 콘텐츠
   가로폭 전체를 차지하게 하고, height:auto로 원본 비율은 그대로 유지한다. */
.post-markdown-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
  margin: 8px 0;
}

/* 다중 이미지 좌우 넘김 뷰어(gallery.js insertImageViewerNode / homepage.ui.js
   renderSafeMarkdown+bindImageViewers가 공유하는 마크업). 한 번에 한 장만 보이고
   (JS가 각 <img data-viewer-slide>의 display를 토글), 이전/다음 버튼과 위치
   표시는 이미지 위에 겹쳐 그린다. */
.post-image-viewer {
  position: relative;
  display: block;
  margin: 8px 0;
}

.post-image-viewer .post-markdown-image {
  margin: 0;
}

.post-image-viewer-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .45);
  color: #fff;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.post-image-viewer-nav:disabled {
  opacity: .35;
  cursor: default;
}

.post-image-viewer-prev { left: 8px; }
.post-image-viewer-next { right: 8px; }

.post-image-viewer-position {
  position: absolute;
  bottom: 8px;
  right: 8px;
  padding: 2px 8px;
  border-radius: 10px;
  background: rgba(0, 0, 0, .45);
  color: #fff;
}

/* 읽기용 게시글 본문에서만 켜지는 좌우 25%/가운데 50% 클릭 탐색·크게 보기
   (homepage.ui.js bindImageViewers) — 클릭 가능함을 커서로 알린다. */
.post-image-viewer-zoomable .post-markdown-image {
  cursor: pointer;
}

/* 뷰어 블록 밖의 낱장 이미지(영화 포스터 등, UI.makeImageZoomable)용 —
   위와 같은 커서 힌트만 이미지 자신에게 직접 준다. */
.img-zoomable {
  cursor: pointer;
}

/* 크게 보기 오버레이. .window(overflow:hidden, position:fixed)의 자식으로 붙여
   window-bar와 주소창 높이만큼 top을 실측해 띄우므로 창 밖이나 상단 UI를
   가리지 않고, 창 리사이즈/최대화에도 .window 크기를 그대로 따라간다. */
.post-image-lightbox {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, .82);
}

.post-image-lightbox[hidden] {
  display: none;
}

.post-image-lightbox-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
  transform-origin: center center;
  transition: transform .1s ease-out;
  touch-action: none;
  will-change: transform;
}

.post-image-lightbox.is-zoomed .post-image-lightbox-img {
  cursor: grab;
  border-radius: 0;
}

.post-image-lightbox.is-panning .post-image-lightbox-img {
  cursor: grabbing;
  transition: none;
}

.post-image-lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.post-image-lightbox-nav:disabled {
  opacity: .3;
  cursor: default;
}

.post-image-lightbox-prev { left: 12px; }
.post-image-lightbox-next { right: 12px; }

.post-image-lightbox-position {
  position: absolute;
  right: 16px;
  bottom: 12px;
  padding: 3px 8px;
  border-radius: 10px;
  background: rgba(0, 0, 0, .55);
  color: #fff;
}

.post-image-lightbox-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

/* 라이브2D 모델이 연결된 본문 이미지 위에 겹치는 배지(homepage.ui.js
   bindLive2DBadges). 뷰어(다중이미지) 슬라이드는 이미 .post-image-viewer가
   position:relative라 배지를 바로 그 위에 얹지만, 단일(뷰어 아닌) <img>는
   감싸는 요소가 없어서 이 span으로 새로 감싼다. .post-markdown-image가 이미
   display:block;width:100%(에디터와 똑같이 한 줄에 하나, 포스트 폭 100%를
   차지)이므로 감싸개도 같은 block;width:100%여야 한다 — 예전에 inline-block;
   max-width:100%였을 때는 이미지가 자기 원본 크기로 쪼그라들어, 라이브2D
   배지가 뜨는 게시글(관리자에게는 배지 미연결 이미지에도 항상 뜬다)에서
   이미지 두 장이 폭에 따라 한 줄에 나란히 보이는 버그가 있었다. */
.post-markdown-image-wrap {
  position: relative;
  display: block;
  width: 100%;
}

.live2d-badge {
  position: absolute;
  right: 8px;
  top: 8px;
  width: auto;
  height: 26px;
  padding: 0 8px;
  border: 0;
  border-radius: 10px;
  background: var(--focus-color);
  color: var(--focus-font-color);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
}

/* 관리자에게만 보이는 "아직 연결 안 됨" 상태 — 채워진 배경 대신 테두리만
   그려 "연결된 모델을 본다"(live2d-badge)와 시각적으로 구분한다. */
/* 테두리 색은 .focus-border 유틸리티(광역 * {border-color …!important}에
   지지 않도록) — 여기선 굵기/모양만. */
.live2d-badge.is-empty {
  background: transparent;
  border: 1px dashed;
  color: var(--focus-color);
}

/* "정보"(해시태그/YouTube/X 링크) 배지 — Live2D 배지와 같은 이미지 위에 함께
   뜰 수 있어(둘 다 관리자 전용) 반대쪽 모서리에 둔다. */
.gallery-image-meta-badge {
  right: auto;
  left: 8px;
}

/* 라이브2D 모델 뷰어 오버레이 — post-image-lightbox와 같은 패턴(.window의
   자식으로 붙어 window-bar 높이만큼 top을 실측해 띄운다). */
.live2d-viewer-overlay {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, .85);
}

.live2d-viewer-overlay[hidden] {
  display: none;
}

.live2d-viewer-canvas {
  flex: 1;
  min-height: 0;
  width: 100%;
  touch-action: none;
}

.live2d-viewer-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  z-index: 1;
}

.live2d-viewer-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  text-align: center;
  max-width: 80%;
}

.live2d-viewer-loading[hidden] {
  display: none;
}

/* flex 행으로 자기 자리를 차지해 캔버스 높이를 줄이던 걸, .live2d-viewer-close와
   같은 방식(overlay 자체가 이미 position:absolute라 그 안에서 바로 앵커된다)의
   오버레이로 바꿔 캔버스가 뷰어 전체 높이를 그대로 쓰게 한다. */
.live2d-viewer-toolbar {
  position: absolute;
  left: 12px;
  bottom: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(0, 0, 0, .55);
  z-index: 1;
}

/* 조작 모드/트래킹 설정 패널은 뷰어 자체의 어두운 스크림과 달리
   .confirm-dialog와 같은 System C content 테마를 따른다. */
.live2d-viewer-params {
  position: absolute;
  right: 12px;
  bottom: 62px;
  width: 240px;
  max-height: min(340px, 60%);
  overflow-y: auto;
  padding: 10px;
  border-radius: 8px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  color: var(--system-c-font-color) !important;
}

.live2d-viewer-params[hidden] {
  display: none;
}

.live2d-param-row {
  display: flex;
  align-items: center;
  gap: 8px;
  color: inherit;
  font-size: 11px;
  margin-bottom: 6px;
}

.live2d-param-row span {
  flex: 0 0 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.live2d-param-row input[type="range"] {
  flex: 1;
}

.live2d-viewer-tracking {
  position: absolute;
  right: 12px;
  bottom: 62px;
  width: 340px;
  max-height: min(360px, 60%);
  overflow-y: auto;
  padding: 10px;
  border-radius: 8px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  color: var(--system-c-font-color) !important;
}

.live2d-viewer-tracking[hidden] {
  display: none;
}

.live2d-tracking-hint {
  margin: 0 0 8px;
  color: var(--system-c-desc-color);
  font-size: 11px;
  line-height: 1.4;
}

.live2d-tracking-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  color: inherit;
  font-size: 11px;
  padding: 4px 0;
  border-bottom: 1px solid rgba(var(--system-c-rgb), .2);
}

.live2d-tracking-name {
  flex: 1 0 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.live2d-tracking-axis {
  display: flex;
  align-items: center;
  gap: 3px;
  flex: 0 0 auto;
}

.live2d-tracking-visible {
  margin-left: auto;
  color: var(--focus-color, #ffd479);
}

[data-live2d-tracking-save] {
  margin-top: 6px;
  width: 100%;
}

/* 편집기에서만 쓰는 이미지 삭제(x) 버튼을 얹기 위한 감싸개(gallery.js
   wrapImageFrame). 실제 게시글 보기(post-markdown-body)에는 이 감싸개가 없고
   원본 <img>만 쓰이므로 이미지 자체의 여백(.post-markdown-image의 margin)은
   그대로 두고, 감싸개 안에서만 0으로 덮어써 겹치지 않게 한다. */
.post-image-frame {
  position: relative;
  display: block;
  width: 100%;
  margin: 8px 0;
}

.post-image-frame .post-markdown-image {
  margin: 0;
}

.post-image-viewer .post-image-frame {
  margin: 0;
}

.post-image-frame.is-selected-image {
  outline: 2px solid var(--focus-color);
  outline-offset: 2px;
  border-radius: 8px;
}

.post-image-remove-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.post-image-remove-btn:hover {
  background: rgba(0, 0, 0, .75);
}

/* 이미지 여러 장을 한번에 삽입할 때 세로 순차 표시/좌우 뷰어 중 하나를 고르는
   선택 다이얼로그(gallery.js chooseImageLayout)의 큰 선택 버튼 두 개. */
.image-layout-dialog-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 10px 0;
}

.image-layout-dialog-options .small-btn {
  width: 100%;
}

.confirm-dialog-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .35);
}

/* 게시글 작성 창의 썸네일 선택/크롭 단계만 브라우저 전체가 아니라 그 .window
   내부(작성 창의 position:fixed + overflow:hidden 박스)에 한정해서 덮는다 —
   .window에 직접 append되므로 position:absolute; inset:0만으로 창 경계·둥근
   모서리 안쪽에 자동으로 클리핑되고, 다른 창·브라우저 나머지 영역은 그대로 둔다. */
.confirm-dialog-overlay.is-window-scoped {
  position: absolute;
}

.confirm-dialog {
  min-width: 220px;
  max-width: 320px;
  padding: 18px;
  border-radius: 12px;
  text-align: center;
  background: var(--system-c-content-color) !important;
  box-shadow: 0 12px 28px -6px rgba(0, 0, 0, .22);
}

.confirm-dialog-message {
  margin: 0 0 16px;
  line-height: 1.6;
  /* 한글은 기본적으로 어절 중간에서도 줄바꿈이 허용돼(word-break:normal) 좁은
     다이얼로그 폭에서 단어가 쪼개지기 쉽다 — 공백 단위로만 넘어가게 고정. */
  word-break: keep-all;
}

.confirm-dialog-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.settings-check-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.settings-check-row label {
  display: flex;
  align-items: center;
  gap: 5px;
}

.settings-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  padding-top: 4px;
}

.settings-form-actions button {
  height: 29px;
  padding: 0 12px;
  border: 1px solid #ddd;
  border-radius: 7px;
  background: #fff;
  cursor: pointer;
}

.specific-user-list {
  max-height: 150px;
  overflow: auto;
  border: 1px solid #eee;
  border-radius: 7px;
}

.specific-user-item {
  display: grid;
  grid-template-columns: 68px 1fr 70px;
  gap: 5px;
  align-items: center;
  padding: 6px;
  border-bottom: 1px solid #f0f0f0;
}

.specific-user-item:last-child {
  border-bottom: 0;
}

.settings-inline-message {
  min-height: 12px;
}

/* ==========================================================================
   설정 앱 공통 토글 버튼 (체크박스 대체). 실제 <input type="checkbox">는 시각적으로만
   숨기고(opacity:0) 그대로 두어 checked/disabled/change, name 기반 폼 직렬화가 기존
   체크박스와 동일하게 동작한다. 왼쪽 상태 텍스트(data-on/data-off)는 :checked 여부에
   따라 ::before로 즉시 전환되므로 별도 JS 동기화가 필요 없다.
   ========================================================================== */
.settings-toggle {
  display: inline-flex !important;
  flex-direction: row-reverse;
  align-items: center;
  gap: 6px;
  min-width: 0;
  cursor: pointer;
}
.settings-toggle-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  opacity: 0;
}
.settings-toggle-track {
  position: relative;
  flex: none;
  width: 30px;
  height: 17px;
  border-radius: 999px;
  background: rgba(0,0,0,.18);
  transition: background .15s ease;
}
.settings-toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.35);
  transition: transform .15s ease;
}
.settings-toggle-input:checked ~ .settings-toggle-track {
  background: var(--focus-color) !important;
}
.settings-toggle-input:checked ~ .settings-toggle-track .settings-toggle-thumb {
  transform: translateX(13px);
}
.settings-toggle-input:focus-visible ~ .settings-toggle-track {
  outline: 2px solid var(--focus-color);
  outline-offset: 2px;
}
.settings-toggle-input:disabled ~ .settings-toggle-track {
  opacity: .55;
  cursor: not-allowed;
}
.settings-toggle-input:disabled ~ .settings-toggle-text {
  cursor: not-allowed;
}
.settings-toggle-input:disabled {
  cursor: not-allowed;
}
.settings-toggle-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.settings-toggle-text::before {
  content: attr(data-off);
}
.settings-toggle-input:checked ~ .settings-toggle-text::before {
  content: attr(data-on);
}

@media(max-width:900px){.menu-admin-header{display:none}

  .menu-admin-row{grid-template-columns:32px 1fr 30px}

  .menu-admin-row>*:not(.menu-admin-icon):not(.menu-admin-title):not(.menu-admin-edit){display:none}

  .user-admin-header{display:none}

  .user-admin-row{grid-template-columns:36px 1fr 65px}

  .user-admin-row .admin-action-button:not(:last-child){display:none}}

/* 최초 크기만 960x520(spawnTemplateWindow 호출부 width/height)이고, 그 외에는
   일반 창과 동일하게 테두리/모서리 드래그로 자유롭게 리사이즈된다 — 창 전용
   max-width/max-height, resize-handle 숨김 규칙을 두지 않는다. 공통 .window의
   min-width/min-height 및 뷰포트 경계 클램프(makeWindowInteractive)는 그대로 적용됨. */
/* 컨텐츠(환경설정/테마관리/메뉴관리/사용자관리/이력관리)가 창 크기 안에 다 들어오면
   그대로 보이고, 안 들어오면(작은 창 등) 잘리지 않고 스크롤되도록 한다. */
.window[data-root="settings"] .window-content {
  padding: 12px;
  overflow-y: auto;
  overflow-x: hidden;
}

/* 좁은 창의 내비게이션은 위 window-content의 안쪽 여백까지 덮어
   윈도우바 아래 콘텐츠 영역 전체를 가린다. */
.settings-shell.is-nav-small .settings-nav-backdrop {
  inset: -12px;
}

.settings-shell {
  gap: 14px;
}

.settings-nav {
  flex-basis: 168px;
  min-width: 96px;
  gap: 3px;
  padding-right: 8px;
}

.settings-nav-btn {
  min-height: 35px;
  border-left: 3px solid transparent !important;
}

.settings-content {
  gap: 10px;
  padding-left: 4px;
}

.settings-shell.is-nav-small .settings-nav {
  inset: -12px auto -12px -12px;
  width: 220px;
  max-width: 80%;
  padding: 10px 8px;
  border-radius: 0 10px 10px 0;
  box-shadow: 3px 0 10px -3px rgba(0,0,0,.16);
}

.settings-panel-header {
  gap: 8px;
  padding-bottom: 8px;
}

.settings-header-toggle {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: 6px;
}

.settings-header-toggle.transparent-button {
  border: 0 !important;
}

.settings-header-text span {
  margin-top: 3px;
}

.settings-header-actions {
  gap: 10px;
  padding-top: 1px;
}

.settings-header-action-group {
  gap: 6px;
}

.settings-header-action-group .settings-inline-message {
  max-width: 130px;
  text-align: right;
}

.settings-header-action-group button {
  height: 27px;
  padding: 0 10px;
  border: 1px solid rgba(var(--system-c-rgb), var(--system-c-alpha));
  border-radius: 7px;
  cursor: pointer;
}

/* 모니터 열은 더 이상 고정 폭이 아니라 auto — 실제 폭은 아래 .settings-pc-preview의
   aspect-ratio가 "높이"로부터 역산한다. 그 높이는 이 grid row의 기본 정렬
   (align-items:stretch)에 의해 .settings-info-list의 실제 콘텐츠 높이(라벨 4줄+
   간격)에 맞춰지므로, 정보 목록 쪽 줄 수가 늘거나 줄어도 모니터가 항상 그 높이를
   그대로 따라간다. 정보 목록 열은 minmax(0,1fr)이라 남는 폭을 모두 차지하다가
   모니터가 커지는 만큼 자연히 좁아진다("정보 목록 열 너비는 좁아져도 됨" 요구사항). */
.settings-home-grid {
  grid-template-columns: auto minmax(0,1fr);
  gap: 10px;
}

.settings-pc-preview {
  box-sizing: border-box;
  width: auto;
  aspect-ratio: 210 / 131;
  padding: 6px 6px 11px;
}

.settings-pc-screen {
  height: 100%;
}

.settings-info-list {
  gap: 5px;
}

.settings-info-row {
  min-height: 35px;
  grid-template-columns: 105px minmax(0,1fr);
  padding: 5px 8px;
}

.settings-info-label {
  font-weight: 700;
}

.settings-inline-input,.settings-inline-select, .settings-info-value {
  height: 27px;
}


.settings-music-summary {
  min-width: 0;
  height: 29px;
  display: flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: transparent;
  padding: 0 5px;
  text-align: left;
  cursor: text;
}

.settings-music-input {
  display: none;
  grid-column: 2;
}

.settings-music-row.is-editing .settings-music-summary {
  display: none;
}

.settings-music-row.is-editing .settings-music-input {
  display: block;
}

.settings-main-message {
  grid-column: 1/-1;
  min-height: 12px;
  color: rgba(80,80,80,.7);
}

.settings-panel-head {
  padding-bottom: 7px;
}

/* 시작/검색/날짜/재생목록 팝업은 기존 대비 약 120%, 아이콘 크기는 유지 */

.shortcut-popover {
  /* 시작 메뉴는 한 줄에 아이콘 4개(.shortcut-grid-flat 4열, .shortcut-footer와
     같은 열 수)에 맞춰 폭을 잡는다 — 위 섹션의 검색/날짜 팝업 120% 확대와는
     별개. 열이 부족하면 행이 늘어나 max-height를 넘겨 세로 스크롤이 생기므로,
     70px 고정폭 아이콘 4개+gap+padding이 다 들어갈 만큼 넓힌다(정확히 맞추면
     서브픽셀 반올림으로 가로 스크롤이 생길 수 있어 여유를 둔다). left:8px
     기준 양쪽 8px 여백을 넘지 않도록 좁은 뷰포트에서만 줄어들게 한다. */
  width: min(360px, calc(100vw - 16px));
  padding: 14px;
}

.search-suggest {
  width: 372px;
  max-height: 360px;
  padding: 9px;
  border-radius: 12px;
}

@media (max-width: 680px) {
  .calendar-popover.open {
    overflow: hidden;
  }

  .clock-flyout-calendar,
  .clock-flyout-notifications {
    width: min(324px, calc(100vw - 16px));
  }

}

.shortcut-grid-flat {
  gap: 9px;
}

.shortcut {
  padding: 10px 5px;
}

.shortcut strong {
  margin-top: 6px;
}

.suggest-item {
  padding: 10px;
}

.suggest-item small {
  margin-top: 3px;
}

.mini-week span {
  padding: 5px;
}

.mini-day,
.mini-day.today {
  width: 35px;
  height: 35px;
}
/* 작업표시줄 검색창 래퍼(<label id="searchBox">) */
.start-menu-search {
  height: 38px;
  display: flex;
  gap: 8px;
}

/* 돋보기 글리프는 <g style="fill:currentColor"> 라 stroke만으론 색이 안 바뀐다.
   게다가 .taskbar-scope * 가 그 <g>를 직접 잡아 색을 덮으므로 자손까지 지정한다. */
.start-menu-search.input-text-box svg,
.start-menu-search.input-text-box svg * {
  stroke: var(--area-input-font-color, var(--system-c-input-font-color)) !important;
  color: var(--area-input-font-color, var(--system-c-input-font-color)) !important;
}
/* 좁은 화면(모바일 등, 다른 곳과 같은 640px 기준)에서 작업표시줄 검색창 —
   입력칸 실측 243px가 작업표시줄 전체 폭(375px 기기 기준)의 65%를 먹어
   앱 아이콘/시계가 밀려난다. 아이콘만 남기고, 탭하면(기존 searchBox.onclick이
   이미 input을 focus시키므로 별도 JS 없이) :focus-within으로 펼쳐지게
   한다 — 접힌 상태에선 배경/테두리(.start-menu-search.input-text-box의
   System A 배경·테두리 !important 규칙들)도 같이 숨겨 순수 아이콘처럼
   보이게 하고, 펼쳤을 때만 되살린다. #searchBox(id)를 써서 클래스
   조합보다 특이도를 확실히 높게 잡는다 — 아래에서 끄는 배경/테두리
   규칙들이 파일 뒤쪽(!important, 클래스 2개)에 있어 클래스만으로는
   소스 순서상 질 수 있기 때문. */
@media (max-width: 640px) {
  .taskbar #searchBox {
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    /* background만 지워도 .input-text-box 기본의 backdrop-filter:blur(18px)가
       그대로 남아있어 뒤가 뿌옇게 흐려진 사각형이 계속 보였다(요청: "배경이
       남아있는데") — 접힌 상태에선 이것도 꺼야 진짜 아이콘만 남는다. */
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  .taskbar #searchBox:not(:focus-within) svg,
  .taskbar #searchBox:not(:focus-within) svg * {
    stroke: var(--system-a-font-color) !important;
    color: var(--system-a-font-color) !important;
  }
  .taskbar #searchBox:focus-within {
    background: rgba(var(--system-a-input-rgb), var(--system-a-input-alpha)) !important;
    border-color: rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha)) !important;
    backdrop-filter: blur(18px) saturate(1.12) !important;
    -webkit-backdrop-filter: blur(18px) saturate(1.12) !important;
  }
  .taskbar #searchBox input {
    width: 0;
    min-width: 0;
    opacity: 0;
    transition: width .18s ease, opacity .15s ease;
  }
  .taskbar #searchBox:focus-within input {
    width: 110px;
    opacity: 1;
  }
}
.start-menu-search input::placeholder {
  color: var(--system-a-rgb);
}


/* 우측 하단 시스템 메시지 */

.system-message-stack {
  position: fixed;
  right: 14px;
  bottom: calc(var(--taskbar-h) + 12px);
  width: min(320px, calc(100vw - 28px));
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 7px;
  pointer-events: none;
}

.system-message {
  min-height: 38px;
  display: flex;
  align-items: center;
  padding: 9px 12px;
  border-radius: 9px;
  box-shadow: 0 12px 30px -6px rgba(0,0,0,.16);
  backdrop-filter: blur(18px) saturate(1.12);
  -webkit-backdrop-filter: blur(18px) saturate(1.12);
  line-height: 1.45;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .18s ease, transform .18s ease;
  pointer-events: auto;
  cursor: pointer;
}

.system-message.show {
  opacity: 1;
  transform: translateY(0);
}

/* 시스템 컬러: 모달 외곽/상단바(System B) */

.window {
  border-color: rgba(var(--system-b-window-border-rgb), var(--system-b-window-border-alpha)) !important;
}

.window-bar {
  border-bottom-color: rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
}
/* 시스템 컬러 85%: 작업표시줄/시작메뉴/볼륨/날짜=System A, 그 외 컨텐츠영역=System C */

.taskbar,
.shortcut-popover,
.sound-popover,
.clock-flyout-calendar,
.clock-flyout-notifications,
.search-suggest,
.preview-card {
  background: rgba(var(--system-a-rgb), var(--system-a-alpha)) !important;
}

.window-content,
select:not(.diary-date-select),
.settings-info-row,
.settings-editor-layer,
.settings-form-field input,
.settings-form-field select,
.settings-pill,
.menu-admin-icon,
.user-admin-avatar,
.preview-thumb,
.settings-pc-preview,
.system-message,
.server-stats-traffic,
.server-stats-disk, .server-stats-visitors,
.post-editor-content,
.post-editor-title-input,
.menu-admin-row:hover,
.settings-editor-dialog,
.activity-thumb {
  background: rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;
}

/* System-color surfaces: previous values -0.05 alpha. (윈도우바=System B, 그 외=System C) */

/*.image-area,*/
/*.small-btn,*/
/*.menu-admin-header,*/
/*.user-admin-header,*/
/*.admin-action-button,*/
/*.settings-form-actions button,*/
/*.profile-avatar,*/
/*.close-all,*/
/*.timeline {*/
/*  background: rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;*/
/*}*/

.app-btn:after,
.timeline span,
.mini-day.today,
.mini-day.has:after,
.user-primary-button,
.settings-form-actions .primary {
  background: var(--focus-color) !important;
  border-color: var(--focus-color) !important;
}

/* Theme-derived error emphasis. */

.settings-main-message.is-error,
.settings-inline-message.is-error {
  color: var(--focus-color) !important;
}
/* Modal frame: top bar is opaque system;
   content is system @ .75. */

/* Buttons: normal background is opaque system. (윈도우바=System B, 그 외=System C) */

.window-bar,
.preview-thumb .window-bar,
.window-minimize,.window-close{
  background: rgba(var(--system-b-rgb), var(--system-b-alpha)) !important;
}

button:disabled {
  opacity: .55;
  pointer-events: none;
}

.profile-card,.user-auth-panel {
  background: transparent !important;
}

/* Fields with focus use focus border/shadow. */
textarea:hover,textarea:focus,
.guest-form textarea:hover,.guest-form textarea:focus {
  border-color: var(--focus-color) !important;
  outline: none !important;
  box-shadow: 0 0 0 2px rgba(var(--focus-rgb),.28) !important;
}
.settings-card-label,.settings-info-value,.settings-music-title,.settings-panel-head strong {
  background: transparent !important;
  border-color: transparent !important;
}

.settings-music-thumb {
  border: 1px solid rgba(var(--system-c-rgb), var(--system-c-alpha));
}

.menu-admin-header,.user-admin-header {
  color: var(--system-c-desc-color) !important;
}

.menu-admin-row,.user-admin-row,.settings-log-item,.specific-user-item {
  border-color: rgba(var(--system-c-rgb), var(--system-c-alpha)) !important;
}
.theme-swatch {
  grid-row: 1/3;
  width: 22px;
  height: 22px;
  border: 1px solid #555 !important;
  border-radius: 5px;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
/* 작업표시줄 아이콘 버튼은 .sys-a-btn-a 가 투명 처리. 여기 남은 둘만 별도. */
.profile-stat,
.settings-music-summary {
  background: transparent !important;
  border-color: transparent !important;
}

/* Form/input fields: no shadow. Focus is expressed with the focus-color border only. */
input,
select,
.guest-form textarea,
.settings-inline-input,
.settings-inline-select,
.settings-form-field input,
.settings-form-field select{
  box-shadow: none !important;
}
input:hover,
select:hover,
input:focus,
select:focus,
.settings-inline-input:hover,
.settings-inline-input:focus,
.settings-inline-select:hover,
.settings-inline-select:focus,
.settings-form-field input:hover,
.settings-form-field input:focus,
.settings-form-field select:hover,
.settings-form-field select:focus {
  box-shadow: none !important;
  outline: none !important;
  border-color: var(--focus-color) !important;
}
/* Text selected by dragging follows the focus theme. */
::selection {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}
::-moz-selection {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}
/* Display-settings preview: hover/highlight is intentionally visual-noop. */

/*hover, focus 관리*/

.input-text-box:hover,
.input-text-box:focus,
.input-text-box:focus-within {
  border-color: var(--focus-color) !important;
  box-shadow: inset 0 0 2px 1px var(--focus-color) !important;
}
.content-input-box,
.content-input-box:hover,
.content-input-box:focus,
.content-input-box:focus-within {
  box-sizing: border-box;
  border: 1px solid rgba(var(--system-c-input-border-rgb), var(--system-c-input-border-alpha)) !important;
  border-radius: 5px !important;
  outline: none !important;
  background: rgba(var(--system-c-input-rgb), var(--system-c-input-alpha)) !important;
  color: var(--system-c-input-font-color) !important;
  box-shadow: none !important;
}
/* 공통 입력 상자 크기 — 프로필·캐릭터·가계부 등 창 본문 어디서나 쓰는
   System C 입력 표면이라 위 테마 규칙과 같이 여기(공통)에 둔다. */
.content-input-box {
  width: 100%;
  min-height: 27px;
  padding: 6px;
}

.content-input-box > input,
.content-input-box > textarea,
.content-input-box > input:hover,
.content-input-box > textarea:hover,
.content-input-box > input:focus,
.content-input-box > textarea:focus {
  background: transparent !important;
  color: inherit !important;
  border-color: transparent !important;
  border-radius: inherit !important;
  outline: none !important;
  box-shadow: none !important;
}
/* 검색창 테두리는 평소에도 System A 입력 테두리 테마를 따른다(.taskbar-scope *의
   표면색 테두리 !important보다 특이도가 높아 이긴다). */
.start-menu-search.input-text-box {
  border-color: rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha)) !important;
}
.start-menu-search.input-text-box:hover,
.start-menu-search.input-text-box:focus,
.start-menu-search.input-text-box:focus-within {
  border-color: rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha)) !important;
  box-shadow: inset 0 0 2px 1px rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha)) !important;
}

/* ==========================================================================
   버튼 상호작용 (docs/click-event-buttons.md 분류 기준)
   - normal-button: 기본 System C content, hover/focus에 System C hover
   - transparent-button: 기본/hover 모두 투명, 글자색은 영역 font-color 고정(커서만 변함)
   - primary-transparent-button: 기본/hover 모두 투명, 글자색 focus-color 고정
   - primary-button: 기본/hover 모두 focus-color 배경 + focus-font-color 글자(변화 없음)
   기본 영역은 System C. 윈도우바는 .area-b를 추가로 붙인다.
   작업표시줄/시작메뉴/날짜/미리보기(System A)는 전용 클래스 sys-a-btn-* 사용 — 아래 참고.
   ========================================================================== */
.normal-button {
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border-color: rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  color: var(--system-c-font-color) !important;
}
.normal-button:hover,
.normal-button:focus,
.normal-button:focus-within{
  background:
    linear-gradient(rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha)), rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha))),
    rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  color: var(--system-c-hover-font-color) !important;
  border-color: rgba(var(--system-c-hover-border-rgb), var(--system-c-hover-border-alpha)) !important;
}
.normal-button:not(.settings-nav-btn):hover,
.normal-button:not(.settings-nav-btn):focus,
.normal-button:not(.settings-nav-btn):focus-within{
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%) !important;
}
.normal-button.flat:hover,
.normal-button.flat:focus,
.normal-button.flat:focus-within {
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%) !important;
}

/* ==========================================================================
   System A 전용 버튼 — bg/글자/stroke/그림자를 버튼 규칙에서 직접 선언하지 말고
   아래 클래스를 붙인다.
   - sys-a-btn-a        : 아이콘 버튼. 기본 투명 + System A font, hover(및 키보드
                          포커스)에 System A hover 톤. .flat 병용 시 hover 그림자는
                          inset만. .focused(최상단 창 아이콘, JS 부여)도 hover와 동일.
   - sys-a-btn-b        : System A 입력 톤 고정. hover/focus 변화 없음.
   - sys-a-btn-a-static : 기본은 sys-a-btn-a와 동일, hover/focus 변화 없음.
   ========================================================================== */
.sys-a-btn-a,
.sys-a-btn-a-static {
  background: transparent !important;
  border-color: transparent !important;
  color: var(--system-a-font-color) !important;
}
.sys-a-btn-a svg,
.sys-a-btn-a-static svg {
  stroke: var(--system-a-font-color);
}
.sys-a-btn-b {
  background: rgba(var(--system-a-input-rgb), var(--system-a-input-alpha)) !important;
  border: 1px solid rgba(var(--system-a-input-border-rgb), var(--system-a-input-border-alpha)) !important;
  color: var(--system-a-input-font-color) !important;
}
.sys-a-btn-b * {
  color: var(--system-a-input-font-color) !important;
}
.sys-a-btn-a:hover,
.sys-a-btn-a:focus-visible,
.sys-a-btn-a.focused {
  background: rgba(var(--system-a-hover-rgb), var(--system-a-hover-alpha)) !important;
  color: var(--system-a-hover-font-color) !important;
  border-color: transparent !important;
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%),
    0 5px 14px rgba(var(--system-a-hover-shadow-rgb), var(--system-a-hover-shadow-alpha)) !important;
}
.sys-a-btn-a.flat:hover,
.sys-a-btn-a.flat:focus-visible,
.sys-a-btn-a.flat.focused {
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%) !important;
}
.sys-a-btn-a:hover svg,
.sys-a-btn-a:focus-visible svg,
.sys-a-btn-a.focused svg {
  stroke: var(--system-a-hover-font-color) !important;
}
.sys-a-btn-a:hover :is(small, strong, span),
.sys-a-btn-a:focus-visible :is(small, strong, span),
.sys-a-btn-a.focused :is(small, strong, span) {
  color: var(--system-a-hover-font-color) !important;
}
/* 알림 개수 뱃지는 Focus 색 배경 위에 얹혀 있어, 시계 버튼 hover 시 위 span
   규칙(System A hover 글자색)을 따라가면 배경에 묻혀 안 보인다 — Focus 글자색 유지. */
.sys-a-btn-a:hover .clock-bell-count,
.sys-a-btn-a:focus-visible .clock-bell-count,
.sys-a-btn-a.focused .clock-bell-count {
  color: var(--focus-font-color) !important;
}
/* 오늘 날짜 셀은 Focus 색 배경(공용 규칙) 위에 놓이므로 글자는 Focus-font 색.
   hover만 작업표시줄 강조색(위 규칙). */
.mini-day.today:not(:hover) {
  color: var(--focus-font-color) !important;
}
.settings-nav-btn
{
  padding-left: 15px;
  background: transparent;
  border: 0;
}
/* 환경설정 좌측 내비게이션의 활성 메뉴: normal-button의 System C hover 효과를
   항상(실제 hover 여부와 무관하게) 유지하고, 왼쪽에 focus-color 강조선을 붙인다. */
.settings-nav-btn.is-active {
  background: rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha)) !important;
  color: var(--system-c-hover-font-color) !important;
  border-color: rgba(var(--system-c-hover-border-rgb), var(--system-c-hover-border-alpha)) !important;
  border-left-color: var(--focus-color) !important;
}

.transparent-button,
.primary-transparent-button,
.primary-button {
  box-shadow: none !important;
}
.transparent-button {
  background: transparent !important;
  border-color: transparent !important;
  color: var(--system-c-font-color) !important;
}
.transparent-button.area-b {
  color: var(--system-b-font-color) !important;
}
.transparent-button:hover,
.transparent-button:focus,
.transparent-button:focus-within {
  background: transparent !important;
  box-shadow: none !important;
  text-decoration: none;
}

.primary-transparent-button {
  background: transparent !important;
  border-color: transparent !important;
  color: var(--focus-color) !important;
}
.primary-transparent-button * {
  color: var(--focus-color) !important;
}
.primary-transparent-button:hover,
.primary-transparent-button:focus,
.primary-transparent-button:focus-within {
  background: transparent !important;
  box-shadow: none !important;
  color: var(--focus-color) !important;
}

.primary-button {
  background: var(--focus-color) !important;
  border-color: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}
.primary-button:hover,
.primary-button:focus,
.primary-button:focus-within {
  background: var(--focus-color) !important;
  border-color: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
  box-shadow: none !important;
}

/* 작업표시줄 검색창 테마는 검색창에만 적용한다. 다른 System A 컨트롤은
   sys-a-btn-* 클래스를 그대로 쓴다. */
.start-menu-search.input-text-box {
  --area-input-rgb: var(--system-a-input-rgb);
  --area-input-alpha: var(--system-a-input-alpha);
  --area-input-font-color: var(--system-a-input-font-color);
  --area-input-border-rgb: var(--system-a-input-border-rgb);
  --area-input-border-alpha: var(--system-a-input-border-alpha);
}
:where(.window-bar, .area-b) {
  --area-input-rgb: var(--system-b-input-rgb);
  --area-input-alpha: var(--system-b-input-alpha);
  --area-input-font-color: var(--system-b-input-font-color);
  --area-input-border-rgb: var(--system-b-input-border-rgb);
  --area-input-border-alpha: var(--system-b-input-border-alpha);
}
.input-text-box,
input:not([type="range"]):not([type="color"]):not([type="file"]):not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not(#searchInput):not(.window-bar-search-input):not(.window-address-input):not(.window-address-suggest-query-input):not(.auth-input):not(.input-text-box *),
select:not([data-no-theme]):not(.input-text-box *),
textarea:not([data-no-theme]):not(.input-text-box *),
[contenteditable="true"] {
  background: rgba(var(--area-input-rgb, var(--system-c-input-rgb)), var(--area-input-alpha, var(--system-c-input-alpha))) !important;
  color: var(--area-input-font-color, var(--system-c-input-font-color)) !important;
  border-color: rgba(var(--area-input-border-rgb, var(--system-c-input-border-rgb)), var(--area-input-border-alpha, var(--system-c-input-border-alpha))) !important;
}
:is(.window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) button {
  background: transparent !important;
}
/* 더보기/게시물 관리 메뉴 안의 글자는 삭제(.danger) 포함 전부 System B 입력 글자색. */
:is(.window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) :is(button, .post-admin-menu-item),
:is(.window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) :is(button, .post-admin-menu-item) * {
  color: var(--system-b-input-font-color) !important;
}
:is(.window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) button:not(:disabled):is(:hover, :focus-visible) {
  background: rgba(var(  --system-b-input-hover-rgb), var(--system-b-input-hover-alpha)) !important;
  color: var(--system-b-input-hover-font-color) !important;
}
:is(.window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) button:not(:disabled):is(:hover, :focus-visible) * {
  color: var(--system-b-input-hover-font-color) !important;
}
:is(.window-bar, .window-toolbar, .window-more-panel, .post-admin-menu.window-more-dropdown, .post-visibility-dropdown) button:is(:hover, :focus, :focus-visible, :focus-within) {
  box-shadow: none !important;
}
/* label.input-text-box처럼 실제 input을 감싸는 필드는 배경/테두리를 래퍼에 한 번만 그린다. */
.input-text-box > input:not([type="range"]):not([type="color"]):not([type="file"]):not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
.input-text-box > select:not([data-no-theme]),
.input-text-box > textarea:not([data-no-theme]) {
  background: transparent !important;
  color: inherit !important;
  border-color: transparent !important;
}
/* System C 안에서 별도 카드/본문으로 읽히는 표면은 컨텐츠 배경을 공유한다. */
.comment {
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 2px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
}

/* focus-color 공용 유틸리티. 광역 규칙(* {border-color … !important},
   body * {color …}) 을 특이도로 이기도록 !important — 하위 클래스와 겹쳐 써도
   색만 focus로 고정된다. focus-color를 직접 박지 말고 이 클래스를 붙일 것. */
.focus-bg {
  background: var(--focus-color) !important;
  color: var(--focus-font-color) !important;
}
.focus-border {
  border-color: var(--focus-color) !important;
}
.focus-font {
  color: var(--focus-color) !important;
  stroke: var(--focus-color) !important;
}

.post-meta {
  margin-bottom: 16px;
  text-align: right;
}

/*임시*/

.post-thumb-wrap {
  position: relative;
}

.post-thumb {
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: 7px;
  box-shadow: 1px 1px 3px 0px rgba(0, 0, 0, .15);
  /* 썸네일이 지정된 카드는 <img>로 렌더링된다(비어있으면 여전히 배경만 채우는
     .image-area 빈 <div>) — 크롭 자체가 이미 16:9라 cover는 안전망일 뿐이다. */
  object-fit: cover;
  display: block;
}

/* 썸네일 우측 하단 "이미지 N개" 배지(본문 이미지가 1장 이상일 때만 렌더링됨).
   pointer-events:none이라 카드 클릭(.grid-cell 위임)을 가로채지 않는다. */
.post-thumb-image-badge {
  position: absolute;
  right: 6px;
  bottom: 6px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 6px;
  border-radius: 10px;
  background: rgba(var(--system-b-rgb), var(--system-b-alpha));
  color: var(--system-b-font-color);
  pointer-events: none;
}

.post-thumb-image-badge-icon {
  width: 11px;
  height: 11px;
  /* imageCountIconHTML()의 svg/rect/circle/path엔 fill 속성이 없어 SVG 기본값인
     검정 채우기로 그려지고 있었다 — 배지 글자색(--system-b-font-color)을 직접
     선 색으로 지정한다. !important: homepage.css의 전역 `* { color: ... }`류
     리셋(다른 곳의 stroke/색 규칙들이 !important를 쓰는 것과 같은 이유)보다
     우선해야 한다. */
  fill: none;
  stroke: var(--system-b-font-color) !important;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.post-thumb-live2d-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  padding: 2px 6px;
  border-radius: 10px;
  background: rgba(var(--system-b-rgb), var(--system-b-alpha));
  color: var(--system-b-font-color);
  pointer-events: none;
}

.post-title {
  font-weight: 700;
  margin-top: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}


.movie-poster {
  width: 100%;
  aspect-ratio: 2/3;
  border-radius: 7px;
}

.movie-card-title {
  font-weight: 700;
  margin-top: 7px;
}

.movie-card-rating {
  display: flex;
  align-items: center;
  margin-top: 4px;
}

.movie-card-rating .movie-star-rating-score {
  display: none;
}

.movie-detail-poster {
  width: 100%;
  aspect-ratio: 2/3;
  border-radius: 8px;
  box-shadow: 0 -4px 7px -4px rgba(var(--system-c-font-rgb), .18);
}

.movie-detail-window,
.comment-window {
  min-width: min(550px, 100vw);
}

/* 영화 등록·상세 정보블록은 포스터 + 오른쪽 4행 구조와 외곽 스타일을 공유한다. */
.movie-editor-head,
.movie-detail-info {
  display: grid;
  grid-template-columns: 120px 1fr;
  align-items: stretch;
  gap: 16px;
  margin-bottom: 16px;
  padding-bottom: 15px;
  box-shadow: 0 4px 5px -5px rgba(var(--system-c-font-rgb), .18);
}

.movie-editor-head {
  border-bottom: 0;
}

.movie-editor-head-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-bottom: 16px;
}

.movie-editor-poster {
  grid-row: 1;
  grid-column: 1;
  width: 120px;
  aspect-ratio: 2/3;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0;
  box-sizing: border-box;
  position: relative;
  overflow: hidden;
  border: 0;
  color: var(--system-c-font-color);
  font-size: 11px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
}

.movie-editor-poster-empty {
  padding: 8px;
}

.movie-editor-poster.is-uploadable {
  cursor: pointer;
}

/* 전역 button:disabled의 opacity는 유지하고, 선택된 포스터를 단순히
   비활성 버튼으로 표시하는 이 영역만 원본 명도로 보인다. */
.movie-editor-poster:disabled {
  opacity: 1 !important;
}

.movie-editor-poster-upload {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  background: rgba(var(--system-c-rgb), .72);
  color: var(--system-c-font-color);
}

.movie-editor-poster.is-uploadable:hover .movie-editor-poster-upload,
.movie-editor-poster.is-uploadable:focus .movie-editor-poster-upload {
  opacity: 1;
}

.movie-editor-poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
}

.movie-editor-title-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.movie-editor-title-row > .movie-info-field {
  width: 100%;
}

.movie-editor-meta-row.movie-info-pair-row,
.movie-detail-meta-row.movie-info-pair-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 16px;
}

/* 등록·상세 정보 모두 라벨/점/값 3열을 공유한다. 라벨 길이와 무관하게
   첫 번째 구분점이 같은 세로선에 놓인다. */
.movie-info-field {
  display: inline-grid;
  grid-template-columns: 3em auto minmax(0, 1fr);
  align-items: center;
  column-gap: 4px;
  min-width: 0;
}

.movie-info-label {
  white-space: nowrap;
}

.movie-info-separator {
  text-align: center;
}

.movie-info-value {
  min-width: 0;
  min-height: 24px;
  margin: 0;
  padding: 0 9px;
  line-height: 24px;
}

.movie-info-description {
  color: var(--system-c-desc-color);
}

.movie-info-description-field .movie-info-label,
.movie-info-description-field .movie-info-separator {
  color: var(--system-c-desc-color);
}

.movie-watch-value {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  white-space: nowrap;
}

.movie-editor-date-input {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding-block: 0;
  line-height: 24px;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

.movie-editor-date-input::-webkit-datetime-edit {
  padding: 0;
}

.movie-editor-date-input::-webkit-calendar-picker-indicator {
  display: none;
  -webkit-appearance: none;
}

.movie-editor-episode-input {
  width: 3ch;
  height: 24px;
  padding-inline: 0;
  line-height: 24px;
  text-align: center;
  appearance: textfield;
  -moz-appearance: textfield;
}

.movie-editor-episode-input::-webkit-inner-spin-button,
.movie-editor-episode-input::-webkit-outer-spin-button {
  margin: 0;
  -webkit-appearance: none;
}

.movie-editor-title-controls .post-editor-title-input {
  height: 24px;
  padding-right: 32px;
  line-height: 24px;
}

.movie-search-loading {
  position: absolute;
  top: 50%;
  right: 9px;
  width: 14px;
  height: 14px;
  box-sizing: border-box;
  border: 2px solid var(--system-c-desc-color);
  border-top-color: var(--focus-color) !important;
  border-radius: 50%;
  transform: translateY(-50%);
  animation: movie-search-spin .7s linear infinite;
  pointer-events: none;
  z-index: 6;
}

.movie-search-loading[hidden] {
  display: none;
}

@keyframes movie-search-spin {
  to { transform: translateY(-50%) rotate(360deg); }
}

/* 제목 입력창 바로 아래 뜨는 검색 결과 드롭다운 — 입력창과 같은 폭(부모
   .post-editor-title-wrap 기준), 최대 3개까지 보이고 그 이상은 스크롤. */
.movie-search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 5;
  margin-top: 4px;
  max-height: 192px;
  overflow-y: auto;
  scrollbar-width: none;
  border-radius: 8px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
}

.movie-search-dropdown::-webkit-scrollbar {
  display: none;
}

.movie-search-dropdown-message {
  padding: 10px;
  font-size: 12px;
  opacity: .7;
}

/* 별점 위젯 — 진짜 별 글리프(★) 두 겹을 겹쳐 채움 레이어를 %로 잘라
   half-star까지 표현한다(사각형 마스크가 아니라 별 모양 그대로 채워짐). */
.movie-star-rating {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  vertical-align: middle;
}

.movie-star-rating-score {
  display: inline-flex;
  align-items: center;
  height: 12px;
  font-weight: 700;
  line-height: 12px;
}

.movie-star-rating-stars {
  position: relative;
  display: inline-block;
  height: 12px;
  line-height: 12px;
  letter-spacing: 2px;
  cursor: pointer;
  user-select: none;
}

.movie-star-rating.is-readonly .movie-star-rating-stars {
  cursor: default;
}

.movie-star-rating-track,
.movie-star-rating-fill {
  display: block;
  font: inherit;
  line-height: inherit;
  letter-spacing: inherit;
  white-space: nowrap;
}

.movie-star-rating-track {
  color: var(--system-c-desc-color);
}

.movie-star-rating-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  overflow: hidden;
  color: var(--focus-color);
}

/* 오른쪽 정보 영역과 각 행도 등록·상세에서 같은 레이아웃을 사용한다. */
.movie-detail-info-fields {
  grid-row: 1;
  grid-column: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
}

/* 기존 포스터가 있어(재업로드 버튼이 disabled) "제거"만 따로 여는 버튼 —
   포스터(row1/col1) 바로 아래(row2/col1)에 둔다. 위 grid-row/column을
   명시해 아래 버튼이 auto-placement로 정보 칸(col2) 자리를 가로채지 않게 한다. */
.movie-editor-poster-remove-btn {
  grid-row: 2;
  grid-column: 1;
  width: 120px;
  margin-top: 6px;
  padding: 4px 2px;
  font-size: 11px;
}

.movie-detail-meta-row {
  display: flex;
  align-items: center;
  gap: 16px;
}

@media (max-width: 640px) {
  .movie-editor-head,
  .movie-detail-info {
    grid-template-columns: 1fr;
  }
  .movie-editor-poster {
    margin: 0 auto 8px;
  }
  .movie-detail-poster {
    width: 120px;
    margin: 0 auto 8px;
  }
  .movie-editor-meta-row.movie-info-pair-row,
  .movie-detail-meta-row.movie-info-pair-row {
    grid-template-columns: 1fr;
    row-gap: 6px;
  }
}

/* .confirm-dialog와 같은 System C content 테마 — 이 항목만 배경 없이
   창 바탕이 그대로 비쳐 보이던 걸 맞춘다. */
.movie-search-result-item {
  display: flex;
  width: 100%;
  gap: 10px;
  align-items: center;
  padding: 8px;
  border-radius: 8px;
  text-align: left;
  cursor: pointer;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha)) !important;
  color: var(--system-c-font-color) !important;
}

/* <img>(TMDB 매칭 성공)와 placeholder <div>(매칭 실패) 둘 다 이 클래스를
   쓴다 — object-fit은 div에는 그냥 무시되는 안전한 공통 규칙. */
.movie-search-result-poster {
  flex: 0 0 auto;
  width: 46px;
  aspect-ratio: 2/3;
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  object-fit: cover;
}

/* TMDB에서 이 영화의 포스터를 찾지 못했을 때(제목/연도로 매칭, 항상 성공하는
   건 아님 — service/tmdbClient.go 참고)의 placeholder — 자리만 잡아두는
   대신 무엇이 비어있는지 짧게 알려준다. */
.movie-search-result-poster-label {
  font-size: 9px;
  text-align: center;
  opacity: .7;
}

.movie-search-result-info {
  min-width: 0;
}

.movie-search-result-title {
  font-weight: 700;
}

.movie-search-result-title-en {
  font-weight: 400;
  opacity: .7;
}

/* ==========================================================================
   유튜브 감상 후기 — 목록 카드는 그림 모달과 완전히 같은 .grid-cell/
   .post-thumb-wrap/.grid-cell-meta 마크업을 쓰며 위의 그림 목록 규칙과
   함께 선언한다. 별점 위젯(.movie-star-rating*)/정보 3열(.movie-info-field 등)/
   검색 드롭다운(.movie-search-*)은 영화 후기와 완전히 같은 모양이라 새
   클래스를 만들지 않고 그대로 재사용한다(위 규칙들 참고).
   ========================================================================== */
/* 유튜브 링크 미리보기 썸네일은 영화 포스터(2:3)와 달리 16:9라 별도
   비율만 덮어쓴다(마크업은 .movie-search-result-poster 그대로 재사용). */
.youtube-search-result-thumb {
  aspect-ratio: 16/9;
}

/* 에디터의 미리보기 플레이어 — post-editor-head와 post-editor-body 사이
   (요청), 헤드/툴바처럼 스크롤되지 않는 고정 자리다. 링크를 아직 못
   골랐으면 hidden. */
.youtube-editor-player {
  flex: 0 0 auto;
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 8px;
  background: #000;
}
.youtube-editor-player[hidden] {
  display: none;
}
[data-youtube-player-mount] {
  width: 100%;
  height: 100%;
}
.youtube-editor-player iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* 상세보기 플레이어 도크 — 상단 바는 확대 중 핀과 제목을, 축소 중에는
   썸네일과 재생 컨트롤을 표시한다. */
.youtube-detail-player-dock {
  position: sticky;
  top: 0;
  z-index: 3;
  max-width: 720px;
  margin: 0 auto 15px;
}
.youtube-detail-player-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: 0 0 10px 10px;
  overflow: hidden;
  background: #000;
  box-shadow: 0 6px 14px -2px rgba(0, 0, 0, .18);
}
.youtube-detail-player-frame iframe {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
.youtube-detail-player-frame.is-collapsing {
  pointer-events: none;
  animation: youtube-detail-player-collapse .22s ease-in forwards;
}
@keyframes youtube-detail-player-collapse {
  from {
    clip-path: inset(0);
    transform: translateY(0);
    opacity: 1;
  }
  to {
    clip-path: inset(0 0 100% 0);
    transform: translateY(-18px);
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .youtube-detail-player-frame.is-collapsing {
    animation-duration: .01ms;
  }
}
/* 축소 상태 — iframe을 display:none 대신 2px로 시각적으로만 숨긴다.
   music.js의 .youtube-player-area와 같은 이유: display:none은 유튜브가
   "화면에서 사라짐"으로 판단해 재생을 바로 멈춘다(요청 — 영상이 가려져도
   멈추지 않아야 함). */
.youtube-detail-player-frame.is-collapsed {
  position: absolute;
  width: 2px;
  height: 2px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
.youtube-detail-player-toggle {
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  color: var(--focus-color) !important;
  background: transparent !important;
  opacity: .7;
  cursor: pointer;
}
.youtube-detail-player-toggle[aria-pressed="true"] {
  opacity: 1;
}
.youtube-detail-player-toggle[aria-pressed="true"] svg path:last-child {
  fill: currentColor;
}
.youtube-detail-player-toggle svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.youtube-detail-player-mini {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 12px;
  border-radius: 10px 10px 0 0;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha)) !important;
  box-shadow: 0 4px 12px -2px rgba(0, 0, 0, .18);
}
.youtube-detail-player-dock.is-collapsed .youtube-detail-player-mini {
  border-radius: 20px;
  cursor: pointer;
}
.youtube-detail-player-mini-thumb {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: center/cover no-repeat;
}
.youtube-detail-player-toggle[hidden],
.youtube-detail-player-mini-thumb[hidden],
[data-youtube-mini-controls][hidden] {
  display: none !important;
}
[data-youtube-mini-controls] {
  display: contents;
}
.youtube-detail-player-mini-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.youtube-detail-player-mini-play {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 50%;
  background: transparent !important;
  cursor: pointer;
}
.youtube-detail-player-mini-progress {
  flex: 1 1 80px;
  min-width: 60px;
}

/* 본문 안 타임라인 링크 — 실제로 저장된 마크다운은 평범한 [MM:SS](url)
   한 겹짜리 링크다(이중 대괄호를 텍스트에 직접 넣지 않음, 파서가 깨지는
   걸 피하기 위함) — 대괄호는 여기 pseudo-content로만 붙인다. */
.youtube-timeline-link::before {
  content: "[";
}
.youtube-timeline-link::after {
  content: "]";
}

.diary-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 9px;
}
.sound-popover {
  width: 250px;
}

/* 볼륨 팝오버는 항상 검은색 앨범아트 오버레이 위에 표시되므로,
   System A 설정과 무관하게 테두리 없이 · 흰 글자로 고정 */
.sound-popover,
.sound-popover * {
  border: 0px solid transparent !important;
  color: #fff !important;
}

/* display:none이면 iframe이 렌더 트리에서 제외되어 YouTube가 "화면에 보이지 않음"으로
   판단해 재생을 곧바로 멈춤. 렌더링은 유지한 채 시각적으로만 숨김. */
.youtube-player-area {
  position: absolute;
  width: 2px;
  height: 2px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* 커스텀 음악 UI */
.music-panel {
  position: relative;
  overflow: hidden;
  border-radius: 11px;
}

.music-background {
  position: absolute;
  inset: 0;

  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;

  transform: scale(1.02);
}

.music-overlay {
  position: absolute;
  inset: 0;
  background:linear-gradient(270deg, rgba(0, 0, 0, 50%), rgb(0 0 0 / 70%))
}

.music-content {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;

  padding: 10px;
}
.music-title {
  overflow: hidden;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
  margin-bottom: 7px;
}

.music-progress-area {
  margin-top: auto;
}

#musicProgress {
  width: 100%;
  height: 5px;
}

.music-time {
  display: flex;
  justify-content: space-between;
  margin-top: 3px;
  opacity: .8;
}

.music-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.music-play-button,
.music-volume-button {
  border: 0;
  background: transparent;

  cursor: pointer;
}

.music-play-button {
  width: 38px;
  display: grid;
  place-items: center;
}

.music-volume-control {
  width: 80px;
  display: flex;
  align-items: center;
  gap: 7px;
}

.music-volume-button {
  width: 27px;
  height: 20px;
  display: grid;
  place-items: center;
}

.music-volume-button svg {
  width: 17px;
  height: 17px;
}

.music-volume-button .icon-muted {
  display: none;
}

.music-volume-button.is-muted .icon-unmuted {
  display: none;
}

.music-volume-button.is-muted .icon-muted {
  display: block;
}

#musicVolume {
  min-width: 0;
  flex: 1;
  height: 5px;
}

#musicVolume,
#musicProgress {
  height: 4px;
  border: 0;
  border-radius: 999px;
  outline: none;
  appearance: none;
  -webkit-appearance: none;

  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
  cursor: pointer;
}

/* Chrome / Edge / Safari */
#musicVolume::-webkit-slider-thumb,
#musicProgress::-webkit-slider-thumb {
  width: 12px;
  height: 12px;

  border: 1px solid transparent;
  border-radius: 50%;

  background: var(--focus-color);

  appearance: none;
  -webkit-appearance: none;
}

/* Firefox */
#musicVolume::-moz-range-thumb,
#musicProgress::-moz-range-thumb {
  width: 12px;
  height: 12px;

  border: 1px solid transparent;
  border-radius: 50%;

  background: var(--focus-color);
}

#musicVolume::-moz-range-track,
#musicProgress::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
}

#musicVolume::-moz-range-progress,
#musicProgress::-moz-range-progress {
  height: 4px;
  border-radius: 999px;
  background: var(--focus-color);
}
/* ==========================================================================
   테마 관리 패널 (환경설정 셸의 "테마 관리" 탭 콘텐츠로 항상 내장됨)
   과거에는 모니터 클릭으로 열리는 전체 화면 오버레이였지만, 지금은 왼쪽
   내비게이션을 가리지 않는 일반 패널이라 position:fixed나 흰색 강제 배경이
   필요 없다 — 다른 관리 화면 카드류와 같은 방식으로 System C 톤을 따른다.
   ========================================================================== */
/* 테마 프리셋 바 — 저장된 프리셋 칩 목록 + "프리셋으로 저장" 버튼.
   .theme-panel-columns(flex:1) 위에 얹히는 고정 높이 줄이라 flex:1 없음. */
.theme-preset-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-bottom: 10px;
}
.theme-preset-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1;
}
.theme-preset-chip {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 2px 4px 2px 10px;
  border: 1px solid rgba(var(--system-c-content-border-rgb), var(--system-c-content-border-alpha));
  border-radius: 999px;
  background: rgba(var(--system-c-content-rgb), var(--system-c-content-alpha));
  font-size: 13px;
}
.theme-preset-delete {
  width: 18px;
  height: 18px;
  line-height: 1;
  padding: 0;
}

/* 좌(바탕화면 배경 이미지 전용 패널)/우(System A~C·Focus·바탕화면 아이콘
   색상 아코디언 목록) 분할. 오른쪽만 내부 스크롤하고(.settings-theme-groups,
   기존 그대로) 왼쪽은 고정 높이 콘텐츠라 스크롤하지 않는다. */
.theme-panel-columns {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 14px;
}

.theme-desktop-panel {
  flex: 0 0 200px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.theme-desktop-panel-head {
  font-weight: 700;
}

/* 배경 이미지 미리보기(.bg-region-stage)를 감싸는 모니터 베젤 — .settings-pc-preview와
   같은 System C 톤(밝은 테마에서는 흰색)/모서리/그림자를 그대로 따른다. */
.monitor-frame {
  box-sizing: border-box;
  width: 100%;
  padding: 10px;
  border-radius: 9px;
  background: rgba(var(--system-c-rgb), var(--system-c-alpha));
  box-shadow: 0 6px 20px rgba(0, 0, 0, .07);
}

/* 세로 모드에서는 .bg-region-stage.is-portrait가 폭을 110px로 좁히는데,
   베젤(padding)이 그대로 폭 100%를 유지하면 좌우 여백만 두꺼워져 보인다 —
   베젤 두께(10px)는 그대로 두고 프레임 자체를 스테이지 폭에 맞춰 좁힌 뒤
   영역 안에서 가운데로 옮긴다. */
.monitor-frame.is-portrait {
  width: 130px;
  margin: 0 auto;
}

.bg-region-stage.is-empty {
  display: grid;
  place-items: center;
  background: rgba(120, 120, 120, .18);
  cursor: default;
}

.bg-region-stage.is-empty::before {
  content: "이미지를 업로드하세요";
  padding: 0 10px;
  text-align: center;
  opacity: .6;
}

.theme-bg-upload-btn,
.theme-bg-remove-btn {
  width: 100%;
}

.theme-hex-input {
  flex: 0 0 66px;
  width: 66px;
  height: 22px;
  padding: 0 6px;
  font-family: monospace;
  text-transform: lowercase;
}

/* 그룹 목록만 스크롤(드래그 없음). 수정/취소 버튼·메시지는 .settings-form-actions로 분리되어 있어 스크롤에 딸려가지 않음 */
.settings-theme-groups {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 0, #000 100%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 0, #000 100%, transparent);
  transition: -webkit-mask-image .15s ease, mask-image .15s ease;
}

/* 스크롤 가능한 방향에만 위/아래 투명도 그라데이션 표시 */
.settings-theme-groups.can-scroll-up {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 28px, #000 100%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 28px, #000 100%, transparent);
}
.settings-theme-groups.can-scroll-down {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 0, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 0, #000 calc(100% - 28px), transparent);
}
.settings-theme-groups.can-scroll-up.can-scroll-down {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 28px, #000 calc(100% - 28px), transparent);
}

.theme-group {
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(120,120,120,.18);
  background: rgba(255,255,255,.52);
}

.theme-group-head {
  display: flex;
  align-items: flex-start;
  gap: 6px;
}

.theme-group-toggle {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 0;
  background: transparent !important;
  border: 0 !important;
  cursor: pointer;
  text-align: left;
}

/* 접힌 카드는 헤더 안 어디에 마우스를 올려도(토글 글자 위뿐 아니라 카드
   여백·초기화 버튼 위까지) 카드 전체가 다른 .normal-button과 동일한 System C
   hover 배경/글자색/그림자를 보이게 한다 — 트리거를 .theme-group-toggle이
   아니라 .theme-group.is-collapsed 자체의 :hover로 두고, 카드 안 어디를 눌러도
   포커스가 가는 토글 버튼의 :focus-visible은 :has()로 같은 카드 규칙을
   트리거하게 해 마우스/키보드 모두 카드 전체가 같은 모습으로 강조되게 한다.
   .is-collapsed로 범위를 좁혔으므로 펼친 카드에는 이 규칙 자체가 매치되지
   않아(별도의 "효과 없음" 규칙 없이도) 펼친 상태에는 전혀 적용되지 않는다.
   초기화 버튼(.theme-group-reset-btn) 위에 마우스가 있어도 이 카드 hover는
   그대로 유지되며, 초기화 버튼 자신의 독립적인 hover 규칙(아래, 항상 투명
   유지)도 함께 적용된다 — 서로 다른 요소를 대상으로 하므로 충돌하지 않는다. */
.theme-group.is-collapsed:hover,
.theme-group.is-collapsed:has(.theme-group-toggle:focus-visible) {
  background: rgba(var(--system-c-hover-rgb), var(--system-c-hover-alpha)) !important;
  color: var(--system-c-hover-font-color) !important;
  border-color: rgba(var(--system-c-hover-border-rgb), var(--system-c-hover-border-alpha)) !important;
  box-shadow: inset 0 1px 0 1px rgb(0 0 0 / 10%),
    0 5px 14px rgba(var(--system-c-hover-shadow-rgb), var(--system-c-hover-shadow-alpha)) !important;
}

.theme-group.is-collapsed .theme-group-body {
  display: none;
}

.theme-group-head-text {
  min-width: 0;
}

.theme-group-head-text strong {
  display: block;
}

.theme-group-head-text small {
  display: block;
  margin-top: 1px;
  opacity: .72;
}

.theme-group-reset-btn {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  padding: 0;
  display: grid;
  place-items: center;
  background: transparent !important;
  border: 0 !important;
  border-radius: 6px;
  cursor: pointer;
  opacity: .85;
}

.theme-group-reset-btn svg {
  width: 13px;
  height: 13px;
}

/* 초기화 버튼은 hover 시각효과 없음 */
.theme-group-reset-btn:hover,
.theme-group-reset-btn:focus-visible {
  opacity: .85;
  background: transparent !important;
}

.theme-group-body {
  display: flex;
  flex-direction: column;
  margin-top: 5px;
}

.theme-subsection + .theme-subsection {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(120, 120, 120, .18);
}

.theme-subsection-label {
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  opacity: .55;
  margin-bottom: 2px;
}

/* 이 화면 자체가 테마 색상(System A/B/C 등)을 편집하는 곳이라, 행 배경/글자색을
   그 변수들로 두면 사용자가 값을 바꾸는 동안 편집기 자신의 가독성이 흔들린다
   (예: System C 글자색을 흰색에 가깝게 바꾸면 이 화면 라벨도 함께 흐려짐). 그래서
   각 행은 항상 고정된 불투명 #fff 배경 + #000 글자로 두고, 실제 설정색은
   .theme-swatch(아래에서 원래 색을 그대로 유지)에서만 보여준다. */
.theme-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 6px;
  border-radius: 6px;
  background: #fff !important;
  color: #000 !important;
}

.theme-row + .theme-row {
  margin-top: 2px;
}

.bg-region-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 6px;
}

.bg-region-tab {
  flex: 1;
  height: 30px;
  border: 0px solid rgba(120, 120, 120, .3);
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

.bg-region-tab.is-active {
  border-color: var(--focus-color) !important;
  color: var(--focus-color);
  border-bottom: 3px solid;
}

.bg-region-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(120, 120, 120, .3);
  cursor: crosshair;
  touch-action: none;
}

.bg-region-stage.is-portrait {
  aspect-ratio: 9/16;
  max-width: 110px;
  margin: 0 auto;
}

.bg-region-image {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.bg-region-marker {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .4), 0 2px 6px rgba(0, 0, 0, .35);
  background: var(--focus-color);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.bg-region-hint {
  margin: 6px 0 0;
  opacity: .65;
  line-height: 1.5;
}

.theme-swatch-btn {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid transparent !important;
  border-radius: 6px;
  background: transparent !important;
  cursor: pointer;
}

.theme-row-label {
  flex: 0 0 150px;
  width: 150px;
  min-width: 0;
  font-weight: 600;
}

/* 라벨 영역(고정 150px) 대비 값 영역 — 남은 폭 전체를 쓰며, 스와치+hex
   그룹은 좌측정렬, 투명도(있으면)는 우측정렬. 그룹이 하나뿐(투명도 없음)이면
   space-between이 할 일이 없어 그대로 좌측에 남는다. */
.theme-row-value {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 7px;
}

/* 스와치와 hex 코드를 [■] #ffd561 처럼 붙여 보이게 하는 그룹 — 간격만 좁힌다. */
.theme-swatch-group {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 3px;
}

.theme-alpha-group {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 3px;
}

.theme-alpha-slider {
  flex: 0 0 56px;
  width: 56px;
  height: 4px;
  border: 0;
  border-radius: 999px;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  background: rgba(var(--focus-rgb), .18);
  cursor: pointer;
}

/* Chrome / Edge / Safari — 채워진 부분과 안 채워진 부분을 따로 그릴 수 없어
   (::-webkit-slider-runnable-track는 트랙 전체 하나뿐) 트랙 전체를 옅은
   focus 톤으로, thumb만 진한 focus-color로 둔다. */
.theme-alpha-slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: rgba(var(--focus-rgb), .18);
}

.theme-alpha-slider::-webkit-slider-thumb {
  width: 12px;
  height: 12px;
  /* WebKit/Blink는(Firefox와 달리) thumb를 트랙 중앙에 자동으로 맞춰주지
     않는다 — 트랙(4px)과 thumb(12px) 높이 차이의 절반만큼(-4px) 끌어올려야
     정확히 수직 중앙에 온다. 이 보정이 없으면 thumb가 트랙 아래쪽으로 치우쳐
     보인다. */
  margin-top: -4px;
  border: 1px solid transparent;
  border-radius: 50%;
  background: var(--focus-color);
  appearance: none;
  -webkit-appearance: none;
}

/* Firefox — ::-moz-range-progress로 채워진 구간만 진하게 그릴 수 있어 트랙
   자체는 옅은 톤, progress는 진한 focus-color로 실제 "진행률" 느낌을 준다. */
.theme-alpha-slider::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: rgba(var(--focus-rgb), .18);
}

.theme-alpha-slider::-moz-range-progress {
  height: 4px;
  border-radius: 999px;
  background: var(--focus-color);
}

.theme-alpha-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: 1px solid transparent;
  border-radius: 50%;
  background: var(--focus-color);
}

.theme-alpha-value {
  flex: 0 0 42px;
  width: 42px;
  height: 22px;
  padding: 0 4px;
  box-sizing: border-box;
  text-align: right;
  color: var(--focus-color) !important;
  font-weight: 600;
}

.theme-alpha-unit {
  color: var(--focus-color) !important;
  font-weight: 600;
}

/* Main settings preview: show the settings modal only, not a desktop/taskbar mock. */
.settings-pc-screen {
  background-position: var(--desktop-background-position-landscape, center);
  background-size: cover;
  background-repeat: no-repeat;
}

/* ==========================================================================
   Desktop background layer / modal glass blur
   Keep the wallpaper as a real rendered layer so backdrop-filter on windows
   can blur it together with the desktop content behind each translucent window.
   ========================================================================== */

.desktop-background {
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: #fff;
  background-image: var(--desktop-background-image) !important;
  background-position: var(--desktop-background-position-landscape, center) !important;
  background-size: cover!important;
  background-repeat: no-repeat!important;
  opacity: 0.95;
}

/* 세로(portrait) 비율의 브라우저에서는 세로용으로 선택한 위치를 보여준다. */
@media (orientation: portrait) {
  .desktop-background {
    background-position: var(--desktop-background-position-portrait, center) !important;
  }
}

/* 상단 .window-bar와 .window-toolbar는 부모 .window의 단일 블러 레이어를
   공유한다. 바에 개별 backdrop-filter를 다시 걸면 투명 테마에서 두 영역의
   질감이 분리돼 보인다. 본문은 별도 System C 표면이라 자체 블러를 유지한다. */
.window-content {
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
}

/* Native color input remains near the legend button before showPicker() opens. */
.display-theme-anchor {
  position: fixed !important;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0 !important;
  opacity: .001;
  pointer-events: none;
}

