/* 탐색 화면(3D 건물·층 도면 옆 패널)과 특별실 상세 — Atelier.
   여기서는 패널·목록·상세와 "지도 칸의 크기·모양"만 다룬다. 지도 칸 안쪽(하늘, 배지·힌트·말풍선·오버레이)은 viewer.css.
   순서: 뼈대 → 탐색 패널 → 층 묶음·특별실 줄 → 특별실 상세 → 예약 바 → 반응형 */

/* ==========================================================================
   1. 뼈대 — 종이 위에 놓인 두 장: 왼쪽 surface 카드(정보) + 오른쪽 둥근 무대(3D). 기획서 §7.4
   ========================================================================== */
.explore, .split {
    --ex-pad: 16px;                                   /* 종이 가장자리와 두 장 사이의 여백 — 하루 패널(.rday, PC)도 이 값으로 자리를 잡는다 */
    flex: none; display: grid; grid-template-columns: var(--panel-w) minmax(0, 1fr); gap: var(--ex-pad);
    height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h));
    padding: var(--ex-pad);
}
.explore-panel, .split .side {
    position: relative; z-index: 2; min-width: 0; min-height: 0; display: flex; flex-direction: column;
    overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--line-2) transparent;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
}
/* 지도 칸: 둥근 무대. 바탕색은 3D 가 뜨기 전 잠깐 보이는 하늘빛 (진짜 하늘은 viewer.css) */
.explore-map, .split .map {
    position: relative; min-width: 0; min-height: 0; overflow: hidden; isolation: isolate;
    border-radius: var(--r-xl); background: linear-gradient(180deg, #DCE4FF 0%, #EEF0FB 52%, #FBF3E8 100%);
}
/* 하늘과 종이가 맞닿는 가장자리에 머리카락 같은 선 하나 */
.explore-map::after, .split .map::after {
    content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
    border-radius: inherit; box-shadow: inset 0 0 0 1px rgba(45, 35, 15, .09);
}
/* 뷰어는 지도 칸을 꽉 채운다. 캔버스 위 터치는 스크롤·확대 대신 3D 조작으로 쓴다 (building3d.js) */
.explore-map > .viewer, .split .map > .viewer { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; }
.explore-map canvas, .split .map canvas { display: block; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
/* 도면이 없는 층 (상세 화면) */
.map-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.map-empty .empty-ico { background: var(--surface); }

/* ==========================================================================
   2. 탐색 패널
   ========================================================================== */
/* 층 고르기는 목록이 흘러가는 동안 위에 붙어 있다. 붙는 것은 알약이 아니라 이 칸 전체이고, 바탕을 끝까지 불투명하게 칠한다 —
   바탕이 알약 아래에서 옅어지면 알약의 둥근 모서리 옆으로 잘린 줄이 비친다. 줄은 칸 아래 12px 번짐 속에서 사라진다 */
.explore-tabs {
    position: sticky; top: 0; z-index: 3; flex: none; padding: 18px 28px 8px;
    background: var(--surface);
}
.explore-tabs::after {
    content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 12px; pointer-events: none;
    background: linear-gradient(var(--surface), rgba(255, 254, 251, 0));
}
/* 층 고르기는 손가락으로 누르는 필터다: 칸 하나가 44px (SPEC 3-9). 트랙 안쪽을 3px 로 줄여 전체 높이는 50px 에서 멈춘다 */
.floor-nav { padding: 3px; }
.floor-nav a { min-height: var(--tap); }
.explore-body { --pad-x: 28px; --pad-top: 18px; --pad-bottom: 32px; flex: 1; padding: var(--pad-top) var(--pad-x) var(--pad-bottom); }
/* PC: 목록이 카드 아래 모서리에서 뚝 잘리면 더 있는 줄 모른다. 아래 36px 를 종이색으로 번지게 해 "이어진다"를 알린다. */
@media (min-width: 961px) {
    .explore-panel { scroll-padding: 96px 0 48px; }
    .explore-panel::after {
        content: ""; position: sticky; bottom: 0; z-index: 2; flex: none; height: 36px; margin-top: -36px; pointer-events: none;
        background: linear-gradient(rgba(255, 254, 251, 0), var(--surface) 92%);
    }
}
/* 옆 패널은 건물/층 단위로 통째로 바뀐다. 새로 보이는 패널이 살짝 떠오른다. */
.pane { animation: pane-in var(--t-mid) var(--ease); }
@keyframes pane-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.pane .empty { margin-top: 24px; padding: 40px 16px; border-radius: var(--r-lg); background: var(--paper); }
.pane .empty .empty-ico { background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }

/* ==========================================================================
   3. 층 묶음과 특별실 줄
   ========================================================================== */
.floor-group { margin-top: 28px; }
.pane > .floor-group:first-of-type { margin-top: 0; }      /* 칸의 첫 묶음: 위는 층 탭·찾기 칸이다 (칸 머리는 v0.5.14 에 뺐다) */
/* 머리: 세리프 층 숫자 + 작은 설명, 아래 잉크 괘선. "도면 보기"는 44px 높이로 누른다 */
.floor-group-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: var(--tap); border-bottom: 1px solid var(--line-ink); }
.floor-group-head h2 { display: flex; align-items: baseline; gap: 10px; min-width: 0; margin: 0; font-size: var(--fs-small); font-weight: 600; line-height: 1.3; letter-spacing: -.01em; color: var(--ink-3); }
.floor-no { flex: none; font-family: var(--font-display); font-weight: 700; font-size: 24px; line-height: 1; letter-spacing: -.02em; color: var(--ink); }

.room-list { list-style: none; margin: 0; padding: 4px 0 0; }
/* 줄 하나 = 분류 타일 + 이름·추천 활동 + 화살표. 패널 여백 쪽으로 10px 씩 넓혀 두어, 채워질 때 글자 자리는 그대로다 */
.room-card {
    position: relative; display: grid; grid-template-columns: 48px minmax(0, 1fr) auto; align-items: center; gap: 14px;
    min-height: 72px; margin: 0 -10px; padding: 12px 10px; border-radius: var(--r-md); color: var(--ink);
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.room-card:hover { text-decoration: none; }
.room-card:focus-visible { border-radius: var(--r-md); outline-offset: 0; }
/* 줄 사이 실선 (채워진 줄과 그 윗줄에서는 숨는다) */
.room-card::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: 0; height: 1px; background: var(--line); transition: opacity var(--t-fast); }
.room-list li:last-child .room-card::after { display: none; }
.room-card .cat-tile { transition: background-color var(--t-fast) var(--ease); }
.room-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.room-main strong { font-size: 16.5px; font-weight: 700; line-height: 1.35; letter-spacing: -.015em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-main span { font-size: 13.5px; line-height: 1.45; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 줄 끝: 화살표 하나. 연결되면 흰 동그라미에 담긴다 (글자는 두지 않는다 — v0.5.14). 줄 전체가 링크다 */
.room-go {
    display: inline-flex; align-items: center; justify-content: center; height: 30px; min-width: 30px; padding: 0 6px;
    border-radius: var(--r-pill); color: var(--ink-4); line-height: 1;
    transition: background-color var(--t-fast) var(--ease), color var(--t-fast);
}
.room-go .icon { width: 16px; height: 16px; stroke-width: 2.2; }

/* 연결된 줄: 도면에서 그 실에 마우스를 올렸을 때(.is-hover, building3d.js) · 줄에 마우스를 올렸을 때 · 키보드로 왔을 때.
   분류 bg 로 채우고 1.5px 분류 fg 링. 색은 줄의 data-cat 이 정한다 */
.room-card.is-hover, .room-card:focus-visible { background: var(--cat-bg, var(--paper-2)); box-shadow: 0 0 0 1.5px var(--cat-fg, var(--ink-3)); }
.room-card.is-hover::after, .room-card:focus-visible::after,
.room-list li:has(+ li .room-card.is-hover) .room-card::after, .room-list li:has(+ li .room-card:focus-visible) .room-card::after { opacity: 0; }
.room-card.is-hover .cat-tile, .room-card:focus-visible .cat-tile { background: var(--surface); }
.room-card.is-hover .room-main span, .room-card:focus-visible .room-main span { color: var(--ink-2); }
.room-card.is-hover .room-go, .room-card:focus-visible .room-go { background: var(--surface); color: var(--cat-fg, var(--ink)); }
@media (hover: hover) {
    .room-card:hover { background: var(--cat-bg, var(--paper-2)); box-shadow: 0 0 0 1.5px var(--cat-fg, var(--ink-3)); }
    .room-card:hover::after, .room-list li:has(+ li .room-card:hover) .room-card::after { opacity: 0; }
    .room-card:hover .cat-tile { background: var(--surface); }
    .room-card:hover .room-main span { color: var(--ink-2); }
    .room-card:hover .room-go { background: var(--surface); color: var(--cat-fg, var(--ink)); }
}
/* 손가락: 누르는 동안 분류색이 비친다 (hover 가 없는 기기의 눌림 표시) */
.room-card:active { background: var(--cat-bg, var(--paper-2)); }
.room-card:active::after { opacity: 0; }
.room-card:active .cat-tile { background: var(--surface); }

/* ==========================================================================
   4. 특별실 상세 (S-03)
   ========================================================================== */
.room-detail .photos { flex: none; }
.room-detail .photo-slider { background: var(--paper-2); }
/* 사진이 없을 때: 분류 색 띠 + 비스듬히 걸친 큰 분류 그림. 색은 data-cat 이 정한다 */
.photo-empty { position: relative; flex: 4 1 176px; min-height: 176px; max-height: 272px; overflow: hidden; background: var(--cat-bg, var(--paper-2)); color: var(--cat-fg, var(--ink-3)); }
.photo-empty::before {
    content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .7;
    background-image: radial-gradient(rgba(45, 35, 15, .13) 1px, transparent 1.4px); background-size: 16px 16px;
    -webkit-mask-image: linear-gradient(100deg, transparent 30%, #000 100%); mask-image: linear-gradient(100deg, transparent 30%, #000 100%);
}
.photo-empty-art { position: absolute; right: 12px; bottom: -34px; width: 168px; height: 168px; stroke-width: 1.1; opacity: .42; transform: rotate(-10deg); }

/* 패널이 내용보다 길면 남는 높이는 위쪽 사진 띠가 먼저(4:1) 가져간다 — 추정 배지와 예약 바 사이에 구멍이 나지 않게 */
.room-body { flex: 1 0 auto; padding: 20px 28px 28px; }
.room-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 16px; }
.room-head h1 { margin: 0; font-size: 30px; line-height: 1.2; }
.room-where { display: flex; align-items: center; gap: 4px; margin: 4px 0 0; color: var(--ink-3); font-size: 13.5px; font-weight: 600; line-height: 1.4; }
.room-where .icon { width: 15px; height: 15px; }
.room-detail .desc { margin: 20px 0 0; color: var(--ink-2); line-height: 1.65; }
/* 사실 줄: 프로그램 북의 표처럼 — 위 잉크 괘선, 줄 사이 실선, 왼쪽에 작은 이름표 */
.facts { list-style: none; margin: 22px 0 0; padding: 0; border-top: 1px solid var(--line-ink); }
.facts li { display: grid; grid-template-columns: 20px 72px minmax(0, 1fr); gap: 12px; align-items: start; padding: 15px 0; border-bottom: 1px solid var(--line); line-height: 22px; }
.facts .icon { margin-top: 1px; color: var(--ink-3); }
.facts small { color: var(--ink-3); font-size: var(--fs-small); font-weight: 600; line-height: 22px; }
.facts b { font-size: var(--fs-body); font-weight: 600; line-height: 22px; }
.fact-note { margin-left: 6px; padding: 2px 7px; border-radius: var(--r-xs); background: var(--paper-2); color: var(--ink-3); font-size: var(--fs-caption); font-weight: 600; }
/* 특별실 찾기: 층 탭 바로 아래. 초성도 받는다 (js/search.js) */
.room-search {
    display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 0 12px 0 14px;
    height: 42px; border-radius: var(--r-pill); background: var(--paper-2);
    transition: box-shadow var(--t-fast), background-color var(--t-fast);
}
.room-search:focus-within { background: var(--surface); box-shadow: inset 0 0 0 2px var(--accent); }
.room-search > .icon { flex: none; color: var(--ink-3); vertical-align: 0; }
.room-search input {
    flex: 1; min-width: 0; height: 100%; border: 0; background: none; color: var(--ink);
    font-family: inherit; font-size: var(--fs-sub); font-weight: 600;
}
.room-search input::placeholder { color: var(--ink-4); font-weight: 500; }
.room-search input:focus { outline: 0; }
.room-search input::-webkit-search-cancel-button { display: none; }
.room-search .icon-btn { width: 30px; height: 30px; flex: none; }

/* ---- 예약 현황 달력 (v0.5.13). 채워진 칸이 "예약 가능"(오늘부터, 쉬지 않는 날) — 예약 1단계 달력의 "고를 수 있는 날만 채운다" 와 같은 말투.
   예약이 있는 날은 그보다 두 단 진한 모래색(점 하나가 한 건, 셋까지), 내 것이 있는 날은 코발트,
   오늘은 잉크 테, 휴일·시험기간은 점선 테, 열려 있는 날은 잉크로 채운다. 지난 날은 채우지 않지만 누를 수 있다(그 날의 이력 — 예약이 있었으면 옅은 모래색).
   날짜를 누르면 그 날의 예약이 .rday 에 열린다 — PC 는 지도 오른쪽 위에 뜨는 긴 패널(아래 "PC:" 블록), 휴대폰은 달력 바로 아래. js/roomcal.js */
.rcal { --rcal-has: #D7CCB6; --rcal-has-hover: #CBBEA4; --rcal-has-past: #E5DDCC; margin-top: 22px; }
.rcal-head { display: flex; align-items: center; gap: 4px; margin: 0 0 10px; padding-bottom: 8px; border-bottom: 1px solid var(--line-ink); }
.rcal-title { flex: 1; min-width: 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; font-variant-numeric: tabular-nums; }
.rcal-nav {
    width: 36px; height: 36px; flex: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
    background: var(--paper-2); color: var(--ink); cursor: pointer; transition: background-color var(--t-fast), transform var(--t-fast) var(--ease);
}
.rcal-nav .icon { width: 20px; height: 20px; }
.rcal-nav:hover { background: var(--paper-3); }
.rcal-nav:active { transform: scale(.94); }
.rcal-nav:focus-visible { border-radius: 50%; }
.rcal-nav:disabled { background: transparent; color: var(--ink-4); cursor: not-allowed; transform: none; }
/* 요일 줄 + 늘 6줄(여섯 줄짜리 달도 있다): 줄 수가 달라도 높이가 같아 달을 넘길 때 아래 내용이 들썩이지 않는다 */
.rcal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: auto repeat(6, 44px); gap: 4px; }
.rcal-dow { padding: 2px 0 4px; text-align: center; font-size: var(--fs-micro); font-weight: 700; color: var(--ink-3); }
.rcal-dow.sun { color: var(--st-rejected-fg); }
.rcal-dow.sat { color: var(--st-done-fg); }
.rcal-cell {
    position: relative; min-width: 0; height: 44px; padding: 0; border: 0; border-radius: var(--r-sm);
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    background: var(--paper-2); color: var(--ink); font-family: inherit; font-size: 14.5px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: background-color var(--t-fast), color var(--t-fast), transform var(--t-fast) var(--ease);
}
.rcal-blank { visibility: hidden; }
.rcal-cell .d { line-height: 1; }
.rcal-cell.sun .d { color: var(--st-rejected-fg); }
.rcal-cell.sat .d { color: var(--st-done-fg); }
.rcal-cell:hover { background: var(--paper-3); }
.rcal-cell:active { transform: scale(.95); }
.rcal-cell:focus-visible { border-radius: var(--r-sm); }
.rcal-dots { display: flex; gap: 3px; height: 4px; }
.rcal-dots i { width: 4px; height: 4px; border-radius: 50%; background: var(--ink-2); }
/* 칸의 상태는 아래로 갈수록 세다: 예약 있음 < 지난 날 < 휴일·시험기간 < 내 것 < 오늘 < 열려 있음.
   겹치는 상태(.past.has, .blocked.has …)가 (0,3,0) 이라 그보다 센 상태는 클래스를 한 번 더 적어 같은 무게로 만들고 순서로 이긴다
   (에이전트 검토: 지난 날·휴일의 열린 칸이 모래색 바탕에 종이색 숫자가 되던 것) */
/* 예약이 있는 날 */
.rcal-cell.has { background: var(--rcal-has); }
.rcal-cell.has:hover { background: var(--rcal-has-hover); }
/* 지난 날: 예약할 수 없으니 채우지 않는다 (범례의 "예약 가능" = 채워진 칸, v0.5.14). 예약이 있었던 날만 옅은 모래색으로 남는다.
   글자는 --ink-3 까지만 (--ink-4 는 글자에 쓰지 않는다, app.css 토큰 설명) */
.rcal-cell.past { background: transparent; font-weight: 600; }
.rcal-cell.past:hover { background: var(--paper-2); }
.rcal-cell.past .d { color: var(--ink-3); }
.rcal-cell.past.has { background: var(--rcal-has-past); }
.rcal-cell.past.has:hover { background: var(--rcal-has); }
.rcal-cell.past.has .d { color: var(--ink-2); }
.rcal-cell.past .rcal-dots i { background: var(--ink-3); }
/* 휴일·시험기간: 채우지 않고 점선 테. 까닭(이름)은 하루 패널 머리에 적힌다 */
.rcal-cell.blocked { background: transparent; border: 1px dashed rgba(216, 69, 47, .55); color: var(--ink-3); font-weight: 600; }
.rcal-cell.blocked .d { color: var(--ink-3); }
.rcal-cell.blocked.exam { border-color: rgba(200, 138, 0, .65); }
.rcal-cell.blocked:hover { background: var(--paper-2); }
/* 쉬는 날에 남은 예약: 예약할 수 없는 날이므로 지난 날과 같은 옅은 모래색 (진한 모래색은 예약 가능한 날만) */
.rcal-cell.blocked.has { background: var(--rcal-has-past); }
.rcal-cell.blocked.has:hover { background: var(--rcal-has); }
.rcal-cell.blocked.has .d { color: var(--ink-2); }
/* 내 것이 있는 날: 코발트 — 다른 화면의 "내 신청" 과 같은 색. 지난 날·휴일이어도 (범례와 같게) */
.rcal-cell.rcal-cell.mine, .rcal-cell.rcal-cell.mine:hover { background: var(--accent-wash-2); box-shadow: inset 0 0 0 1.5px var(--accent); }
.rcal-cell.rcal-cell.mine .d { color: var(--ink); }
.rcal-cell.rcal-cell.mine .rcal-dots i { background: var(--accent); }
/* 오늘: 잉크 테 (코발트 테는 "내 것" 의 말투) */
.rcal-cell.rcal-cell.today { box-shadow: inset 0 0 0 1.5px var(--ink); }
.rcal-cell.blocked.today { border-color: transparent; }
/* 열려 있는 날: 잉크로 채운다 */
.rcal-cell.rcal-cell.sel, .rcal-cell.rcal-cell.sel:hover { background: var(--ink); color: var(--paper); box-shadow: none; border-color: transparent; }
.rcal-cell.rcal-cell.sel .d { color: inherit; }
.rcal-cell.rcal-cell.sel .rcal-dots i { background: var(--paper); }
.rcal-msg { margin: 8px 0 0; font-size: var(--fs-small); font-weight: 600; color: var(--ink-3); }
.rcal-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; margin: 10px 0 0; font-size: var(--fs-caption); font-weight: 500; color: var(--ink-2); line-height: 1.3; }
.rcal-legend span { display: inline-flex; align-items: center; gap: 6px; }
.rcal-sw { width: 14px; height: 14px; border-radius: 4px; flex: none; }
.rcal-sw-open { background: var(--paper-2); box-shadow: inset 0 0 0 1px var(--line); }      /* "예약 가능" — 채워진 보통 칸 (예약 1단계 달력의 .cal-sw-open 과 같다) */
.rcal-sw-mine { background: var(--accent-wash-2); box-shadow: inset 0 0 0 1.5px var(--accent); }
.rcal-sw-today { background: var(--paper-2); box-shadow: inset 0 0 0 1.5px var(--ink); }
.rcal-sw-blocked { border: 1px dashed rgba(216, 69, 47, .75); }

/* ---- 누른 하루의 예약 (.rday): 머리(날짜 · 휴일 이름 · 닫기) + 시간표(.tt). 한 번에 하나만 열린다.
   휴대폰·태블릿(960px 이하)에서는 달력 바로 아래 흐름 속의 상자다 — 겹치는 것이 없다 */
.rday { display: flex; flex-direction: column; min-height: 0; margin-top: 12px; background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md); }
.rday[hidden] { display: none; }
.rday-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 12px 8px 10px 16px; border-bottom: 1px solid var(--line); }
.rday-when { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding-top: 6px; }
.rday-title { font-family: var(--font-display); font-size: 18px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; }
.rday-sub { font-size: var(--fs-caption); font-weight: 600; color: var(--ink-3); line-height: 1.3; }
.rday-sub:empty { display: none; }
.rday-body { flex: 1; min-height: 0; overflow: auto; padding: 12px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.rday[aria-busy="true"] .rday-body { opacity: .6; }
.rday-none { margin: 0; padding: 4px 0; font-size: var(--fs-sub); font-weight: 600; color: var(--ink-2); }      /* 불러오지 못했을 때의 한 줄 */
.rday-go { flex: none; justify-content: center; }

/* ---- 하루 시간표 (.tt, v0.5.14 — 사용자 결정: 시 단위, 운영 시간만). 세로축이 시간이고 가로줄 하나가 정각이다.
   12:00 ~ 13:00 만 여는 실이면 한 칸짜리 표가 된다. 예약 한 건은 그 위에 얹힌 구간(.tt-ev): 위치와 높이가 시작·끝 시각이고,
   10분 단위의 정확한 시각은 구간 안에 숫자로 적는다. 겹치는 신청은 옆으로 나란히 선다 (칸 수 --cols, 제 칸 --col — roomcal.js lanes).
   한 시간의 높이(--hh)는 144px 로 고정이다 — 10분이 24px, 글자 한 줄. 패널을 꽉 채우도록 늘리지 않는다 (사용자: "더 짧게").
   모양은 휴대폰 달력의 하루 보기다 (사용자 지정): 왼쪽에 시각, 정각마다 가로줄, 예약은 옅은 바탕 + 왼쪽 색 띠의 둥근 블록.
   색은 상태 배지와 같다(.st-APPROVED … — app.css 가 바탕·글자·--dot 을 준다), 신청중은 빗금, 내 것은 코발트 띠와 테. */
.tt { --hh: 144px; --axis: 46px; position: relative; flex: none; height: calc(var(--hours) * var(--hh)); margin: 8px 0;
      min-width: calc(var(--axis) + var(--maxcols, 1) * 76px); }      /* 한 칸이 76px 아래로 좁아지지 않는다 (세 칸 + 세로 스크롤 막대가 340px 패널에 들어가는 값) — 넷 이상 겹치면 패널 안에서 옆으로 민다 */
.tt::before { content: ""; position: absolute; left: var(--axis); right: 0; top: 0; bottom: 0; border-radius: var(--r-xs); background: var(--paper); }
.tt.is-blocked::before { background: transparent; border: 1px dashed rgba(216, 69, 47, .55); }      /* 휴일·시험기간: 달력의 점선 칸과 같은 말투 */
.tt-hour { position: absolute; left: 0; right: 0; top: calc(var(--i) * var(--hh)); height: 0; border-top: 1px solid var(--line-2); }
.tt-hour b {
    position: absolute; left: 0; top: 0; transform: translateY(-50%); padding-right: 8px; background: var(--surface);
    font-size: 11.5px; font-weight: 700; line-height: 1; color: var(--ink-3);
}
.tt-lane { position: absolute; left: var(--axis); right: 0; top: 0; bottom: 0; margin: 0; padding: 0; list-style: none; }
.tt-ev {
    position: absolute; top: calc(var(--s) * var(--hh) / 60 + 1px); height: calc(var(--d) * var(--hh) / 60 - 2px);
    left: calc(var(--col) * 100% / var(--cols) + 2px); width: calc(100% / var(--cols) - 4px);
    display: flex; flex-wrap: wrap; align-content: flex-start; align-items: baseline; gap: 0 8px;
    padding: 3px 8px 3px 11px; overflow: hidden; border-radius: 6px; box-shadow: inset 3px 0 0 var(--dot, var(--ink-3));
    font-size: 11.5px; font-weight: 600; line-height: 1.3;
}
.tt-ev.st-REQUESTED { background-image: repeating-linear-gradient(135deg, rgba(200, 138, 0, .14) 0 3px, transparent 3px 8px); }
.tt-ev.me { box-shadow: inset 3px 0 0 var(--accent), inset 0 0 0 1.5px var(--accent); }
.tt-time { color: var(--ink); font-weight: 800; letter-spacing: -.01em; white-space: nowrap; }
.tt-who, .tt-mine, .tt-st { white-space: nowrap; }      /* "2학년 김*수" — 학년과 가운데를 가린 이름 */
.tt-mine { color: var(--accent-ink); font-weight: 700; }
.tt-st { margin-left: auto; font-weight: 700; }
/* 겹쳐서 좁아진 블록: 시각("12:10~12:30" 로 붙여 쓴다 — roomcal.js) · 누구 · 상태를 세로로 쌓는다 */
.tt-ev.narrow { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; gap: 1px; padding: 3px 2px 3px 8px; font-size: 11px; }
.tt-ev.narrow .tt-time { font-size: 10.5px; letter-spacing: -.035em; }      /* 세 칸으로 나뉜 76px 칸에 "14:00~16:00" 이 한 줄로 들어가는 크기 */
.tt-ev.narrow .tt-st { margin-left: 0; }
.tt-st::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 5px; border-radius: 50%; background: var(--dot, currentColor); vertical-align: 1px; }

