:root{
  --bg:#0f1420;
  --sidebar:#141b2d;
  --sidebar-hover:#1e2740;
  --sidebar-active:#28345a;
  --panel:#182238;
  --panel-2:#1d2942;
  --border:#2a3550;
  /* cmd_0324: 殿の実機確認(2026-08-19 20:40)「黒色のボタン(『閉じる』『表示列』
     『取込再開』など)の枠線を鮮明にしてほしい」是正。旧--border(#2a3550)は
     .btn.secondaryの背景--panel-2(#1d2942)に対しコントラスト比1.190しかなく、
     縁がほぼ溶けて見えない実測値だった(test/style_black_button_border_cmd0324.test.jsの
     [border-strong.2]が是正前値として実測・裏付け)。--panel-2上で目標3.0:1
     (WCAG 2.1 SC1.4.11非テキストコントラスト、UIコンポーネントの境界に推奨される値)
     以上を確保しつつ、docs/ui_design_guidelines.md「目を引かせようとするな」に反し
     大きく振らぬよう既存の配色(--sidebar-active系の青系統)から選んだ
     (実測3.141:1、--bg上では3.986:1)。.btn.secondary専用の変数とし、他41箇所の
     --border利用(パネル区切り線・入力欄等)には影響させない。 */
  --border-strong:#5c74ac;
  --text:#e8ecf5;
  /* 殿の可読性補正(2026-08-11): 旧#8b96b3は最も明るい実背景(--panel-2 #1d2942、thead
     sticky・.import-card等の明示背景)に対しコントラスト比4.911止まりで、目標7:1に
     届いていなかった。同じ色相・彩度のまま明度のみ引き上げ、--panel-2上で7.399
     (最も暗い--bg上では9.388)まで確保する(全実背景中で--panel-2が最も明るく、
     ここを満たせば他は自動的に満たす——暗い地ほど明るい文字とのコントラストは
     上がるため。test/style_text_dim_contrast_cmd0163.test.jsが全実使用箇所を機械
     検査する)。オペレーター名(.import-card-title、--text継承)・自動認識札
     (.import-tag.ok、--accent)は本変数を参照しておらず無変更。 */
  /* cmd_0325: 薄色文字の全51実使用箇所（ナビ・一覧・集計・詳細・取込確認）を
     共通トークンで統一。個別の意味色(--text/--accent/--danger)と、非活性ボタンの
     意図的なopacityは対象外。暗い実背景(--bg〜--panel-2)すべてで7:1以上を維持する。 */
  --text-dim:#d8d8d8;
  --accent:#4fd1c5;
  --accent-2:#f2c14e;
  --danger:#ef6f6f;
  --rar1:#dcdde0;
  --rar2:#9fd13a;
  --rar3:#6fb8ef;
  --rar4:#c69bef;
  --rar5:#f2c14e;
  --rar6:#c1590f;
  /* cmd_0181 FIND-2是正: 本ページはcolor-schemeを宣言していなかったため、モバイル
     ブラウザは既定でlight向けのネイティブ描画をform要素(select等)へ適用しようとする。
     select.inline-edit-input(cmd_0156導入)はborder/backgroundを明示指定しているが、
     ネイティブ側の想定(light)と実際の見た目(dark)が食い違う環境では、境界線や
     ドロップダウン矢印がブラウザ側のテーマ処理で潰れ、素のテキスト入力欄のように
     見えてしまう(PC実Chromeでは再現しないため、ヘッドレスChrome+viewport変更だけの
     実測では検知不能——ネイティブfont control描画はOSレベルのテーマ処理に依るため)。
     dark固定を宣言し、ネイティブform要素の描画自体をdark想定へ揃える。 */
  color-scheme:dark;
}
*{box-sizing:border-box;}
html,body{
  margin:0;padding:0;height:100%;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Hiragino Kaku Gothic ProN","Yu Gothic",Meiryo,sans-serif;
  background:var(--bg);color:var(--text);
}
a{color:inherit;text-decoration:none;}
button{font-family:inherit;}

.app{display:flex;min-height:100vh;}

/* ---------- Sidebar ---------- */
.sidebar{
  width:230px;flex-shrink:0;
  background:var(--sidebar);
  border-right:1px solid var(--border);
  display:flex;flex-direction:column;
  position:sticky;top:0;height:100vh;
  /* cmd_0169: 100vhはモバイルブラウザのURL/下部バーが畳まれた「最大」高さで
     固定され、実際にバーが表示中の可視領域より大きくなる(実測: 390px幅で
     .sidebar自体のbottomが可視領域外に出ていた)。dvh対応ブラウザではcascadeで
     100dvh(動的可視領域)が上書きし、バー表示中でも.sidebar全体が画面外へ
     はみ出さない。100vhは非対応ブラウザ向けのフォールバックとして残す。
     ★cmd_0181追記★: ログインUIは上部(.sidebar-account)へ移設済みだが、この
     dvh自体は.sidebar全体(nav末尾の項目到達性等)の可視領域対応であり、特定の
     要素専用ではないため引き続き必要——撤去対象は下記768px以下メディア
     クエリ側で撤去した「login用の固定64px余白」のみ。 */
  height:100dvh;
}
.sidebar-brand{padding:20px 18px 14px;border-bottom:1px solid var(--border);}
.sidebar-brand .logo{font-size:14px;font-weight:700;letter-spacing:.5px;color:var(--accent);}
.sidebar-brand .sub{font-size:11px;color:var(--text-dim);margin-top:2px;}
.sidebar-nav{flex:1;padding:10px 0;overflow-y:auto;}
.nav-group-label{
  font-size:10px;color:var(--text-dim);text-transform:uppercase;
  letter-spacing:1px;padding:14px 18px 6px;
}
.nav-item{
  display:flex;align-items:center;gap:10px;
  padding:10px 18px;margin:1px 8px;border-radius:8px;
  font-size:13px;color:var(--text-dim);cursor:pointer;
  border:1px solid transparent;
}
.nav-item:hover{background:var(--sidebar-hover);color:var(--text);}
.nav-item.active{background:var(--sidebar-active);color:var(--text);border-color:#3a4a7a;}
.nav-icon{
  width:20px;height:20px;border-radius:5px;
  display:flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:700;
  background:var(--panel-2);color:var(--text-dim);flex-shrink:0;
}
.nav-item.active .nav-icon{background:var(--accent);color:#0f1420;}
.nav-item-label{display:flex;align-items:center;gap:6px;flex:1;min-width:0;}
/* cmd_0158是正: opacity:.7だと--text-dim(#8b96b3)がsidebar(#141b2d)へ収束し
   コントラスト比3.15(soon-badge側)まで低下し読めなかった(WCAG AA 4.5未達)。
   .95へ緩和(実測: 是正後4.58以上を維持)。
   ★cmd_0163可読性補正・軍師QC是正★: --text-dimを明るくした(#b2b9cd)後に
   opacity:.95を合成すると、soon-badge側のコントラスト比は実測6.846まで下がり
   目標7:1に届かない(opacityがsidebar地へ収束させる経路自体が残っていたため)。
   .soon-badge(近日公開を示す専用の文言バッジ)が既に「近日」状態を明示しており、
   opacityによる追加の薄化は不要な二重表現だったため撤去する(実測: opacity無しで
   7.399——同ファイル内の他text-dim箇所と同じ値、cmd_0158b「読みやすさと状態表現を
   同じつまみで動かさない」の方針をここにも適用)。★.nav-item-soon/.nav-item-soon:hover
   ルール自体を撤去(opacity以外に付与していたスタイルが無かったため空になった)。
   HTML側のclass="nav-item-soon"付与は近日追加予定機能を示す目印として残したまま
   (JS側の分岐に使われている可能性への配慮・見た目には影響しない)。 */
.soon-badge{
  font-size:9px;font-weight:700;color:var(--text-dim);
  background:var(--panel-2);border:1px solid var(--border);
  border-radius:10px;padding:1px 6px;flex-shrink:0;
}
/* cmd_0181: 旧.sidebar-footer(下部)を.sidebar-brand直下(上部)へ移設した名残。
   実機でスマホ下部バーに隠れて押せなかった問題を、位置そのものを変えて解消する
   (以前の対症療法=固定64px+safe-area余白は、対象が上部へ移ったため撤去した)。 */
.sidebar-account{
  padding:14px 18px;border-bottom:1px solid var(--border);
  font-size:11px;color:var(--text-dim);
  display:flex;align-items:center;gap:8px;
}
.avatar-mini{
  width:26px;height:26px;border-radius:50%;
  background:var(--accent);color:#0f1420;font-weight:700;font-size:11px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
#auth-status-text{
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.sidebar-account .link-btn{
  display:inline;background:none;border:none;padding:0;margin-left:auto;
  flex-shrink:0;color:var(--accent);font-size:11px;text-decoration:underline;
  white-space:nowrap;cursor:pointer;
}

/* ---------- Main ---------- */
.main{flex:1;min-width:0;}
.topbar{
  height:56px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;
  padding:0 24px;background:var(--bg);position:sticky;top:0;z-index:5;
}
.topbar-title{font-size:15px;font-weight:700;}
.topbar-crumb{font-size:11px;color:var(--text-dim);margin-top:2px;}
.topbar-right{display:flex;gap:10px;align-items:center;}
.content{padding:22px 26px 60px;}

/* スマホ幅のみで表示するハンバーガー（PC/タブレットではdisplay:noneのまま非表示） */
.topbar-hamburger{
  display:none;flex-shrink:0;
  width:34px;height:34px;margin-right:12px;
  align-items:center;justify-content:center;
  background:var(--panel-2);color:var(--text);
  border:1px solid var(--border);border-radius:8px;
  font-size:16px;cursor:pointer;
}
.topbar-hamburger:hover{border-color:var(--accent);}

/* スマホ幅でサイドバー展開時にメイン領域を覆うオーバーレイ（PC/タブレットでは非表示のまま） */
.nav-overlay{display:none;position:fixed;inset:0;background:rgba(5,7,14,.6);z-index:90;}

.view{display:none;}
.view.active{display:block;}

/* ---------- Common widgets ---------- */
.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:22px;}
.stat-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:16px;}
.stat-card .label{font-size:11px;color:var(--text-dim);}
.stat-card .value{font-size:22px;font-weight:700;margin-top:6px;}
.stat-card .delta{font-size:11px;color:var(--accent);margin-top:4px;}

.panel{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:18px;margin-bottom:18px;}
.panel-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;flex-wrap:wrap;gap:8px;}
.panel-head h2{font-size:14px;margin:0;}
.panel-head .hint{font-size:11px;color:var(--text-dim);}
.panel-head-actions{
  display:grid;grid-template-columns:repeat(6,max-content);align-items:center;gap:12px;
}
.panel-head-actions .roster-action-clear{grid-column:1;}
.panel-head-actions .roster-action-import{grid-column:2;}
.panel-head-actions #col-settings{grid-column:3;}
.panel-head-actions #btn-edit{grid-column:4;}
.panel-head-actions #btn-save{grid-column:5;}
.panel-head-actions #btn-cancel{grid-column:6;}

