/* plive 管理ページ共通スタイル
 *
 * 管理は4ページに分かれている（admin.html＝ハブ / admin-users / admin-servers / admin-output）。
 * ページ毎に <style> を持つと同じ 200 行を4重に抱えることになるので、ここに集約する。
 * テーマ変数（--bg 等）は index.html / monitor.html のインライン定義と同じ値。
 * ※ FOUC 防止のテーマ適用スクリプトだけは各ページの <head> にインラインで置く（描画前に走らせる必要があるため）。
 */

:root{
  --bg:#07080F; --panel:#0E1018; --panel-2:#12141E; --surface:#161925;
  --line:rgba(255,255,255,.08); --line-2:rgba(255,255,255,.15);
  --text:#EEF1F8; --text-dim:#A2A9BC; --text-faint:#646B80;
  --accent:#FF2D55; --accent-2:#FF5E7A; --live:#27E0A1; --warn:#F7B955; --error:#FF5468;
  /* 停止（TERMINATED）専用の色。★他で使っていない青にする（2026-08-12・利用者の要望）。
     以前は「停止」も「未作成」も同じ灰で、一覧のどれが**起動すれば使える**のかが
     一目で分からなかった。意味は「正常だが今は止まっている＝起動すれば戻る」。
     未作成（NOT_FOUND）は灰のまま＝そこには何も無い、という別の意味を保つ。 */
  --idle:#5AA0FF;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --display:'Space Grotesk',var(--sans);
  --radius:14px;
  color-scheme:dark;
}
:root[data-theme="light"]{
  color-scheme:light;
  --bg:#F4F5FA; --panel:#FFFFFF; --panel-2:#FFFFFF; --surface:#FFFFFF;
  --line:rgba(13,16,24,.10); --line-2:rgba(13,16,24,.20);
  --text:#11141C; --text-dim:#535A6B; --text-faint:#878E9E;
  /* 明るい地では #5AA0FF は薄い。同じ青のまま濃度だけ上げる。 */
  --idle:#2C74D6;
}
*{box-sizing:border-box}
body{
  margin:0; min-height:100vh; font-family:var(--sans); font-size:15px; line-height:1.6; color:var(--text);
  -webkit-font-smoothing:antialiased;
  background:
    radial-gradient(900px 520px at 10% -12%, rgba(59,123,255,.10), transparent 60%),
    radial-gradient(900px 600px at 100% 0%, rgba(255,45,85,.08), transparent 55%),
    var(--bg);
  background-attachment:fixed;
}
.wrap{ max-width:1080px; margin:0 auto; padding:0 18px 48px; }
body[data-auth="pending"] .wrap{ visibility:hidden; }