/* PC: 하루 패널은 지도 오른쪽 위에 뜨는 긴 직사각형이다 (사용자 결정 — 도면을 가려도 된다). 왼쪽 패널 안의 조각이지만 화면에 고정해 지도 위에 얹는다:
   지도 칸의 위·아래·오른쪽 가장자리(--ex-pad)에서 12px 안쪽. 상자의 높이는 늘 지도만큼이다 — 짧게 하는 것은 안의 시간표뿐이고(한 시간 144px),
   상자까지 내용에 맞춰 줄이지 않는다 (2026-10-11 사용자). 시간표가 상자보다 길면 안에서 스크롤한다. 겹치는 것이 없도록 — 도우미는 상세가 열려 있는 동안 이미 숨어 있고(4절 .helper),
   아래 가운데 힌트는 남은 너비의 가운데로 옮기며, 마우스 말풍선(viewer.css .viewer-tip)은 지도 칸 안에 갇혀 패널 밑에 그려진다.
   조상에 transform 이 있으면 fixed 가 딸려 가므로 .pane-room 은 opacity 로만 나타난다 (아래 pane-fade) */
@media (min-width: 961px) {
    .rday {
        position: fixed; z-index: 6; top: calc(var(--topbar-h) + var(--ex-pad) + 12px); right: calc(var(--ex-pad) + 12px); bottom: calc(var(--ex-pad) + 12px);
        width: 340px; margin: 0; border: 0; border-radius: var(--r-lg); box-shadow: var(--sh-pop);
        animation: rday-in var(--t-mid) var(--ease);
    }
    .rday-head { padding: 16px 10px 12px 20px; }
    .rday-body { padding: 14px 20px 20px; overscroll-behavior: contain; }      /* 지도 위에 뜬 패널: 끝까지 굴려도 뒤의 화면이 따라 움직이지 않게 (휴대폰은 흐름 속이라 가두지 않는다) */
    /* 패널이 덮지 않는 지도 너비의 가운데로 (340px + 안쪽 12px) — 그 너비가 알약보다 좁은 창(1180px 이하)에서는 숨긴다.
       층·건물로 돌아가면 상세 칸(.pane-room)만 숨고 안의 패널은 열린 채 남으므로, 칸이 보일 때만 센다 */
    .explore:has(.pane-room:not([hidden]) .rday:not([hidden])) .explore-map .viewer-hint { left: calc((100% - 352px) / 2); }
}
@media (min-width: 961px) and (max-width: 1180px) {
    .explore:has(.pane-room:not([hidden]) .rday:not([hidden])) .explore-map .viewer-hint { display: none; }
}
/* 휴대폰·태블릿: 달력 아래에 열리는 패널을 보이는 곳으로 끌어올 때(roomcal.js scrollIntoView) 고정 예약 바·탭 바와 붙어 있는 시트 머리 밑으로 들어가지 않게.
   운영 시간이 긴 실의 시간표는 길다 — 패널의 높이를 묶고 안에서 스크롤한다 (첫 예약이 보이는 데서 시작한다, roomcal.js show). 한 칸짜리(12:00 ~ 13:00)는 다 들어간다 */