/* subtask_0163_import_button_layout: white-space:nowrapが無いと、CJK文字は文字境界ごとに
   改行機会を持つため、flexアイテムのmin-content幅が実質1文字分まで縮む——狭幅で
   flex:1(.panel-head-actions .btn、768px以下)と組み合わさると、ボタン内テキストが
   1文字ずつ折り返す「縦一列」崩れを起こす(390pxで#btn-importが48px×7行に潰れる実測
   不具合を確認)。nowrapで最小幅をテキスト全幅まで引き上げ、内部改行そのものを防ぐ。
   本ファイル内の.btnラベルは全て短い単一行文言のため(最長10文字)、副作用は無い。 */
.btn{
  background:var(--accent);color:#0b1220;border:none;border-radius:7px;
  padding:8px 16px;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;
}
.btn:hover{opacity:.9;}
.btn.secondary{background:var(--panel-2);color:var(--text);border:1px solid var(--border-strong);}
.btn.small{padding:5px 10px;font-size:11px;}
/* cmd_0163可読性補正・軍師QC是正での検分対象: opacity:.4は合成後の実測でボタン自身の
   ラベル文字コントラストが3.2前後(secondary)/2.7前後(primary)まで下がり7:1には
   遠く及ばない。★意図的に対象外とする★——WCAG 2.1 SC1.4.3/1.4.6の適用注記は
   「非活性なUIコンポーネントの一部であるテキスト」にコントラスト要件を課さない
   (押せないボタン自身のラベルは「読ませる情報」ではなく「今は押せないという状態」を
   示すのが主目的のため)。cursor:not-allowedも併用しており、opacityは無効状態を
   目立たせる意匠として維持する(cmd_0158b「読みやすさと状態表現を同じつまみで
   動かさない」の対象は、まだ読ませる必要がある情報(説明文・データ値等)であり、
   非活性ボタン自身のラベルはこの原則の対象外と判断)。詳細判断根拠はqueue/reports/
   ashigaru2_report.yaml参照・軍師/殿の再検分を歓迎する。 */
.btn:disabled{opacity:.4;cursor:not-allowed;}

.edit-mode-badge{
  font-size:10px;font-weight:700;color:#0b1220;background:var(--accent-2);
  border-radius:12px;padding:3px 10px;letter-spacing:.3px;margin-left:8px;
}
.dirty-indicator{font-size:11px;color:var(--accent-2);margin-left:10px;}
.readonly-badge{
  font-size:10px;font-weight:700;color:var(--text-dim);background:var(--panel-2);
  border:1px solid var(--border);border-radius:12px;padding:2px 8px;
}

/* ---------- Tool hub cards (home) ---------- */
.tool-hub-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
.tool-hub-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:18px;cursor:pointer;position:relative;}
.tool-hub-card:hover{border-color:var(--accent);}
/* cmd_0158是正: opacity:.6だと.hub-desc(--text-dim)が背景(--bg)へ収束し
   コントラスト比2.78まで低下し読めなかった(WCAG AA 4.5未達)。
   .9へ緩和(実測: 是正後4.62)。
   ★cmd_0163可読性補正・軍師QC是正★: --text-dimを明るくした後もopacity:.9との合成では
   実測6.837までしか届かず7:1未達。.hub-badge(「今後追加」/「利用可能」の明示文言)が
   既に状態を伝えており、opacityによる追加の薄化は不要な二重表現だったため撤去する
   (実測: opacity無しで--textが11.043、hub-desc(text-dim)も[text-dim.1]試験と同じ
   パネル基準の7:1以上を維持)。★.tool-hub-card.disabledルール自体は撤去(opacity以外に
   付与していたスタイルが無かったため空になった。class="disabled"のHTML付与自体は
   将来のクリック抑止実装等に備え残す・現状はJS側でも未使用)。 */