.topbar{ display:flex; align-items:center; justify-content:space-between; gap:14px; padding:16px 0; border-bottom:1px solid var(--line); flex-wrap:wrap; }
.brand{ display:flex; align-items:center; gap:12px; text-decoration:none; color:inherit; }
.brand .logo{ width:36px; height:36px; flex:none; }
.brand-name{ font-family:var(--display); font-weight:700; letter-spacing:.04em; font-size:16px; }
.brand-name .accent{ background:linear-gradient(135deg,var(--accent),var(--accent-2)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.brand-sub{ font-family:var(--mono); font-size:9.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--text-faint); margin-top:2px; }
.brand-ver{ font-family:var(--mono); font-size:9px; color:var(--text-faint); opacity:.7; }
.brand-ver:empty{ display:none; }
.topbar-right{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.nav-link{ display:inline-flex; align-items:center; gap:7px; text-decoration:none; font-family:var(--mono); font-size:12px; font-weight:600;
  color:var(--text-dim); padding:8px 13px; border-radius:999px; border:1px solid var(--line-2); background:transparent;
  transition:color .15s, border-color .15s; }
.nav-link:hover{ color:var(--text); border-color:var(--text-dim); }
.nav-link svg{ width:14px; height:14px; }
.role-pill{ font-family:var(--mono); font-size:11px; letter-spacing:.12em; text-transform:uppercase; color:#fff; font-weight:600;
  padding:7px 13px; border-radius:999px; background:linear-gradient(135deg,var(--accent),var(--accent-2)); box-shadow:0 2px 10px rgba(255,45,85,.4); }
.theme-toggle{ display:inline-grid; place-items:center; width:38px; height:38px; flex:none; cursor:pointer; color:var(--text-dim);
  border-radius:999px; border:1px solid var(--line); background:var(--panel-2); transition:color .15s, border-color .15s; }
.theme-toggle:hover{ color:var(--text); border-color:var(--text-dim); }
.theme-toggle svg{ width:18px; height:18px; }
.theme-toggle .ico-moon{ display:none; }
:root[data-theme="light"] .theme-toggle .ico-sun{ display:none; }
:root[data-theme="light"] .theme-toggle .ico-moon{ display:block; }

h1{ font-family:var(--display); font-weight:700; font-size:23px; margin:34px 0 4px; letter-spacing:-.01em; }
.lede{ color:var(--text-dim); font-size:13.5px; margin:0 0 24px; }

/* 管理ページ間のタブ（現在のページを強調） */
.subnav{ display:flex; gap:8px; flex-wrap:wrap; margin:0 0 26px; }
.subnav a{ text-decoration:none; font-size:13px; font-weight:600; color:var(--text-dim);
  padding:8px 15px; border-radius:999px; border:1px solid var(--line-2); background:transparent;
  transition:color .15s, border-color .15s, background .15s; }
.subnav a:hover{ color:var(--text); border-color:var(--text-dim); }
.subnav a[aria-current="page"]{ color:#fff; border-color:transparent;
  background:linear-gradient(135deg,var(--accent),var(--accent-2)); box-shadow:0 2px 10px rgba(255,45,85,.32); }

.panel{ border-radius:var(--radius); border:1px solid var(--line); background:linear-gradient(180deg, var(--panel-2), var(--panel));
  padding:22px; margin-bottom:20px; }
.panel h2{ font-family:var(--display); font-size:16px; font-weight:700; margin:0 0 4px; }
.panel .hint{ color:var(--text-dim); font-size:12.5px; margin:0 0 18px; }
.panel.muted{ opacity:.62; }

/* ハブ（admin.html）のカード */
.menu{ display:grid; gap:14px; }
.card{ display:flex; align-items:center; gap:16px; padding:20px 22px; border-radius:var(--radius); text-decoration:none; color:inherit;
  border:1px solid var(--line); background:linear-gradient(180deg, var(--panel-2), var(--panel));
  transition:border-color .15s, transform .15s, box-shadow .2s; width:100%; text-align:left; font-family:var(--sans); font-size:15px; cursor:pointer; }
.card:hover{ border-color:var(--line-2); transform:translateY(-1px); box-shadow:0 10px 30px rgba(0,0,0,.28); }
.card .ico{ flex:none; display:grid; place-items:center; width:46px; height:46px; border-radius:12px;
  color:#3B7BFF; background:rgba(59,123,255,.10); border:1px solid rgba(59,123,255,.26); }
.card[data-kind="servers"] .ico{ color:var(--accent); background:rgba(255,45,85,.10); border-color:rgba(255,45,85,.24); }
.card[data-kind="output"] .ico{ color:var(--text-dim); background:var(--surface); border-color:var(--line); }
.card[data-kind="status"] .ico{ color:var(--live); background:rgba(39,224,161,.10); border-color:rgba(39,224,161,.24); }
.card[data-kind="overlay"] .ico{ color:var(--warn); background:rgba(247,185,85,.10); border-color:rgba(247,185,85,.26); }
.card .body{ flex:1; min-width:0; }
/* title/desc は span なので block 化しないと 1 行に並んでしまう */
.card .title{ display:block; font-family:var(--display); font-weight:700; font-size:16px; margin-bottom:2px; }
.card .desc{ display:block; color:var(--text-dim); font-size:13px; }
.card .arrow{ flex:none; color:var(--text-faint); }
.card:hover .arrow{ color:var(--text-dim); }
.card .badge{ margin-left:10px; font-family:var(--mono); font-size:10.5px; font-weight:600; letter-spacing:.04em;
  color:var(--warn); border:1px solid rgba(247,185,85,.4); border-radius:999px; padding:2px 9px; vertical-align:middle; white-space:nowrap; }

/* 追加フォーム */
.form-row{ display:flex; gap:10px; flex-wrap:wrap; align-items:flex-end; }
.field{ display:flex; flex-direction:column; gap:6px; }
.field label{ font-family:var(--mono); font-size:10.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-faint); }
input[type="email"], input[type="text"], select{
  font-family:var(--sans); font-size:14px; color:var(--text); background:var(--surface);
  border:1px solid var(--line-2); border-radius:10px; padding:10px 12px; min-width:0;
}
input[type="email"]{ width:290px; max-width:100%; font-family:var(--mono); font-size:13px; }
input[type="email"]:focus, input[type="text"]:focus, select:focus{ outline:2px solid rgba(59,123,255,.5); outline-offset:1px; }
.mono-in{ font-family:var(--mono); font-size:13px; width:100%; }
.check{ display:inline-flex; align-items:center; gap:8px; font-size:13.5px; color:var(--text-dim); padding-bottom:10px; }
.btn{ font-family:var(--sans); font-size:14px; font-weight:600; cursor:pointer; padding:10px 20px; border-radius:10px;
  border:1px solid transparent; background:linear-gradient(135deg,var(--accent),var(--accent-2)); color:#fff;
  transition:transform .15s, box-shadow .2s, opacity .15s; }
.btn:hover{ transform:translateY(-1px); box-shadow:0 8px 22px rgba(255,45,85,.32); }
.btn:disabled{ opacity:.5; cursor:not-allowed; transform:none; box-shadow:none; }
.btn-ghost{ background:transparent; color:var(--text-dim); border-color:var(--line-2); }
.btn-ghost:hover{ color:var(--text); border-color:var(--text-dim); box-shadow:none; }
.btn-danger{ background:transparent; color:var(--error); border-color:rgba(255,84,104,.4); }
.btn-danger:hover{ background:rgba(255,84,104,.1); box-shadow:none; }
.btn-sm{ font-size:12.5px; padding:7px 12px; border-radius:9px; }

/* 発行したゲスト閲覧リンク（D-5／P25）。★平文が出るのはここだけ・1回だけなので、
 * 見落とさない見た目にして、閉じるまで残す（コピーし損ねたら再発行しかない）。 */
.issued{ margin-top:14px; padding:14px 16px; border-radius:12px;
  background:rgba(39,224,161,.08); border:1px solid rgba(39,224,161,.36); }
.issued[hidden]{ display:none; }
.issued-head{ display:flex; align-items:center; gap:12px; justify-content:space-between; margin-bottom:10px; }
.issued-head b{ color:var(--live); font-size:13.5px; }
.issued-row{ display:flex; gap:8px; align-items:center; }
.issued-row input{ flex:1; }

/* メッセージ */
.msg{ display:none; margin-top:14px; padding:11px 14px; border-radius:10px; font-size:13.5px; }
.msg[data-kind="error"]{ display:block; background:rgba(255,84,104,.1); border:1px solid rgba(255,84,104,.34); color:var(--text); }
.msg[data-kind="ok"]{ display:block; background:rgba(39,224,161,.1); border:1px solid rgba(39,224,161,.32); color:var(--text); }

/* 制御面との接続が切れている間の共通バナー（全管理ページで同じ場所・同じ文言）。
   ★出ている間は画面の値が古いので、パネル全体を薄くして「今の値ではない」と分かるようにする。 */
.connbar{ margin-top:14px; padding:11px 14px; border-radius:10px; font-size:13.5px; color:var(--text);
  background:rgba(247,185,85,.1); border:1px solid rgba(247,185,85,.4); }
.connbar[hidden]{ display:none; }
.connbar b{ color:var(--warn); }
body[data-conn="lost"] .card{ opacity:.62; }
body[data-conn="lost"] .connbar{ opacity:1; }

/* 直近のジョブ結果（起動に失敗した理由など）。行のそばに残す＝ログ窓を閉じても消えない。 */
.jobnote{ margin-top:6px; font-size:12px; line-height:1.5; color:var(--text-dim); }
.jobnote[data-tone="error"] b{ color:var(--error); }

/* ヘッダーの全体ヘルス。どのページからでも1手でサーバー状態ページへ行ける。 */
.health-pill{ display:inline-flex; align-items:center; gap:8px; text-decoration:none;
  font-family:var(--mono); font-size:11.5px; color:var(--text-dim);
  padding:7px 13px; border-radius:999px; border:1px solid var(--line-2); background:transparent;
  transition:color .15s, border-color .15s; }
.health-pill:hover{ color:var(--text); border-color:var(--text-dim); }
.health-pill .dot{ width:8px; height:8px; border-radius:50%; flex:none; background:var(--text-faint); }
.health-pill[data-s="ok"] .dot{ background:var(--live); box-shadow:0 0 8px var(--live); }
.health-pill[data-s="bad"]{ color:var(--error); border-color:rgba(255,84,104,.45); }
.health-pill[data-s="bad"] .dot{ background:var(--error); box-shadow:0 0 8px var(--error); animation:pulse 1s infinite; }

/* 色の意味の凡例（全ページ共通）。緑=正常 / 黄=遷移中 / 赤=要対応 / 青=停止 / 灰=未作成・未設定 */
.legend{ display:flex; flex-wrap:wrap; gap:8px 16px; margin-top:10px;
  font-family:var(--mono); font-size:11px; color:var(--text-faint); }
.legend .lg{ display:inline-flex; align-items:center; gap:7px; }
.legend .dot{ width:8px; height:8px; border-radius:50%; flex:none; background:var(--text-faint); }
.legend .lg[data-s="ok"] .dot{ background:var(--live); }
.legend .lg[data-s="busy"] .dot{ background:var(--warn); }
.legend .lg[data-s="bad"] .dot{ background:var(--error); }
.legend .lg[data-s="idle"] .dot{ background:var(--idle); }

/* 表 */
.table-scroll{ overflow-x:auto; margin:0 -6px; padding:0 6px; }
table{ width:100%; border-collapse:collapse; font-size:13.5px; min-width:640px; }
th, td{ text-align:left; padding:11px 10px; border-bottom:1px solid var(--line); vertical-align:middle; }
th{ font-family:var(--mono); font-size:10.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-faint); font-weight:600;
  border-bottom-color:var(--line-2); white-space:nowrap; }
td.email, td.mono{ font-family:var(--mono); font-size:12.5px; word-break:break-all; }
td.actions{ text-align:right; white-space:nowrap; }
/* 「あなた」バッジはメール列だけ。登録者列は td.mono にして巻き添えを防ぐ。 */
tr[data-self="1"] td.email::after{ content:'あなた'; margin-left:8px; font-family:var(--sans); font-size:10.5px; font-weight:600;
  color:var(--text-faint); border:1px solid var(--line-2); border-radius:999px; padding:1px 7px; }
.tag{ display:inline-block; font-family:var(--mono); font-size:10.5px; letter-spacing:.06em; padding:3px 9px; border-radius:999px;
  border:1px solid var(--line-2); color:var(--text-dim); }
.tag[data-status="active"]{ color:var(--live); border-color:rgba(39,224,161,.4); }
.tag[data-status="invited"]{ color:var(--warn); border-color:rgba(247,185,85,.4); }
select.role-sel{ padding:6px 10px; font-size:12.5px; border-radius:9px; }
.empty{ color:var(--text-faint); font-family:var(--mono); font-size:12.5px; padding:28px 4px; text-align:center; }

/* LiveKit サーバー（VM）管理 */
.srv-state{ display:inline-flex; align-items:center; gap:8px; font-family:var(--mono); font-size:12px; }
.srv-state .dot{ width:9px; height:9px; border-radius:50%; background:var(--text-faint); flex:none; }
.srv-state[data-s="RUNNING"]{ color:var(--live); } .srv-state[data-s="RUNNING"] .dot{ background:var(--live); box-shadow:0 0 8px var(--live); }
/* ★停止は青、未作成は灰（2026-08-12）。同じ灰だと「起動すれば使える」ものと
   「まだ何も無い」ものが見分けられず、一覧から次の操作を判断できなかった。 */
.srv-state[data-s="TERMINATED"]{ color:var(--idle); } .srv-state[data-s="TERMINATED"] .dot{ background:var(--idle); }
.srv-state[data-s="NOT_FOUND"]{ color:var(--text-faint); }
.srv-state[data-s="PROVISIONING"],.srv-state[data-s="STAGING"],.srv-state[data-s="STOPPING"]{ color:var(--warn); }
.srv-state[data-s="PROVISIONING"] .dot,.srv-state[data-s="STAGING"] .dot,.srv-state[data-s="STOPPING"] .dot{ background:var(--warn); animation:pulse 1s infinite; }
@keyframes pulse{ 0%,100%{opacity:1} 50%{opacity:.35} }
.cpu-bar{ display:inline-block; width:90px; height:8px; border-radius:999px; background:var(--surface); border:1px solid var(--line); overflow:hidden; vertical-align:middle; }
.cpu-bar > i{ display:block; height:100%; background:linear-gradient(90deg,var(--live),var(--warn)); width:0; }
.cpu-txt{ font-family:var(--mono); font-size:11.5px; color:var(--text-dim); margin-left:8px; }
/* サーバー表の「タイプ」の下に出す、この台に入れている本数（と実測の飽和）。
   ★定格を超えているときだけ赤くする。常に赤いと「要対応」の意味が薄れる（表示の5原則）。 */
.srv-cap{ margin-left:0; }
.srv-cap[data-warn]{ color:var(--error); }
td.srv-actions{ text-align:right; white-space:nowrap; }
td.srv-actions .btn{ margin-left:6px; }

/* 操作ログウィンドウ（作成中／タイプ切替中／完了 などをポーリングで表示） */
.logwin{ display:none; margin-top:16px; border:1px solid var(--line-2); border-radius:12px; overflow:hidden; background:var(--bg); }
.logwin[data-open="1"]{ display:block; }
.logwin .head{ display:flex; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line);
  background:var(--panel-2); font-family:var(--mono); font-size:12px; color:var(--text-dim); }
