/* 全画面共通の土台。reload.js が使う .btn と状態オーバーレイだけここに置き、他の部品は各機能の CSS に置く。値は UI.md「具体値の一覧」 */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-md);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

button, input, textarea, select { font: inherit; color: inherit; }
img { display: block; max-width: 100%; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ボタンの文字は折り返させない。「全画 面」のように割れると、
   押す場所が読み取れなくなる */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 32px; padding: 0 12px; white-space: nowrap;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text);
  cursor: pointer; transition: background .12s var(--ease);
}
.btn:hover { background: var(--surface-3); }
.btn:disabled { color: var(--text-dim); cursor: default; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn--danger:hover { background: var(--danger-ink); border-color: var(--danger-ink); }
/* アイコンだけのボタンは 32×32（UI.md「具体値の一覧」）。**.btn 本体より後ろに置く** ——
   詳細度が同じなので、前に置くと padding と display が .btn に負ける */
.btn--icon { padding: 0; width: 32px; flex: none; }

/* 状態オーバーレイ（UI.md「文言」）と、panic 後の再読み込み */
.overlay, .reload {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid; place-content: center; gap: var(--gap); text-align: center;
  padding: var(--gap-lg); background: var(--bg);
}
.overlay h1, .reload p { margin: 0; font-size: 20px; font-weight: 700; }
.overlay p { margin: 0; color: var(--text-mut); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ---- 参加コードの入力（UI.md「ログイン（`/`）」「具体値の一覧」）---- */
.join {
  min-height: 100dvh; display: grid; align-content: center; gap: var(--gap);
  padding: var(--gap-lg); width: min(460px, 100%); margin: 0 auto;
}
.join__title { margin: 0; font-size: 20px; font-weight: 700; }
.join__row { display: flex; gap: var(--gap); }
.join__input {
  flex: 1; min-width: 0; height: 46px; padding: 0 12px;
  font-family: var(--font-num); font-size: 18px; letter-spacing: .12em;
  font-variant-numeric: tabular-nums; text-transform: uppercase;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.join__input[aria-invalid="true"] { border-color: var(--danger); }
.join__row > .btn { height: 46px; padding: 0 18px; }
/* 理由が出ても下の行が動かないよう、1 行ぶんを空けておく */
.join__problem { margin: 0; min-height: 1.6em; color: var(--danger); font-size: var(--fs-sm); }
/* 縦に積むと flex: 1 が高さに効いて潰れるので、積んだら伸ばさない */
@media (max-width: 639px) {
  .join__row { flex-direction: column; }
  .join__input { flex: none; }
}

/* ---- ルーム画面（UI.md「ルーム画面のレイアウト」）---- */
.room {
  display: grid; grid-template-rows: var(--topbar-h) 1fr;
  height: 100dvh; background: var(--bg);
}
.topbar {
  display: flex; align-items: center; gap: var(--gap);
  padding: 0 var(--gap-lg); border-bottom: 1px solid var(--line-soft);
  background: var(--surface);
}
.topbar__title {
  font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar__host { color: var(--text-mut); font-size: var(--fs); white-space: nowrap; }

/* ページ自体はスクロールさせない（スクロールするのはチャット欄だけ）。
   flex なのは、コメント欄を隠したときにスライドが自分で全幅へ広がるため
   —— grid の列で組むと、隠しても空の列が残る */
.room__body {
  position: relative; min-height: 0; padding: var(--gap);
  display: flex; gap: var(--gap);
}
@media (max-width: 1023px) {
  /* 1024px 未満はスライド上・チャット下（UI.md「レイアウト」） */
  .room__body { flex-direction: column; }
}
@media (min-width: 1024px) {
  /* 登壇者がコメントの位置を「左」にしたら、ドックをスライドの左へ。
     DOM の順序は変えない（読み上げ順と Tab 順。UI.md「表示のオン / オフ」）。
     視聴画面には位置の設定が無いので、登壇画面だけ */
  .room--host:not(.room--right) .room__body { flex-direction: row-reverse; }
}

/* ---- スライド枠（UI.md「スライド枠」）---- */
.stage {
  display: grid; place-items: center; height: 100%;
  background: var(--stage); border-radius: var(--radius);
  /* min-* は flex の子が中身の幅で押し広げるのを止める */
  flex: 1; min-width: 0; min-height: 0;
}
/* --ar は資料の実寸の比（`web/src/slides/mod.rs` が入れる） */
.stage__box {
  position: relative; aspect-ratio: var(--ar); max-width: 100%; max-height: 100%;
  border-radius: var(--radius-sm); background: #FAFAF8; overflow: hidden;
}
.stage__box--empty { width: min(100%, 960px); aspect-ratio: 16 / 9; }
/* 収まりの規則は UI.md「スライドの収まり」（#184）。枠の高さを cq 単位で引くのは、
   それを読むためだけに JS を置かないため。比が届く前（--empty）は広げる先が決まらない。
   ⚠️ container-type は枠を絶対配置・固定配置の包含ブロックにする ——
   ここに position: absolute を足すと、基準は画面ではなく枠になる
   （重ねるものは画像の箱の中に入れる） */
.room--host .stage { container-type: size; }
.room--host .stage__box:not(.stage__box--empty) { width: min(100cqw, calc(100cqh * var(--ar))); }
.stage__img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* 先読みは見せない（前後 1 枚だけ。DESIGN.md §7.3） */
.stage__preload { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ページが変わったことを枠で伝える（FR-7.3 / UI.md「時間」: 入り .1s、抜け .5s）。
   box-shadow だけを動かしてレイアウトに触らない。
   a / b の 2 本あるのは、animation-name が変わらないと 2 回目が走らないため
   （要素は使い回されるので、名前を交互に入れ替えて頭から流す） */
.stage__box--flash-a { animation: slide-flash-a .7s var(--ease) 1; }
.stage__box--flash-b { animation: slide-flash-b .7s var(--ease) 1; }
@keyframes slide-flash-a {
  0% { box-shadow: inset 0 0 0 2px transparent; }
  14% { box-shadow: inset 0 0 0 2px var(--accent-line); }
  29% { box-shadow: inset 0 0 0 2px var(--accent-line); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}
@keyframes slide-flash-b {
  0% { box-shadow: inset 0 0 0 2px transparent; }
  14% { box-shadow: inset 0 0 0 2px var(--accent-line); }
  29% { box-shadow: inset 0 0 0 2px var(--accent-line); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}

/* 読み込み中は前のページを薄く残す（UI.md「読み込み中の画像」） */
.stage__img--loading { opacity: .35; }

/* ルームの状態。**スライドを隠さない**（FR-12.7「最後のスライドは残す」）ので、
   幕の上にカードだけを置く。全画面を塗るのは panic 後の .reload だけ。
   幕は後ろにスライドがあるときだけ（--over-slide）—— 隠すものが無いのに暗くしない */
.status {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid; place-items: center; padding: var(--gap-lg);
}
.status--over-slide { background: var(--scrim); }
/* 幕が無いときは見えない面でクリックを奪わない（読むのはカードだけ）。
   幕があるときは奪う —— 暗くした下を触らせない */
.status:not(.status--over-slide) { pointer-events: none; }
.status__card { pointer-events: auto; }
.status__card {
  max-width: min(420px, 100%); padding: var(--gap-lg);
  background: var(--on-slide-firm); color: var(--on-slide-text);
  border: 1px solid var(--on-slide-line); border-radius: 14px;
  box-shadow: var(--shadow); text-align: center;
}
.status__card h1 { margin: 0; font-size: 20px; font-weight: 700; }
.status__card p { margin: 8px 0 0; color: rgba(255, 255, 255, .72); font-size: var(--fs-md); }

/* ---- コメント欄（UI.md「チャット欄」「具体値の一覧」）---- */
.chat {
  display: flex; flex-direction: column; min-height: 0;
  flex: 0 0 var(--chat-w);
  background: var(--surface); border-radius: var(--radius);
  border: 1px solid var(--line-soft);
}
@media (max-width: 1023px) {
  /* flex: 1 にするとスライドが潰れるので、高さで持つ */
  .chat { flex: 0 0 clamp(220px, 38vh, 340px); }
}
.chat__head {
  display: flex; align-items: center; justify-content: space-between;
  height: 40px; padding: 0 10px; border-bottom: 1px solid var(--line-soft);
}
/* 見出しに状態文言は出さない（UI.md。受付可否は登壇中に変わらない） */
.chat__title { margin: 0; font-size: var(--fs); font-weight: 700; }
/* 閉じる操作は閉じられる物の上に置く。普段は沈め、触れたときだけ出す */
.chat__close {
  border: 0; background: none; color: var(--text-mut); cursor: pointer;
  padding: 2px 4px; border-radius: var(--radius-sm); opacity: .35;
  display: inline-grid; place-items: center;
  transition: opacity .12s var(--ease);
}
.chat:hover .chat__close, .chat__close:focus-visible { opacity: 1; }

/* 「新着 N 件 ▼」を一覧の上に重ねるための入れ物。一覧の中に置くと、
   絶対配置でも中身と一緒にスクロールしてしまう */
.chat__log { position: relative; flex: 1; min-height: 0; display: flex; }
.chat__list {
  flex: 1; min-height: 0; overflow-y: auto;
  scrollbar-width: thin;
  display: flex; flex-direction: column; gap: 5px;
  padding: 8px 10px 10px;
}
.chat__list::-webkit-scrollbar { width: 8px; }
.chat__list::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--radius-pill); }
/* 1 行 = 名前 + 本文をインラインに詰める（縦を使うと十数件しか入らない） */
.chat__row { margin: 0; font-size: var(--fs); line-height: 1.5; overflow-wrap: anywhere; }
.chat__name { color: var(--text-mut); margin-right: 6px; }
.chat__row--host .chat__name { color: var(--accent); font-weight: 700; }
/* 登壇者の行は色とチップで区別する（FR-8.7） */
.chat__chip {
  display: inline-block; margin-right: 6px; padding: 0 6px;
  font-size: var(--fs-xs); line-height: 16px; border-radius: var(--radius-pill);
  background: var(--accent-weak); color: var(--accent);
}

/* 追従を外している間だけ出す（FR-8.5） */
.chat__pill {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 10px; height: 28px; padding: 0 12px; border: 0; cursor: pointer;
  border-radius: var(--radius-pill); background: var(--on-slide);
  color: var(--on-slide-text); font-size: var(--fs-sm); box-shadow: var(--shadow);
}
/* 参加名は一覧の外。行として流すと読んでいるうちに消える */
.chat__you {
  margin: 0; padding: 6px 10px; border-top: 1px solid var(--line-soft);
  color: var(--text-mut); font-size: var(--fs-xs);
}

/* 上に線を引かない。足元は「参加する手段」の 1 つの塊（UI.md「コメント欄の表示切替」「配色」） */
.composer { padding: 8px 10px 10px; }
.composer__input {
  width: 100%; max-height: 80px; resize: none; overflow-y: auto;
  padding: 8px 10px; font: inherit; color: var(--text);
  background: var(--surface-2); border: 1px solid transparent;
  border-radius: var(--radius-sm);
}
.composer__input:focus-visible { outline: none; border-color: var(--accent-line); }
.composer__input:disabled { cursor: not-allowed; opacity: .6; }
/* 残り 15 文字から（FR-8.12）。常時は色を付けない */
.composer__input--warn { border-color: var(--warn); }
.composer__foot {
  display: flex; align-items: center; gap: 8px; margin-top: 6px;
}
/* 残り時間は入力欄の下の注記。押しても何も起きない状態を放置しない（FR-8.4） */
.composer__note { flex: 1; color: var(--warn); font-size: var(--fs-xs); }
.composer__count {
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs); color: var(--text-mut);
}
.composer__count--warn { color: var(--warn); }

/* 隠している間の道具立て。開き直す口とリアクションを同じ塊に置く
   （復帰口を別の場所に置くと、閉じた人が戻し方を探すことになる） */
.stage__tools {
  position: absolute; right: calc(var(--gap) + 10px); bottom: calc(var(--gap) + 10px);
  display: flex; gap: 6px;
}
.tool {
  width: 40px; height: 32px; border: 0; cursor: pointer; opacity: .4;
  border-radius: var(--radius-sm); background: var(--on-slide);
  color: var(--on-slide-text);
  display: inline-grid; place-items: center;
  transition: opacity .12s var(--ease);
}
.tool:hover, .tool:focus-visible { opacity: 1; }

/* ---- リアクション（UI.md「リアクション」「時間」）---- */
.reactbar { display: flex; gap: 6px; padding: 8px 10px 0; }
.reactbtn {
  width: 40px; height: 32px; border: 0; cursor: pointer; font-size: 17px;
  border-radius: var(--radius-sm); background: var(--surface-2);
}
.reactbtn:disabled { opacity: .5; cursor: not-allowed; }
/* スライドの上では沈める。集中するために隠したのに濃い箱が居座っては本末転倒 */
.stage__tools .reactbar { padding: 0; }
.stage__tools .reactbtn {
  background: var(--on-slide); opacity: .4;
  transition: opacity .12s var(--ease);
}
.stage__tools .reactbtn:hover, .stage__tools .reactbtn:focus-visible { opacity: 1; }

/* 粒の層は画像の箱に重ねる（スライド枠だとレターボックスの余白に乗る） */
.reactions { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.reaction {
  position: absolute; bottom: -40px; left: var(--x);
  font-size: var(--size); line-height: 1;
  /* 動かすのは transform だけ。JS から毎フレーム座標を書かない */
  will-change: transform, opacity;
  animation: reaction-rise var(--secs) linear var(--delay) 1 both;
}
@keyframes reaction-rise {
  0% { transform: translate3d(0, 0, 0) scale(.7); opacity: 0; }
  12% { opacity: 1; }
  /* 揺れは行って戻る。一方向だと風に流されたように見える */
  50% { transform: translate3d(var(--drift), -39vh, 0) scale(1); }
  70% { opacity: 1; }
  100% { transform: translate3d(0, -78vh, 0) scale(1.15); opacity: 0; }
}

/* ---- 登壇画面（UI.md「ルーム画面のレイアウト」）---- */
/* 登壇はヘッダーに操作が並ぶ。スライドの下には何も置かない（UI.md「スライド枠」） */
.room--host .topbar { gap: 8px; }
/* 長い資料名でも右端の操作を画面外へ押し出さない。flex / grid の子は既定で
   中身の幅より縮まない（min-width: auto）ので、0 にして題名の省略（…）を効かせる */
.topbar, .livebar, .livebar__title { min-width: 0; }
/* 登壇画面の帯の左側。残りの幅を取るのはここだけ（width: 100% だと取り切って、
   隣のアイコンボタンが 32px より押し縮められる）。長い題名は省略する */
.livebar { display: flex; align-items: center; gap: 8px; flex: 1; }
.livebar__title {
  font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.livebar__page {
  font-family: var(--font-num); font-size: var(--fs-sm); color: var(--text-mut); white-space: nowrap;
}
/* 参加 URL は押すとコピー（FR-10.11）。幅が変わると連続で狙えないので文字は入れ替えない */
.copy-url {
  display: inline-flex; align-items: center; gap: 8px; min-width: 0;
  height: 32px; max-width: 340px; padding: 0 10px; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); color: var(--text);
}
.copy-url__text {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-num); font-size: var(--fs-sm);
}
.copy-url .icon { font-size: 16px; color: var(--text-mut); flex: none; }
/* 押した後 1.2 秒だけ面を変える（UI.md「具体値の一覧」） */
.copy-url--copied { background: var(--accent-weak); border-color: var(--accent-line); }

/* LIVE の印。点は LIVE バッジと同じ周期で明滅する（UI.md「時間」） */
.badge {
  display: inline-flex; align-items: center; flex: none; height: 22px; padding: 0 8px;
  border-radius: var(--radius-pill); font-size: var(--fs-xs); font-weight: 700; white-space: nowrap;
}
.badge--live { background: var(--live); color: #fff; }
.badge--live::before, .side__dot {
  content: ""; width: 6px; height: 6px; border-radius: 50%; animation: live-blink 1.8s infinite;
}
.badge--live::before { margin-right: 5px; background: #fff; }
@keyframes live-blink { 50% { opacity: .3; } }
.btn--lg { height: 40px; padding: 0 16px; }
.icon--sm { font-size: 15px; opacity: .8; }
.controls__error { color: var(--danger); font-size: var(--fs-sm); }

/* ---- 管理画面（UI.md「管理画面」「具体値の一覧」）---- */
/* 幅は画面いっぱい。サイドメニューを左端に付け、中央に寄せない（UI.md「共通の判断」） */
.admin { display: grid; grid-template-columns: 200px minmax(0, 1fr); min-height: 100dvh; }
/* サイドメニューは白を敷く。hover で沈めず、輪郭で持ち上げる */
.side {
  position: sticky; top: 0; height: 100dvh;
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 10px; background: var(--surface); border-right: 1px solid var(--line-soft);
}
.side__brand {
  display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 10px; margin-bottom: 10px;
  font-weight: 800; font-size: var(--fs-lg);
}
.side__brand .icon { color: var(--accent); }
.side__item {
  display: flex; align-items: center; gap: 10px; width: 100%; height: 38px; padding: 0 10px;
  border: 0; border-radius: var(--radius-sm); background: none; font: inherit;
  color: var(--text-mut); text-decoration: none; cursor: pointer; text-align: left;
}
.side__item:hover { color: var(--text); box-shadow: inset 0 0 0 1px var(--line); }
.side__item[aria-current="page"] { background: var(--accent-weak); color: var(--accent-ink); font-weight: 700; }
.side__item .icon { flex: none; }
.side__label { flex: 1; min-width: 0; white-space: nowrap; }
.side__count { font-family: var(--font-num); font-size: var(--fs-sm); color: var(--text-dim); }
.side__dot { flex: none; width: 8px; height: 8px; background: var(--live); box-shadow: 0 0 0 3px var(--live-weak); }
.side__foot { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.side__item--quiet { font-size: var(--fs); }

.admin__main { min-width: 0; padding: 28px 32px 48px; }
.page__title { margin: 0 0 20px; font-size: 20px; }
/* 節の間は 36px（UI.md「具体値」） */
.section + .section { margin-top: 36px; }
.section { display: grid; gap: 12px; }
.section__title { margin: 0; font-size: var(--fs-lg); }
.panel {
  padding: 20px; background: var(--surface);
  border: 1px solid var(--line-soft); border-radius: var(--radius);
}
/* LIVE が無いときは 1 行に畳む（FR-15.1） */
.panel--folded { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; padding: 12px 16px; color: var(--text-mut); }
.panel__link {
  margin-left: auto; display: inline-flex; align-items: center; gap: 4px;
  color: var(--accent); font-weight: 700; font-size: var(--fs); text-decoration: none;
}
.panel__link .icon { font-size: 16px; }
/* 開いている LIVE は --live の枠で目立たせる */
.mylive { display: grid; gap: 14px; border-color: transparent; box-shadow: inset 0 0 0 2px var(--live); }
.mylive__head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mylive__title { margin: 0; font-size: 20px; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mylive__join {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 20px;
  padding: 14px 16px; background: var(--surface-2); border-radius: var(--radius-sm);
}
.mylive__join .copy-url { background: var(--surface); }
.join-code { display: grid; }
.join-code__label { font-size: var(--fs-sm); color: var(--text-mut); }
.join-code__value {
  font-family: var(--font-num); font-size: 28px; font-weight: 700; letter-spacing: .12em; line-height: 1.2;
}
.mylive__actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
/* 終了は取り消せないので、右端に離して誤爆を減らす */
.mylive__end { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }

/* 登壇画面に LIVE が無いとき（終えた後・閉じ忘れたタブ） */
.no-live { min-height: 100dvh; display: grid; place-items: center; padding: var(--gap-lg); }
.no-live__card { display: grid; justify-items: center; gap: 10px; max-width: 420px; text-align: center; }
.no-live__card h1 { margin: 0; font-size: 20px; }
.no-live__card p { margin: 0 0 6px; color: var(--text-mut); }
.no-live__icon { font-size: 44px; color: var(--text-dim); }

.dialog__input {
  width: 100%; height: 38px; padding: 0 10px; font: inherit;
  background: var(--surface-2); border: 1px solid transparent;
  border-radius: var(--radius-sm);
}
.dialog__input:focus-visible { outline: none; border-color: var(--accent-line); }
.dialog__error { margin: 8px 0 0; color: var(--danger); font-size: var(--fs-sm); }

/* ---- 登壇画面の見せ方（UI.md「表示のオン / オフ」「参加用 QR」）---- */
/* 全画面ではヘッダーを隠し、上端に近づいたときだけ降ろす（FR-10.8 / UI.md「時間」） */
.topbar { transition: transform .16s var(--ease), opacity .16s var(--ease); }
.topbar--hidden {
  transform: translateY(-100%); opacity: 0; pointer-events: none;
}
/* 全画面ではヘッダーを重ねて、グリッドを 1 行にする。行を残すと、隠しても
   上端に 52px の死んだ帯ができる（UI.md「実装上の注意 / 全画面」） */
.room--full { grid-template-rows: 1fr; }
.room--full .topbar {
  position: absolute; left: 0; right: 0; top: 0; z-index: var(--z-chrome);
}

/* ---- スライド画面（UI.md「スライドのカードを伸ばさない」「具体値の一覧」）---- */
.page__count { margin-left: 8px; font-family: var(--font-num); font-size: var(--fs-md); font-weight: 400; color: var(--text-dim); }
.page__error { margin: 0 0 16px; color: var(--danger); font-size: var(--fs-sm); }
/* 追加欄。ドロップできることが見て分かるよう、大きく取る（FR-3.7） */
.drop {
  position: relative; display: grid; justify-items: center; gap: 4px; padding: 22px; cursor: pointer; text-align: center;
  background: var(--surface); border: 1.5px dashed var(--line); border-radius: var(--radius);
  transition: border-color .12s var(--ease), background .12s var(--ease);
}
.drop:hover, .drop--over { border-color: var(--accent); background: var(--accent-weak); }
.drop--busy { cursor: progress; }
.drop > * { pointer-events: none; } /* 子に入っても dragleave が来ないように */
/* 見た目だけ隠す。Tab で止まり、focus-within で枠が出る */
.drop input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.drop:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.drop__icon { font-size: 32px; color: var(--accent); }
.drop__main { font-weight: 700; }
.drop__sub { color: var(--text-mut); font-size: var(--fs-sm); }
.drop__error { color: var(--danger); font-size: var(--fs-sm); }

.cards {
  list-style: none; margin: 0; padding: 0; align-items: start;
  display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
}
/* hover で沈めない。白のまま輪郭と影で持ち上げる（UI.md「共通の判断」） */
.card {
  position: relative; background: var(--surface);
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  transition: box-shadow .12s var(--ease), border-color .12s var(--ease);
}
.card:hover { box-shadow: var(--shadow-sm); border-color: var(--line); }
/* 配信中の枠（UI.md「具体値の一覧」）。表紙の上に重ねる（inset の影は表紙の背景に隠れる） */
.card--live::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit; box-shadow: inset 0 0 0 2px var(--live);
}
.card__cover {
  aspect-ratio: 16 / 9; display: grid; place-items: center; overflow: hidden;
  background: var(--surface-2); border-bottom: 1px solid var(--line-soft);
  border-radius: var(--radius) var(--radius) 0 0;
}
.card__thumb { width: 100%; height: 100%; object-fit: contain; }
.card__placeholder { font-size: 32px; color: var(--text-dim); }
.card__body { display: grid; gap: 4px; padding: 12px 14px 14px; }
.card__title { margin: 0; font-size: var(--fs-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card__state { margin: 0; display: flex; align-items: center; gap: 6px; font-size: var(--fs); color: var(--text-mut); }
.card__state--error { color: var(--danger); }
.card__meta { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); }
.card__cta { margin-top: 8px; width: 100%; height: 36px; }
.btn--primary:disabled, .btn--primary:disabled:hover {
  background: var(--surface-3); border-color: var(--surface-3); color: var(--text-dim);
}
/* 変換の進捗バー（UI.md「具体値の一覧」: 4px） */
.progress { height: 4px; margin: 8px 0 4px; overflow: hidden; background: var(--surface-3); border-radius: 2px; }
.progress span { display: block; height: 100%; background: var(--accent); }
.dialog__label { display: grid; gap: 4px; font-size: var(--fs-sm); color: var(--text-mut); }

/* 表紙からプレビューを開く。ポインタとフォーカスのときだけ「プレビュー」を重ねる（タッチでは重ねない） */
.card__cover--preview { position: relative; width: 100%; padding: 0; border: 0; border-bottom: 1px solid var(--line-soft); font: inherit; cursor: zoom-in; }
.card__peek {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 6px;
  background: var(--scrim); color: #fff; font-weight: 700; font-size: var(--fs);
  opacity: 0; transition: opacity .12s var(--ease);
}
@media (hover: hover) {
  .card__cover--preview:hover .card__peek { opacity: 1; }
}
.card__cover--preview:focus-visible .card__peek { opacity: 1; }
/* 右上の「…」。表紙の上に置くので白い面を敷く（UI.md「キーボードとフォーカス」のメニューと同じ扱い） */
.card__more { position: absolute; top: 8px; right: 8px; }
.card__more-btn {
  width: 30px; height: 30px; display: grid; place-items: center; cursor: pointer;
  background: var(--surface); color: var(--text-mut);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm); box-shadow: var(--shadow-sm);
}
.card__more-btn:hover, .card__more-btn[aria-expanded="true"] { color: var(--text); border-color: var(--line); }
.card__menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: var(--z-menu);
  width: 200px; padding: 6px; display: grid; gap: 2px;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.card__menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 34px; padding: 0 8px;
  border: 0; border-radius: var(--radius-sm); background: none; font: inherit; color: var(--text);
  cursor: pointer; text-align: left;
}
.card__menu-item .icon { font-size: 18px; }
.card__menu-item:hover:not(:disabled) { background: var(--surface-2); }
.card__menu-item--danger { color: var(--danger); }
.card__menu-item:disabled { color: var(--text-dim); cursor: not-allowed; }

/* ---- プレビュー（UI.md「スライドのプレビュー」）---- */
.preview {
  position: fixed; inset: 0; z-index: var(--z-dialog);
  display: grid; grid-template-rows: 56px minmax(0, 1fr) 112px;
  background: #141418; color: var(--on-slide-text);
}
.preview__head { display: flex; align-items: center; gap: 14px; min-width: 0; padding: 0 16px 0 24px; }
.preview__title { margin: 0; min-width: 0; font-size: var(--fs-lg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.preview__page { font-family: var(--font-num); font-size: var(--fs); color: rgba(255, 255, 255, .7); white-space: nowrap; }
.preview__close, .preview__nav {
  display: grid; place-items: center; cursor: pointer; color: inherit;
  border: 1px solid var(--on-slide-line); background: rgba(255, 255, 255, .06);
}
.preview__close { margin-left: auto; width: 36px; height: 36px; border-radius: var(--radius-sm); flex: none; }
.preview__main {
  position: relative; min-height: 0; padding: 8px 16px;
  display: grid; grid-template-columns: 56px minmax(0, 1fr) 56px; align-items: center; gap: 12px;
}
/* 登壇画面の枠を暗い面の上に置く */
.preview__main .stage { background: transparent; }
.preview__error {
  position: absolute; inset: 0; margin: auto; height: fit-content; text-align: center; pointer-events: none;
  color: var(--on-slide-text); font-size: var(--fs-sm);
}
.preview__nav { width: 48px; height: 48px; border-radius: 50%; }
.preview__nav .icon { font-size: 28px; }
.preview__nav:hover:not(:disabled) { background: rgba(255, 255, 255, .14); }
.preview__nav:disabled { opacity: .3; cursor: default; }
.preview__thumbs {
  list-style: none; margin: 0; padding: 10px 24px 14px;
  display: flex; gap: 10px; overflow-x: auto; scrollbar-width: thin;
  border-top: 1px solid var(--on-slide-line);
}
.preview__thumb {
  position: relative; width: 136px; aspect-ratio: 16 / 9; flex: none; padding: 0; cursor: pointer;
  background: #fafaf8; border: 2px solid transparent; border-radius: 6px; overflow: hidden;
}
.preview__thumb img { width: 100%; height: 100%; object-fit: contain; }
.preview__thumb[aria-current="page"] { border-color: var(--accent); }
.preview__thumb > span {
  position: absolute; left: 4px; bottom: 4px; padding: 0 5px; border-radius: 3px;
  background: rgba(0, 0, 0, .6); color: #fff; font-family: var(--font-num); font-size: 10px;
}
/* 640px 未満: 送りのボタンをスライドの上に重ねる（横に並べるとスライドが小さくなりすぎる） */
@media (max-width: 639px) {
  .preview__main { grid-template-columns: minmax(0, 1fr); padding: 8px; }
  .preview__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 1; width: 40px; height: 40px; background: rgba(0, 0, 0, .45); }
  .preview__nav--prev { left: 12px; }
  .preview__nav--next { right: 12px; }
  .preview__thumbs { padding: 10px 12px 14px; }
}

.menu { position: relative; }
.menu__gear {
  width: 32px; height: 32px; border: 1px solid var(--line-soft); cursor: pointer;
  background: var(--surface-2); border-radius: var(--radius-sm);
  display: inline-grid; place-items: center; color: var(--text);
}
/* 開いている間は押した状態に見せる（閉じ忘れに気づけるように） */
.menu__gear[aria-expanded="true"] { background: var(--accent-weak); border-color: var(--accent-line); }
.menu__panel {
  position: absolute; right: 0; top: 40px; z-index: var(--z-menu);
  min-width: 258px; padding: 8px; display: flex; flex-direction: column; gap: 4px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
/* 配置と位置はコメントの子。字下げと縦罫で従属関係を示す（UI.md） */
.menu__sub {
  margin-left: 10px; padding-left: 10px; display: flex; flex-direction: column; gap: 4px;
  border-left: 2px solid var(--line-soft);
}

.switch, .menu__code {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 6px 8px; border: 0; cursor: pointer; font: inherit;
  background: none; border-radius: var(--radius-sm); color: var(--text);
}
/* 表示設定の参加コード。押すとコピーし、1.2 秒だけ面を変える（参加 URL と同じ） */
.menu__code:hover { background: var(--surface-2); }
.menu__code--copied, .menu__code--copied:hover { background: var(--accent-weak); }
.menu__code-value {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-num); font-weight: 700; letter-spacing: .12em;
}
.menu__code-value .icon { font-size: 16px; color: var(--text-mut); letter-spacing: 0; }
.switch:hover:not(:disabled) { background: var(--surface-2); }
.switch__box {
  width: 34px; height: 20px; border-radius: var(--radius-pill);
  background: var(--line); position: relative; transition: background .12s var(--ease);
}
.switch__box::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; transition: transform .12s var(--ease);
}
.switch[aria-checked="true"] .switch__box { background: var(--accent); }
.switch[aria-checked="true"] .switch__box::after { transform: translateX(14px); }

.toggle { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 8px; }
.toggle__label { color: var(--text-mut); font-size: var(--fs-sm); white-space: nowrap; }
.toggle__options {
  display: flex; gap: 3px; padding: 3px;
  background: var(--surface-2); border-radius: var(--radius-sm);
}
.toggle__option {
  height: 26px; padding: 0 10px; border: 0; cursor: pointer; font: inherit;
  white-space: nowrap;
  font-size: var(--fs-sm); background: none; color: var(--text-mut);
  border-radius: 4px;
}
.toggle__option[aria-pressed="true"] { background: var(--accent-weak); color: var(--accent); }
/* 押せないものは薄くするだけでなく disabled（NFR-A.7） */
.toggle__option:disabled, .switch:disabled { opacity: .45; cursor: not-allowed; }

/* 吹き出し（FR-10.2 / 10.3。値は UI.md「具体値の一覧」）。
   **件数ではなく高さで切る** —— 長文が 1 件来ただけで画面の半分を覆うのを防ぐ。
   古い側が上へ溢れて切れ、切れ目はマスクでぼかす */
.bubbles {
  position: absolute; left: 14px; right: 14px; bottom: 14px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  max-height: 152px; overflow: hidden; justify-content: flex-end;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 30px);
  mask-image: linear-gradient(to bottom, transparent 0, #000 30px);
}
.room--bubbles.room--right .bubbles { align-items: flex-end; }
.bubble {
  margin: 0; max-width: min(340px, 32%); padding: 5px 11px;
  font-size: var(--fs); line-height: 1.45; overflow-wrap: anywhere;
  background: var(--on-slide); color: var(--on-slide-text);
  border-radius: 14px; backdrop-filter: blur(6px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}
.bubble__name { color: rgba(255, 255, 255, .62); margin-right: 6px; }
/* 登壇者は黄（アクセントの紫は「自分」と混ざる。UI.md §配色） */
.bubble--host .bubble__name { color: #F5B93B; font-weight: 700; }

/* 参加 QR（FR-11。白地のまま出し、パネル側を暗くして浮かせる） */
.qr {
  position: fixed; z-index: var(--z-qr); padding: 8px; cursor: grab;
  display: flex; flex-direction: column; gap: 6px; touch-action: none;
  background: var(--on-slide-firm); border-radius: var(--radius);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .30);
  user-select: none;
}
.qr:active { cursor: grabbing; box-shadow: 0 20px 52px rgba(0, 0, 0, .42); }
.qr__code { display: block; width: 100%; height: auto; background: #fff; color: #000; padding: 8px; border-radius: var(--radius-sm); }
.qr__close .icon, .chat__close .icon { font-size: 18px; }
.qr__url {
  margin: 0; color: var(--on-slide-text); font-family: var(--font-num);
  font-size: var(--fs-xs); overflow-wrap: anywhere;
}
.qr__close {
  position: absolute; right: 6px; top: 6px; width: 24px; height: 24px;
  border: 0; cursor: pointer; border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .18); color: var(--on-slide-text);
  display: inline-grid; place-items: center;
}
/* 右下のつまみ（UI.md「具体値の一覧」） */
.qr__grip {
  position: absolute; right: 0; bottom: 0; width: 16px; height: 16px;
  cursor: nwse-resize; touch-action: none;
  background: linear-gradient(135deg, transparent 50%, rgba(255, 255, 255, .5) 50%);
  border-bottom-right-radius: var(--radius);
}

/* ---- ダイアログ（入室）---- */
.scrim {
  position: fixed; inset: 0; z-index: var(--z-dialog);
  display: grid; place-items: center; padding: var(--gap-lg);
  background: var(--scrim);
}
.scrim--modal { z-index: var(--z-modal); }
.dialog {
  width: min(400px, 100%); padding: var(--gap-lg);
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow);
}
.dialog__head { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 var(--gap); }
.dialog__title { flex: 1; margin: 0; font-size: 19px; font-weight: 700; }
.dialog__close {
  width: 32px; height: 32px; margin: -4px -6px 0 0; flex: none; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-sm); background: none; color: var(--text-mut); cursor: pointer;
}
.dialog__close:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.dialog__close:disabled { opacity: .4; cursor: default; }
.dialog__name { margin: 0; font-size: 20px; font-weight: 700; }
.dialog__note { margin: 6px 0 var(--gap-lg); color: var(--text-mut); font-size: var(--fs); }
/* 説明文を置かないダイアログで、入力欄と実行ボタンの間を空ける（説明文の下と同じ幅） */
.dialog__field { margin-bottom: var(--gap-lg); }
.dialog__actions { display: grid; }
.dialog__actions .btn { height: 40px; }

/* ---- トースト（UI.md「時間」: 2.6 秒）---- */
.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
  z-index: var(--z-toast); padding: 10px 16px;
  background: var(--on-slide); color: var(--on-slide-text);
  border-radius: var(--radius); box-shadow: var(--shadow);
}

@media (max-width: 1023px) {
  /* 参加 URL と登壇者名の文字を隠す（UI.md「ブレークポイント」） */
  .topbar__host, .livebar .copy-url__text { display: none; }
  /* 文字を隠したら、アイコンのボタンとして縮ませない */
  .livebar .copy-url { flex: none; }
}

/* 860px 未満: サイドメニューを上部の帯にして横スクロール（UI.md「ブレークポイント」） */
@media (max-width: 859px) {
  .admin { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; min-height: 0; }
  .side {
    position: sticky; top: 0; z-index: var(--z-topbar); height: auto;
    flex-direction: row; align-items: center; overflow-x: auto;
    padding: 6px 10px; border-right: 0; border-bottom: 1px solid var(--line-soft);
  }
  .side__brand { margin: 0 6px 0 0; padding: 0 4px; }
  .side__name { display: none; }
  .side__item { width: auto; flex: none; }
  .side__foot { margin: 0 0 0 auto; padding: 0; border: 0; }
  .side__item--quiet .side__label { display: none; }
  .admin__main { padding: 20px 16px 48px; }
}

/* 640px 未満: 自分の LIVE の操作を縦に積む。登壇画面の帯はページ番号を隠す（帯に収まらない） */
@media (max-width: 639px) {
  .livebar__page { display: none; }
  .mylive__actions { flex-direction: column; align-items: stretch; }
  .mylive__end { margin-left: 0; }
  .mylive__end .btn { flex: 1; }
  .mylive__join .copy-url { max-width: 100%; width: 100%; }
  .panel__link { margin-left: 0; }
}

/* ================= ページ一覧（登壇画面。FR-7.7） =================
   スライドの下端に重ねる。全面を覆うと投影からスライドが消え、観客に一覧が映る。
   トップバー（--z-topbar）より上、トースト（--z-toast）と QR（--z-qr）より下 ——
   QR は置いたまま話すもので、配信の失敗を一覧が隠してもいけない */
/* stagewrap はスライドの列。一覧の位置の基準になる（ドックの下端を覆わない） */
.stagewrap { position: relative; display: flex; flex: 1; min-width: 0; min-height: 0; }
.stagewrap > .stage { flex: 1; min-width: 0; }
.strip {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: var(--z-strip);
  background: var(--on-slide-firm); border-top: 1px solid var(--on-slide-line);
}
.strip__list {
  list-style: none; margin: 0; padding: 12px 14px 14px;
  display: flex; gap: 9px; overflow-x: auto; scrollbar-width: thin;
}
.strip__thumb {
  position: relative; width: 122px; aspect-ratio: 16 / 9; flex: none; padding: 0; cursor: pointer;
  background: #fafaf8; border: 2px solid transparent; border-radius: 4px; overflow: hidden;
}
.strip__thumb img { width: 100%; height: 100%; object-fit: contain; }
/* 配信中のページは枠、選択カーソルは外側の輪。色だけに頼らない（NFR-A.2） */
.strip__thumb[aria-current="page"] { border-color: var(--accent); }
.strip__thumb[aria-selected="true"] { box-shadow: 0 0 0 3px var(--accent-line); }
.strip__thumb > span {
  position: absolute; left: 4px; bottom: 4px; padding: 0 5px; border-radius: 3px;
  background: rgba(0, 0, 0, .6); color: #fff; font-family: var(--font-num); font-size: 10px;
}
