/* public/css/style.css */

/* ブランドの表示書体（README: Archivo Bold, OFL）。ローカル同梱・CDN依存なし */
@font-face {
  font-family: 'Archivo Brand';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-bold.ttf') format('truetype');
}

:root {
  color-scheme: light dark;

  /* ブランド不変トークン（ライト/ダーク共通） */
  --red: #ec3013;
  --home: #1e56c8;
  --away: #d8232a;
  --font-brand: 'Archivo Brand', system-ui, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", Consolas, "Roboto Mono", monospace;

  /* ライト（既定） */
  --bg: #faf8f5;
  --surface: #ffffff;
  --ink: #201e1d;
  --muted: #6b6663;
  --divider: #e4e1db;
  --border-c: #201e1d;
  --border-w: 2px;
  --radius: 0px;
  --grid-line: transparent;
  --btn-primary-bg: var(--red);
  --btn-primary-fg: #ffffff;
  --btn-primary-border: var(--red);
  --input-bg: #ffffff;
}
/* OS設定が先に効く。data-theme属性（テーマ切替ボタン・theme.js）が明示的に上書きする */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0a0d11; --surface: #131820; --ink: #d7e1e8; --muted: #7c8896; --divider: #212832;
    --border-c: #212832; --border-w: 1px; --radius: 6px; --grid-line: #212832;
    --btn-primary-bg: rgba(236, 48, 19, .16); --btn-primary-fg: #ff8a72; --btn-primary-border: var(--red);
    --input-bg: #0a0d11;
  }
}
:root[data-theme="light"] {
  --bg: #faf8f5; --surface: #ffffff; --ink: #201e1d; --muted: #6b6663; --divider: #e4e1db;
  --border-c: #201e1d; --border-w: 2px; --radius: 0px; --grid-line: transparent;
  --btn-primary-bg: var(--red); --btn-primary-fg: #ffffff; --btn-primary-border: var(--red);
  --input-bg: #ffffff;
}
:root[data-theme="dark"] {
  --bg: #0a0d11; --surface: #131820; --ink: #d7e1e8; --muted: #7c8896; --divider: #212832;
  --border-c: #212832; --border-w: 1px; --radius: 6px; --grid-line: #212832;
  --btn-primary-bg: rgba(236, 48, 19, .16); --btn-primary-fg: #ff8a72; --btn-primary-border: var(--red);
  --input-bg: #0a0d11;
}

* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; margin: 0; padding: 1rem; background: var(--bg); color: var(--ink); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* キャプチャー専用画面（chart.html）は映像として取り込むため、既定の余白を消してコートを全面表示する。
   フレームの既定背景は純黒（?bg=省略時）。?bg=transparent|green|blue|<6桁16進>で変更できる
   （2026-08-25、龍さんの要望：傾け表示(tilt)時にクロマキー合成しやすいよう透過/任意色にしたい。
   ranking.html等と同じstatsGraphics.jsのapplyBackgroundParam()を共有、bg-*クラスはそちらと同じ値） */