@media (max-width: 960px) {
    .rday { scroll-margin-top: calc(var(--topbar-h) + 104px); scroll-margin-bottom: calc(var(--tabbar-h) + 90px); }
    .rday-body { max-height: 70vh; max-height: min(70svh, 560px); }
}
@keyframes rday-in { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .rday { animation: none; } }

.room-body .estimate-badge { margin-top: 16px; box-shadow: inset 0 0 0 1px rgba(224, 161, 0, .38); }

/* 상세는 탐색 패널의 한 칸(.pane-room)에 조각으로 들어온다 (2026-10-04). 칸의 여백은 .explore-body 가 주므로
   조각 안쪽은 가로 여백을 두지 않고, 사진 띠와 아래 붙는 바만 그 여백을 뚫고 패널 가장자리까지 간다.
   예약 신청·완료는 제 페이지다 (reserve.css) */
.pane-room { display: flex; flex-direction: column; min-height: 100%; animation-name: pane-fade; }   /* transform 이 있으면 fixed 요소(휴대폰의 예약 바, PC 의 하루 패널)가 220ms 동안 딸려 간다 */
@keyframes pane-fade { from { opacity: 0; } to { opacity: 1; } }
/* 상세가 열려 있는 동안은 빈 시간 도우미 말풍선을 치운다 — 아래 붙는 바의 "예약하기" 와 겹친다 */
.explore:has(.pane-room:not([hidden])) .helper { display: none; }
.pane-room[aria-busy="true"] { opacity: .6; transition: opacity var(--t-fast); }
.pane-room .room-detail { display: flex; flex-direction: column; flex: 1 0 auto; min-width: 0; }
.pane-room .photos, .pane-room .photo-empty { margin: calc(var(--pad-top) * -1) calc(var(--pad-x) * -1) 0; }
.pane-room .room-body { padding: 20px 0 24px; }