.logwin .head .spin{ width:12px; height:12px; border-radius:50%; border:2px solid var(--line-2); border-top-color:var(--accent);
  animation:spin .8s linear infinite; flex:none; }
.logwin[data-state="done"] .head .spin{ border-top-color:var(--live); animation:none; border-color:var(--live); }
.logwin[data-state="error"] .head .spin{ border-top-color:var(--error); animation:none; border-color:var(--error); }
@keyframes spin{ to{ transform:rotate(360deg) } }
.logwin .head .ttl{ flex:1; color:var(--text); font-weight:600; }
.logwin .head .x{ cursor:pointer; color:var(--text-faint); border:none; background:none; font-size:16px; padding:2px 6px; }
.logwin .head .x:hover{ color:var(--text); }
.logwin .body{ max-height:220px; overflow-y:auto; padding:12px 14px; font-family:var(--mono); font-size:12px; line-height:1.9; }
.logwin .body .line{ display:flex; gap:10px; }
.logwin .body .line .ts{ color:var(--text-faint); flex:none; }
.logwin .body .line .tx{ color:var(--text-dim); white-space:pre-wrap; word-break:break-word; }
.logwin .body .line.ok .tx{ color:var(--live); }
.logwin .body .line.err .tx{ color:var(--error); }

/* SRT 入力 / テストソース パネル */
.toolbar{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:16px; }
.toolbar .spacer{ flex:1 1 auto; }
.dirty{ font-family:var(--mono); font-size:11.5px; color:var(--warn); }
.gen-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; padding:12px 14px; margin-top:6px;
  border:1px solid var(--line); border-radius:12px; background:var(--surface); }