.tool-hub-card .hub-icon{
  width:34px;height:34px;border-radius:8px;background:var(--panel-2);
  display:flex;align-items:center;justify-content:center;
  font-weight:700;color:var(--accent);margin-bottom:10px;font-size:13px;
}
.tool-hub-card .hub-title{font-size:13px;font-weight:700;}
.tool-hub-card .hub-desc{font-size:11px;color:var(--text-dim);margin-top:4px;line-height:1.5;}
.hub-badge{
  position:absolute;top:14px;right:14px;font-size:10px;font-weight:700;
  background:var(--panel-2);color:var(--text-dim);
  padding:3px 9px;border-radius:12px;border:1px solid var(--border);
}
.hub-badge.active-badge{background:var(--accent);color:#0b1220;border-color:var(--accent);}

/* ---------- Roster list ---------- */
/* cmd_070 段階1①: フィルタ部分(タイトル/ボタン・サマリー・検索/絞り込み)をピン留めし、
   一覧をスクロールしても常に操作できるようにする。cmd_065の抽出結果プレビュー
   (.import-confirm-sticky-header)と同じ「negative margin+paddingで.panelの内側パディングへ
   食い込ませてからposition:stickyでtopbar直下に貼り付ける」手法を踏襲。 */
/* subtask_0163_table_controls_outside: JSON書き出し/書き戻し・退避説明文・サーバ版切替は
   表操作(編集/保存/列設定)と別物のため、非stickyな独立区画として.roster-sticky-headより
   前に置く(テーブル外の区画)。.roster-sticky-headは.panelの1番目の子でなくなったため、
   上方向のnegative margin(旧-18px)は外し左右のみ残す(sticky時の全幅bleedは維持)。 */
.roster-toolbar{margin-bottom:14px;}
/* cmd_0181 FIND-1是正: .roster-sticky-head(ページ単位position:sticky)と
   #roster-table thead th(table-scroll単位position:sticky)は別々のスクロール
   基準を持つ独立したsticky要素であり、ページをある程度スクロールした遷移帯で
   互いの矩形が実際に重なる(実測: 390px幅・window.scrollTo(0,260)でthead(top:254)が
   roster-sticky-head(bottom:348)の内側に入り込み、モジュール集計行と視覚的に衝突する)。
   従来z-index:4はthead(5)・thead th.col-name(6)より低く、重なった際にthead側が
   前面へ描画され列名行が特化/モジュール集計へ「食い込む」ように見えていた。
   roster-sticky-headは自身に不透明背景(--panel)を持つため、thead以上のz-indexへ
   引き上げれば「下を通り過ぎる内容をきれいに覆い隠す」通常のsticky headerの挙動へ戻る
   (col-settings-popover:20・hf-popover系:30より下は維持、それらのポップアップ表示を妨げない)。 */
.roster-sticky-head{
  position:sticky;top:56px;z-index:8;background:var(--panel);
  margin:0 -18px 0;padding:0 18px 14px;
}
.col-settings{position:relative;}
.col-settings-popover{
  position:absolute;top:calc(100% + 6px);right:0;z-index:20;min-width:170px;
  background:var(--panel-2);border:1px solid var(--border);border-radius:8px;
  padding:8px 12px;box-shadow:0 8px 24px rgba(0,0,0,.4);
}
.col-settings-popover label{
  display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text);
  padding:5px 0;cursor:pointer;white-space:nowrap;
}
.chip{
  background:var(--panel-2);border:1px solid var(--border);border-radius:20px;
  padding:5px 12px;font-size:11px;color:var(--text-dim);cursor:pointer;
}
.chip.active{background:var(--accent);color:#0b1220;border-color:var(--accent);}
.chip.fav-filter.active{background:var(--accent-2);color:#0b1220;border-color:var(--accent-2);}

.server-toggle{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  width:min(100%,260px);border:1px solid var(--border);border-radius:20px;overflow:hidden;
}
.server-toggle button{
  width:100%;min-width:0;background:var(--panel-2);color:var(--text-dim);border:none;
  padding:5px 10px;font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap;
}
.server-toggle button:first-child{border-radius:18px 0 0 18px;}
.server-toggle button:last-child{border-radius:0 18px 18px 0;}
.server-toggle button.active{background:var(--accent);color:#0b1220;}

/* cmd_0181 FIND-3是正: border-collapse:collapseは、position:stickyをtd/th
   (#roster-table .col-name)へ適用した際にWebKit系ブラウザ(Safari/iOS)で無効化される
   既知の相互作用がある(collapseされた境界線の計算がstickyのoffset計算と競合する)。
   本アプリの各セルはborder-bottomを個別に持ち、列間の縦境界線は元々使っていないため、
   border-spacing:0のseparateへ変更しても見た目は変化しない(横方向の隙間が生じない)。
   ヘッドレスChrome(Blink)は本バグを持たないため実測で再現しないが、既知の回避策として
   適用する(スマホで名前列がsticky-leftへ留まらない症状の対処・実機最終確認は別途要)。 */
table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;}
th{
  text-align:left;color:var(--text-dim);font-weight:600;
  padding:8px 10px;border-bottom:1px solid var(--border);font-size:11px;white-space:nowrap;
}
th.sortable{cursor:pointer;user-select:none;}
th.sortable:hover{color:var(--text);}
.sort-icon{font-size:9px;color:var(--text-dim);margin-left:3px;}
.sort-icon.active{color:var(--accent);}
td{padding:9px 10px;border-bottom:1px solid #202b45;}
tr.op-row{cursor:pointer;}
tr.op-row:hover{background:var(--panel-2);}
tr.op-row.locked{cursor:default;}
tr.op-row.locked:hover{background:none;}
/* cmd_0163可読性補正・軍師QC是正: opacity:.7だと行内のtext-dim系セル(.lvl-dash等)が
   実測4.710まで下がり7:1未達(--text系セルは7.222で足りていたが、行全体を一律に
   同じopacityで薄めていたためtext-dim側が先に割れていた)。行内には既に
   「🔒閲覧のみ」という明示ラベル(roster.js op-nameセル参照)があり、view-onlyである
   ことはopacityに頼らず伝わっているため、opacityによる薄化自体を撤去する
   (ルール自体も他に付与していたスタイルが無いため撤去。class="view-only"の付与は
   roster.js側に残る——将来の見た目調整用の目印として維持)。 */

.op-avatar{
  width:32px;height:32px;border-radius:7px;
  display:flex;align-items:center;justify-content:center;
  font-weight:700;font-size:12px;color:#0b1220;flex-shrink:0;
}
.op-name-cell{display:flex;align-items:center;gap:10px;}
/* cmd_0181 FIND-4是正: white-space未指定のため、table(layout:auto)が列幅を
   全407行の内容から自動算出する際に名前列が実測75.7pxまで圧縮され、長い名前
   (実測214/407行)が2行折返しになっていた(PC 1280px幅でも再現・列幅問題であり
   スマホ固有ではない)。nowrapを指定すると、auto layoutが各セルの最小内容幅
   (=折返し不可の全文字幅)を列幅の下限として尊重するため、列自体が必要幅まで
   自動的に広がり2行化を解消する(#roster-table自体がmin-width:1360pxかつ
   .table-scrollが横スクロール可能なため、列が広がっても表全体のレイアウトは壊れない)。 */
.op-name{font-weight:600;white-space:nowrap;}
.lock-icon{font-size:9px;color:var(--text-dim);margin-left:6px;}
.jp-unavailable-cell{position:relative;}
.jp-unavailable-cell::after{content:"※";position:absolute;top:1px;right:2px;font-size:9px;color:var(--text-dim);}

.rarity-star{font-size:11px;letter-spacing:1px;}
/* cmd_070 段階2→cmd_0187是正: 見出し行固定(Excel風列ヘッダー絞り込み)。
   subtask_070k/070nで実機検証済みの「.table-scroll自体を上限高さ+overflow:auto(縦横とも)の
   内部スクロール箱にし、theadのposition:stickyをその内部スクロール基準にする」方式(bounded方式)
   をcmd_0187で撤回した——殿の実機Safari実測(discord添付IMG_3238/IMG_3240、2026-08-13朝)で、
   ページ全体を縦送りするとbounded箱ごと画面外へ流れ、thead(列名行)がページに対して
   固定されない不具合が実際に確認された(「ページに対してテーブルヘッダーが固定されてない」)。
   theadのsticky基準が.table-scroll自身の内部スクロールであり、ページのスクロールとは独立した
   別基準だったことが原因——bounded方式の構造そのものに起因し、max-heightの値を変えても
   解決しない。
   ★是正: theadを.table-scrollの外へ出し、ページ基準でstickyする独立した箱
   (.roster-thead-wrap、index.html参照)へ移した。
   ★注意(既に実機検証済みの失敗パターンを再び踏まぬこと)★: theadを.table-scrollの子孫に
   残したまま.table-scroll{overflow-x:auto}(max-height無し)にする「naive方式」だけでは直らない
   ——poc/cmd070_excel_style/standalone.htmlの「素朴な方法は失敗する」検証(sticky_test_naive.html
   で実機再現・スクリーンショット確認済み)のとおり、overflow-x:auto等overflowがvisible以外の
   値を持つ祖先は、軸を問わず子孫のposition:stickyの基準スクロールポートを自分自身へ変えて
   しまう。.table-scrollは高さ制約が無く実際には縦方向へ内部スクロールし得ない(scrollTopが
   常に0のまま)ため、子孫のtheadに対するtop方向stickyの基準としては永久に「動かない」判定に
   なり、ページをいくら縦送りしてもtheadは一切固定されない。theadを子孫から構造的に
   分離する以外に解は無い。
   分離に伴い#roster-table(tbody専用)と#roster-thead-table(thead専用)は別々の<table>となり、
   table-layout:autoの列幅計算が独立するため両者の列境界がズレる——
   roster.js syncTheadColumnWidths()が両者を実測(getBoundingClientRect)し、列ごとの最大値を
   colgroupへ書き込みtable-layout:fixedへ固定することで列境界を一致させる(呼び出し箇所は
   showView()/refreshAll()、roster.js参照)。 */
.table-scroll{overflow-x:auto;}
/* .table-scrollがoverflow-x:autoを持つと、CSS仕様上overflow-yも(明記せずとも)auto相当に
   計算される(overflow-x/yの一方のみvisible以外だと他方もvisible以外へ計算される仕様)。
   ただし本要素はheight/max-heightを持たず内容に応じて自然に伸びるため、実際に縦方向の
   クリップ・内部スクロールバーが生じることは無い(.roster-thead-wrapも同じ理屈で安全)。 */
#roster-table{min-width:1360px;}
/* cmd_0187: theadを収める独立箱。.roster-sticky-head(top:56px)の直下へ隙間なく貼り付くよう、
   topは--thead-sticky-top(roster.js wireStickyHeadOffset()がResizeObserverで
   .roster-sticky-headの実高さを継続測定して設定する。折返しで高さが変わる390px/1280px双方に
   追従する)を使う。フォールバック値110pxはJS実行前の一瞬のみ使われる概算値。
   overflow-x:autoは.table-scroll側のscrollイベントに合わせてscrollLeftをJSで同期するための
   もの(直接ドラッグは想定しないため、スクロールバー自体は下の規則で視覚上隠す)。
   z-index:7は.roster-sticky-head(8)より低い——両者は本来隣接して重ならない設計だが、
   万一のずれで重なった場合にroster-sticky-head側が前面に出るようcmd_0181 FIND-1と
   同じ考え方を踏襲する。 */
.roster-thead-wrap{
  position:sticky;top:var(--thead-sticky-top, 110px);z-index:7;
  overflow-x:auto;background:var(--panel-2);
}
.roster-thead-wrap::-webkit-scrollbar{display:none;}
.roster-thead-wrap{scrollbar-width:none;-ms-overflow-style:none;}
#roster-thead-table{min-width:1360px;}
#roster-thead-table th{background:var(--panel-2);}
/* subtask_0163_operator_name_sticky→cmd_0187継承: 名前列を横スクロールでも左端に残す。
   tbody側(#roster-table)は.table-scroll(横送りのみ)の内部で実際にスクロールするため、
   position:sticky;left:0が有効に働く(theadが分離された今もtbody側の挙動は不変)。
   #(通し番号)・所持列は390px実測(docs/real_chrome_measure_runbook.md準拠、
   .verify_scratch/roster_name_sticky_measure.js)の結果、追加固定しない
   ——名前列単独で約100px前後を占め、#・所持まで固定すると残り幅が実データ列を
   1列も収められぬほど狭くなる(詳細はqueue/reports/ashigaru2_report.yaml参照)。 */
#roster-table .col-name{position:sticky;left:0;}
#roster-table tbody td.col-name{z-index:2;background:var(--panel);}
#roster-table tr.op-row:hover td.col-name{background:var(--panel-2);}
/* cmd_0187: theadは#roster-thead-table(別table)側にあるため、col-name(名前列)の横sticky・
   隅の重ね順(角セル)は#roster-thead-table側にも別途必要——.roster-thead-wrap自身が
   overflow-x:autoで実際に横スクロールするため、この中でもposition:sticky;left:0は有効に働く。
   z-index:6はwrap内の他th(暗黙のauto)より上、不透明背景は横スクロールで奥へ消える他列を
   隠すために必要(tbody側z-index:2/背景と同じ理屈)。 */
#roster-thead-table th.col-name{position:sticky;left:0;z-index:6;background:var(--panel-2);}
/* cmd_070 段階1③④: 「人材発掘」「公開求人」「他入手法」「大陸実装日」はデフォルト非表示、
   #btn-col-settingsの設定で殿が個別に再表示できる（min-widthはroster.jsのJSで動的調整）。
   cmd_0187: theadが#roster-thead-tableへ分離したため、同じ列を隠す規則を両tableへ用意する
   (roster.js applyColumnVisibility()が両方のtable要素へ同じhide-col-*クラスを付与する)。 */
#roster-table.hide-col-recruit .col-recruit,
#roster-table.hide-col-headhunt .col-headhunt,
#roster-table.hide-col-otherAcq .col-otherAcq,
#roster-table.hide-col-releaseCN .col-releaseCN,
#roster-thead-table.hide-col-recruit .col-recruit,
#roster-thead-table.hide-col-headhunt .col-headhunt,
#roster-thead-table.hide-col-otherAcq .col-otherAcq,
#roster-thead-table.hide-col-releaseCN .col-releaseCN{display:none;}

/* ---------- Excel風 列ヘッダー絞り込み(cmd_070 段階2、subtask_070k/070n実証済みモック踏襲) ---------- */
.hf-th{position:relative;}
.hf-th-row{display:flex;align-items:center;gap:4px;white-space:nowrap;}
.hf-filter-btn{
  appearance:none;background:transparent;border:none;color:var(--text-dim);cursor:pointer;
  font-size:10px;padding:2px 3px;border-radius:4px;line-height:1;
}
.hf-filter-btn:hover{background:var(--panel);color:var(--text);}
.hf-filter-btn.has-value{color:var(--accent);}
/* subtask_070s: position:absoluteだと.table-scroll(overflow:auto)の外側へ出た分がスマホ幅の右端列
   (β列・大陸実装日列等)で見切れる(実機確認済み)。position:fixedへ変え、開時にJS側で
   getBoundingClientRect()を基にビューポート座標で配置することで.table-scrollの外へ完全に逃がす。 */
.hf-popover{
  display:none;position:fixed;z-index:30;
  background:var(--panel-2);border:1px solid var(--border);border-radius:8px;
  padding:10px 12px;box-shadow:0 10px 28px rgba(0,0,0,.45);
  min-width:180px;font-weight:400;
}
.hf-popover.open{display:block;}
.hf-popover-title{font-size:10px;color:var(--text-dim);margin-bottom:6px;font-weight:700;}
/* subtask_070i踏襲: ポップオーバー内チップは.filter-row系クラスを一切継承しない専用クラスを使う
   (768px以下での縦積みメディアクエリの罠を再発させないため)。 */
.hf-popover-chips{display:flex;gap:5px;flex-wrap:wrap;max-width:230px;}
.hf-popover-chips.scrollable{max-height:150px;overflow-y:auto;padding-right:2px;}
.hf-popover .chip{font-size:10px;padding:4px 9px;}
.hf-search-input{
  background:var(--panel);border:1px solid var(--border);border-radius:6px;
  padding:5px 8px;font-size:11px;color:var(--text);width:160px;
}
.hf-range-row{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--text-dim);}
.hf-range-row input[type="date"],.hf-range-row input[type="number"]{
  background:var(--panel);border:1px solid var(--border);border-radius:6px;color:var(--text);
  font-size:11px;padding:3px 6px;width:92px;
}
.hf-range-row input[type="number"]{width:56px;}
.hf-jp-only{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--text-dim);margin-top:6px;cursor:pointer;}
.hf-stage-select{
  background:var(--panel);border:1px solid var(--border);border-radius:6px;color:var(--text);
  font-size:11px;padding:4px 6px;
}
/* 編集モード中は列ヘッダー絞り込みを無効化する(旧#filter-panel.disabledの後継) */
/* cmd_0158是正: opacity:.4だと--text-dimがthead sticky背景(--panel-2)へ収束し
   コントラスト比1.93まで低下し読めなかった(WCAG AA 4.5未達)。.96へ緩和(実測: 4.65)。
   cmd_0158b是正(軍師FIND-1): opacityを上げた結果、有効時とほぼ見分けが付かなくなった
   (「読みやすさ」と「無効らしさ」を同じつまみで動かしていた)。opacityは撤去して
   textDim地の色そのまま(=1.0、実測4.91、opacityが背後色へ収束させる経路自体を断つため
   将来どの背後色に置かれても4.5を割らない)、無効らしさはdashed下線という別の合図へ
   分離する。無効化自体はpointer-events:noneで維持。 */
#roster-table.editing .hf-filter-btn{pointer-events:none;border-bottom:1px dashed var(--text-dim);}

.lvl-badge{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:22px;height:20px;border-radius:5px;font-size:10px;font-weight:700;padding:0 4px;
}
.lvl-dash{color:var(--text-dim);font-size:11px;}
.inline-edit-input{
  width:52px;min-height:26px;background:var(--panel-2);border:1px solid var(--accent);border-radius:5px;
  color:var(--text);font-size:11px;padding:3px 2px;text-align:center;
}
.inline-edit-input:focus{outline:none;}
/* cmd_0156: number input→select化に伴う調整。selectはOS標準の矢印アイコンを右側に描画するため
   text-align:centerのままだと数字と矢印が重なって読みにくい。中央寄せをやめ、paddingで
   数字を左寄りへ、右側に矢印分の余白を確保する。タップ領域はmin-height:26pxで拡張
   (スマホでの押しやすさ・殿要望「キーボードなるべく使いたくない」に伴う操作性確保)。
   cmd_0163是正(殿ご指摘「プルダウンデカすぎて数字見切れてんじゃん」): 実測(375/390/1280px・
   実Chrome・スクリーンショット)で原因確定。text-align:left+padding-right:14pxの組により、
   Chromeが自前で確保するネイティブ矢印領域とCSS padding-rightが二重に効き、
   幅44pxでは中身の数字が1px前後まで潰れ判読不能になっていた(width44/46/48/50/52pxの
   総当たりで検証、48pxから実用上安定・52pxで確実に安定を確認)。widthを44→52pxへ拡張して
   是正。高さ(min-height:26px)は変更していない(cmd_0163指示・タッチ領域維持のため)。 */
select.inline-edit-input{
  text-align:left;padding:3px 14px 3px 6px;cursor:pointer;
}

.owned-toggle{
  width:22px;height:22px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;cursor:pointer;border:1px solid var(--border);
  background:var(--panel-2);color:var(--text-dim);
}
.owned-toggle.owned{background:var(--accent);color:#0b1220;border-color:var(--accent);}
/* cmd_0158是正: opacity:.5だと自身の背景(--panel-2)ごと行の背景(--panel/hover時--panel-2)へ
   収束し、コントラスト比2.27〜2.29まで低下し読めなかった(WCAG AA 4.5未達)。.96へ緩和(実測:4.65)。
   cmd_0158b是正(軍師FIND-1): opacity.96は有効時の枠(solid)と見分けが付かず「押せると
   思って押せぬ」を誘発する。opacityは撤去(実測4.91、自身のbg=panel-2ごと収束する経路を
   断つので背後の行がどちらの縞色でも一定)、枠をdashedへ変えることで無効らしさを示す
   (既存の.import-card.skipped/.import-dropzoneと同じ「dashed=非活性」の意匠を流用)。
   無効化自体はcursor:not-allowedとJS側判定で維持。 */
.owned-toggle.locked{cursor:not-allowed;border-style:dashed;}
.fav-toggle{font-size:15px;cursor:pointer;color:var(--text-dim);user-select:none;}
.fav-toggle.active{color:var(--accent-2);}
/* cmd_0158是正: opacity:.5だと--text-dimが行の背景(--panel/hover時--panel-2)へ収束し
   コントラスト比2.29〜2.37まで低下し読めなかった(WCAG AA 4.5未達)。.96へ緩和(実測:4.65)。
   cmd_0158b是正(軍師FIND-1): fav-toggleは元来枠を持たぬため、owned-toggleと同じdashed枠は
   使えない。opacity撤去(実測4.91〜5.37、行の縞色に依らず安定)の上、下線(dashed)で
   無効らしさを示す。無効化自体はcursor:not-allowedとJS側判定で維持。 */
.fav-toggle.locked{cursor:not-allowed;border-bottom:1px dashed var(--text-dim);}

.summary-table-wrap{overflow-x:auto;margin-bottom:14px;border:1px solid var(--border);background:var(--panel);}
.summary-table{width:max-content;min-width:0;border-collapse:collapse;font-size:11px;}
.summary-table th,.summary-table td{padding:6px;border-right:1px solid var(--border);border-bottom:1px solid var(--border);text-align:left;white-space:nowrap;}
.summary-table thead th{background:var(--panel-2);color:var(--text-dim);font-weight:700;vertical-align:top;}
.summary-table thead th:last-child,.summary-table td:last-child{border-right:0;}
.summary-table tbody tr:last-child th,.summary-table tbody tr:last-child td{border-bottom:0;}
.summary-table tbody th{color:var(--text-dim);font-size:10px;}
.summary-table-hint{color:var(--text-dim);font-size:10px;}
.summary-chip{border-left:3px solid var(--border);border-radius:2px;cursor:default;}
.summary-chip b{color:var(--text);font-size:12px;margin-left:2px;}
.summary-stat{display:inline-flex;flex-direction:column;gap:2px;min-width:76px;padding:0;border:0;background:transparent;color:var(--text-dim);font:inherit;text-align:left;cursor:pointer;}
.summary-stat:hover,.summary-stat.active{color:var(--accent);}
.summary-stat-label{font-size:10px;font-weight:700;color:inherit;}
.summary-stat-value{color:var(--text);font-size:12px;font-weight:700;}
.summary-stat.active .summary-stat-value{color:var(--accent);}
.summary-stat-detail{display:flex;gap:7px;align-items:center;flex-wrap:wrap;}
.summary-stat-detail button{padding:2px 4px;border:1px solid var(--border);border-radius:2px;background:var(--panel-2);color:var(--text-dim);font:inherit;cursor:pointer;}
.summary-stat-detail button:hover,.summary-stat-detail button.active{border-color:var(--accent);color:var(--accent);}
/* cmd_0319: 特化/モジュール集計の各数値は四桁が収まれば足りる。共通の
   .summary-stat(min-width:76px)をそのまま使うと、特化4列・モジュール4列が
   不要に広がり、狭幅画面で表の横幅を大きく占有する。集計内の小ボタンだけ
   四桁＋ラベルを収める幅へ限定し、値はnowrapで桁溢れ・折返しを防ぐ。 */
.summary-stat-detail .summary-stat{
  width:40px;min-width:40px;white-space:nowrap;
}

/* ---------- 個別編集画面（モーダル） ---------- */
.modal-overlay{
  display:none;position:fixed;inset:0;background:rgba(8,11,20,.65);
  align-items:center;justify-content:center;z-index:50;
}
.modal-overlay.active{display:flex;}
.modal-box{
  background:var(--panel);border:1px solid var(--border);border-radius:12px;
  padding:22px;width:440px;max-width:90vw;max-height:86vh;overflow-y:auto;
  box-shadow:0 12px 40px rgba(0,0,0,.5);
}
.modal-box h2{font-size:14px;margin:0 0 4px;}
.modal-box .modal-sub{font-size:11px;color:var(--text-dim);margin-bottom:16px;}
.modal-banner{
  background:rgba(242,193,78,.12);border:1px solid rgba(242,193,78,.4);
  color:var(--accent-2);font-size:11px;border-radius:8px;padding:8px 12px;margin-bottom:14px;
}

/* ---------- cmd_0288: URL共有での閲覧専用ビュー(operators-tool.com/roster?userId=…) ---------- */
/* .guest-view-banner自体は既定で非表示(空文字/display:none)。roster.js init()が
   guestUserIdを検出した時のみ、body.guest-viewクラス付与+textContent書き込みで見えるように
   なる(=通常表示への影響ゼロ)。.modal-banner(閲覧専用の帯)と同系統の見た目に揃える。 */
.guest-view-banner{
  display:none;background:rgba(242,193,78,.12);border:1px solid rgba(242,193,78,.4);
  color:var(--accent-2);font-size:12px;line-height:1.6;border-radius:8px;padding:10px 14px;margin-bottom:14px;
}
.guest-view-banner--error{
  background:rgba(239,111,111,.12);border-color:rgba(239,111,111,.4);color:var(--danger);
}
body.guest-view .guest-view-banner{display:block;}
/* サイドバー(ツール切替・ログイン導線)・一覧の書込み系導線を丸ごと隠す。
   「見せてよい範囲」は所持オペと育成状況のみ(cmd_0288 acceptance criteria)であり、
   他ツールへのナビ・ログイン・取込・編集・書き出し/書き戻しはいずれもこの画面の
   本題ではないため、閲覧専用ビューでは一切出さない(画面側の防御——サーバ側の
   防御はserver/handlers.js handleRosterPublicGetのdocstring参照)。 */
body.guest-view .sidebar,
body.guest-view .nav-overlay,
body.guest-view .topbar-hamburger,
body.guest-view .roster-toolbar,
body.guest-view #btn-edit,
body.guest-view #btn-save,
body.guest-view #btn-cancel,
body.guest-view #btn-import{display:none !important;}
/* ---------- cmd_0163是正: モーダルではなく遷移する独立した別ページ(殿の既往要望の復元) ---------- */
/* .modal-overlay(暗い背景の幕+中央寄せflex、z-index:50)を使わず、ページ背景そのもの
   (var(--bg))で画面全体を覆う——「別画面が浮かんでいる」のではなく「別ページへ遷移した」
   体感にするため。z-indexは.modal-overlayと同格(50、通常同時に両方は開かない)。 */
.page-view{
  display:none;position:fixed;inset:0;z-index:50;background:var(--bg);overflow-y:auto;
}
/* .page-view直下の.modal-boxは「浮いた箱」の見た目(角丸・影・独立した背景色・
   中央寄せの最大高さ制限)を持つ必要が無いため打ち消す。幅自体は.import-modal-box
   (cmd_0163第一段・min(1180px,94vw))をそのまま活かし、margin:0 autoで中央寄せのみ残す。 */
.page-view .modal-box{
  background:none;border:none;border-radius:0;box-shadow:none;
  max-height:none;overflow-y:visible;margin:0 auto;
}
/* #import-version-bannerはSTEP1(モーダル)/STEP2(別ページ)のどちらにも属さない共有部品と
   なったため、画面全体に対し固定位置で常時最上位に出す(取込画面である限り必ず視界に
   入るようにする、という従来からの要件をDOM分離後も維持する)。 */
.import-version-banner-floating{
  position:fixed;top:0;left:0;right:0;z-index:51;
  border-radius:0;margin-bottom:0;border-left:none;border-right:none;
  text-align:center;
}
.detail-field-row{display:flex;align-items:center;justify-content:space-between;font-size:12px;padding:7px 0;border-bottom:1px solid #202b45;gap:10px;}
.detail-field-row .k{color:var(--text-dim);flex-shrink:0;}
.detail-field-row input[type=number]{
  width:70px;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;
  padding:5px 8px;color:var(--text);font-size:12px;text-align:right;
}
/* cmd_0158是正: opacity:.5だと--textが背景(モーダルの--panel)へ収束しコントラスト比4.21まで
   低下しWCAG AA 4.5未達だった。.7へ緩和(実測: 是正後6倍超まで回復)。
   ★cmd_0163可読性補正・軍師QC是正の過程で判明★: 本ルールの対象input(#detail-potential・
   スキル特化/モジュールStageの各input)はいずれもclass="visually-hidden"併用であり、
   .visually-hidden自体がposition:absolute+width/height:1px+clip:rect(0,0,0,0)で
   常時視覚的に1px四方へ切り取っている——本ルールのopacity値がどうであれ実際には
   一切見えない(セレクタ詳細度は本ルールが勝りopacity:0を上書きするが、clip等の
   他プロパティは.visually-hidden側が生きたまま残るため無効化はされない)。つまり
   本ルールは死んだスタイル(視覚効果ゼロ)であり、実際に読まれるのは代わりの
   .seg-btn(セグメントボタン、cmd_053)側——.seg-btn:disabledは既にopacity非依存
   (dashed下線)で対処済み(本ファイル該当ルール参照)。誤解を招く死んだopacity値を
   置いたままにせず、ルールごと撤去する。 */
.modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:16px;}

/* ---------- cmd_053 Option A: セグメントボタン(スキル特化/モジュールStage/潜在) ---------- */
/* 既存の.value直接読み取り経路を壊さないため、置換対象のinputはvisually-hiddenでDOMに残す
   (display:noneは避ける — 非表示inputへの値設定+イベント発火がブラウザによっては
   正しく動作しない実装があるため、視覚的に隠すだけでレイアウトから外す)。 */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;opacity:0;pointer-events:none;}
.seg-control{display:inline-flex;flex-wrap:wrap;border:1px solid var(--border);border-radius:8px;overflow:hidden;}
.seg-btn{
  background:var(--panel-2);color:var(--text-dim);border:none;
  border-right:1px solid var(--border);padding:6px 12px;font-size:12px;
  font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;
}
.seg-btn:last-child{border-right:none;}
.seg-btn:hover{color:var(--text);}
.seg-btn.active{background:var(--accent);color:#0b1220;}
/* cmd_0158是正: opacity:.4だと--text-dimが背景(モーダルの--panel)へ収束しコントラスト比1.91まで
   低下し読めなかった(WCAG AA 4.5未達)。.96へ緩和(実測:4.65)。
   cmd_0158b是正(軍師FIND-1): opacityを上げた分だけ.active(.seg-btn.active)との見分けが
   付きにくくなっていた。opacity撤去(実測4.91、自身のbg=panel-2で背後のモーダル色に依らず
   一定)、下線(dashed)を無効らしさの合図として足す。無効化自体はpointer-events:noneで維持。 */
.seg-btn:disabled{cursor:not-allowed;pointer-events:none;border-bottom:2px dashed var(--text-dim);}

/* ---------- 画像取込：入口 ---------- */
.import-dropzone{
  border:1px dashed var(--border);border-radius:8px;padding:22px;text-align:center;
  color:var(--text-dim);font-size:12px;margin-bottom:16px;background:var(--panel-2);
  transition:border-color .15s,background .15s;
}
.import-dropzone.dragover{
  border-color:var(--accent);background:rgba(110,168,254,.12);color:var(--text);
}
.import-dropzone-hint{margin-top:8px;font-size:11px;color:var(--text-dim);}
.modal-desc{font-size:12px;color:var(--text-dim);line-height:1.7;margin-bottom:16px;}
.import-tip{
  font-size:11px;color:var(--text);line-height:1.6;margin-bottom:16px;
  padding:8px 10px;border:1px solid var(--accent-2);border-radius:6px;
  background:rgba(242,193,78,.1);
}
/* cmd_0158是正: opacity:.5だと--text-dimが背景(.modal-boxの--panel)へ収束し
   コントラスト比2.27まで低下し読めなかった(WCAG AA 4.5未達)。
   .96へ緩和(実測: 是正後4.65)。無効化自体はpointer-events:noneで維持。
   ★cmd_0163可読性補正・軍師QC是正★: --text-dimを明るくした後もopacity:.96との合成では
   実測6.924までしか届かず7:1未達(.96はもともと4%の薄化に過ぎずほぼ知覚できない
   演出だった)。.import-dropzone自体が常時dashed枠(border:1px dashed var(--border))を
   持っており「取込中は操作できない」はpointer-events:noneで機能的に足りているため、
   opacityは撤去する(実測: opacity無しで--text-dimの基準値7.399まで回復)。 */
.import-dropzone-disabled{pointer-events:none;}
/* subtask_042a: 枠を使わず、既存のlink-btnと同じ見た目のボタンを一行だけ置く(戒め1)。 */
.import-roster-export-row{margin-bottom:10px;}
.import-roster-export-row .link-btn{
  display:inline;background:none;border:none;padding:0;margin-right:16px;
  color:var(--accent);font-size:11px;text-decoration:underline;cursor:pointer;
}
/* subtask_043d: 複数世代からの選択復元行。selectとボタンを横並びにするだけの単純な形
   (戒め1・枠を使わない)。 */
.import-roster-restore-undo-row{display:inline-flex;align-items:center;gap:6px;}
.import-roster-restore-undo-row .link-btn{
  display:inline;background:none;border:none;padding:0;margin-right:16px;
  color:var(--accent);font-size:11px;text-decoration:underline;cursor:pointer;
}
/* subtask_043d: 世代数上限の告知(将軍裁可の条件2)。装飾せず、既存の控えめな案内文と同じ
   トーン(text-dim・小さめ)で足す(戒め2・目を引かせない)。 */
.import-backup-note{font-size:11px;color:var(--text-dim);margin:-4px 0 10px;}
/* subtask_041a: 枠で囲わず、単純な直線区切り+余白のみで済ませる(戒め1)。控えめな案内であって警告ではない。 */
.import-export-reminder{
  font-size:11px;color:var(--text-dim);line-height:1.7;
  padding-top:10px;margin-bottom:16px;border-top:1px solid var(--border);
}
.import-export-reminder code{
  background:var(--panel-2);color:var(--text);padding:1px 5px;border-radius:4px;font-size:10px;
}
.import-export-reminder .link-btn{
  display:inline;background:none;border:none;padding:0;margin-left:4px;
  color:var(--accent);font-size:11px;text-decoration:underline;cursor:pointer;
}
.import-progress-bar{
  width:100%;height:8px;border-radius:4px;background:var(--panel-2);
  border:1px solid var(--border);overflow:hidden;margin-bottom:8px;
}
.import-progress-bar-fill{
  height:100%;width:0%;background:var(--accent);transition:width .2s ease-out;
}
.import-progress-text{font-size:11px;color:var(--text-dim);margin-bottom:4px;text-align:center;}
.import-stats-text{font-size:11px;color:var(--text-dim);margin-bottom:16px;text-align:center;}
.import-large-notice{font-size:11px;color:var(--text-dim);margin:-8px 0 16px;text-align:center;}

/* ---------- 画像取込：確認画面（subtask_030b） ---------- */
/* cmd_0163第一段: 殿の絵(queue/discord_attachments/1536595090267574362_image.png)の
   仕様。基本は既存のまま(幅440pxの.modal-boxの上に個別width指定を重ねる従来の
   やり方を維持)、PCブラウザで見た時の横幅だけを増やす。560px固定では絵にある
   3列カードが入らないため、ブラウザ幅に応じて94vwまで伸びる形へ変更する
   （後述の@media(max-width:768px)側は従来通り94vwのまま・据置き＝スマホは変更なし）。
   ★殿の実機確認による緊急是正(cmd_0163是正)★: 当初は本クラスをSTEP1(#import-modal、
   実際にモーダルである画面)とSTEP2(#import-step-confirm、後にモーダルから独立ページへ
   分離済み)の両方で共用していたが、STEP2側は「モーダルではない」ため、
   クラス名「import-modal-box」が実態と食い違っていた。★.import-modal-boxはSTEP1
   (実モーダル)専用に限定し、STEP2(独立ページ)側は下記.import-page-boxへ分離した★。
   .import-modal-box自体の値はSTEP1の見た目を変えぬため据置き(min(1180px,94vw)のまま)。 */
.import-modal-box{width:min(1180px, 94vw);}
/* ★殿の実機確認による緊急是正(cmd_0163是正)★: STEP2(#import-step-confirm)は.page-view
   による独立した別ページであり、モーダルのような「浮いた箱を画面中央に収める」ための
   頭打ち(1180px)は実態に合わない——1280px/1920px等の広い画面でも1180pxで頭打ちし、
   grid(auto-fill, minmax(300px,1fr))が3列で止まっていた(殿ご指摘)。頭打ちを外し、
   ウィンドウ幅にそのまま追従する94vw単独へ変更する(スマホは@media側で.modal-boxの
   汎用94vw規則が既に効くため、本クラス独自のモバイル上書きは不要)。
   実測(test/import_preview_columns_cmd0163.test.jsのcolumn-count計算参照):
   1280px viewport → 3列(旧頭打りと同じ、300+14の等式上ここでは変化なし・正直に報告)、
   1920px viewport → 5列(旧頭打まり3列から改善)。 */
.import-page-box{width:94vw;}
/* cmd_0163第一段: カード一覧を1列固定から、PCではブラウザ幅に応じて列数が変わる
   グリッドへ変更する（絵では3列。auto-fillのため厳密に3固定ではなく、より広い
   ウィンドウでは4列以上にも自然に増える＝「ブラウザ幅によって列数が変わる」を
   そのまま満たす）。スマホは@media(max-width:768px)側で1fr(1列)へ戻し、
   「スマホは今のまま1列」を明示的に保証する（auto-fillの成り行き任せにしない）。
   .import-card自体のmargin-bottomはgapと二重に効いてしまうため、この一覧の
   直接の子である場合に限りゼロへ戻す(他の.import-card利用箇所には影響しない)。 */
#import-candidate-list{
  display:grid;grid-template-columns:repeat(auto-fill, minmax(300px, 1fr));gap:14px;
}
#import-candidate-list > .import-card{margin-bottom:0;}
.import-legend{display:flex;gap:16px;margin-bottom:12px;font-size:11px;color:var(--text-dim);}
.import-legend-item{display:flex;align-items:center;gap:5px;}
.import-legend-dot{width:9px;height:9px;border-radius:3px;display:inline-block;}
.import-legend-dot.ok{background:var(--accent);}
.import-legend-dot.warn{background:var(--accent-2);}
.import-legend-dot.occlusion{background:var(--danger);}

/* cmd_0163第二段: 頁分けヘッダー(何人目〜何人目/全N件・前へ/次へ)。スマホでも
   崩れぬよう中央寄せ+折り返し可にし、範囲表示は左右のボタンに挟まれた形で置く。 */
.import-confirm-pagination{
  display:flex;align-items:center;justify-content:center;gap:12px;
  margin-bottom:12px;flex-wrap:wrap;
}
.import-page-range{font-size:12px;color:var(--text-dim);white-space:nowrap;}
/* cmd_0289: 保存済み範囲の一言添え(戒め2に沿い、枠や強調色は使わず地の文言のみ)。 */
.import-page-saved-indicator{font-size:12px;color:var(--text-dim);white-space:nowrap;}

.import-card{
  background:var(--panel-2);border:1px solid var(--border);border-radius:10px;
  padding:12px 14px;margin-bottom:10px;
}
.import-card.needs-review{border-color:var(--accent-2);background:rgba(242,193,78,.07);}
/* subtask_041f: occlusion_suspectedは「遮蔽で原理的に読み取り不能」という、単なる低確信度
   (OCR再読で解決しうる)より深刻な要確認理由のため、warnより優先して目立つdangerカラーで
   上書きする(同じカードがneeds-reviewとocclusion-suspectedを両方持つ場合はこちらを優先)。 */
.import-card.occlusion-suspected{border-color:var(--danger);background:rgba(239,111,111,.09);}
/* cmd_0158是正: opacity:.5だとカード内の--text-dim文言(.import-card-field .k等)が
   背景(.modal-boxの--panel)へ収束しコントラスト比2.27まで低下し読めなかった
   (WCAG AA 4.5未達)。.95へ緩和(実測: 是正後4.58)。opacityだけでは「除外」の見分けが
   ほぼ付かなくなる分は、本ファイル内で既に確立済みの.import-dropzoneと同じ
   「dashed罫線=非活性」の意匠を流用して補う。
   ★cmd_0163可読性補正・軍師QC是正★: --text-dimを明るくした後もopacity:.95との合成では
   実測6.777までしか届かず7:1未達。「除外」の見分けは既にborder-style:dashedが
   担っており(上記コメントの通り、opacityに頼らない意匠として導入済み)、opacity自体は
   もはや不要な二重表現だったため撤去する(実測: opacity無しで基準値7.399まで回復)。 */
.import-card.skipped{border-style:dashed;}
.import-card-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px;}
/* subtask_065a: プレビュー画面のカード画像（殿裁可の権利物例外、取込元画像の切り出しのみ）。
   縮小サムネイル(縦横比維持・幅上限)としてカード先頭に表示し、抽出値との目視突合を助ける。
   subtask_068a: 旧実装は56x56の正方形枠にcontain指定していたが、実カード比率は縦長
   (実測218x470px前後)のため正方形枠内では横幅26px相当まで潰れ、モジュール/潜在バッジが
   判読不能だった。実カード比率に合わせたaspect-ratioの縦長枠へ変更し、幅も80pxへ拡大する
   （一覧性とのバランス、常時これ以上の拡大はカードリストが過度に縦長化するため見送り——
   さらなる拡大確認はクリックでのライトボックス拡大(.import-thumb-zoom-*)で担保する）。 */