body.chart { margin: 0; padding: 0; overflow: hidden; background: #000; }
body.chart.bg-transparent { background: transparent; }
body.chart.bg-green { background: #00b140; }
body.chart.bg-blue { background: #0057ff; }
body.chart #court-wrap { height: 100vh; display: flex; align-items: center; justify-content: center; }
body.chart #court { width: auto; height: 100%; cursor: none; }
body.chart .shot-mark { font-size: 3vh; }
/* フルコート表示（放送演出用、2026-08-25、?layout=full）。chart.js の parseLayoutParam が
   body要素に layout-full クラスを付ける。#court の aspect-ratio はハーフコート実寸（50/47、
   line 416付近）が既定だが、ここで94/50（横向き、NBA/FIBAフルコート実寸）に上書きする。
   court-svg-half/court-svg-full の表示切替もこのブロックで行う（既定はhalf表示）。
   width/heightをmin()で明示するのは、67行目の`height:100%; width:auto`のままだと
   flexアイテムのmin-width:auto（aspect-ratio転送サイズが最小幅の候補になる仕様）により、
   横長比率94/50が画面のアスペクト比を超えたときに縮小されず左右が画面外に切れる
   バグがあったため（Fableレビューで発見・2026-08-25、16:9で約110px＝実寸2.6ft相当の
   ベースライン欠け）。widthを「画面幅」と「高さ基準の幅」の小さい方に固定し、
   heightをautoにしてaspect-ratioから逆算させることで、どちらの画面比率でも収まる */
.court-svg-full { display: none; }
body.chart.layout-full #court { aspect-ratio: 94 / 50; width: min(100vw, calc(100vh * 94 / 50)); height: auto; }
body.chart.layout-full .court-svg-half { display: none; }
body.chart.layout-full .court-svg-full { display: block; }

/* DataLinq Statsのグラフィック版キャプチャー画面（ranking.html/teamstats.html/stats.html、
   2026-08-20追加）。chart.htmlと同じ「既定は純黒・不透明」にしつつ、?bg=パラメータで
   transparent（NDI Alpha等、透過チャンネル対応のキャプチャー経路向け）・green/blue
   （XPression側のクロマキーエフェクトで抜く前提の単色塗り）を選べる
   （statsGraphics.jsのapplyBackgroundParam()がbodyへクラスを付与する）。 */
/* --sg-thickness：バー本体の太さの倍率。--sg-length：グラフィック全体の横幅の倍率。
   既定1（従来通りの見た目）。statsGraphics.jsのapplySizeParams()が?barThickness=&barLength=
   から書き込む（bgと同じ「無人画面をURLパラメータで設定する」慣習、2026-08-20追加） */
body.stats-chart { margin: 0; padding: 0; overflow: hidden; background: #000; font-family: var(--font-brand); position: relative; height: 100vh; --sg-thickness: 1; --sg-length: 1; }
body.stats-chart.bg-transparent { background: transparent; }
body.stats-chart.bg-green { background: #00b140; }
body.stats-chart.bg-blue { background: #0057ff; }

/* max-width：--sg-length（?barLength=）は当初3倍まで許容していたが、widthをそのままcalcで
   伸ばすと大きな倍率で画面外にはみ出すことが実機レビューで発覚したため上限を1.6に下げた
   （statsGraphics.jsのSIZE_PARAM_RANGE参照）。ここのmax-widthは、URLを直接手打ちされた場合の
   二重の安全策として引き続き残している */
.sg-ranking { position: absolute; left: 5%; top: 12%; width: calc(44% * var(--sg-length)); max-width: 90%; display: flex; flex-direction: column; gap: .55vw; }
.sg-ranking-title { font-size: .9vw; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: #fff; margin-bottom: 2px; text-shadow: 0 2px 6px rgba(0,0,0,.5); display: flex; align-items: center; gap: .5vw; }
.sg-ranking-title::before { content: ''; display: inline-block; width: .55vw; height: .55vw; border-radius: 50%; background: var(--red); flex: none; }

.sg-rank-row { display: flex; flex-direction: column; gap: 3px; }
.sg-rank-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: .6vw; }
.sg-rank-name { font-size: .95vw; font-weight: 700; color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sg-rank-name .num { font-family: var(--font-mono); opacity: .6; margin-right: .4em; }
.sg-rank-value { font-family: var(--font-mono); font-weight: 700; font-size: .95vw; color: #fff; }
.sg-rank-barwrap { height: calc(.75vw * var(--sg-thickness)); background: rgba(255, 255, 255, .12); border-radius: 3px; overflow: hidden; }
.sg-rank-bar { height: 100%; border-radius: 3px; transition: width .4s ease; }

/* left:50%+translateXでwidthを中心固定のまま伸縮できるようにする（left:8%;right:8%という
   両端マージン指定のままだと--sg-lengthで幅だけを倍率できないため、widthベースに変更した） */
.sg-teamstats { position: absolute; left: 50%; bottom: 8%; width: calc(84% * var(--sg-length)); max-width: 94%; transform: translateX(-50%); display: flex; flex-direction: column; gap: .65vw; }
.sg-ts-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: .3vw; }
.sg-ts-team-tag { display: flex; align-items: center; gap: .5vw; font-size: .85vw; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: #fff; text-shadow: 0 1px 4px rgba(0, 0, 0, .5); }
.sg-ts-team-tag .chip { width: .7vw; height: .7vw; border-radius: 2px; flex: none; }
.sg-ts-rows { display: flex; flex-direction: column; gap: .5vw; }
.sg-ts-row { display: grid; grid-template-columns: 1fr 3.2vw 1fr; align-items: center; gap: .6vw; }
/* value列を固定幅、bar列を残り全部にすることで、値の位置を動かさずバーだけをラベル側へ
   伸縮させる（flexのjustify-contentだけだと値の位置がバー長に連動して動いてしまうため） */
.sg-ts-side { display: grid; align-items: center; gap: .5vw; height: calc(.85vw * var(--sg-thickness)); }
.sg-ts-home { grid-template-columns: 2.4vw 1fr; }
.sg-ts-away { grid-template-columns: 1fr 2.4vw; }
.sg-ts-bar { height: 100%; border-radius: 2px; transition: width .4s ease; }
.sg-ts-home .sg-ts-bar { justify-self: start; }
.sg-ts-away .sg-ts-bar { justify-self: end; }
.sg-ts-value { font-family: var(--font-mono); font-weight: 700; font-size: .8vw; color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .5); }
.sg-ts-home .sg-ts-value { text-align: right; }
.sg-ts-away .sg-ts-value { text-align: left; }
.sg-ts-label { font-size: .66vw; font-weight: 700; letter-spacing: .06em; text-align: center; color: rgba(255, 255, 255, .65); text-transform: uppercase; }

/* stats.html（Combined）はrankingを上、teamstatsを下に少し詰めて配置し直す */
body.stats-chart.layout-combined .sg-ranking { top: 8%; width: calc(40% * var(--sg-length)); }
body.stats-chart.layout-combined .sg-teamstats { bottom: 8%; }

/* ============================================================
   デザインテーマ（2026-08-20追加・ユーザー要望：現行のFlat Barに加えて複数の見た目を
   選べるようにしたい）。body.theme-*クラスでスコープし、上のsg-rank-row等（Flat Bar専用）
   とは別クラス名にする。共通のsg-ranking/sg-teamstats（位置決めコンテナ）・
   sg-ts-header/sg-ts-team-tag（チーム名見出し）はテーマ間で使い回す。
   ============================================================ */

/* --- Card：半透明パネル・角丸・チームカラーのアクセントバー・影 --- */
.sg-rank-card { display: flex; align-items: center; gap: .7vw; background: rgba(10, 13, 17, .62); border-radius: 10px; padding: .5vw .8vw; box-shadow: 0 8px 20px rgba(0, 0, 0, .4); border-left: .28vw solid; }
.sg-rank-card.home { border-left-color: var(--home, #3d8bfd); }
.sg-rank-card.away { border-left-color: var(--away, #d8232a); }
.sg-rank-card .sg-rank-num { font-family: var(--font-mono); font-weight: 800; font-size: 1.3vw; color: rgba(255, 255, 255, .28); width: 1.6vw; text-align: center; flex: none; }
.sg-rank-card .sg-rank-body { flex: 1; min-width: 0; }
.sg-rank-card .sg-rank-name { font-size: .9vw; font-weight: 700; color: #fff; white-space: nowrap; }
.sg-rank-card .sg-rank-name .num { font-family: var(--font-mono); opacity: .55; margin-right: .4em; }
.sg-rank-card .sg-rank-barwrap { margin-top: .3vw; height: calc(.3vw * var(--sg-thickness)); background: rgba(255, 255, 255, .14); border-radius: 2px; overflow: hidden; }
.sg-rank-card .sg-rank-bar { height: 100%; border-radius: 2px; }
.sg-rank-card .sg-rank-value { font-family: var(--font-mono); font-weight: 800; font-size: 1.1vw; color: #fff; flex: none; }

.sg-ts-card { background: rgba(10, 13, 17, .62); border-radius: 10px; box-shadow: 0 8px 20px rgba(0, 0, 0, .4); padding: .55vw .9vw; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .6vw; }
.sg-ts-card .sg-ts-label { font-size: .62vw; font-weight: 700; letter-spacing: .08em; text-align: center; color: rgba(255, 255, 255, .6); text-transform: uppercase; }
.sg-ts-card .sg-ts-value { font-family: var(--font-mono); font-weight: 800; font-size: .95vw; color: #fff; }
.sg-ts-card .sg-ts-home-cell { display: flex; align-items: center; justify-content: flex-end; gap: .4vw; }
.sg-ts-card .sg-ts-away-cell { display: flex; align-items: center; gap: .4vw; }
.sg-ts-card .sg-ts-dot { width: .5vw; height: .5vw; border-radius: 50%; flex: none; }

/* --- Ticker：画面下部の帯（ロワーサード風）。位置は下固定のみ意味を持つため、
   position系の指定（statsGraphics.jsのapplyRankingPosition/applyTeamstatsPositionが
   書き込むインラインstyle）が付いていても無効化する */
body.stats-chart.theme-ticker .sg-ranking, body.stats-chart.theme-ticker .sg-teamstats { position: static; left: auto; right: auto; top: auto; bottom: auto; width: auto; transform: none; }
/* ranking.html/stats.htmlの静的な"Top Scorers"見出しは、他テーマではsg-rankingが
   position:absoluteの枠として機能する前提で常時表示している。ticker themeではsg-rankingが
   position:staticになり、この見出しがticker帯とは別に画面左上へ孤立して二重表示されてしまう
   （tickerは内部に自前のタイトルsg-tk-titleを持つため）。2026-08-20、実機レビューで発覚 */
body.stats-chart.theme-ticker .sg-ranking-title { display: none; }
.sg-ticker { position: absolute; left: 0; right: 0; bottom: 6%; background: rgba(6, 8, 11, .72); display: flex; align-items: center; padding: calc(.55vw * var(--sg-thickness)) 3%; gap: 0; overflow: hidden; border-top: 2px solid var(--red); }
/* Combined（stats.html）はranking用・teamstats用の2本のtickerが同時に存在するが、
   どちらも上のsg-ticker既定ルールでbottom:6%に描画されるため完全に重なって判読不能になっていた
   （2026-08-20、実機レビューで発覚）。rankingのtickerを上部へ移動し、teamstats側は
   既定の下部のままにすることで分離する */
body.stats-chart.layout-combined.theme-ticker .sg-ranking .sg-ticker { top: 0; bottom: auto; border-top: none; border-bottom: 2px solid var(--red); }
.sg-ticker .sg-tk-title { font-size: .62vw; font-weight: 800; letter-spacing: .1em; color: var(--red); text-transform: uppercase; padding-right: 1.2vw; margin-right: 1.2vw; border-right: 1px solid rgba(255, 255, 255, .2); flex: none; }
.sg-ticker .sg-tk-item { display: flex; align-items: baseline; gap: .4vw; padding: 0 1.1vw; border-right: 1px solid rgba(255, 255, 255, .14); white-space: nowrap; }
.sg-ticker .sg-tk-item:last-child { border-right: none; }
.sg-ticker .sg-tk-num { font-family: var(--font-mono); font-size: .66vw; color: rgba(255, 255, 255, .5); }
.sg-ticker .sg-tk-name { font-size: .8vw; font-weight: 700; color: #fff; }
.sg-ticker .sg-tk-val { font-family: var(--font-mono); font-weight: 800; font-size: .8vw; }
.sg-ticker .sg-tk-stat-label { font-size: .62vw; font-weight: 700; letter-spacing: .06em; color: rgba(255, 255, 255, .55); text-transform: uppercase; }
.sg-ticker .sg-tk-stat-val { font-family: var(--font-mono); font-weight: 800; font-size: .8vw; }

/* --- Dot：バーの塊を使わず、細線＋ドットで値を示す --- */
.sg-dot-item { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: .4vw; }
.sg-dot-item .sg-rank-top { display: flex; justify-content: space-between; align-items: baseline; }
.sg-dot-item .sg-rank-name { font-size: .85vw; font-weight: 700; color: rgba(255, 255, 255, .92); }
.sg-dot-item .sg-rank-name .num { font-family: var(--font-mono); opacity: .5; margin-right: .4em; font-size: .7vw; }
.sg-dot-item .sg-rank-value { font-family: var(--font-mono); font-weight: 700; font-size: .78vw; color: rgba(255, 255, 255, .75); }
/* margin-right：pct=100%（1位）のときrank-dotがtrack右端からはみ出し、右隣のrank-valueと
   重なって見づらくなるため、ドット半径分の余白をtrack自体に持たせて内側に収める */
.sg-dot-item .sg-rank-track { position: relative; height: calc(2px * var(--sg-thickness)); background: rgba(255, 255, 255, .16); margin: .35vw calc(.4vw * var(--sg-thickness)) 0 0; }
.sg-dot-item .sg-rank-fill { position: absolute; left: 0; top: 0; height: 100%; background: rgba(255, 255, 255, .3); }
.sg-dot-item .sg-rank-dot { position: absolute; top: 50%; width: calc(.55vw * var(--sg-thickness)); height: calc(.55vw * var(--sg-thickness)); border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 3px rgba(0, 0, 0, .5); }

.sg-ts-dot-row { display: grid; grid-template-columns: 1fr 3vw 1fr; align-items: center; gap: .6vw; }
.sg-ts-dot-row .sg-ts-label { font-size: .6vw; font-weight: 700; letter-spacing: .08em; text-align: center; color: rgba(255, 255, 255, .55); text-transform: uppercase; }
/* margin：ts-dotが0%/100%端に来たとき隣のts-valueと重なるのを防ぐため、ドット半径分の
   余白をtrack自体の左右に持たせる（sg-rank-trackと同じ理由） */
.sg-ts-dot-row .sg-ts-track { position: relative; height: calc(1px * var(--sg-thickness)); background: rgba(255, 255, 255, .2); width: 70%; margin: 0 calc(.45vw * var(--sg-thickness)); }
.sg-ts-dot-row .sg-ts-home-wrap .sg-ts-track { margin-left: auto; }
.sg-ts-dot-row .sg-ts-dot { position: absolute; top: 50%; width: calc(.6vw * var(--sg-thickness)); height: calc(.6vw * var(--sg-thickness)); border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 3px rgba(0, 0, 0, .55); }
.sg-ts-dot-row .sg-ts-value { font-family: var(--font-mono); font-weight: 700; font-size: .75vw; color: rgba(255, 255, 255, .85); flex: none; }
.sg-ts-dot-row .sg-ts-value-wrap { display: flex; align-items: center; gap: .4vw; }
.sg-ts-dot-row .sg-ts-home-wrap { justify-content: flex-end; }

/* 「奥行きのある表示」オプション（2026-08-15、実機テスト中のユーザー要望：ブロードキャスト風の
   角度付きコート表現をXPression側で使いたい）。chart.jsがtilt/swing/perspクエリパラメータを
   このCSS変数へ書き込む。既定値（0deg/0deg/1200px）ではtransformは実質恒等変換のままなので、
   パラメータを指定しない限り従来通りの真上からの平面表示になる。座標計算・ショットマークの
   位置ロジック（shotChart.js）は無改修——コート全体を1枚の平面としてCSSで傾けるだけ。
   transform-originを手前（bottom）にすることで、手前の縁を軸に奥（ゴール側）が
   カメラから遠ざかるように傾く、見慣れた「見下ろし」の見た目になる */
/* #chart-previewはsetup.htmlの配信画面プレビュー（2026-08-15追加）。body.chart #courtと
   同じ変数・transformを共有し、実際のchart.htmlと見た目を一致させる */
body.chart #court, #chart-preview {
  --court-tilt: 0deg;
  --court-swing: 0deg;
  --court-perspective: 1200px;
  --court-scale: 1;
  transform-origin: 50% 100%;
  transform: perspective(var(--court-perspective)) rotateX(var(--court-tilt)) rotateY(var(--court-swing)) scale(var(--court-scale));
}
/* プレビューはサムネイル程度の固定幅（chart.html自体は100vhでキャプチャー枠いっぱいに広げるが、
   setup.html上はフォームの一部として控えめに表示する。当初はwidth:55%で親要素いっぱいに
   広がる設計だったが、.setupにmax-widthが無くページ全幅に対する55%になり画面のほとんどを
   占領してしまっていたため、2026-08-20に固定幅へ変更した）。背景・線色はコート本体（#court）と
   同じCSS変数（--court-bg-override等、shotChart.jsのapplyCourtColors()が書き込む）を参照する */
#chart-preview-wrap { background: #000; padding: .6rem; display: flex; align-items: center; justify-content: center; overflow: hidden; }
/* 幅は11rem→24remへ拡大（2026-08-26、龍さんの要望：「プレビュー内の画像をもう一回り大きく」）。
   コート画像を貼ったときに絵柄まで確認できる大きさを優先した。当初の失敗（width:55%＝
   ページ全幅に対する割合指定で画面のほとんどを占領した）を繰り返さないよう、
   割合ではなくrem固定＋max-width:100%のままにしてある（画面幅がいくら広くても24remで頭打ち） */
#chart-preview { position: relative; width: 24rem; max-width: 100%; aspect-ratio: 50 / 47; background: var(--court-bg-override, var(--surface)); }
/* ハーフ/フルコート切替プレビュー（2026-08-25追加）。chart.html側の
   court-svg-half/court-svg-full表示切替・aspect-ratio上書きと同じパターン。
   widthは11rem固定のまま（heightはaspect-ratioから自動計算されるので、
   フル時は横長=高さが縮む形でサムネイル内に収まる） */
#chart-preview .court-svg-full { display: none; }
#chart-preview.layout-full { aspect-ratio: 94 / 50; }
#chart-preview.layout-full .court-svg-half { display: none; }
#chart-preview.layout-full .court-svg-full { display: block; }
/* プレビューにもコート画像を反映する（2026-08-26追加）。#court.custom-court-image と同じく、
   画像を敷いたときは簡易コート線を消す（実写画像と二重に見えるため）。
   .court-lineはhalf/full両方のSVGが持つクラスなので、この1行で両レイアウトに効く */
#chart-preview.custom-court-image .court-line { display: none; }
.preview-layout-toggle { display: flex; align-items: center; gap: .4rem; margin-bottom: .5rem; font-size: .85rem; }

/* 既存試合の設定変更モード（2026-08-26追加、/setup.html?gameId=...）。
   ロースター欄（.roster-field＝テキストエリアとCSVボタン）とチーム単位記録モードの
   トグルを隠す：この画面からロースターを保存し直すと先頭5人がスターター＝コート上の
   5人として再解釈され、試合中の出場選手が入れ替わってしまうため、setup.js側でも
   保存しない（チーム単位記録モードもロースターの有無を決める設定なので同じ理由で隠す）。
   チーム単位記録モードのトグル（.team-only-toggle）が既存の非表示ロジックと衝突しないよう、
   ここではbody側のクラスで指定して詳細度を上げている */
body.setup-edit-mode .roster-field,
body.setup-edit-mode .team-only-toggle,
body.setup-edit-mode .team-only-toggle + .hint { display: none; }
#setup-edit-banner #setup-edit-game { font-weight: 700; }

/* --- ヘッダー（ロゴロックアップ・テーマ/言語トグル。setup.html/live.html共通） --- */
.app-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-bottom: .9rem; margin-bottom: 1rem; border-bottom: 1px solid var(--divider); flex-wrap: wrap; }
.brand-group { display: flex; align-items: center; }
.lockup { display: flex; align-items: center; height: 1.9rem; text-decoration: none; }
.lockup img { height: 1.9rem; width: auto; display: block; }
.lockup .logo-dark { display: none; }
:root[data-theme="dark"] .lockup .logo-light { display: none; }
:root[data-theme="dark"] .lockup .logo-dark { display: block; }
.page-title { font-family: var(--font-brand); font-weight: 700; font-size: .8rem; letter-spacing: .04em; color: var(--muted); margin: 0 0 0 .9rem; padding-left: .9rem; border-left: 1px solid var(--divider); }
.header-actions { display: flex; align-items: center; gap: .5rem; }
.theme-toggle { display: inline-flex; align-items: center; gap: .35rem; }

/* アシスト確認トグル（2026-08-15、実機テスト中のユーザー要望：チェックボックスだと
   ON/OFFが分かりにくいのでスイッチ見た目にしたい）。裏のinput[type=checkbox]自体は
   残す（アクセシビリティ・キーボード操作・既存のchangeイベント配線をそのまま使うため）。
   trackの色とthumbの位置、および明示的なON/OFF文字の両方で状態を分かりやすくする。 */
.assist-prompt-toggle { display: inline-flex; align-items: center; gap: .4rem; cursor: pointer; user-select: none; font-size: .8rem; }
.assist-prompt-toggle input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.assist-prompt-toggle .switch-track {
  position: relative; display: inline-block; width: 2.4rem; height: 1.3rem; flex-shrink: 0;
  background: var(--muted); border: var(--border-w) solid var(--border-c); border-radius: 999px;
  transition: background-color .15s ease;
}
.assist-prompt-toggle .switch-thumb {
  position: absolute; top: 50%; left: .15rem; transform: translateY(-50%);
  width: .9rem; height: .9rem; border-radius: 50%; background: var(--surface);
  transition: left .15s ease;
}
.assist-prompt-toggle input:checked + .switch-track { background: var(--red); }
.assist-prompt-toggle input:checked + .switch-track .switch-thumb { left: calc(100% - .9rem - .15rem); }
.assist-prompt-toggle input:focus-visible + .switch-track { outline: 2px solid var(--red); outline-offset: 2px; }
.assist-prompt-toggle .switch-state { font-family: var(--font-brand); font-weight: 700; letter-spacing: .03em; min-width: 2em; }
.assist-prompt-toggle .switch-state-on { display: none; color: var(--red); }
.assist-prompt-toggle .switch-state-off { display: inline; color: var(--muted); }
.assist-prompt-toggle input:checked ~ .switch-state-on { display: inline; }
.assist-prompt-toggle input:checked ~ .switch-state-off { display: none; }

#lang-toggle { min-width: 3rem; }

/* --- ログイン画面（login.html） --- */
.login-page { display: flex; min-height: calc(100vh - 2rem); align-items: center; justify-content: center; }
.login-card { width: 100%; max-width: 22rem; padding: 2rem; background: var(--surface); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.login-card .lockup { height: 2.4rem; margin-bottom: .5rem; }
.login-card .lockup img { height: 2.4rem; }
.login-card h1 { font-family: var(--font-brand); font-size: 1rem; letter-spacing: .04em; margin: 0; color: var(--muted); }
.login-card form { width: 100%; display: flex; flex-direction: column; gap: .9rem; }
.login-card label { display: block; }
.login-card label span { display: block; margin-bottom: .3rem; font-family: var(--font-brand); font-weight: 700; font-size: .75rem; letter-spacing: .04em; color: var(--muted); text-transform: uppercase; }
.login-card input { width: 100%; background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .55rem .6rem; }
.login-card button { width: 100%; }
.login-card .error { margin: 0; }

/* --- オンラインデモ版の開始画面（demo-start.html、2026-08-15） --- */
/* .login-card（22rem）だと日英併記の文章には狭すぎて、単語の途中や
   「不要で／す。」のように不自然な位置で折り返ってしまうバグの対策（実機確認）。
   幅を広げ、text-wrap: prettyで折り返し自体も改善する */
.demo-card { text-align: center; max-width: 28rem; }
.bilingual-heading { font-size: .9rem; }
/* 日英併記（海外からの来訪者向け）。2行目（日本語）をやや控えめにして視線誘導する */
.bilingual-block span { display: block; text-wrap: pretty; }
.bilingual-block span:last-child { margin-top: .25rem; color: var(--muted); font-size: .9em; }
.demo-welcome { width: 100%; display: flex; flex-direction: column; align-items: center; gap: .7rem; }
.demo-badge { font-family: var(--font-brand); font-weight: 700; font-size: .7rem; letter-spacing: .1em; color: var(--red); border: 1.5px solid var(--red); padding: .25rem .6rem; text-transform: uppercase; }
.demo-welcome-text { margin: 0; color: var(--muted); }
.demo-welcome button.primary { width: auto; padding: .65rem 1.6rem; }
.demo-intro { margin: 0; color: var(--muted); }
.demo-wait { width: 100%; display: flex; flex-direction: column; align-items: center; gap: .8rem; }
.demo-wait-message { margin: 0; color: var(--ink); }
.demo-position { margin: 0; font-family: var(--font-brand); font-weight: 700; color: var(--red); }
.demo-characters { display: flex; gap: 1.1rem; align-items: flex-end; }
.demo-characters img { width: 4.2rem; height: auto; }
.demo-countdown-label { margin: 0; font-family: var(--font-brand); font-weight: 700; font-size: .75rem; letter-spacing: .04em; color: var(--muted); text-transform: uppercase; }
.demo-countdown { margin: 0; font-family: "Consolas", "SFMono-Regular", monospace; font-variant-numeric: tabular-nums; font-size: 2rem; color: var(--red); }
/* .demo-welcome/.demo-waitのdisplay:flexが[hidden]（UAスタイル）と同格の詳細度のため、
   後勝ちの author stylesheet 側が常に勝ってしまい、hidden属性を付けても表示され続ける
   既知のバグパターン（.roster-field[hidden]等と同じ）。ウェルカム画面追加で新たに顕在化した
   （以前はavailable時に即リダイレクトしていたため隠れて見えていなかった） */
.demo-welcome[hidden], .demo-wait[hidden] { display: none; }
/* 2026-08-15追加：「順番が近づいたらメールで知らせる」の任意登録フォーム */
.demo-email-form { width: 100%; display: flex; flex-direction: column; align-items: center; gap: .5rem; padding-top: .6rem; border-top: var(--border-w) solid var(--border-c); }
.demo-email-label { font-size: .85rem; }
.demo-email-row { width: 100%; display: flex; gap: .5rem; }
.demo-email-row input { flex: 1; min-width: 0; background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .5rem .6rem; }
.demo-email-row button { width: auto; white-space: nowrap; }
.demo-email-consent { display: flex; align-items: flex-start; gap: .4rem; text-align: left; font-size: .8rem; color: var(--muted); cursor: pointer; }
.demo-email-consent input { margin-top: .2rem; }
.demo-email-status { margin: 0; font-size: .85rem; color: var(--muted); }

/* --- TOPページ（index.html） --- */
.top-page { max-width: 40rem; margin: 0 auto; }
.top-actions { margin-bottom: 1.5rem; }
.games-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.games-list li { border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .75rem .9rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.game-info { display: flex; flex-direction: column; gap: .2rem; }
.game-teams { font-family: var(--font-brand); font-weight: 700; }
.game-meta { color: var(--muted); font-size: .85rem; }
.games-empty { color: var(--muted); }
.game-actions { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.import-backup { margin-bottom: 1.5rem; padding: .75rem; border: 1px solid var(--divider); border-radius: var(--radius); }
.import-backup h2 { margin-top: 0; }

/* --- マニュアル一覧ページ（manual.html） --- */
.page-heading { font-family: var(--font-brand); font-weight: 700; font-size: 1.1rem; margin: 0 0 1rem; }
.manual-card { margin-bottom: 1rem; padding: .9rem 1rem; border: var(--border-w) solid var(--border-c); border-radius: var(--radius); }
.manual-card h2 { margin: 0 0 .6rem; font-family: var(--font-brand); font-weight: 700; font-size: .95rem; }
.manual-links { display: flex; flex-wrap: wrap; gap: .5rem; }
/* max-width：無指定だと#chart-previewのwidth:55%等、割合指定の子要素がページ全幅基準で
   巨大化する（2026-08-20に発覚・修正）。.live（max-width:64rem）と同じ考え方で読みやすい幅に収める */
.setup { max-width: 48rem; margin: 0 auto; }
.setup fieldset { margin-bottom: 1rem; }
.setup label { display: block; margin-bottom: 0.5rem; }
.error { color: var(--red); font-weight: 700; }
input, textarea, button { font: inherit; }
input[type="checkbox"] { accent-color: var(--red); }
button, .link-btn {
  padding: 0.5rem 0.75rem; cursor: pointer; touch-action: manipulation; /* touch-action: タッチ時のダブルタップズームを抑止 */
  font-family: var(--font-brand); font-weight: 700; font-size: .8rem; letter-spacing: .02em;
  border: var(--border-w) solid var(--border-c); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}
.link-btn { display: inline-block; text-decoration: none; } /* <a>タグはbuttonのタグセレクタ由来の見た目を継承しないため明示する */
button:hover, .link-btn:hover { border-color: var(--red); color: var(--red); }
button:focus-visible, .link-btn:focus-visible { outline: 3px solid var(--red); outline-offset: 2px; }
button.primary, .btn-primary {
  background: var(--btn-primary-bg); color: var(--btn-primary-fg); border-color: var(--btn-primary-border);
}
button.primary:hover, .btn-primary:hover { color: var(--btn-primary-fg); }
.setup input[type="text"], .setup input[type="number"], .setup textarea { width: 100%; max-width: 24rem; box-sizing: border-box; }
.setup input[type="text"], .setup input[type="number"], .setup input[type="date"], .setup input[type="time"], .setup textarea {
  background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .45rem .55rem;
}
.csv-controls, .bulk-csv-controls { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin: 0.25rem 0 0.75rem; }
/* チーム単位記録モード（2026-08-15）のチェックボックスでロースター欄を隠す際のバグ対策。
   .roster-fieldは<label>（.setup labelのdisplay:blockが適用される）と<div class="csv-controls">
   （.csv-controlsのdisplay:flexが適用される）の両方に付くが、どちらもorigin/詳細度が
   [hidden]のUAスタイル（display:none）と同格以上のため、hidden属性をJSでtrueにしても
   実際には隠れないバグが実機確認で発覚した（.panel[hidden]と同じ既知の問題パターン）。
   同じoriginでより詳細度の高いセレクタとして明示的に上書きする */
.roster-field[hidden] { display: none; }
.csv-import-label { display: inline-flex; align-items: center; width: auto; margin: 0; padding: 0.5rem 0.75rem; border: var(--border-w) solid var(--border-c); border-radius: var(--radius); background: var(--surface); color: var(--ink); cursor: pointer; touch-action: manipulation; font-family: var(--font-brand); font-weight: 700; font-size: .8rem; }
.csv-import-label:hover { border-color: var(--red); color: var(--red); }
/* .setup label（display:block; margin-bottom:.5rem）が.csv-import-labelのinline-flex/marginを
   詳細度で上書きしてしまい、一括CSV/ロースターCSVの読み込みボタンだけ列からずれて表示される
   バグの対策（実機確認・2026-08-15。.roster-field[hidden]と同じCSS詳細度の衝突パターン） */
.setup .csv-import-label { display: inline-flex; margin-bottom: 0; }
.bulk-csv-controls { padding: 0.75rem; border: 1px solid var(--divider); border-radius: var(--radius); }
.bulk-csv-hint { flex-basis: 100%; margin: 0 0 0.25rem; color: var(--muted); }
.hint { color: var(--muted); font-size: 0.85rem; margin: 0.25rem 0 0; }
fieldset { border: var(--border-w) solid var(--border-c); border-radius: var(--radius); }
legend { font-family: var(--font-brand); font-weight: 700; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding: 0 .4rem; }

/* --- ライブ入力画面 --- */
.live { max-width: 64rem; margin: 0 auto; }
.scoreboard { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.5rem 0; }
.scoreboard .team { display: flex; flex-direction: column; align-items: center; border-top: 4px solid var(--team-color, #888); padding-top: 0.25rem; }
.scoreboard .score { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 2.5rem; font-weight: 700; }
.scoreboard .center { text-align: center; }
.clock { font-family: var(--font-mono); font-size: 1.5rem; font-variant-numeric: tabular-nums; }
.shot-clock { font-family: var(--font-mono); font-size: 1.25rem; color: var(--red); font-variant-numeric: tabular-nums; }

/* standaloneモード（会場システム非連携）：CourtTap自身のQ/クロックは信頼できる値ではないため隠し、
   F/TO表示も消してチーム名をフルネーム・大きめで表示する（2026-08-07追加） */
.scoreboard.standalone .center,
.scoreboard.standalone .sub {
  display: none;
}
.scoreboard.standalone #home-name,
.scoreboard.standalone #away-name {
  font-family: var(--font-brand);
  font-weight: 700;
  font-size: 1.8rem;
  letter-spacing: .02em;
}
.main-row { display: flex; gap: 0.5rem; align-items: stretch; }
/* max-heightはlive.jsがコートの実描画高さに合わせてJSで設定する（12人ロースターでも
   コートの高さを超えて縦に伸び続けないよう、超えた分は内部スクロールにする） */
.players { display: flex; flex-direction: column; gap: 0.25rem; width: 9rem; overflow-y: auto; }
.player-btn { width: 100%; text-align: left; border: var(--border-w) solid var(--border-c); border-left: 4px solid var(--team-color, #888); border-radius: var(--radius); background: var(--surface); padding: .5rem .6rem; }
/* 背番号を大きく・太く見せて瞬時に見分けやすくする（実機確認時のユーザー要望） */
.player-number { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 1.4em; font-weight: 800; margin-right: 0.35em; }
.player-name { font-size: 0.9em; color: var(--muted); }
#court-wrap { position: relative; flex: 1; }
/* オンラインデモ版専用の透かし（2026-08-15。右下1個→全画面斜め繰り返し→本体ロゴ1個を
   大きく斜め配置、の順で変更）。操作を妨げないようpointer-events:noneにする */
.demo-watermark {
  position: absolute; top: 50%; left: 50%; width: 85%;
  transform: translate(-50%, -50%) rotate(-30deg);
  opacity: 0.12; pointer-events: none;
}
/* ハーフコートの実寸（NBA/FIBA準拠、幅50ft×ゴールからハーフコートラインまで47ft）と
   同じ比率にする。ゴールを上端に置く（攻撃方向=上、y=1がゴール側） */
/* --court-bg-override/--court-line-overrideは、shotChart.jsのapplyCourtColors()が
   setup.htmlの任意設定（live.htmlはmeta.liveCourtColors、chart.htmlはmeta.chartCourtColors。
   2026-08-15追加）に応じてJSから書き込む。未設定時はvar()の第2引数（既定のテーマ色）にフォールバックする */
#court { position: relative; width: 100%; aspect-ratio: 50 / 47; background: var(--court-bg-override, var(--surface)); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); overflow: hidden; cursor: crosshair; }
/* カスタムコート画像（setup.htmlの任意項目）を設定した場合、shotChart.jsのapplyCourtImage()が
   このクラスを付ける。既存の簡易コート線は実写画像と二重に見えるため非表示にする */
#court.custom-court-image .court-line { display: none; }
/* コートライン本体はviewBox="0 0 50 47"のSVG（1ユニット=1ft）。#courtのaspect-ratioと
   viewBoxの比率を完全に一致させているため、円・弧は歪まず正しい円として描画される。
   stroke-widthはvector-effectで画面px指定に固定（ftのuser unitのままだと線が太くなりすぎるため） */
.court-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.court-svg * { fill: none; stroke: var(--court-line-override, var(--muted)); stroke-width: 2px; vector-effect: non-scaling-stroke; }
/* フリースローサークルの実線/点線分割（2026-08-25、参照画像に合わせて統一）。
   レーン（cl-key）の外側＝フリースローラインからセンターライン方向の半分は実線（.cl-ftcircle）、
   レーンの内側＝ペイントエリアに重なる半分は点線（.cl-dashed）で描く。
   vector-effect: non-scaling-strokeと同じ理由でdasharrayもuser unit(ft)基準だと
   スケール依存で崩れるため、strokeと同じpx換算になるよう小さめの固定値にする */
.cl-dashed { stroke-dasharray: 2px 1.5px; }
#shot-marks { position: absolute; inset: 0; pointer-events: none; }
.shot-mark { position: absolute; transform: translate(-50%, -50%); font-weight: 700; font-size: 1.15rem; line-height: 1; opacity: 0.35; text-shadow: 0 0 3px #000, 0 0 3px #000; }
.shot-mark.highlighted { opacity: 1; }
.panel { position: absolute; z-index: 10; background: var(--surface); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: 0.5rem; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); display: flex; flex-direction: column; gap: 0.25rem; max-width: 16rem; }
/* HOME/AWAY両方が選択肢にある場合、appendPlayerChoices()がpanelへ付ける修飾クラス。左右2列ぶん幅を広げる */
.panel.wide { max-width: 28rem; }
.player-columns { display: flex; gap: 0.5rem; }
.player-col { display: flex; flex-direction: column; gap: 0.25rem; flex: 1; min-width: 0; }
/* [hidden]属性はUAスタイルシート由来（display:none）で、上のdisplay:flexと同じ「author normal」より
   優先度が低いオリジンのため、.panelにdisplay:flexを設定した時点でhidden属性が効かなくなっていた
   （実機確認で「キャンセルを押しても消えない」として発覚したバグ）。同じorigin内で明示的に上書きする */
.panel[hidden] { display: none; }
.panel-row { display: flex; gap: 0.25rem; }
.panel-title { font-family: var(--font-brand); font-weight: 700; }
.panel .selected { outline: 3px solid var(--red); }
/* コート幅（#court-wrapの子として100%幅）いっぱいに広げる。固定列数のgridだと
   選手が増えてコートが狭くなった時に文字が1文字ずつ縦折り返しされてしまったため、
   flex-basisを目安に均等伸縮しつつ、入りきらない時だけ自然に次の行へ折り返す方式にした */
.actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.actions button { flex: 1 1 5.6rem; padding: 0.5rem 0.25rem; }
.controls { margin-top: 0.5rem; display: flex; gap: 0.5rem; align-items: center; }
.chart-links { margin-top: 0.75rem; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; border-top: 1px solid var(--divider); padding-top: 0.5rem; }
.chart-links label { display: inline-flex; align-items: center; gap: .35rem; }
.chart-links select { background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .3rem .4rem; font-family: inherit; font-size: .85rem; }
/* オンラインデモ版（2026-08-15）：chart.html/DataLinq欄をJSでhiddenにする際、[hidden]がこの
   display:flexルールに詳細度で負けて効かない既知のパターン（.panel[hidden]と同じ）への対策 */
.chart-links[hidden] { display: none; }

/* 汎用タブコンポーネント（2026-08-20追加。当初はDataLinq Statsの設定パネル専用に.stats-tabs
   という名前で作ったが、setup.htmlの試合作成フォームでも使うことになったため汎用化した）。
   .tabs=タブボタンの行、.tab-btn=各ボタン、.tab-panel=対応する中身。
   非表示パネルは素の[hidden]（display:none）のまま特別なCSSを当てない。
   一時期はvisually-hiddenパターン（1pxに潰すがDOM上はフォーカス可能）でrequired項目の
   サイレント失敗を回避していたが、実機レビューで「非アクティブタブの入力欄がTab順・
   スクリーンリーダーの読み上げ対象に残る」というアクセシビリティ上の問題が発覚したため撤回した。
   代わりにsetup.js側でform novalidate＋JS制御バリデーション（送信時にcheckValidity()→
   無効な項目のあるタブへ切替→reportValidity()）に変更し、display:noneのままでも
   サイレント失敗しないようにしている（setup.jsのvalidateSetupFormAndFocusTab()参照）。 */
.tabs { display: flex; gap: .3rem; margin-bottom: .6rem; border-bottom: 1px solid var(--divider); flex-wrap: wrap; }
.tab-btn { font-family: var(--font-brand); font-weight: 700; font-size: .78rem; color: var(--muted); background: transparent; border: none; border-bottom: 2px solid transparent; padding: .45rem .3rem; cursor: pointer; }
.tab-btn:hover { color: var(--ink); }
.tab-btn.active { color: var(--ink); border-bottom-color: var(--red); }
/* [hidden]のUAデフォルト（display:none）は、同じ詳細度の作者スタイル（.stats-panelの
   display:flex等）にOrigin優先順位で負けるため、非アクティブなタブパネルが実際には
   隠れずに表示され続けてしまう（.roster-field[hidden]と同じ既知の問題パターン。
   2026-08-20、実機確認で発覚：非表示のはずのteamstatsパネルがrankingパネルの下に
   丸ごと見えていた）。明示的に上書きする。 */
.tab-panel[hidden] { display: none; }

/* DataLinq Statsのグラフィック版キャプチャー画面の設定タブ（Ranking/Team Stats/Combined、
   2026-08-20追加）。.chart-linksと同じ枠内トークンを再利用しつつ、画面ごとに独立した設定パネルを
   タブで切り替える。設定項目が多いため、背景色付きのカードで囲んで意味のあるグループ
   （デザイン／色／サイズ）ごとに区切る（2026-08-20、ユーザー要望：「もっと見やすく」）。 */
.stats-links { margin-top: 0.75rem; border-top: 1px solid var(--divider); padding-top: 0.5rem; }
.stats-links h3 { margin: 0 0 .5rem; font-family: var(--font-brand); font-weight: 700; font-size: .85rem; }
/* grid-template-columns：当初はflexでプレビュー＋各field-groupを横並び→折り返しにしていたが、
   プレビューの右に「デザイン」グループだけ並んで大きな空白ができ、色/サイズ/配置は
   プレビューの下段に回り込んで視線がZ字に飛んでいた（2026-08-20、実機レビュー指摘）。
   左列にプレビュー、右列に設定グループ一式（.stats-controls、縦積み）を置くことで、
   「操作→すぐ左のプレビューで確認」の視線移動を最短にする。
   当初は.stats-preview-wrapをgrid-row:1/-1で左列いっぱいに伸ばし、各field-groupを
   直接gridの子として並べていたが、`-1`は暗黙グリッドでは常にrow1を指す（明示的な
   grid-template-rowsが無いグリッドでは全行スパンにならない）というCSS仕様の罠に嵌り、
   プレビューの高さがrow1にしか配分されず「デザイン」グループの下に大きな空白ができていた。
   さらに狭い画面でgrid-template-columns:1frにリセットしても、子要素に残ったgrid-column:2が
   暗黙の2列目を生成してしまい、1カラム化が効かない副作用もあった（2026-08-20、実機レビューで
   発覚）。右側の設定グループ一式を単一のラッパー要素にまとめることで、gridの子は
   「プレビュー」「controls」の2つだけになり、どちらの問題も構造的に起きなくなる。 */
.stats-panel { background: var(--surface); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .75rem .9rem; display: grid; grid-template-columns: minmax(14rem, 22rem) 1fr; gap: .9rem 1.2rem; align-items: start; max-width: 56rem; }
@media (max-width: 640px) {
  .stats-panel { grid-template-columns: 1fr; }
}
/* ライブプレビュー(2026-08-20追加・ユーザー要望：「設定結果がその場で見えた方がいい」)。
   実際のranking.html/teamstats.html/stats.htmlをiframeでそのまま縮小表示する方式にした
   （テーマ4種×背景4種×位置5種の組み合わせをCSSで別途シミュレートするより、実際のページを
   小さく映す方が見た目のズレが起きない）。背景は市松模様にしておくことで、bg=transparent
   選択時に「透過している」ことが視覚的に分かる（bg=black/green/blueの時はiframe自身が
   その色で塗りつぶすので市松は隠れる）。pointer-events:noneでプレビュー内の誤操作を防ぐ。 */
.stats-preview-wrap { position: relative; width: 100%; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden; background: repeating-conic-gradient(#3a3a3a 0% 25%, #2a2a2a 0% 50%) 0 0/16px 16px; border: var(--border-w) solid var(--border-c); }
/* 右列の設定グループ一式をまとめるラッパー（理由は上のコメント参照）。縦積みなので単純にflex。 */
.stats-controls { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.stats-preview { width: 100%; height: 100%; border: none; pointer-events: none; display: block; }
/* プレビュー再読み込み中の薄いオーバーレイ（2026-08-20追加・実機レビュー提案）。デバウンス
   （350ms）＋iframeのロード時間があるため、設定を変えてから反映されるまで一瞬間があり、
   「反映されていない？」と感じる余地があった。live.jsがiframe.onloadで消す。 */
.stats-preview-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, .55); color: #fff; font-size: .75rem; font-weight: 700; font-family: var(--font-brand); letter-spacing: .04em; }
.stats-preview-loading[hidden] { display: none; }
/* 3画面（Ranking/Team Stats/Combined）でパネルの背景とタブ下線の色を変え、タブの文字だけでなく
   色でも「今どれを開いているか」が一目で分かるようにする（2026-08-20、ユーザー要望：
   「タブでは分かるけどパッと見た時にUIが一緒なのでどれを開いているか分かりづらい」）。
   linear-gradientの単色2点＋var(--surface)は、テーマ色の上に薄い色味を重ねる手法
   （color-mix()は古いブラウザ非対応のため避けた）。tint濃度・左ボーダー幅は当初.1前後/3pxで
   組んでいたが、ライトテーマのsurface（ほぼ白）の上では埋もれて見えづらかったため
   2026-08-20の実機レビューを受けて濃くした。
   色は意図的に--home/--awayではなくブランド外の3色（青・緑・紫）を選んでいる：
   --home/--awayは「その試合のホームチーム/アウェイチームの色」という意味を既に持つ
   トークンで、これをタブの色分けに流用すると「Rankingタブ＝ホームチーム専用」のような
   誤解を招く。ここでの色は試合のチームカラーとは無関係な「画面の見分け」だけが目的なので、
   意味が重複しない別系統の色を割り当てている（実機レビューで指摘された「トークンの
   一貫性」については、home/awayへ寄せるより意味の独立性を優先した判断）。 */
#statsPanel-ranking { background: linear-gradient(rgba(47, 111, 237, .2), rgba(47, 111, 237, .2)), var(--surface); border-left: 4px solid #2f6fed; }
#statsPanel-teamstats { background: linear-gradient(rgba(16, 150, 122, .22), rgba(16, 150, 122, .22)), var(--surface); border-left: 4px solid #10967a; }
#statsPanel-combined { background: linear-gradient(rgba(139, 92, 246, .2), rgba(139, 92, 246, .2)), var(--surface); border-left: 4px solid #8b5cf6; }
/* タブボタン自体にも選択色の薄い背景を付け、下のパネルと同色で視覚的に繋がって見えるようにする
   （2026-08-20、実機レビュー提案：「タブ→パネルの視覚的連結」） */
#statsTabs .tab-btn[data-panel="ranking"].active { border-bottom-color: #2f6fed; background: rgba(47, 111, 237, .12); }
#statsTabs .tab-btn[data-panel="teamstats"].active { border-bottom-color: #10967a; background: rgba(16, 150, 122, .14); }
#statsTabs .tab-btn[data-panel="combined"].active { border-bottom-color: #8b5cf6; background: rgba(139, 92, 246, .12); }
/* 区切り線はgrid化前（横並び時代）はborder-rightだったが、.stats-controls内で縦積みに
   なったのでborder-bottomに変更した（2026-08-20、レイアウトgrid化に合わせて） */
.stats-field-group { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; padding-bottom: .6rem; border-bottom: 1px solid var(--divider); }
.stats-field-group:last-of-type { border-bottom: none; padding-bottom: 0; }
.stats-field-group-label { flex-basis: 100%; font-size: .62rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: .1rem; }
.stats-panel label { display: inline-flex; align-items: center; gap: .35rem; }
.stats-panel select { background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .3rem .4rem; font-family: inherit; font-size: .85rem; }
.stats-panel select:disabled { opacity: .45; cursor: not-allowed; }
/* Combinedで位置が衝突している間、警告文だけでなく「開く」ボタン自体にも注意色を付ける。
   警告に気付かないまま本番でキャプチャー画面を開いてしまう事故の最終防波堤（2026-08-20、
   実機レビュー提案）。live.jsのupdateCombinedPositionWarning()がクラスを付け外しする。 */
.link-btn.stats-open-warning { border-color: var(--red); color: var(--red); }
/* Ticker選択時は位置指定が効かない旨の注記（statsHint）、Combinedでranking/teamstatsに
   同じ位置を選んだ場合の重なり警告（statsWarning）。2026-08-20、実機レビュー対応 */
.stats-hint { flex-basis: 100%; margin: 0; font-size: .68rem; color: var(--muted); }
.stats-warning { flex-basis: 100%; margin: 0; font-size: .68rem; color: var(--red); font-weight: 700; }
/* flex-basis:100%でOpenボタンを独立した行にし、上にセパレータを引く。当初はmargin-left:auto
   で右端に飛ばしていたが、直前のfield-group群との間に不自然に大きな空白ができていた
   （特にウルトラワイドモニターで顕著。2026-08-20、実機レビュー指摘） */
.stats-open-row { display: flex; justify-content: flex-end; margin-top: .2rem; padding-top: .6rem; border-top: 1px solid var(--divider); }

/* 使用中の本人向け残り時間バッジ（2026-08-15追加、後日オレンジ+キャラクターに変更：
   「楽しんでる感じ」にしたいという要望）。他の操作の邪魔にならないよう
   固定位置・小さめ・pointer-events:noneにする */
.demo-session-timer {
  position: fixed; top: .6rem; right: .6rem; z-index: 40;
  display: flex; align-items: center; gap: .35rem;
  font-family: "Consolas", "SFMono-Regular", monospace; font-variant-numeric: tabular-nums; font-size: .78rem; font-weight: 700;
  background: #f28c28; color: #201e1d; padding: .3rem .7rem .3rem .3rem; border-radius: 999px;
  pointer-events: none; box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
}
.demo-session-timer-char { width: 1.6rem; height: 1.6rem; animation: demo-timer-bob 1.4s ease-in-out infinite; }
@keyframes demo-timer-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .demo-session-timer-char { animation: none; } }
/* 外部送信の注記フッター（電気通信事業法対応、2026-08-15追加）。GA4/Clarity計測が
   実際に動いているページだけに、控えめな常設リンクとして出す（public/js/analytics.js参照） */
.demo-privacy-footer {
  position: fixed; left: .6rem; bottom: .6rem; z-index: 40;
  font-size: .7rem; background: rgba(32, 30, 29, .55); border-radius: 999px; padding: .25rem .65rem;
}
.demo-privacy-footer a { color: #fff; opacity: .85; text-decoration: underline; }
.demo-privacy-footer a:hover { opacity: 1; }
/* --- 外部送信の注記ページ（privacy-demo.html） --- */
.privacy-card { text-align: left; max-width: 34rem; }
.privacy-card .bilingual-heading { text-align: center; }
.privacy-block { margin: 1.1rem 0 0; }
.privacy-block:first-of-type { margin-top: 1.4rem; }
.privacy-links { margin: .4rem 0 0; padding-left: 1.1rem; font-size: .9rem; }
p.privacy-links { padding-left: 0; }
.datalinq-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; flex-basis: 100%; }
.url-field { flex: 1; min-width: 16rem; font-size: .8rem; background: var(--input-bg); color: var(--ink); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: .4rem .5rem; }
.stats-row { margin-top: 0.75rem; border-top: 1px solid var(--divider); padding-top: 0.5rem; }
.stats-heading { margin-top: 0.25rem; font-family: var(--font-brand); font-weight: 700; }
.stats-ranking { margin: 0.25rem 0 0; padding-left: 1.5rem; }
.log-row { margin-top: 0.75rem; border-top: 1px solid var(--divider); padding-top: 0.5rem; }
.log-row h3 { margin: 0 0 0.25rem; font-family: var(--font-brand); font-weight: 700; font-size: 1rem; }
/* 1行の高さ(実測 約28px=1.75rem)×10行+わずかな余白で、ちょうど10件分が
   途切れず見える高さに固定し、11件目以降はスクロールで見る */
.event-log { list-style: none; margin: 0; padding: 0; max-height: 17.7rem; overflow-y: auto; }
.event-log li { display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.3rem 0; border-bottom: 1px solid var(--divider); font-size: 0.85rem; line-height: 1.3; }
.event-log li:last-child { border-bottom: none; }
.log-time { color: var(--muted); }
.log-team { font-weight: 700; }
.log-team-home { color: var(--home); }
.log-team-away { color: var(--away); }
.log-player { color: var(--muted); }
.log-empty { color: var(--muted); }
#toast { position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%); background: var(--ink); color: var(--bg); padding: 0.5rem 1rem; border-radius: var(--radius); z-index: 20; }

/* --- オンラインデモ版：TOP画面の「使い方」ポップアップ（2026-08-15） --- */
.modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .6); display: flex; align-items: center; justify-content: center; padding: 1rem; z-index: 30; }
.modal-overlay[hidden] { display: none; }
/* 60rem固定上限だと大画面（ウルトラワイド等）でも小さいまま頭打ちになり、細かい文字が
   読みづらいバグの対策（実機確認・2026-08-15）。rem上限を無くし、viewport一杯まで拡大する */
.modal-box { position: relative; max-width: 95vw; max-height: 95vh; background: var(--surface); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); padding: 0.5rem; }
.modal-image { display: block; max-width: 100%; max-height: calc(95vh - 3rem); border-radius: calc(var(--radius) - 2px); }
/* [hidden]（UAスタイル、詳細度0,1,0）と.modal-imageのdisplay:block（同じ詳細度）が衝突すると
   後勝ちでdisplay:blockが勝ってしまい、hidden属性を付けても表示され続ける既知のバグパターン
   （.demo-welcome[hidden]等と同じ、2026-08-15） */
.modal-image[hidden] { display: none; }
.modal-close { position: absolute; top: -0.9rem; right: -0.9rem; width: 2rem; height: 2rem; border-radius: 999px; background: var(--surface); color: var(--ink); border: var(--border-w) solid var(--border-c); cursor: pointer; font-size: 1.1rem; line-height: 1; }
.modal-close:hover { border-color: var(--red); color: var(--red); }

/* フルコート表示モーダル（放送演出用、2026-08-25）。既存の.modal-overlay/.modal-boxを流用。
   タップ入力(#court)とは別要素なのでcursorは既定のまま（クリックしても何も起きない） */
#full-court-wrap { display: flex; align-items: center; justify-content: center; }
/* widthの上限にcalc(85vh * 94/50)も含めるのは、.modal-boxのmax-height:95vh制約内に
   縦長画面でも収まるようにするため（chart.html側の#courtで見つかった横幅の
   はみ出しバグと同種の問題を、モーダルの高さ制約側で先回りして防ぐ） */
#full-court { position: relative; width: min(90vw, 56rem, calc(85vh * 94 / 50)); aspect-ratio: 94 / 50; background: var(--surface); border: var(--border-w) solid var(--border-c); border-radius: var(--radius); overflow: hidden; }
#full-court-shot-marks { position: absolute; inset: 0; pointer-events: none; }
/* 2026-08-15追加：日英2枚を縦スクロールで見せる方式から、横並びタブで切り替える方式に変更
   （龍さんの要望）。既定は日本語タブ */
.modal-tabs { display: flex; gap: .4rem; margin: 0 0 .6rem; }
.modal-tab { font-family: var(--font-brand); font-weight: 700; font-size: .8rem; border: var(--border-w) solid var(--border-c); border-radius: var(--radius); background: var(--surface); color: var(--muted); padding: .4rem .9rem; cursor: pointer; }
.modal-tab:hover { color: var(--ink); }
.modal-tab.is-active { background: var(--ink); color: #fff; border-color: var(--ink); }