.gen-head .spacer{ flex:1 1 auto; }
.gen-head .btn{ margin-left:6px; }
/* 「今どの段階か」を1行で説明する。VM の状態（稼働中）だけでは
   「起動したのに映像が来ない」の理由が分からないため、次にすることまで書く。 */
.gen-hint{ display:flex; align-items:flex-start; gap:8px; margin-top:8px; padding:0 4px;
  font-size:12.5px; line-height:1.7; color:var(--text-dim); }
.gen-hint:empty{ display:none; }
.gen-hint::before{ content:''; flex:none; width:6px; height:6px; margin-top:8px; border-radius:50%;
  background:var(--text-faint); }
.gen-hint[data-tone="busy"]{ color:var(--warn); }
.gen-hint[data-tone="busy"]::before{ background:var(--warn); animation:pulse 1.2s infinite; }
.gen-hint[data-tone="live"]{ color:var(--live); }
.gen-hint[data-tone="live"]::before{ background:var(--live); box-shadow:0 0 8px var(--live); }
.gen-hint[data-tone="error"]{ color:var(--error); }
.gen-hint[data-tone="error"]::before{ background:var(--error); }

/* --- 段階表示（どこで止まっているかを一目で分かるようにする）-----------------
   映像が出ない時、利用者は「どの工程まで進んでいるのか」が分からず迷子になる。
   送信VM → 送信プログラム → テスト映像 → SRT 送出 → 受信 の各段を並べ、
   ✓ 済み / ● 進行中 / ✕ ここで止まっている を色で示す。 */