.import-card-thumb{
  flex-shrink:0;width:80px;aspect-ratio:218/470;object-fit:contain;border-radius:6px;
  background:var(--panel);border:1px solid var(--border);
}
.import-card-thumb-loading{opacity:.35;}
.import-card-thumb:not(.import-card-thumb-loading){cursor:pointer;}
.import-card-thumb:not(.import-card-thumb-loading):hover{outline:2px solid var(--accent);outline-offset:1px;}

/* ---------- カード画像クリック時のライトボックス拡大（subtask_068a） ---------- */
.import-thumb-zoom-overlay{
  display:none;position:fixed;inset:0;z-index:110;
  align-items:center;justify-content:center;
  background:rgba(5,7,14,.82);padding:24px;
}
.import-thumb-zoom-overlay.active{display:flex;}
.import-thumb-zoom-box{
  position:relative;max-width:92vw;max-height:92vh;
  background:var(--panel);border:1px solid var(--border);border-radius:10px;
  padding:18px;display:flex;flex-direction:column;align-items:center;gap:8px;
}
.import-thumb-zoom-img{max-width:min(78vw,420px);max-height:74vh;object-fit:contain;border-radius:6px;}
.import-thumb-zoom-label{font-size:13px;font-weight:700;color:var(--text);}
.import-thumb-zoom-close{
  position:absolute;top:6px;right:6px;width:28px;height:28px;border-radius:999px;
  border:1px solid var(--border);background:var(--panel-2);color:var(--text);
  font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;
}
.import-thumb-zoom-close:hover{opacity:.85;}
.import-card-title{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;flex:1;min-width:0;}
.import-card-title .stars{color:var(--rar5);font-size:11px;letter-spacing:1px;font-weight:400;}
.import-card-tags{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end;}
.import-tag{
  font-size:10px;font-weight:700;border-radius:999px;padding:1px 8px;white-space:nowrap;
}
.import-tag.ok{color:var(--accent);background:rgba(79,209,197,.14);border:1px solid var(--accent);}
.import-tag.warn{color:var(--accent-2);background:rgba(242,193,78,.14);border:1px solid var(--accent-2);}
.import-tag.occlusion{color:var(--danger);background:rgba(239,111,111,.14);border:1px solid var(--danger);}
/* cmd_0158是正: rgba(148,148,148,.14)は.import-card自体の背景(--panel-2)とほぼ同じ明度の
   グレーで、実測コントラスト比3.98(WCAG AA 4.5未達・唯一opacityでなく常時表示の是正箇所)。
   同ファイル内の他.import-tag(ok/warn/occlusion)と違い前景色と無関係な固定グレーを
   使っていた不整合でもある。.readonly-badge等と同じ「--panel(単色)+--text-dim」の
   組へ揃え、他タグと同じく前景色ベースの背景へ改める(実測: 是正後5.37)。 */