/* ==========================================================================
   5. 예약 바 — 패널 아래에 붙는다. 한 가지 전진 동작
   ========================================================================== */
.cta-bar {
    position: sticky; bottom: 0; z-index: 5; flex: none; display: flex; align-items: center; gap: 16px;
    margin: auto calc(var(--pad-x) * -1) calc(var(--pad-bottom) * -1);
    padding: 14px var(--pad-x) 16px; background: var(--surface); border-top: 1px solid var(--line);
    box-shadow: 0 -14px 24px -18px rgba(45, 35, 15, .22);
}
/* 붙는 바가 있는 동안은 아래 번짐(::after)을 끈다 — 바 위에 번짐이 덮이면 바가 흐려 보인다 */
@media (min-width: 961px) { .explore-panel:has(.pane-room:not([hidden]) .cta-bar)::after { display: none; } }
.cta-bar > .btn { flex: 1; min-width: 0; }
/* 교사·관리자: 전진 동작이 없는 안내 — 글 한 줄, 그 아래 자기 일로 가는 중립 버튼 */
.cta-note { flex-direction: column; align-items: stretch; gap: 10px; }
.cta-links { display: flex; flex-wrap: wrap; gap: 8px; }
.cta-links .btn { flex: 1 1 auto; }

/* ==========================================================================
   6. 반응형
   ========================================================================== */