.flow{ display:flex; align-items:stretch; flex-wrap:wrap; gap:0; margin:14px 0 4px;
  border:1px solid var(--line); border-radius:10px; overflow:hidden; background:var(--panel-2); }
.flow-step{ flex:1 1 130px; min-width:130px; padding:9px 12px; border-right:1px solid var(--line); }
.flow-step:last-child{ border-right:0; }
.flow-step .k{ display:flex; align-items:center; gap:6px; font-family:var(--mono); font-size:10.5px;
  letter-spacing:.06em; color:var(--text-faint); text-transform:uppercase; }
.flow-step .k::before{ content:''; flex:none; width:7px; height:7px; border-radius:50%; background:var(--text-faint); }
.flow-step .v{ margin-top:3px; font-size:12.5px; font-weight:600; color:var(--text-dim); }
.flow-step[data-s="ok"] .k::before{ background:var(--live); box-shadow:0 0 7px var(--live); }
.flow-step[data-s="ok"] .v{ color:var(--live); }
.flow-step[data-s="busy"] .k::before{ background:var(--warn); animation:pulse 1.2s infinite; }
.flow-step[data-s="busy"] .v{ color:var(--warn); }
/* ★止まっている段だけを赤で強調する（それ以降は淡いまま＝視線がここに集まる） */
.flow-step[data-s="stop"]{ background:rgba(255,84,104,.08); }
.flow-step[data-s="stop"] .k::before{ background:var(--error); }
.flow-step[data-s="stop"] .v{ color:var(--error); }
.flow-step[data-s="idle"] .v{ color:var(--text-faint); }
/* 次の一手。ここに「押すべきボタン」を1行で書く。 */
.flow-next{ margin:8px 0 0; padding:10px 13px; border-radius:9px; font-size:12.5px; line-height:1.65;
  background:rgba(247,185,85,.10); border:1px solid rgba(247,185,85,.32); color:var(--text); }