.import-tag.jp-unavailable{color:var(--text-dim);background:var(--panel);border:1px solid var(--text-dim);}
.import-occlusion-note{font-size:11px;color:var(--danger);margin-top:4px;}
.import-card-fields{display:grid;grid-template-columns:1fr 1fr;gap:5px 12px;font-size:12px;margin-bottom:8px;}
.import-card-field{display:flex;justify-content:space-between;gap:6px;color:var(--text-dim);}
.import-card-field b{color:var(--text);font-weight:600;}
.import-card-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:6px 0;border-top:1px solid #202b45;font-size:12px;}
.import-card-row .k{color:var(--text-dim);flex-shrink:0;}
/* cmd_0163第五段再追補(殿要望・三まとまりの区切り線): 潜在・スキル特化・モジュールの
   各まとまりの★前★にだけ、既存の行線(#202b45)とは別色の差し色細線を置く。色は
   殿指定の#2ee6c5系を薄めた(rgba .35、数字より目立たぬ強さ)ものを使う。まとまり
   内部(S1→S2→S3間、X→Y→α間)は線を入れない(import-card-row-no-border)。
   border-topは行の横方向の位置・幅には影響しないため、右揃え(f8856a6で確立)は
   影響を受けない。実測はtest/import_card_row_alignment_cmd0163.test.js・
   test/import_card_row_alignment_real_chrome_cmd0163.test.js参照。 */