@media (max-width: 1180px) {
    .explore, .split { --ex-pad: 12px; grid-template-columns: 384px minmax(0, 1fr); }
    .explore-tabs { padding: 16px 22px 8px; }
    .explore-body { --pad-x: 22px; --pad-top: 16px; --pad-bottom: 28px; }
    .room-body { padding: 18px 22px 24px; }
}

/* 960px 아래: 지도가 위(화면 끝까지), 패널은 그 밑동을 덮고 올라오는 시트 */
@media (max-width: 960px) {
    .explore, .split { display: flex; flex-direction: column; height: auto; padding: 0; gap: 0; }
    .explore { min-height: calc(100vh - var(--topbar-h) - var(--tabbar-h)); min-height: calc(100svh - var(--topbar-h) - var(--tabbar-h)); }
    .explore-map {
        --map-overlap: 28px;                        /* 시트가 덮는 높이 — viewer.css 가 힌트 자리를 잡을 때 읽는다 */
        order: -1; position: sticky; top: var(--topbar-h); z-index: 1; flex: none;
        height: 46vh; height: 46svh; min-height: 300px; max-height: 520px; border-radius: 0;
    }
    .explore-map::after { display: none; }
    .explore-panel {
        flex: 1; margin-top: -28px; overflow: visible; border: 0; border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: var(--sh-bar);
    }
    /* 시트 머리(손잡이 + 층 고르기)가 통째로 붙는다. 손잡이가 있는 위 13px 는 머리 막대 밑으로 밀어 넣어 붙었을 때 자리를 먹지 않게 한다.
       둥근 모서리가 시트 모서리와 같은 자리에서 시작하므로, 붙은 뒤에도 모서리 밖으로 목록이 비치지 않는다
       (모서리를 칸 위쪽에서 따로 굴리면 그 28px 안으로 줄 실선과 타일이 지나갔다) */
    .explore-tabs { top: calc(var(--topbar-h) - 13px); padding: 23px var(--gutter) 6px; border-radius: var(--r-xl) var(--r-xl) 0 0; }
    /* 시트 손잡이 */
    .explore-tabs::before { content: ""; position: absolute; left: 50%; top: 9px; width: 38px; height: 4px; margin-left: -19px; border-radius: 2px; background: var(--line-2); }
    .explore-body { --pad-x: var(--gutter); --pad-top: 12px; --pad-bottom: 28px; }

    /* 상세: 사진 → 내용 순서로 흐르고, 예약 바는 화면 아래에 붙어 있다 (시트가 바 뒤로 들어가지 않게 아래 여백) */
    .explore:has(.pane-room:not([hidden]) .cta-bar:not(.cta-note)) { padding-bottom: calc(73px + env(safe-area-inset-bottom, 0px)); background: var(--surface); }
    .pane-room .room-body { padding: 16px 0 24px; }
    .photo-empty { flex: none; height: 148px; min-height: 0; }
    /* 바로 아래 지도 카드에 같은 호박색 배지가 또 있다. 여기서는 알약을 벗기고 조용한 각주 한 줄로 둔다 (출처 등급은 남긴다) */
    .room-body .estimate-badge { display: flex; min-height: 0; margin-top: 14px; padding: 0; border-radius: 0; background: none; box-shadow: none; color: var(--ink-3); font-weight: 500; }
    .room-body .estimate-badge .icon { color: var(--ink-4); }
    .cta-bar {
        position: fixed; left: 0; right: 0; bottom: var(--tabbar-h); z-index: 34; margin: 0;
        padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom, 0px)); box-shadow: var(--sh-bar);
    }
    .cta-bar > .btn { max-width: 420px; margin-left: auto; }      /* 태블릿 폭에서 버튼이 끝없이 길어지지 않게 */
    .cta-note { position: static; margin: 0 0 24px; padding: 14px 16px; border: 0; border-radius: var(--r-md); background: var(--paper-2); box-shadow: none; }
    .cta-note .btn { flex: 0 1 auto; background: var(--surface); }
    .cta-note .btn:hover { background: var(--paper-3); }
}