.flow-next[hidden]{ display:none; }
.flow-next b{ color:var(--warn); }
/* 打ち上げ（P14）の状態チップ。ing-st と同じ見た目を使い回す。 */
.ing-st[data-s="STREAMING"]{ color:var(--live); border-color:rgba(39,224,161,.4); }
.ing-st[data-s="STARTING"]{ color:var(--warn); border-color:rgba(247,185,85,.4); }
.ing-st[data-s="STOPPED"]{ color:var(--text-dim); }
.ing-st[data-s="FAILED"]{ color:var(--error); border-color:rgba(255,90,110,.4); }
.clip-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:10px; }
.tag[data-ready="1"]{ color:var(--live); border-color:rgba(39,224,161,.4); }
.tag[data-ready="0"]{ color:var(--warn); border-color:rgba(247,185,85,.4); }
/* Ingress の実状態（LiveKit 上の state.status） */
.ing-st{ font-family:var(--mono); font-size:11px; letter-spacing:.04em; padding:3px 8px; border-radius:999px;
  border:1px solid var(--line-2); color:var(--text-dim); white-space:nowrap; }
.ing-st[data-s="ENDPOINT_PUBLISHING"]{ color:var(--live); border-color:rgba(39,224,161,.4); }
.ing-st[data-s="ENDPOINT_BUFFERING"]{ color:var(--warn); border-color:rgba(247,185,85,.4); }
.ing-st[data-s="ENDPOINT_ERROR"]{ color:var(--error); border-color:rgba(255,84,104,.4); }
/* 入力そのものの実測（解像度 / fps / ビットレート・D-3②）。判定ではなく確認用の数字なので
 * 小さく添えるだけ。取れないときは空＝行の高さも変わらない。 */
.ing-in{ margin-top:4px; font-family:var(--mono); font-size:10.5px; color:var(--text-faint);
  font-variant-numeric:tabular-nums; white-space:nowrap; }
.ing-in:empty{ display:none; }
td.tight{ padding:7px 8px; }
td.tight input[type="text"], td.tight select{ padding:7px 9px; font-size:13px; border-radius:8px; }
/* JSON ビュー（読むだけ）。ダウンロードして別のアプリで開かなくても、
 * 「いま何が保存されているか」と「各項目が何を意味するか」をその場で確かめられるようにする。
 * 編集は上の表で行う＝ここはテキストを選択してコピーできるだけの表示面。 */
.jsonview{ display:none; margin-top:16px; border:1px solid var(--line-2); border-radius:12px; overflow:hidden; background:var(--bg); }
.jsonview[data-open="1"]{ display:block; }
.jsonview .head{ display:flex; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line); background:var(--surface); }
.jsonview .head .ttl{ flex:1; color:var(--text); font-weight:600; font-size:13.5px; }
.jsonview .head .x{ cursor:pointer; color:var(--text-faint); border:none; background:none; font-size:16px; padding:2px 6px; }
.jsonview .head .x:hover{ color:var(--text); }
.jsonview pre{ margin:0; max-height:340px; overflow:auto; padding:12px 14px;
  font-family:var(--mono); font-size:12px; line-height:1.75; color:var(--text-dim); }