.import-card-row-section-start{border-top:1px solid rgba(46,230,197,.35);}
.import-card-row-no-border{border-top:none;}
/* ★cmd_0163第五段追補・殿訂正で撤回★: 直前まで.import-card-row-aligned
   (display:grid;grid-template-columns:100px 1fr)で潜在/スキル特化/モジュールSTAGEの
   3行のボタン列を左揃えへ変更していたが、殿の実見の上でのご指示により撤回した。
   正: 候補再選択(altRow)・全オペレーター検索(searchRow)と同じく、ボタン列は
   カードの右辺へ右揃えとする。.import-card-row(flex+justify-content:space-between)の
   まま(左のspanラベルが左端、右の内容(セグメントボタン/select/input)が右端へ
   space-betweenで押し出される)であれば、右側の内容要素は常に行の右端=カードの
   右端(paddingを除く)へ一致する——この性質はflexboxの仕様上、行の横幅やラベルの
   文字数に依存せず常に成立する(★狭幅/広幅どちらでも構造的に保証される★)。
   ★さらに殿再指摘(現物確認)・軍師QC FIND-1で判明★: モジュール/スキルが複数ある
   場合、旧実装は.import-module-stage-inputs/.import-spec-inputs(flex-wrap:wrap)で
   複数のseg-controlを1行にまとめて詰め込んでいた。グループ全体の右端は行の右端に
   揃っても、折り返し(flex-wrap)が起きると個々のボタンは折り返し先の行の左端から
   並び直すため、「最後のボタンの右端=行の右端」という前提が崩れる(軍師QC FIND-1が
   指摘した現象そのもの)。是正として、モジュール種別・スキルの1つ1つを★独立した
   .import-card-row★として展開する形に改めた(renderCard()のmoduleStageRows/specRows
   参照)——1行あたりのseg-controlは単独(0〜3の4ボタンのみ)となり、通常のカード幅
   では折り返しが起きる想定が無く、折り返しに起因する右端ズレの起きようが無い
   設計そのものにした(justify-content:flex-endのような折り返し時の緩和策ではなく、
   折り返しが起きる構造自体を無くす形で対処)。実測はtest/
   import_card_row_alignment_cmd0163.test.js・test/import_card_row_alignment_real_chrome_cmd0163.test.js参照。 */