@media (max-width: 767px) {
    /* 첫 화면(390×844)에 특별실 줄이 2.5개 이상 보이게 (SPEC 3-6): 지도는 화면의 38%, 층 묶음 사이를 좁힌다 (칸 머리는 v0.5.14 에 뺐다) */
    .explore-map { height: 38vh; height: 38svh; min-height: 264px; max-height: 310px; }
    .explore-tabs { padding-top: 21px; }
    .explore-body { --pad-top: 10px; }
    .floor-group { margin-top: 14px; }
    .room-card { min-height: 68px; padding: 10px; }
    /* 사진이 없는 띠는 장식이다: 96px 로 낮추고 그림도 그만큼 줄인다 */
    .photo-empty { flex: none; height: 96px; min-height: 0; }
    .photo-empty-art { right: 8px; bottom: -22px; width: 104px; height: 104px; stroke-width: 1.3; }
    .room-head { gap: 14px; }
    .room-head h1 { font-size: 26px; }
    /* 탭 바가 있는 화면에서는 safe-area 를 탭 바가 이미 챙긴다 */
    .cta-bar { padding-bottom: 10px; }
    .explore:has(.pane-room:not([hidden]) .cta-bar:not(.cta-note)) { padding-bottom: 73px; }
    .cta-bar { gap: 14px; }
}