.jsonview .keys{ border-top:1px solid var(--line); padding:12px 14px 14px; background:var(--panel); }
.jsonview .keys h3{ margin:0 0 10px; font-family:var(--mono); font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-faint); font-weight:600; }
.jsonview .keys dl{ display:grid; grid-template-columns:auto 1fr; gap:7px 14px; margin:0; font-size:12.5px; line-height:1.65; }
.jsonview .keys dt{ font-family:var(--mono); font-size:12px; color:var(--text); white-space:nowrap; }
.jsonview .keys dd{ margin:0; color:var(--text-dim); }
.jsonview .keys dd b{ color:var(--text); }
@media (max-width:640px){
  .jsonview .keys dl{ grid-template-columns:1fr; gap:2px; }
  .jsonview .keys dd{ margin:0 0 8px; }
}
.hint code, .jsonview .keys code{ font-family:var(--mono); font-size:11.5px; padding:1px 5px; border-radius:5px;
  background:var(--surface); border:1px solid var(--line); color:var(--text-dim); }
.copy-cell{ display:flex; align-items:center; gap:8px; }
.copy-cell code{ font-family:var(--mono); font-size:12px; color:var(--text-dim); word-break:break-all; flex:1; }
.icon-btn{ flex:none; cursor:pointer; border:1px solid var(--line-2); background:transparent; color:var(--text-dim);
  border-radius:8px; padding:4px 8px; font-size:11px; font-family:var(--mono); }
.icon-btn:hover{ color:var(--text); border-color:var(--text-dim); }

/* ===== サーバー状態ページ（/admin-status.html・読むだけ）===================
 * 操作ボタンは置かない。ここは「いま何がどうなっているか」を一目で見る面。
 * 表ではなくカードにするのは、VM ごとに見せたい項目の数がまったく違うため
 * （LiveKit は SRT 一覧、送信VMはクリップと listener、配信VMは systemd ユニット）。 */
.stat-row{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin:0 0 22px; }
.stat{ padding:14px 16px; border-radius:12px; border:1px solid var(--line); background:var(--panel); }
.stat .k{ font-family:var(--mono); font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:var(--text-faint); }
.stat .v{ font-family:var(--display); font-size:26px; font-weight:700; line-height:1.15; margin-top:6px; }
.stat .v small{ font-size:13px; font-weight:600; color:var(--text-dim); margin-left:3px; }
.stat .s{ font-size:11.5px; color:var(--text-dim); margin-top:3px; }
.stat[data-tone="live"] .v{ color:var(--live); }
.stat[data-tone="warn"] .v{ color:var(--warn); }
.stat[data-tone="error"] .v{ color:var(--error); }
.stat[data-tone="off"] .v{ color:var(--text-faint); }

.cards{ display:grid; grid-template-columns:repeat(auto-fill,minmax(330px,1fr)); gap:14px; }
/* 1枚しか無いカード（制御VM／送信VM／配信VM）は横幅いっぱいに広げ、中身を段組みにする。
   1列のまま置くと右半分が丸ごと空いて、情報量の割に読みづらい。 */
.cards[data-wide="1"]{ grid-template-columns:1fr; }
.vmcard .grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:10px 22px; align-items:start; }
/* SRT の一覧だけは段に押し込めない（URL が切れて読めなくなる）。 */
.vmcard .grid > .sec.full{ grid-column:1 / -1; }
.vmcard{ border-radius:12px; border:1px solid var(--line); background:var(--panel);
  padding:14px 16px 15px; display:flex; flex-direction:column; gap:10px; }
.vmcard[data-s="RUNNING"]{ border-color:rgba(39,224,161,.28); }
/* 停止は「起動すれば戻る」＝薄くするだけでなく青で示す（未作成とは意味が違う）。 */
.vmcard[data-s="TERMINATED"]{ border-color:rgba(90,160,255,.30); opacity:.85; }
.vmcard[data-s="NOT_FOUND"]{ opacity:.72; }
.vmcard .hd{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.vmcard .hd .nm{ font-family:var(--display); font-weight:700; font-size:15px; }
.vmcard .hd .sub{ font-family:var(--mono); font-size:10.5px; color:var(--text-faint); }
.vmcard .hd .sp{ flex:1 1 auto; }
.kv{ display:grid; grid-template-columns:auto 1fr; gap:4px 12px; font-size:12.5px; }
.kv dt{ font-family:var(--mono); font-size:10.5px; letter-spacing:.06em; color:var(--text-faint); white-space:nowrap; padding-top:1px; }
.kv dd{ margin:0; color:var(--text-dim); word-break:break-all; }
.kv dd.mono{ font-family:var(--mono); font-size:11.5px; }
.sec{ border-top:1px solid var(--line); padding-top:9px; }
.sec > .t{ font-family:var(--mono); font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--text-faint); margin-bottom:6px; display:flex; gap:8px; align-items:center; }
.sec > .t .n{ color:var(--text-dim); }
.chips{ display:flex; gap:6px; flex-wrap:wrap; }
.chip{ font-family:var(--mono); font-size:10.5px; padding:3px 8px; border-radius:999px;
  border:1px solid var(--line-2); color:var(--text-dim); white-space:nowrap; }