.import-alt-select{
  background:var(--panel);border:1px solid var(--border);border-radius:6px;
  color:var(--text);font-size:11px;padding:4px 6px;max-width:220px;
  /* cmd_0318是正: 殿の実機指摘「オペレーター名が長くなるとプルダウンがはみ出る」。
     真因は.import-card-row(display:flex)の子であるselectの既定min-width:auto
     ——flexアイテムは中身(選択中option文字列)の最小コンテンツ幅より縮まない既定
     挙動により、max-width:220pxを指定していても狭幅(375px)ではラベル(候補を選び
     直す)+gapと合わせてカード右端をはみ出していた(実測: 375pxでselect右端が
     カード右端を19.5pxはみ出し。1280pxでは発生せず——狭幅特有)。
     min-width:0で自動最小幅を解除しflex-shrinkを効かせ、text-overflow:ellipsis
     (要overflow:hidden;white-space:nowrap)で縮んだ分だけ選択中テキストを省略
     表示する(選択自体・値は変わらない、見た目の収まりのみの是正)。 */
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.import-potential-input{
  width:60px;background:var(--panel);border:1px solid var(--border);border-radius:6px;
  padding:4px 6px;color:var(--text);font-size:12px;text-align:right;
}
.import-search-input{
  background:var(--panel);border:1px solid var(--border);border-radius:6px;
  color:var(--text);font-size:11px;padding:4px 6px;max-width:220px;width:100%;
}
.import-module-stage-input{
  width:44px;background:var(--panel);border:1px solid var(--border);border-radius:6px;
  padding:4px 6px;color:var(--text);font-size:12px;text-align:right;
}
.import-spec-input{
  width:44px;background:var(--panel);border:1px solid var(--border);border-radius:6px;
  padding:4px 6px;color:var(--text);font-size:12px;text-align:right;
}
.import-skip-row label{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-dim);cursor:pointer;}
.import-unresolved-note{font-size:11px;color:var(--danger);margin-top:4px;}

/* ---------- 画像取込：確認画面のヘッダー/フッター固定（subtask_065a・殿要望） ----------
   .modal-box自体がスクロールコンテナ(overflow-y:auto)のため、その内側でposition:stickyを
   使う。.modal-boxのpadding(22px、cmd_051の@media内訳は下記2箇所で追従)を負のmarginで
   相殺しつつ同じ値をpaddingで戻すことで、スクロール時にヘッダー/フッターがスクロール
   コンテナの縁まで隙間なく張り付く（下記の定番パターン）。他の.modal-box利用箇所
   （個別編集モーダル等）には影響しないよう、import-step-confirm配下のみに限定するクラス名とした。 */
.import-confirm-sticky-header{
  position:sticky;top:-22px;z-index:5;background:var(--panel);
  margin:-22px -22px 0;padding:22px 22px 10px;
  box-shadow:0 4px 8px -6px rgba(0,0,0,.4);
}
.import-confirm-sticky-header h2{margin-bottom:4px;}
.import-confirm-sticky-header .modal-sub{margin-bottom:10px;}
.import-confirm-sticky-header .import-legend{margin-bottom:0;}
.import-confirm-sticky-footer{
  position:sticky;bottom:-22px;z-index:5;background:var(--panel);
  /* cmd_0317: 殿の実機確認「ボタン下にもスペースが欲しい」を反映。
     stickyの底辺はmodal-boxの内側へ合わせたまま、ボタンの下に最低32pxを
     確保する。safe-areaのある端末ではその分も加算し、画面の縁に指が貼り
     付かないようにする。 */
  margin:0 -22px -22px;padding:10px 22px calc(32px + env(safe-area-inset-bottom));
  box-shadow:0 -4px 8px -6px rgba(0,0,0,.4);
}
.import-confirm-sticky-footer .modal-desc{margin-bottom:10px;}
/* cmd_0163第三段: フッターが2ボタン(戻る/一括確定する)から3ボタン(キャンセル/
   閉じる/保存)へ増えたため、狭幅スマホでの横あふれを避けflex-wrapを許可する
   (.import-confirm-pagination等、同ファイル内の他フッター系要素と同じ対処)。 */
.import-confirm-sticky-footer .modal-actions{margin-top:0;flex-wrap:wrap;}

/* cmd_0291: 破棄を伴う「キャンセル」は、隣接する「閉じる」(中立)・
   「保存」(主操作)と同じ見た目にならぬよう、彩度を抑えた暖色境界で意味を
   分ける。先頭の×記号でもキャンセル操作を識別できるようにする。文言は
   既存の読み上げ/回帰契約を保つため変更しない。
   ★cmd_0316是正★: 殿の実機確認(2026-08-19 20:40)「キャンセルボタンの
   枠線は破線じゃなくていい」を受け、破線(dashed)だけを通常の実線(solid)へ
   改める。暖色(background/color/border色)と間合い(margin-inline-end)は
   cmd_0291のまま維持する——殿はその区別自体は良しとされておる。 */
.import-confirm-cancel-action{
  background:#5b3d3a;color:#ffe8df;border:1px solid #c58a7d;
}
.import-confirm-cancel-action::before{content:"× ";font-weight:800;}
.import-confirm-sticky-footer .btn.secondary.import-confirm-cancel-action{
  /* .btn.secondary (specificity 0,2)より強くし、secondaryの背景へ戻らぬようにする。 */
  background:#5b3d3a;color:#ffe8df;border:1px solid #c58a7d;
}
.import-confirm-sticky-footer .btn.secondary.import-confirm-cancel-action:hover{background:#704a45;opacity:1;}
.import-confirm-sticky-footer .btn.secondary.import-confirm-cancel-action:focus-visible{
  outline:2px solid #e5a99a;outline-offset:2px;
}
.import-confirm-sticky-footer .modal-actions{
  justify-content:flex-end;column-gap:14px;row-gap:10px;
}
/* cmd_0291 redo3: column-gapは隣接ボタン共通の14pxを維持しつつ、破棄を伴う
   キャンセルだけに追加の14pxを持たせる。これによりキャンセル→閉じるは28px、
   閉じる→取込確定(保存)は14pxとなり、操作の危険度の境界を視覚的にも保つ。 */
.import-confirm-sticky-footer .modal-actions .import-confirm-cancel-action{
  margin-inline-end:14px;
}

/* cmd_0323: 保存通知を画面中央上部へ置き、操作対象を覆わない。
   幅の狭い端末でも左右16pxの余白内へ収め、pointer-events:noneで通知表示中も
   背後のボタン操作を奪わない。z-indexはcmd_0285の実描画是正を維持する。 */
/* cmd_0285是正(subtask_cmd0285_toast_occlusion_fix): 従来z-index未指定(auto)だと、
   #import-step-confirm(.page-view、z-index:50、position:fixed)を開いた状態で保存操作を
   行った際、.toastがpage-viewの背後へ回り実描画上見えなくなっていた(殿実機症状。
   z-index:autoは同一スタッキング文脈内で正のz-indexを持つ要素より必ず下に描かれるため)。
   .page-view/.modal-overlay(いずれもz-index:50)を開いたまま出るmodeless通知である以上、
   その上に常時見える必要がある——既に同じ理由で新設済みの.import-version-banner-floating
   (z-index:51、page-viewの上に常時出す既存の帯)と同じ値へ揃える(整合)。 */
.toast{
  display:none;position:fixed;top:16px;left:50%;right:auto;bottom:auto;
  transform:translateX(-50%);z-index:51;pointer-events:none;
  background:var(--accent);color:#0b1220;padding:10px 18px;border-radius:8px;
  font-size:12px;font-weight:700;box-shadow:0 6px 20px rgba(0,0,0,.4);
  width:max-content;max-width:calc(100vw - 32px);box-sizing:border-box;
}
/* cmd_0285: 保存失敗を成功と見分けられるよう、既定(成功=accent)と別色(危険色)で
   modeless通知を出し分ける。要素・配置・タイミングは成功時と同一(モードレスを保つ)。 */
.toast.toast--error{background:var(--danger);color:#1a0a0a;}

/* =====================================================================
   レスポンシブ対応（cmd_051・subtask_051a）
   PC向けスタイルは上記のまま維持し、以下のメディアクエリのみでスマホ／
   タブレット幅の崩れ（カード縦折り返し・横あふれ・過剰な文字折り返し）
   を是正する。デスクトップ幅（769px以上）では一切適用されない。
   ===================================================================== */

/* ---------- タブレット幅（〜768px）：サイドバーをオフキャンバス化 ---------- */
@media (max-width: 768px) {
  .topbar-hamburger{display:inline-flex;}

  .sidebar{
    position:fixed;top:0;left:0;height:100vh;z-index:100;
    /* cmd_0169: 上記base .sidebarと同じ理由でdvhへ上書き(768px以下ではposition:fixedへ
       変わるため、height:100vhの宣言をここでも独立に持つ必要がある)。 */
    height:100dvh;
    width:min(230px,82vw);
    transform:translateX(-100%);
    transition:transform .2s ease;
    box-shadow:4px 0 16px rgba(0,0,0,.45);
  }
  .app.nav-open .sidebar{transform:translateX(0);}
  .app.nav-open .nav-overlay{display:block;}

  /* cmd_0181: cmd_0169追補で.sidebar-footer(下部)へ足していた固定64px+
     safe-area余白は、ログインUIそのものを.sidebar-brand直下(上部)へ移設した
     ことで対象(旧.sidebar-footer)が消え、死んだ規則になったため撤去した。
     実測(390px/1280px)で#auth-login-btnが可視領域内に収まることを確認済み
     (詳細はcmd_0181実測報告参照)。 */

  .main{width:100%;min-width:0;}
  .content{padding:16px 16px 48px;}

  /* 固定3カラムだとカード幅が1/3に潰れ縦折り返しを起こすため、
     スマホ・タブレット幅ではカードを縦積みにする */
  .stat-grid{grid-template-columns:1fr;}
  .tool-hub-grid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));}

  .server-toggle{width:100%;}

  .modal-box{width:94vw;padding:18px;}
  .import-modal-box{width:94vw;}
  /* cmd_0163第一段: 「スマホは今のまま1列」の明示保証。94vw幅では通常auto-fillが
     成り行きで1列になるが、タブレット寄りの幅(768px近辺)では300pxが2つ入り得るため
     ここで確実に1列へ固定する。 */
  #import-candidate-list{grid-template-columns:1fr;}

  /* subtask_065a: .modal-boxのpadding変更(22px→18px)に追従し、隙間/重なりを防ぐ */
  .import-confirm-sticky-header{top:-18px;margin:-18px -18px 0;padding:18px 18px 10px;}
  .import-confirm-sticky-footer{bottom:-18px;margin:0 -18px -18px;padding:10px 18px calc(28px + env(safe-area-inset-bottom));}
}

/* ---------- スマホ幅（〜430px） ---------- */
@media (max-width: 430px) {
  .topbar{padding:0 14px;}
  .content{padding:14px 12px 40px;}
  .panel{padding:14px;}

  .tool-hub-grid{grid-template-columns:1fr;}
  .panel-head-actions{width:100%;grid-template-columns:repeat(2,minmax(0,1fr));}
  .panel-head-actions .btn{width:100%;}
  .panel-head-actions .roster-action-clear{grid-column:1;}
  .panel-head-actions .roster-action-import{grid-column:2;}
  .panel-head-actions #col-settings{grid-column:1;}
  .panel-head-actions #btn-edit{grid-column:2;}
  .panel-head-actions #btn-save{grid-column:1;}
  .panel-head-actions #btn-cancel{grid-column:2;}

  /* subtask_070a: .panelのpadding変更(18px→14px)に追従し、.roster-sticky-headの隙間/重なりを防ぐ。
     subtask_0163_table_controls_outside: 上方向のnegative marginは.roster-toolbar分離に伴い
     base側と同じ理由で外す(左右のみ残す)。 */
  .roster-sticky-head{margin:0 -14px 0;padding:0 14px 10px;}

  .import-card-fields{grid-template-columns:1fr;}
  .modal-box{padding:14px;}

  /* subtask_065a: .modal-boxのpadding変更(22px→14px)に追従し、隙間/重なりを防ぐ */
  .import-confirm-sticky-header{top:-14px;margin:-14px -14px 0;padding:14px 14px 8px;}
  .import-confirm-sticky-footer{bottom:-14px;margin:0 -14px -14px;padding:8px 14px calc(24px + env(safe-area-inset-bottom));}
  .import-card-thumb{width:58px;} /* 狭幅では縮小しカード本文の圧迫を避ける（比率はaspect-ratioで維持） */
  .import-thumb-zoom-img{max-width:88vw;}

  /* cmd_053・subtask_053b: 潜在(1-6)等の狭所セグメントボタンは横あふれさせず折り返す
     (.seg-controlのflex-wrap:wrapで基本担保済み、スマホ幅ではさらにボタン自体を縮小)。 */
  .seg-btn{padding:6px 9px;font-size:11px;}
}

/* ---------- cmd_0163: デモ表示の帯(?demo=1限定・subtask_0163_preview_rebuild_from_lord_sample) ---------- */
/* cmd_0162(旧実装, commit 5d52b88)は独立overlay+専用グリッドで見た目だけを模して
   いたが、cmd_0163是正により本物のImportConfirm.applyCandidates()へ流し込む形へ
   改めた(demoPreview.js参照)。そのため独立のoverlay/grid CSSは不要になり、
   「これはデモです」と常に判る帯(banner)のみが残る。通常導線には一切現れない
   (demoPreview.jsのisDemoRequested()が?demo=1完全一致の時のみDOMへ追加する)。
   本物のモーダル(.modal-overlay z-index:50)の上に常時見える必要があるため、
   ページ全体に対しfixedで最上位に固定する。 */
.demo-preview-banner{
  position:fixed;top:0;left:0;right:0;z-index:9999;
  background:var(--danger);color:#1a0a0a;
  padding:10px 14px;
  font-size:13px;font-weight:700;line-height:1.6;
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
}
.demo-preview-banner button{
  flex-shrink:0;padding:6px 14px;border-radius:6px;border:1px solid #1a0a0a;
  background:#1a0a0a;color:#fff;cursor:pointer;font-size:12px;
}

/* ---------- cmd_0280: 試し場(dev)識別帯(envBanner.js) ---------- */
/* .demo-preview-bannerと同じfixed最上位の帯だが、意味が異なるため危険色(--danger)は
   使わない——demoは「これは偽データだ」という警告、こちらは「今どちらの環境を
   見ているか」という常時の案内である。--accent-2(既存のdirty-indicator等が使う
   注意喚起色)を使い、殿の実機で常時目に入っても警告のように圧迫しない濃さに留める。 */
.env-banner{
  position:fixed;top:0;left:0;right:0;z-index:9998;
  background:var(--accent-2);color:#1a1305;
  padding:8px 14px;
  font-size:12px;font-weight:700;line-height:1.5;
  text-align:center;
}