.chip[data-s="ok"]{ color:var(--live); border-color:rgba(39,224,161,.4); }
.chip[data-s="warn"]{ color:var(--warn); border-color:rgba(247,185,85,.4); }
.chip[data-s="bad"]{ color:var(--error); border-color:rgba(255,84,104,.4); }
.srt{ display:flex; flex-direction:column; gap:6px; }
.srt .row{ display:flex; align-items:center; gap:8px; font-size:12px; }
.srt .row .dot{ width:7px; height:7px; border-radius:50%; background:var(--text-faint); flex:none; }
.srt .row[data-s="ENDPOINT_PUBLISHING"] .dot{ background:var(--live); box-shadow:0 0 7px var(--live); }
.srt .row[data-s="ENDPOINT_BUFFERING"] .dot{ background:var(--warn); animation:pulse 1.2s infinite; }
.srt .row[data-s="ENDPOINT_ERROR"] .dot{ background:var(--error); }
.srt .row .nm{ flex:none; max-width:38%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.srt .row .u{ flex:1 1 auto; font-family:var(--mono); font-size:10.5px; color:var(--text-faint);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.srt .row .st{ flex:none; font-family:var(--mono); font-size:10.5px; color:var(--text-dim); }
.srt .row[data-off="1"]{ opacity:.5; }
.srt .none{ font-family:var(--mono); font-size:11px; color:var(--text-faint); }
/* カードの CPU 欄。描画は renderCpuInto（サーバー管理の表と同じ実装）で、
   ここではカード幅いっぱいに伸ばす指定だけを足す。★色や値の出し方はここに書かない。 */
.cpu-row{ display:flex; align-items:center; margin-top:6px; }
.cpu-row .cpu-bar{ flex:1 1 auto; width:auto; min-width:60px; height:8px; }
.cpu-row .cpu-txt{ flex:none; min-width:50px; text-align:right; }
/* データの流れ（送信 → 受信 → 出口）。台数と本数だけの簡易図。 */
.flowmap{ display:flex; align-items:stretch; gap:0; flex-wrap:wrap; margin:0 0 22px;
  border:1px solid var(--line); border-radius:12px; background:var(--panel); overflow:hidden; }
.flowmap .node{ flex:1 1 160px; min-width:150px; padding:12px 14px; border-right:1px solid var(--line); }
.flowmap .node:last-child{ border-right:0; }
.flowmap .node .k{ font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-faint); }
.flowmap .node .v{ font-size:14px; font-weight:600; margin-top:4px; }
.flowmap .node .s{ font-size:11.5px; color:var(--text-dim); margin-top:2px; }
.flowmap .node[data-s="live"] .v{ color:var(--live); }
.flowmap .node[data-s="off"] .v{ color:var(--text-faint); }
.asof{ font-family:var(--mono); font-size:11px; color:var(--text-faint); margin:18px 0 0; }

footer{ margin-top:34px; padding-top:16px; border-top:1px solid var(--line); font-family:var(--mono); font-size:11px;
  letter-spacing:.06em; color:var(--text-faint); }
@media (prefers-reduced-motion: reduce){ *{ animation:none !important; transition:none !important } }

/* --- 開発中モード（アクセス制限・2026-08-06）--------------------------------
   ★見落とすと「誰も入れない」だけが残るので、ON のときは面で目立たせる。 */
#maint-panel[data-on="1"]{ border-color:rgba(247,185,85,.55);
  background:repeating-linear-gradient(135deg, rgba(247,185,85,.10), rgba(247,185,85,.10) 14px,
    rgba(247,185,85,.04) 14px, rgba(247,185,85,.04) 28px); }
.maint-row{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:6px; }
.maint-state{ font-family:var(--mono); font-size:13px; font-weight:700; padding:7px 14px;
  border-radius:999px; border:1px solid var(--line-2); color:var(--text-dim); }
#maint-panel[data-on="1"] .maint-state{ color:#fde68a; border-color:rgba(247,185,85,.6);
  background:rgba(247,185,85,.14); }
