/* =========================================================
   しりとり＆デストロイ

   考えかた:
     - 主題は「文字が削られていく」こと。キーは物として作り、
       耐久は「下からたまっている量」で見せる。削られるたびに
       ガラスのようにひびが増え、壊れると砕けてへこむ。
     - 画面のものは「印刷された絵」ではなく「机の上のおもちゃ」に見せる。
       どの面にも濃い輪郭線を回し、影は真下にずらした硬いものを落とす。
       ぼかした影を使わないのは、厚みのある物として見せたいから。
     - ことばのゲームなので、字を主役にする。見出しは丸ゴシックの専用書体、
       本文は端末の書体（速いし読み慣れている）。
     - 対戦画面は PC 基準の「対面」レイアウト。
       左＝自分の盤面と入力、中央＝残り時間と経過、右＝相手の盤面。
       攻撃はいつも左から右へ飛ぶので、どちらが殴ったかが体で分かる。
     - 狭い画面では同じ部品を縦に積み替える。対戦画面はスクロールさせない。

   色の決めごと:
     席の色（青／朱）は「だれのものか」だけを表す。
     オレンジは「あと1回でこの字は消える」だけを表す。
     文字の耐久は 1・2・3 と設定で変わるので、段階を色で数えさせない。
       高さ＝あと何回 ／ ひびの数＝やられた回数 ／ オレンジ＝もう後がない
   ========================================================= */

/* ---------- 見出し用の書体 ----------
   M PLUS Rounded 1c Black（SIL OFL 1.1）を、このゲームが出す字だけに絞ったもの。
   3.5MB → 42KB。著作権表示とライセンス本文は同じ場所の OFL.txt に置いてある。

   丸ゴシックにしたのは、角のとれた字が厚みのあるタイルや丸いボタンと形で揃うから。
   以前 Dela Gothic One を外した理由（線が太すぎて、いちばん大きく出す 1 字で
   濁点・半濁点や小書きが潰れる）はこの書体では起きない。見出し専用の書体ではなく、
   本文系の家族のいちばん太いウェイトなので、Black でも点が残る。

   持っている太さは 1 つだけ。どの font-weight で呼ばれてもこの 1 本を使わせて、
   ブラウザが勝手に太らせる（偽ボールド）のを防ぐ。 */
@font-face {
  font-family: 'Display';
  src: url('/vendor/fonts/display.woff2') format('woff2');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- 輪郭と字。すべての面の縁と、ほとんどの文字がこの 1 色 --- */
  --ink:       #232b45;
  --ink-soft:  #97a0bd;   /* 壊れたものの縁 */

  /* --- 面 --- */
  --paper:     #fffdf6;   /* 板の表。ほとんどのカード */
  --paper-2:   #f1f3fb;   /* 一段くぼんだ面（入力欄など） */
  --sunken:    #e4e9f5;   /* 中身が減って空いたところ */
  --sunken-2:  #cbd1e2;   /* 壊れたキーの底 */

  /* --- 地。空から砂へ。上が明るく、下が暖かい --- */
  --sky:       #bde4ff;
  --sand:      #ffe9a8;
  --sand-deep: #ffd9a0;

  --text:      #232b45;
  --text-dim:  #6b7392;
  --text-faint:#99a0ba;

  /* --- 席の色。席0＝青、席1＝朱。どちらの画面でも同じ色に見える。
         この色が言うのは「だれのものか」だけ。状態は言わない。 --- */
  --p0:      #2f7bff;
  --p0-deep: #1546a8;
  --p0-lite: #7fb0ff;
  --p0-soft: #d6e6ff;
  --p1:      #ff5a3d;
  --p1-deep: #c02d16;
  --p1-lite: #ff9f8c;
  --p1-soft: #ffe0d8;

  /* --- 進めるボタンの色。席の色と別にして、どの席でも同じ緑にする --- */
  --go:      #16c97a;
  --go-lite: #6ff0b0;
  --go-deep: #0a7d4a;

  --gold:      #ffc330;
  --gold-lite: #fff0b8;
  --gold-deep: #c98600;

  /* オレンジは「あと1回で消える」専用。ほかの用途に広げない */
  --warn:      #ff8a1f;
  --warn-lite: #ffc477;
  --warn-deep: #b85600;

  --danger:      #ff3b4d;
  --danger-deep: #a3101f;

  /* --- 字の大きさ。狭い画面では縮むが、広い画面では伸ばしすぎない --- */
  --fs-display: clamp(2.25rem, 9.4vw, 3.9rem);
  --fs-xxl: clamp(1.75rem, 6vw, 2.4rem);
  --fs-xl:  clamp(1.2rem, 4.2vw, 1.5rem);
  --fs-lg:  1.0625rem;
  --fs-md:  0.9375rem;
  --fs-sm:  0.8125rem;
  --fs-xs:  0.6875rem;

  /* --- 余白。4px きざみで揃える --- */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s8: 32px; --s10: 40px;

  /* --- 輪郭の太さ。おもちゃに見せる要。細くすると一気に「アプリ」に戻る --- */
  --bw:      3px;
  --bw-thin: 2.5px;

  --r-sm: 12px;
  --r:    18px;
  --r-lg: 24px;
  --r-pill: 999px;

  /* --- 影。ぼかさず、真下にずらす。それが「厚み」になる。
         色を指定できるよう、段差そのものは各部品で box-shadow に書く。
         ここにあるのは板が机に落とすほうの影。 --- */
  --lift-1: 0 2px 0 var(--ink);
  --lift-2: 0 4px 0 var(--ink);
  --lift-3: 0 6px 0 var(--ink);
  --cast:   0 10px 22px -14px rgba(35, 43, 69, .55);

  --gap: 5px;
  /* キーの大きさ。狭い画面は幅から、広い画面は下の @media で固定値に切り替える。
     高さを別に持てるようにしてあるのは、縦の詰まった端末で「横は余っているのに
     10 段が入らない」ことが起きるから。そこでは平たいキーにして高さだけ削る。 */
  --cell: clamp(26px, calc((min(100vw, 460px) - 24px - 9 * var(--gap)) / 10), 34px);
  --cell-foe: clamp(15px, calc((min(100vw, 460px) - 24px - 9 * 3px) / 10 * 0.72), 24px);
  --key-h: var(--cell);
  --key-h-foe: var(--cell-foe);

  /* --- 動きの語彙。演出はぜんぶこの3本の曲線と4段の長さで作る --- */
  --ease: cubic-bezier(.22,.8,.3,1);      /* ふつうの立ち上がり */
  --ease-back: cubic-bezier(.34,1.56,.64,1); /* ひと押し戻る */
  --ease-in: cubic-bezier(.5,0,.9,.4);    /* 消えるとき */
  --t-tap: .1s;     /* 触った反応 */
  --t-quick: .26s;  /* 状態が変わった */
  --t-beat: .44s;   /* 見せ場 */

  /* --- 割れの絵。盤のキーと、入口の「遊び方」の見本が同じ絵を使う。
         入口で見せた壊れかたと、盤で起きる壊れかたが違っていたら、
         見本の意味がなくなるため。
         同じ線を「太く薄い白」→「細く濃い色」の順に 2 度描いてあるので、
         濃い塗りの上でも、空いた素地の上でも同じように割れて見える。 --- */
  --crack-1: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg stroke='%23ffffff' stroke-width='2.2' opacity='0.42'%3E%3Cpath d='M32 3.5 L24 9.5 L27 15.5 L19.5 20.5 L21.5 26.5 L16.5 32'/%3E%3Cpath d='M27 15.5 L32 18.5'/%3E%3C/g%3E%3Cg stroke='%23232b45' stroke-width='1.7' opacity='0.7'%3E%3Cpath d='M32 3.5 L24 9.5 L27 15.5 L19.5 20.5 L21.5 26.5 L16.5 32'/%3E%3Cpath d='M27 15.5 L32 18.5'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");   /* 1 回やられた */
  --crack-2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg stroke='%23ffffff' stroke-width='2.2' opacity='0.42'%3E%3Cpath d='M32 3.5 L24 9.5 L27 15.5 L19.5 20.5 L21.5 26.5 L16.5 32'/%3E%3Cpath d='M27 15.5 L32 18.5'/%3E%3Cpath d='M0 20.5 L6 16.5 L3.5 11 L10 7 L8 1.5'/%3E%3Cpath d='M6 16.5 L1.5 29'/%3E%3C/g%3E%3Cg stroke='%23232b45' stroke-width='1.7' opacity='0.72'%3E%3Cpath d='M32 3.5 L24 9.5 L27 15.5 L19.5 20.5 L21.5 26.5 L16.5 32'/%3E%3Cpath d='M27 15.5 L32 18.5'/%3E%3Cpath d='M0 20.5 L6 16.5 L3.5 11 L10 7 L8 1.5'/%3E%3Cpath d='M6 16.5 L1.5 29'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");   /* 2 回以上やられた */
  --crack-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg stroke='%23ffffff' stroke-width='1.9' opacity='0.45'%3E%3Cpath d='M11 12 L32 2.5'/%3E%3Cpath d='M11 12 L24 32'/%3E%3Cpath d='M11 12 L0.5 27'/%3E%3Cpath d='M11 12 L0 4'/%3E%3Cpath d='M11 12 L17.5 0'/%3E%3Cpath d='M20.5 7.5 L18.5 20'/%3E%3C/g%3E%3Cg stroke='%234b5573' stroke-width='1.3' opacity='0.68'%3E%3Cpath d='M11 12 L32 2.5'/%3E%3Cpath d='M11 12 L24 32'/%3E%3Cpath d='M11 12 L0.5 27'/%3E%3Cpath d='M11 12 L0 4'/%3E%3Cpath d='M11 12 L17.5 0'/%3E%3Cpath d='M20.5 7.5 L18.5 20'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");   /* 壊れた。1 点から放射状に砕ける */
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; min-height: 100%; }

body {
  background: var(--sand);
  color: var(--text);
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Noto Sans JP",
               system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* ゲームなので、意図しない選択・長押し・ダブルタップ拡大は殺す */
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  overscroll-behavior: none;
}

/* 地。空から砂へ落ちるグラデーションに、白い点を等間隔で散らす。
   点があると、平らな塗りが「紙」ではなく「敷物」に見えて、
   上に置いたものが浮いていることが分かりやすくなる。 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background-color: var(--sand);
  background-image:
    radial-gradient(circle at 50% 50%, rgba(255,255,255,.85) 2.4px, transparent 2.6px),
    linear-gradient(168deg, var(--sky) 0%, var(--sand) 58%, var(--sand-deep) 100%);
  background-size: 26px 26px, 100% 100%;
}

input { user-select: text; -webkit-user-select: text; }

::selection { background: color-mix(in oklab, var(--p0) 30%, transparent); }

/* 見出し・数字・ボタンの文字はぜんぶこの書体。
   1 か所ずつ font-family を書くと必ず取りこぼすので、まとめて指定する。 */
.logo, .btn, .seg, .key, .chip, .pchip,
.word-slot__ch, .word-slot__romaji,
.dial__char, .dial__sec, .roomcode__value, .field__input--code,
.result__verdict, .announce__title, .board__hp b, .board__spare b,
.phase-chip, .vs__mark, .stat__v, .chain__word, .strike__word {
  font-family: 'Display', "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
  font-weight: 900;
}


/* ---------- 画面 ---------- */

.screen {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  padding: max(var(--s3), env(safe-area-inset-top)) var(--s3)
           calc(var(--s3) + env(safe-area-inset-bottom));
  gap: var(--s3);
}
/* 隠した画面は何があっても出さない。
   下の広い画面向けの指定（display:grid 等）に負けないよう !important を付ける。 */
.screen[hidden] { display: none !important; }

/* ---------- 面 ----------
   白い板。濃い輪郭を回して、真下に硬い影を落とす。
   ぼかした影にしないのは、紙に印刷された絵ではなく
   「机の上に置かれた板」に見せたいから。 */

.panel {
  position: relative;
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  padding: var(--s4);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  box-shadow: var(--lift-3), var(--cast);
}

/* ---------- ボタン ----------
   3 段階に分ける。押してほしいものが 1 画面に 1 つだけ目立つように。

   厚みは box-shadow の「ずらした影」で作る。押したときは
   その段差を潰して同じぶんだけ本体を下げるので、面の位置は変わらず、
   高さだけが無くなる。縮小より、こちらのほうが「沈んだ」感じが出る。 */

.btn {
  appearance: none;
  position: relative;
  border: var(--bw) solid var(--ink);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 900;
  letter-spacing: .02em;
  padding: var(--s3) var(--s4);
  min-height: 48px;
  cursor: pointer;
  box-shadow: var(--lift-2);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease),
              background var(--t-quick), opacity var(--t-quick),
              border-color var(--t-quick), color var(--t-quick);
}
.btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 5px 0 var(--ink); }
.btn:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }
.btn:disabled { opacity: .38; cursor: default; box-shadow: var(--lift-1); }
.btn:disabled:active { transform: none; }
.btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
/* ダイアログを開いた直後の自動フォーカスでは枠を出さない。
   キーボードで動かした時点で（この印が外れて）ふつうの枠が戻る。 */
.btn.is-autofocus:focus-visible { outline: none; }

/* いちばん押してほしいもの。緑は席の色と別にしてあるので、
   どちらの席で遊んでも「進むボタン」は同じ色に見える。 */
.btn--primary {
  background: linear-gradient(180deg, var(--go-lite), var(--go) 60%);
  color: #06301f;
  text-shadow: 0 1.5px 0 rgba(255,255,255,.42);
  box-shadow: 0 4px 0 var(--go-deep), inset 0 3px 0 rgba(255,255,255,.5);
  border-color: var(--go-deep);
}
.btn--primary:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 5px 0 var(--go-deep), inset 0 3px 0 rgba(255,255,255,.5);
}
.btn--primary:active:not(:disabled) {
  transform: translateY(4px);
  box-shadow: 0 0 0 var(--go-deep), inset 0 3px 0 rgba(255,255,255,.35);
}
/* 添えるもの。板と同じ白だが、段差を浅くして「軽い」ことを示す */
.btn--ghost {
  background: var(--paper);
  color: var(--text-dim);
  box-shadow: var(--lift-1);
}
.btn--ghost:hover:not(:disabled) { color: var(--ink); transform: translateY(-1px); box-shadow: 0 3px 0 var(--ink); }
.btn--ghost:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 0 0 var(--ink); }
/* 取り消しにくいもの */
.btn--danger {
  color: var(--danger-deep);
  border-color: var(--danger-deep);
  background: #ffeef0;
  box-shadow: 0 2px 0 var(--danger-deep);
}
.btn--danger:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 0 0 var(--danger-deep); }

.btn--lg { font-size: var(--fs-xl); min-height: 58px; border-radius: var(--r); }
.btn--sm { min-height: 38px; padding: var(--s1) var(--s3); font-size: var(--fs-sm); border-radius: 10px; box-shadow: var(--lift-1); }
.btn--sm:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 0 0 var(--ink); }
.btn--icon {
  min-height: 42px; width: 42px; padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-size: 1.05rem;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  box-shadow: var(--lift-2);
  text-decoration: none;
}

/* ---------- 入力 ----------
   入力欄は「くぼんだ面」。板と逆向きの影（内側に落ちる）で、
   ボタンとの上下関係をはっきりさせる。 */

.field { display: flex; flex-direction: column; gap: var(--s1); }
.field__label {
  font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .14em;
}
.field__input {
  background: var(--paper-2);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-weight: 800;
  padding: var(--s3) var(--s4);
  min-height: 50px;
  width: 100%;
  box-shadow: inset 0 3px 0 rgba(35,43,69,.10);
  transition: border-color var(--t-quick), box-shadow var(--t-quick);
}
.field__input::placeholder { color: var(--text-faint); font-weight: 700; }
.field__input:focus {
  outline: none;
  border-color: var(--p0-deep);
  box-shadow: inset 0 3px 0 rgba(35,43,69,.10),
              0 0 0 4px color-mix(in oklab, var(--p0) 32%, transparent);
}
.field__input--code {
  text-align: center;
  letter-spacing: .42em;
  text-indent: .42em;
  font-size: var(--fs-xxl);
  color: var(--gold-deep);
}
/* 空のときは「例」として薄く。入力した文字と同じ強さで出すと、
   すでに何か入っているように見えてしまう。 */
.field__input--code::placeholder { color: rgba(153,160,186,.5); }

.hint { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.7; font-weight: 700; }
.feedback {
  margin: 0; min-height: 1.4em;
  font-size: var(--fs-sm); font-weight: 900; text-align: center;
  color: var(--text-dim);
}
.feedback.is-bad  { color: var(--danger-deep); }
.feedback.is-good { color: var(--go-deep); }

.segmented--sm .seg { min-height: 36px; font-size: var(--fs-sm); }

/* 表示を切り替える箱は、中身のレイアウト指定が [hidden] に勝ってしまうので明示する */
[data-solo-only][hidden], [data-online-only][hidden] { display: none !important; }

.join { display: flex; gap: var(--s2); }
.join .field__input { flex: 1; min-width: 0; }
.join .btn { flex: none; padding-inline: var(--s5); }

.bar { display: flex; align-items: center; gap: var(--s2); min-height: 44px; }
.bar__title { margin: 0; font-size: var(--fs-lg); font-weight: 900; letter-spacing: .04em; }
.bar--slim { min-height: 40px; }
.bar__title + .btn--icon, .phase-chip + .btn--icon { margin-left: auto; }
.bar .btn--icon + .btn--icon { margin-left: 0; }

/* ---------- タイトル ----------
   ロゴは「厚みのある字」。輪郭を回して真下にずらした影を落とす。
   -webkit-text-stroke と paint-order で、縁が字の内側を食わないようにする。

   看板は「見せ場」であって「入口」ではない。以前は画面の 7 割を占めていたが、
   その下に置いた遊び方と 2 つの入口を最初の一目に入れたいので、
   高さは中身なりにして、看板・遊び方・入口を縦に積む。 */

.title-fx {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: var(--bw) solid var(--ink);
  background: linear-gradient(168deg, #a8dcff 0%, #cfeaff 46%, #ffe9a8 100%);
  display: flex;
  align-items: center;
  padding: var(--s5) var(--s4);
  box-shadow: var(--lift-3), var(--cast);
}
/* 崩れるかなタイルを描く canvas。ロゴの下に敷く */
.hero-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  pointer-events: none;
  /* 模様であって主役ではない。ロゴより前に出ない濃さに抑える */
  opacity: .85;
}
/* ロゴの側だけ明るく飛ばして読みやすくする。中身を左に寄せたので、
   明るい芯も左（33%）へ動かす。中央のままだと逆にロゴの外だけが白くなる。 */
.title-fx::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: radial-gradient(62% 78% at 33% 50%,
    rgba(255,253,246,.95) 0%, rgba(255,253,246,.72) 46%, transparent 88%);
}
.title-inner { position: relative; z-index: 2; flex: 1; min-width: 0; }

.logo {
  margin: 0;
  font-size: var(--fs-display);
  letter-spacing: .01em;
  line-height: 1.02;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.logo__a, .logo__b {
  -webkit-text-stroke: .15em var(--ink);
  paint-order: stroke fill;
}
.logo__a {
  color: var(--paper);
  filter: drop-shadow(0 5px 0 var(--ink));
}
/* 「デストロイ」だけ色を持たせる。虹色にはしない（安く見える） */
.logo__b {
  color: var(--p0);
  filter: drop-shadow(0 5px 0 var(--p0-deep));
}
/* 「＆」だけ金。2 行を繋いでいる字なので、ここが光ると題名が 1 つに見える。
   帯や飾りを別に足さないのは、金を 1 画面に 1 つだけにしておきたいから。 */
.logo__amp { color: var(--gold); }

.tagline {
  margin: var(--s3) 0 0;
  color: var(--ink);
  font-size: var(--fs-md);
  font-weight: 800;
  line-height: 1.85;
  letter-spacing: .02em;
}

/* 看板に書いてよいのは、設定で変わらないことだけ。
   持ち時間や残り字数はロビーで動かせるので、ここで約束すると嘘になる。 */
.badges {
  list-style: none;
  margin: var(--s3) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s2);
}
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--paper);
  border: var(--bw-thin) solid var(--ink);
  border-radius: var(--r-pill);
  box-shadow: var(--lift-1);
  padding: 5px 14px;
  font-size: var(--fs-sm); font-weight: 900; letter-spacing: .04em;
  color: var(--ink);
}
.badge svg { width: 15px; height: 15px; flex: none; }

/* ---------- 遊び方の 3 コマ ----------
   ボタンの奥に隠すと、何をする遊びなのか分からないまま入口を選ばせることになる。
   押さなくても目に入る場所（看板のすぐ下）に置く。 */

.how { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.how__step { padding: var(--s3) var(--s4); gap: 7px; }
.how__n {
  width: 30px; height: 30px; flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--gold);
  border: var(--bw-thin) solid var(--ink);
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: var(--fs-md); color: #4a3300;
  box-shadow: 0 3px 0 var(--gold-deep);
}
.how__t { font-size: var(--fs-lg); font-weight: 900; letter-spacing: .02em; }
.how__d { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.75; font-weight: 700; }
.how__d em { font-style: normal; color: var(--p1-deep); }

/* ことばの見本。ここではまだ攻撃の話をしないので、どの字も同じ見た目にする */
.how__word { display: flex; gap: var(--s1); align-items: center; }
.how__word span {
  width: 30px; height: 30px; flex: none;
  border-radius: 8px; display: grid; place-items: center;
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: var(--fs-lg);
  border: 2.5px solid var(--ink);
  background: var(--paper-2); color: var(--ink);
}
.how__word i {
  font-style: normal; font-size: var(--fs-sm); color: var(--text-dim);
  font-weight: 900; margin-left: var(--s1);
}

/* 削られていく様子。盤の上のキーとまったく同じ作りにする ----
   下からたまった色＝あと何回耐えるか、ひび＝やられた回数、
   オレンジ＝あと 1 回で消える、へこんだ穴＋放射状の砕け＝壊れた。
   割れの絵（--crack-1 / --crack-x）はキーと共有しているので、
   ここで見た壊れかたが、そのまま盤の上でも起きる。 */
.how__broke { display: flex; gap: var(--s1); align-items: center; }
.how__key {
  --fill: 100%;
  position: relative; width: 30px; height: 30px; flex: none;
  border-radius: 8px; overflow: hidden;
  border: 2.5px solid var(--ink);
  background: var(--sunken);
  display: grid; place-items: center;
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: var(--fs-lg);
  color: #fff; box-shadow: 0 3px 0 var(--p0-deep);
  text-shadow: 0 1.5px 0 rgba(0,0,0,.22);
}
.how__key::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--fill);
  background: linear-gradient(180deg, var(--p0-lite), var(--p0) 70%);
  box-shadow: inset 0 2px 0 rgba(255,255,255,.6);
}
/* ひび。塗りの上に敷き、字より奥に置く（壊れても字は読めるまま） */
.how__key::after {
  content: ""; position: absolute; inset: 0;
  background-repeat: no-repeat; background-size: 100% 100%;
}
.how__key > span { position: relative; z-index: 1; }
.how__key--half {
  --fill: 50%;
  box-shadow: 0 3px 0 var(--warn-deep);
  color: #4a2600; text-shadow: 0 1.5px 0 rgba(255,255,255,.35);
}
.how__key--half::before { background: linear-gradient(180deg, var(--warn-lite), var(--warn) 70%); }
.how__key--half::after { background-image: var(--crack-1); }
.how__key--dead {
  background: var(--sunken-2); color: #6f7893;
  border-color: var(--ink-soft);
  box-shadow: inset 0 4px 0 rgba(0,0,0,.14), inset 0 -2px 0 rgba(255,255,255,.5);
  text-shadow: none;
}
.how__key--dead::before { display: none; }
.how__key--dead::after { background-image: var(--crack-x); }
.how__arrow { width: 18px; height: 12px; flex: none; color: var(--text-faint); }

/* ---------- 入口 ----------
   ひとりで／ふたりで を同じ大きさの札にして横に並べる。
   前は「ひとりで」だけが上にあり、下まで読まないと友達と遊べることに気づけなかった。 */

.enter { display: grid; grid-template-columns: 300px repeat(2, minmax(0, 1fr)); gap: var(--s3); align-items: stretch; }
.enter__name { padding: var(--s3) var(--s4); gap: var(--s2); }

.way { padding: var(--s3) var(--s4); gap: 7px; }
/* 縁と段差の色で、どちらの入口かを言う。中身を読む前に 2 種類あることが分かる */
.way--solo { border-color: var(--p0-deep); box-shadow: 0 6px 0 var(--p0-deep), var(--cast); }
.way--duo  { border-color: var(--p1-deep); box-shadow: 0 6px 0 var(--p1-deep), var(--cast); }
.way__cap {
  display: inline-flex; align-self: flex-start; align-items: center; gap: 6px;
  border-radius: var(--r-pill); padding: 4px 13px;
  font-size: var(--fs-sm); font-weight: 900; letter-spacing: .06em;
  border: var(--bw-thin) solid currentColor;
}
.way__cap svg { width: 14px; height: 14px; flex: none; }
.way--solo .way__cap { color: var(--p0-deep); background: var(--p0-soft); }
.way--duo  .way__cap { color: var(--p1-deep); background: var(--p1-soft); }
.way__t {
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: var(--fs-xl); letter-spacing: .02em;
}
.way__d { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.75; font-weight: 700; }
/* 入れ違いの案内（「準備しています…」など）はここに出る。文の長さが変わっても
   下のボタンが動かないよう、ボタンの側を margin-top:auto で床に貼り付けておく。 */
/* 案内文は \n で行を分けられるようにしておく。満員のときのように、
   一行に詰めると読み飛ばされる説明があるため。 */
.way__note { font-size: var(--fs-xs); white-space: pre-line; }
.way .btn--lg { margin-top: auto; }
/* 部屋コードの欄は、この札の中では見出しの次に大きいくらいでよい。
   タイトルほど大きいと、入るほうが作るより目立ってしまう。 */
.way .field__input--code { font-size: 1.55rem; letter-spacing: .34em; text-indent: .34em; }

.title-links { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: auto; }
.title-links .btn { flex: 1 1 auto; text-align: center; text-decoration: none; }

/* ---------- サイトのフッター ----------
   タイトルにも読み物のページにも同じものを置く。ここは遊ぶための場所ではないので、
   厚みも輪郭も与えない。地の上に小さく刷ってあるだけに見せて、
   「探せば必ずある」以上の主張はさせない。

   区切りの「｜」は文字として書かず ::after で足す。HTML に区切りを書くと、
   リンクを増やすたびに区切りの入れ忘れ・余りが出る。 */

.site-footer {
  margin-top: auto;
  padding-top: var(--s4);
  text-align: center;
  font-size: var(--fs-xs); line-height: 1.9; font-weight: 700;
  color: var(--text-dim);
}
.site-footer__links {
  display: flex; flex-wrap: wrap; justify-content: center;
}
.site-footer__links a { color: var(--p0-deep); text-decoration: none; }
.site-footer__links a:hover { text-decoration: underline; }
.site-footer__links a::after {
  content: "｜"; margin: 0 var(--s1); color: var(--text-faint); font-weight: 600;
}
.site-footer__links a:last-child::after { content: ""; margin: 0; }
.site-footer__credit { margin: var(--s2) 0 0; }
.site-footer__credit a {
  color: var(--p0-deep); font-weight: 900;
  text-decoration: underline; text-underline-offset: 3px;
}

/* 5 つ並べると 448px 必要になるので、狭い画面では 2 行に折り返る。
   そのとき「｜」が行末に取り残されてぶら下がるので、折り返す幅では
   区切りを消して、隙間だけで分ける。 */
@media (max-width: 520px) {
  .site-footer__links { gap: var(--s1) var(--s6); }
  .site-footer__links a::after { content: none; margin: 0; }
}

/* ---------- 前の対戦に戻る ---------- */

.resume {
  background: #fff6dc;
  border: var(--bw-thin) solid var(--gold-deep);
  border-radius: var(--r-sm);
  padding: var(--s3);
  display: flex; flex-direction: column; gap: var(--s2);
  box-shadow: 0 3px 0 var(--gold-deep);
}
/* display 指定は [hidden] より強いので、消えるようにしておく（出っぱなしになる） */
.resume[hidden] { display: none !important; }
.resume__text { margin: 0; font-size: var(--fs-sm); color: var(--ink); font-weight: 800; }
.resume__text b {
  font-family: 'Display', system-ui, sans-serif;
  color: var(--gold-deep); letter-spacing: .18em; font-size: 1.2em;
}
.resume__actions { display: flex; gap: var(--s2); }
.resume__actions .btn { flex: 1; }

/* ---------- ロビー ----------
   左は「誰と誰が、どんな条件で戦うか」の要約 1 枚、右が設定。
   設定をいじると左が変わるので、右をぜんぶ読まなくても勝負の形が分かる。 */

.lobby { display: flex; flex-direction: column; gap: var(--s3); }
.lobby__col { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.lobby__setup { gap: var(--s4); }
.lobby__room { gap: var(--s2); }
.lobby__room[hidden] { display: none !important; }

.roomcode {
  display: flex; align-items: baseline; gap: var(--s3);
  flex-wrap: wrap;
}
.roomcode__label {
  font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .14em;
}
.roomcode__value {
  font-size: clamp(2rem, 9vw, 2.25rem);
  letter-spacing: .22em;
  text-indent: .22em;
  color: var(--gold);
  -webkit-text-stroke: 6px var(--ink);
  paint-order: stroke fill;
}

.share-row { display: flex; flex-wrap: wrap; gap: var(--s2); }
.share-row .btn { flex: 1 1 auto; min-width: 118px; }

/* 対戦カード。名前が長くても折らずに詰めるので、2 人ぶんの高さが揃う。 */
.who__row { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.who__row .pchip { flex: 0 1 auto; min-width: 0; }
.vsmark {
  flex: none;
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: 1.35rem;
  color: var(--paper);
  -webkit-text-stroke: 5px var(--ink);
  paint-order: stroke fill;
  transform: rotate(-6deg);
}

/* 勝ち筋。この 1 枚でいちばん大事な数なので、いちばん大きく出す。
   「手ごたえ」の説明だけだと、強さを選んでも何が変わるのか決められない。 */
.goal {
  border: var(--bw-thin) solid var(--go-deep);
  border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--go) 9%, var(--paper));
  padding: var(--s3) var(--s4);
  display: flex; flex-direction: column; gap: 6px;
}
.goal[hidden] { display: none !important; }
.goal__k { font-size: var(--fs-xs); letter-spacing: .12em; color: var(--go-deep); font-weight: 900; }
.goal__v {
  font-size: var(--fs-lg); font-weight: 900;
  display: flex; align-items: baseline; gap: 6px;
}
/* 書体を持たせるのは数だけ。見出し書体は必要な字だけに絞ってあるので、
   絞っていない字を混ぜると、そこだけ代替書体になって不揃いに見える。 */
.goal__v b {
  font-family: 'Display', system-ui, sans-serif;
  font-size: 2.6rem; color: var(--go-deep); line-height: 1;
}
.goal__d { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.7; font-weight: 700; }

/* 残りの条件は 3 つ並べるだけ。勝ち筋の下に置いて、大きさで順位を付ける。 */
.sum { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); }
.sum__c {
  border: var(--bw-thin) solid var(--ink);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  padding: var(--s2) var(--s1);
  text-align: center;
  box-shadow: var(--lift-1);
}
.sum__k {
  display: block; font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .06em; margin-bottom: 2px;
}
.sum__v {
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: 1.4rem;
  font-variant-numeric: tabular-nums;
}
.sum__v small {
  font-size: .58em; color: var(--text-dim); margin-left: 1px;
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Noto Sans JP", system-ui, sans-serif;
  font-weight: 800;
}

/* ---------- 設定 ---------- */

.settings { display: flex; flex-direction: column; gap: var(--s4); }
.setting { display: flex; flex-direction: column; gap: var(--s2); }
.setting__label {
  font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .14em;
}
.setting__note { margin: 0; font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.7; font-weight: 700; }

/* 溝に埋まったスイッチとして作る。選ばれた側だけが厚みを持って浮き上がる */
.segmented {
  display: grid; grid-auto-flow: column; gap: var(--s1);
  background: var(--paper-2);
  border: var(--bw-thin) solid var(--ink);
  border-radius: var(--r-sm);
  padding: 5px;
  box-shadow: inset 0 3px 0 rgba(35,43,69,.10);
}
.seg {
  appearance: none;
  border: var(--bw-thin) solid transparent;
  background: transparent;
  color: var(--text-dim);
  border-radius: 9px;
  padding: var(--s2) var(--s1);
  min-height: 44px;
  font: inherit; font-weight: 900;
  /* 「10文字で勝ち」を名前の下に添えるので、中身は縦に 2 段まで積める形にしておく */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; line-height: 1.25;
  cursor: pointer;
  transition: color var(--t-quick), background var(--t-quick),
              border-color var(--t-quick), box-shadow var(--t-tap), transform var(--t-tap);
}
.seg:hover:not(:disabled):not([aria-pressed="true"]) { color: var(--ink); background: rgba(35,43,69,.05); }
.seg[aria-pressed="true"] {
  background: var(--p0);
  border-color: var(--p0-deep);
  color: #fff;
  text-shadow: 0 1.5px 0 rgba(0,0,0,.2);
  box-shadow: 0 3px 0 var(--p0-deep);
  transform: translateY(-1px);
}
.seg:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 0 0 var(--p0-deep); }
.seg:disabled { opacity: .42; cursor: default; }
.seg:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
/* 選んだ強さで「何文字けずれば勝ちか」が変わる。手ごたえの説明だけだと
   どれを選ぶと何が変わるのか決められないので、数をその場に出す。
   本文の書体で出すのは、見出し書体が必要な字だけに絞ってあるため。 */
.seg__sub {
  font-style: normal;
  font-size: var(--fs-xs); font-weight: 800; opacity: .82;
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Noto Sans JP", system-ui, sans-serif;
}

/* ---------- 先攻決め ---------- */

.phase-chip {
  font-size: var(--fs-xs); letter-spacing: .12em;
  color: #4a3300;
  border: var(--bw-thin) solid var(--ink);
  background: var(--gold);
  border-radius: var(--r-pill);
  padding: 5px var(--s3);
  white-space: nowrap;
  box-shadow: var(--lift-1);
}
/* 対戦中だけ、脈打つ小さな点を添える */
.phase-chip--live { display: inline-flex; align-items: center; gap: var(--s2); }
.phase-chip--live::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink);
  animation: livedot 2s var(--ease) infinite;
}
@keyframes livedot {
  0%   { box-shadow: 0 0 0 0 rgba(35,43,69,.55); }
  70%  { box-shadow: 0 0 0 8px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.mg { display: flex; flex-direction: column; gap: var(--s4); text-align: center; }
.mg__lead { display: flex; flex-direction: column; gap: var(--s2); }
.mg__play { display: flex; flex-direction: column; gap: var(--s3); align-items: center; }
.mg__play .dock { width: 100%; }
.mg__caption {
  margin: 0; font-size: var(--fs-xs); color: var(--gold-deep);
  font-weight: 900; letter-spacing: .18em;
}
.mg__puzzle {
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  padding: var(--s5) var(--s4);
  font-size: var(--fs-xl);
  font-weight: 900;
  line-height: 1.75;
  box-shadow: var(--lift-3), var(--cast);
}
.mg__puzzle b {
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900;
  color: var(--gold);
  font-size: 1.5em;
  vertical-align: -.08em;
  margin: 0 .1em;
  -webkit-text-stroke: 5px var(--ink);
  paint-order: stroke fill;
}
.mg__note { margin: 0; font-size: var(--fs-xs); color: var(--text-dim); font-weight: 700; }

/* ---------- 入力中のことば ----------
   ここは「くぼんだ受け皿」。板より一段低く見せて、
   打った字が落ちてくる場所であることを形で示す。 */

.dock { display: flex; flex-direction: column; gap: var(--s2); }
.dock__actions { display: grid; grid-template-columns: 1fr 1.7fr; gap: var(--s2); }
/* キーボードで打てることの案内。指で遊ぶ狭い画面には出さない。 */
.dock__hint { display: none; margin: 0; font-size: var(--fs-xs); color: var(--text-dim); text-align: center; font-weight: 700; }

/* 入力が弾かれた理由。打っているときの目の先は入力欄なので、ここに出す。
   入力欄と同じ幅の帯にして、どちらのものかを迷わせない。

   高さは出ていても消えていても同じ。min-height と line-height を
   同じ 1.4em で揃え、消すときは visibility だけを落とす
   （display:none にすると真下の「ことばを出す」が上下に動いてしまう）。
   1 行に収める指定も同じ理由。長い理由でも折り返して背を伸ばさせない。 */
.dock__alert {
  margin: 0;
  min-height: 1.4em;
  line-height: 1.4;
  padding: 2px var(--s3);
  border: var(--bw-thin) solid var(--danger-deep);
  border-radius: var(--r-pill);
  background: color-mix(in oklab, var(--danger) 16%, var(--paper));
  color: var(--danger-deep);
  font-size: var(--fs-sm);
  font-weight: 900;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  visibility: hidden;
}
.dock__alert.is-on { visibility: visible; }

.word-slot {
  position: relative;
  display: flex; justify-content: center; align-items: center;
  gap: 3px;
  min-height: 58px;
  padding: var(--s2) var(--s3);
  background: var(--paper-2);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r-sm);
  overflow-x: auto;
  scrollbar-width: none;
  box-shadow: inset 0 3px 0 rgba(35,43,69,.10);
  transition: border-color var(--t-quick), box-shadow var(--t-quick);
}
/* 自分の番のあいだは入力欄が生きていることを縁で示す */
.btl[data-turn="me"] .word-slot {
  border-color: var(--p0-deep);
  box-shadow: inset 0 3px 0 rgba(35,43,69,.10),
              0 0 0 4px color-mix(in oklab, var(--p0) 26%, transparent);
}
.word-slot::-webkit-scrollbar { display: none; }
.word-slot__ch {
  font-size: 1.7rem;
  min-width: 1.05em;
  text-align: center;
  color: var(--ink);
}
.word-slot__ch--head { color: var(--gold-deep); }
.word-slot__caret {
  width: 4px; height: 1.6rem; flex: none;
  background: var(--p0);
  border-radius: 2px;
  animation: caret 1.1s steps(1,end) infinite;
}
.word-slot__ph { color: var(--text-faint); font-size: var(--fs-sm); font-weight: 800; }
/* ローマ字で打っている途中の綴り（"ky" など）。
   確定したかなと同じ見た目にすると「もう入った」と勘違いするので、
   小さく・薄く・下線つきで、まだ決まっていないことが分かる形にする。 */
.word-slot__romaji {
  align-self: center;
  font-size: 1rem; font-weight: 900; letter-spacing: .04em;
  color: var(--gold-deep);
  border-bottom: 3px solid color-mix(in oklab, var(--gold) 70%, transparent);
  padding: 0 1px;
  text-transform: lowercase;
}
@keyframes caret { 50% { opacity: 0; } }

/* ============================================================
   対戦画面
   ============================================================ */

.btl {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  flex: 1;
  min-height: 0;
}

/* 左にフェーズの札、真ん中に VS。
   右のヘルプを外したので、flex の「余った幅の中央」だと VS が右へずれてしまう。
   左右に同じ幅の枠を置く格子にして、札の長さや右の中身に関わらず
   VS がバーの真ん中で止まるようにする。
   真ん中の枠にも幅を持たせるのは、名前 2 つが席を分け合うため
   （中身なりの幅にすると、短いほうに合わせて長い名前が切れる）。 */
.btl__bar {
  display: grid;
  /* 左右の枠を同じ幅にしておくと、真ん中の枠が中身の長さに関わらず
     バーの中央で止まる。真ん中は minmax(0, auto)：名前が長いときは
     中身なりに広がってよいが、詰まったら 0 まで縮んでよい
     （縮まないと、名前 2 つがバーからはみ出す）。 */
  grid-template-columns: 1fr minmax(0, auto) 1fr;
  align-items: center;
  gap: var(--s3);
  min-height: 40px;
}
.btl__bar > .phase-chip { grid-column: 1; justify-self: start; }
.btl__bar > .vs { grid-column: 2; min-width: 0; }

/* 上の VS 表示。だれとだれが戦っているのかを常に出しておく */
.vs {
  display: none;
  align-items: center; gap: var(--s3);
  justify-content: center;
  font-size: var(--fs-md); font-weight: 900;
}
.vs__side {
  color: var(--pc-deep, var(--ink));
  max-width: 15ch; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-align: right;
  transition: opacity var(--t-quick);
}
.vs__side--r { text-align: left; }
.vs__side.is-idle { opacity: .4; }
.vs__mark {
  font-size: 1.3rem; color: var(--paper); letter-spacing: .06em;
  -webkit-text-stroke: 5px var(--ink); paint-order: stroke fill;
  flex: none;
}

/* ---------- 盤面（自分・相手で同じ部品） ----------
   盤は 1 枚の板。席の色で縁取るので、どちらの盤かを見なくても分かる。 */

.board {
  position: relative;
  display: flex; flex-direction: column; gap: var(--s2);
  min-width: 0;
  background: var(--paper);
  border: var(--bw) solid var(--pc, var(--p0));
  border-radius: var(--r);
  padding: var(--s3);
  box-shadow: 0 6px 0 var(--pc-deep, var(--p0-deep)), var(--cast);
}
.board--me  { --pc: var(--p0); --pc-lite: var(--p0-lite); --pc-deep: var(--p0-deep); }
.board--foe { --pc: var(--p1); --pc-lite: var(--p1-lite); --pc-deep: var(--p1-deep); }

.board__head { display: flex; align-items: center; gap: var(--s2); font-size: var(--fs-sm); }
.board__hp {
  margin-left: auto; color: var(--text-dim);
  font-variant-numeric: tabular-nums; font-size: var(--fs-xs);
  font-weight: 900; letter-spacing: .06em;
  display: inline-flex; align-items: baseline; gap: 3px;
}
/* 分子（いま何字使えるか）が知りたいことなので、そちらを大きく前に置く。
   分母は「81 のうち」を思い出すための添え物で、読み返す必要はない。 */
.board__hp b { color: var(--ink); font-size: 2.1em; line-height: 1; transition: color var(--t-quick); }
/* 残りが 3 割を切った。バーを外したので、危なさを言うのはこの数字だけになった */
.board__hp.is-low b { color: var(--danger-deep); }
.board__hp i { font-style: normal; }
.board__hp__sep { opacity: .5; margin: 0 1px; }

/* 予備の持ち時間。回復しない資源なので、残り字数とは別の色（金）で持たせる。
   自分のぶんも相手のぶんも同じ形で出すので、削り合いと同じように読める。 */
.board__spare {
  display: inline-flex; align-items: baseline; gap: 3px;
  padding: 2px var(--s2);
  border-radius: var(--r-pill);
  border: 2px solid var(--gold-deep);
  background: #fff6dc;
  color: var(--gold-deep);
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.board__spare[hidden] { display: none; }
.board__spare i { font-style: normal; }
.board__spare b { color: var(--gold-deep); font-size: 1.3em; }
.board__spare.is-empty {
  border-color: var(--text-faint);
  background: var(--paper-2);
  color: var(--text-faint);
}
.board__spare.is-empty b { color: var(--text-faint); }

.board__note {
  margin: 0; font-size: var(--fs-xs); color: var(--text-dim); text-align: center;
  font-weight: 700; line-height: 1.6;
}

/* 相手の削れた文字だけを見せる、モバイル専用の要約。 */
.foe-summary, .foe-aim { display: none; }

/* コンピューターの体力。「あと何文字こわせば勝てるか」だけを言う。
   ひとり用にしかない勝ち筋なので、オンライン対戦ではそもそも置かれない。

   緑（--go）にしたのは、席の色（青・朱）が「だれのものか」しか言わない色だから。
   この帯が言うのは「勝ちまでの距離」で、意味の層が違う。混ぜると、
   同じ朱が「相手のもの」と「あと少しで勝てる」の両方を指してしまう。

   減った直後は白い残像（ghost）が遅れて追いつくので、削った量が目に残る。 */
.hpbar { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.hpbar[hidden] { display: none; }
.hpbar__track {
  position: relative;
  flex: 1 1 auto; min-width: 0;
  height: 15px;
  border-radius: var(--r-pill);
  background: var(--sunken);
  border: var(--bw-thin) solid var(--ink);
  overflow: hidden;
  box-shadow: inset 0 2px 0 rgba(35,43,69,.12);
}
.hpbar__ghost, .hpbar__fill {
  position: absolute; inset: 0 auto 0 0;
  width: 100%;
  border-radius: inherit;
}
.hpbar__ghost { background: #fff; }
.hpbar__fill {
  background: var(--go);
  box-shadow: inset 0 4px 0 rgba(255,255,255,.38);
}
/* 帯だけだと、残りが少ないところで「あと2」と「あと3」の差が読めない。
   決着に近いところこそ数が要るので、数は必ず添える。 */
.hpbar__num {
  flex: none;
  color: var(--go-deep);
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.hpbar__num b { font-size: 1.5em; }

/* ---------- 中央のアリーナ ---------- */

.arena {
  display: flex; flex-direction: column; gap: var(--s2);
  align-items: center;
  padding: var(--s3);
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r);
  box-shadow: var(--lift-3), var(--cast);
  min-width: 0;
  position: relative;
  overflow: hidden;
}
/* 手番の側にアリーナの色が寄る。今どちらの番かが、視界のはしでも分かる */
.arena::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 58% at 50% 0%,
              color-mix(in oklab, var(--turn-color, var(--p0)) 26%, transparent), transparent 72%);
  transition: background var(--t-beat) var(--ease);
}
.btl[data-turn="me"]  .arena { --turn-color: var(--p0); }
.btl[data-turn="foe"] .arena { --turn-color: var(--p1); }
.arena > * { position: relative; z-index: 1; }

/* 誰の番かは、いちばん大きく言う。縁取りで色を持たせるので、
   小さな文字色の違いではなく「形」で分かる。 */
.arena__turn {
  margin: 0;
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; font-size: var(--fs-xl); letter-spacing: .02em;
  text-align: center;
  color: var(--paper);
  -webkit-text-stroke: 6px var(--turn-color, var(--p0));
  paint-order: stroke fill;
}
.arena__turn.is-mine { -webkit-text-stroke-color: var(--p0); }
.arena__turn.is-foe  { -webkit-text-stroke-color: var(--p1); }

/* 残り時間の輪。中に「次に始める文字」を入れて、見るところを1つにする。
   白い皿を下に敷いて輪郭を回すので、輪が地に溶けない。 */
.dial { position: relative; width: 140px; height: 140px; flex: none; }
.dial::before {
  content: "";
  position: absolute; inset: 9px;
  border-radius: 50%;
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  box-shadow: 0 4px 0 var(--ink);
}
.dial svg { position: relative; width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.dial circle { fill: none; stroke-width: 11; }
.dial__track { stroke: var(--sunken); }
.dial__fill {
  stroke: var(--turn-color, var(--p0));
  stroke-linecap: round;
  stroke-dasharray: 326.7;
  stroke-dashoffset: 0;
  transition: stroke var(--t-quick);
}
.dial__char {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 3.6rem; line-height: 1;
  color: var(--gold);
  -webkit-text-stroke: 6px var(--ink);
  paint-order: stroke fill;
  padding-bottom: 4px;
}
.dial__cap {
  margin: 0;
  font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .16em;
}
.dial__meta {
  margin: 0; display: flex; align-items: baseline; gap: var(--s1);
  font-size: var(--fs-xs); color: var(--text-dim); font-weight: 900; letter-spacing: .08em;
}
.dial__sec {
  font-size: 1.75rem; color: var(--paper);
  -webkit-text-stroke: 6px var(--ink);
  paint-order: stroke fill;
  font-variant-numeric: tabular-nums;
  transition: -webkit-text-stroke-color var(--t-quick);
}
.dial__unit { font-size: var(--fs-xs); }
.dial__phase { font-weight: 900; letter-spacing: .08em; }
.timer-urgent .dial__fill { stroke: var(--danger); }
.timer-urgent .dial__sec { -webkit-text-stroke-color: var(--danger-deep); }

/* 基本を使い切って、予備が減り始めた状態。
   輪の色が変わることで「もう後がない時間を使っている」と分かる。 */
.timer-reserve .dial__fill { stroke: var(--gold); }
.timer-reserve .dial__phase { color: var(--gold-deep); }
.timer-reserve .dial__sec { -webkit-text-stroke-color: var(--gold-deep); }
.timer-reserve.timer-urgent .dial__fill { stroke: var(--danger); }
.timer-reserve.timer-urgent .dial__sec { -webkit-text-stroke-color: var(--danger-deep); }

/* 通ったことばを、いちど大きく見せる札。
   どの文字が攻撃になったのかを、その場で色で教える。 */
.strike {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: var(--s2) var(--s4);
  border-radius: var(--r-sm);
  background: var(--paper);
  border: var(--bw-thin) solid var(--strike-color, var(--p0));
  box-shadow: 0 4px 0 var(--strike-color, var(--p0));
  max-width: 100%;
}
.strike[hidden] { display: none; }
/* だれの手か。席の色で塗った小さな札にして、名前を読まなくても
   自分の色か相手の色かで見分けられるようにする。 */
.strike__who {
  align-self: center;
  max-width: 10em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 1px 9px;
  border-radius: var(--r-pill);
  background: var(--strike-color, var(--p0));
  color: #fff;
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .06em;
}
.strike__word {
  font-size: 1.7rem; line-height: 1.2; color: var(--ink);
  letter-spacing: .02em; white-space: nowrap;
}
/* 挟まれた＝攻撃になった文字 */
.strike__word b {
  color: var(--strike-color, var(--p0));
  font-weight: 900;
}
.strike__tag {
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .1em;
  color: var(--text-dim);
}

/* 経過を開くボタン。鎖（.log）が置ける広い画面では出さない
   （すでに中央に出ているものを、もう一度ボタンの奥に隠す意味がない）。 */
.log-open { display: none; }

/* ---------- 経過（しりとりの鎖） ---------- */

.log {
  list-style: none; margin: 0; padding: 0 2px 2px;
  display: flex; flex-direction: column; gap: 5px;
  width: 100%;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--text-faint) transparent;
  flex: 1; min-height: 0;
  /* 新しい手は上、古い手は下。あふれる側（下）をぼかして、
     まだ続きがあることを見せる。 */
  mask-image: linear-gradient(180deg, #000 calc(100% - 16px), transparent);
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 16px), transparent);
}
.log::-webkit-scrollbar { width: 5px; }
.log::-webkit-scrollbar-thumb { background: var(--text-faint); border-radius: 3px; }
.log__empty {
  margin: auto 0; text-align: center;
  font-size: var(--fs-xs); color: var(--text-dim); line-height: 1.9; font-weight: 700;
}
.log__item { display: flex; }
.log__item[data-side="me"]  { justify-content: flex-start; }
.log__item[data-side="foe"] { justify-content: flex-end; }
.log__word {
  background: var(--paper);
  border: var(--bw-thin) solid var(--pc, var(--ink));
  color: var(--ink);
  border-radius: var(--r-pill);
  padding: 4px 12px;
  font-size: var(--fs-sm);
  font-weight: 900;
  white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  box-shadow: 0 2px 0 var(--pc, var(--ink));
}
/* 挟まれた＝相手を削った文字。ここだけ席の色で塗る */
.log__word b { color: var(--pc, var(--p0)); }

/* ---------- キーボード ----------

   ひとつのキーが言わなければいけないことは 3 つある。
     あと何回耐えるか ／ 何回やられたか ／ もう後がないか
   これを色だけに背負わせない。色は 1 段階しか言い分けられないのに、
   耐久は設定で 1・2・3 と変わるからである（耐久 3 なら 4 状態ある）。

     高さ  … 下からたまっている塗りの量が「あと何回」
     ひび  … 削られた回数だけ、縁から中へ割れが増える
     色    … オレンジだけが「あと 1 回で消える」を言う

   ひびは背景画像 1 枚。同じ線を「太く薄い白」→「細く濃い色」の順に
   2 度描いてあるので、濃い塗りの上でも、空いた素地の上でも同じように割れて見える。
   字はひびより手前に置く（--- どの文字を失ったか読めないと次の手が考えられない）。

   かなの表は 2 枚に分ける。清音（ア〜ワヲン）と、濁音・半濁音・小書き・長音。
   10 段つながっていると、どこに何があるか探しにくい。 */

.kbd {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}
.kbd__grid {
  display: grid;
  grid-template-columns: repeat(10, var(--cell));
  gap: var(--gap);
}
.kbd__blank { visibility: hidden; }

.key {
  --hp: 1;
  --fill: calc(var(--hp) * 100%);
  /* 席の色は盤（.board--me / .board--foe）から受け継ぐ。
     ここで --pc を定義すると継承を打ち消してしまうので、
     既定値は使うところの fallback に置く。 */
  position: relative;
  appearance: none;
  border: var(--bw-thin) solid var(--ink);
  border-radius: 9px;
  background-color: var(--sunken);        /* 減って空いたところ */
  color: #fff;
  height: var(--key-h);
  font: inherit;
  font-size: calc(min(var(--cell), var(--key-h)) * .54);
  font-weight: 900;
  line-height: 1;
  display: grid;
  place-items: center;
  cursor: pointer;
  overflow: hidden;
  box-shadow: 0 3px 0 var(--pc-deep, var(--p0-deep));
  text-shadow: 0 1.5px 0 rgba(0,0,0,.22);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease),
              border-color var(--t-quick), color var(--t-quick), opacity var(--t-quick);
}
/* 下からたまっている耐久。高さが「あと何回耐えるか」。
   上端の白い線が水面で、境目をはっきりさせる。 */
.key::before {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--fill);
  background: linear-gradient(180deg, var(--pc-lite, var(--p0-lite)), var(--pc, var(--p0)) 70%);
  box-shadow: inset 0 2px 0 rgba(255,255,255,.6);
  transition: height var(--t-quick) var(--ease-back), background var(--t-quick);
}
/* ひび。塗りの上に敷く。
   --crack-in は「どこまで描けたか」。既定は 1（もう全部見えている）で、
   被弾のときだけ effects.mjs が 0 から動かして、縁から中へ広がって見せる。 */
.key::after {
  content: "";
  position: absolute; inset: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  opacity: 0;
  clip-path: circle(calc(var(--crack-in, 1) * 175%) at 100% 0%);
  transition: opacity .12s linear;
}
/* 字はひびより手前。壊れても読めるままにしておく */
.key__ch { position: relative; z-index: 1; }

.key:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 0 var(--pc-deep, var(--p0-deep)); }
.key:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 0 0 var(--pc-deep, var(--p0-deep)); }
.key:disabled { cursor: default; }
.key:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; z-index: 2; }

/* 1 回やられた／2 回以上やられた。ひびの数で「食らった量」を言う */
.key[data-cracks="1"]::after { opacity: 1; background-image: var(--crack-1); }
.key[data-cracks="2"]::after { opacity: 1; background-image: var(--crack-2); }

/* あと 1 回で消える。色が意味を持つのはここだけなので、
   耐久 1・2・3 のどれで遊んでいても合図は同じになる。 */
.key.is-last {
  --pc: var(--warn);
  --pc-lite: var(--warn-lite);
  --pc-deep: var(--warn-deep);
  color: #4a2600;
  text-shadow: 0 1.5px 0 rgba(255,255,255,.35);
}

/* 壊れた。へこんだ穴になり、1 点から放射状に砕ける。
   字は読めるまま残す。どの文字を失ったのか分からないと、次の手を考えられない。 */
.key.is-dead {
  background-color: var(--sunken-2);
  border-color: var(--ink-soft);
  color: #6f7893;
  text-shadow: none;
  box-shadow: inset 0 4px 0 rgba(0,0,0,.14), inset 0 -2px 0 rgba(255,255,255,.5);
}
.key.is-dead::after { opacity: 1; background-image: var(--crack-x); }
.key.is-dead:hover:not(:disabled), .key.is-dead:active:not(:disabled) { transform: none; }

/* 壊れていても「始めの1字」には打てる。押せることが分かるように縁を灯す */
.key.is-dead.is-open {
  color: var(--gold-deep);
  border-color: var(--gold-deep);
  box-shadow: inset 0 4px 0 rgba(0,0,0,.12), 0 0 0 4px color-mix(in oklab, var(--gold) 42%, transparent);
}
/* いま押すべき 1 字。金でふちどって浮かせる */
.kbd--play .key.is-next {
  --pc: var(--gold);
  --pc-lite: var(--gold-lite);
  --pc-deep: var(--gold-deep);
  color: #4a3300;
  text-shadow: 0 1.5px 0 rgba(255,255,255,.45);
  border-color: var(--gold-deep);
  box-shadow: 0 3px 0 var(--gold-deep), 0 0 0 5px color-mix(in oklab, var(--gold) 42%, transparent);
  transform: translateY(-3px);
  z-index: 1;
}

/* 相手の盤面は「どれだけ削れたか」を眺めるためのもの。作りは同じまま小さくする。 */
.kbd--watch { gap: 9px; }
.kbd--watch .kbd__grid { grid-template-columns: repeat(10, var(--cell-foe)); gap: 3px; }
.kbd--watch .key {
  height: var(--key-h-foe);
  font-size: calc(min(var(--cell-foe), var(--key-h-foe)) * .58);
  border-radius: 6px;
  border-width: 2px;
  pointer-events: none;
  box-shadow: 0 2px 0 var(--pc-deep, var(--p0-deep));
}
.kbd--watch .key.is-dead { box-shadow: inset 0 3px 0 rgba(0,0,0,.14); }

/* ---------- 照準（いま打っていることばが当たる先） ----------
   出す前に「どこに当たるか」が見えていないと、狙いを組み替えることができない。

   印は輪でつける。字の上に何も重ねないので、小さい相手の盤でも字が読めたままになる
   （どの文字を狙っているのか読めなければ、照準そのものが意味を失う）。
   輪を二重にしているのは、的に見せるため。

   色は緑。この印が言うのは「だれのものか」ではなく「勝ちに近づくか」なので、
   体力ゲージと同じ層の色を使う。オレンジは「あと1回で消える」専用なので触らない。 */

/* 当たる。生きている字なので、実際に削れる。 */
.kbd--watch .key.is-aim {
  outline: 3px solid var(--go-deep);
  outline-offset: 1px;
  box-shadow: 0 2px 0 var(--pc-deep, var(--p0-deep)),
              0 0 0 5px color-mix(in oklab, var(--go) 45%, transparent);
  z-index: 2;
}
/* 狙ってはいるが、そこはもう壊れている＝この 1 字は捨てている。
   輪郭を破線にして色も落とす。当たるほうとは **形** でも違うので、
   動きを止めた設定でも、色が見えにくい環境でも、2 つを取り違えない。 */
.kbd--watch .key.is-aim-dead {
  outline: 2.5px dashed var(--ink-soft);
  outline-offset: 1px;
  z-index: 2;
}

/* 被弾の演出（GSAP が動かない環境でも最低限見えるように CSS でも用意） */
@keyframes keyHit {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.26); filter: brightness(2.2); }
  100% { transform: scale(1); }
}
.key.is-hit { animation: keyHit .34s var(--ease); }

/* ---------- プレイヤーの色とアイコン ----------
   席ごとに固定の色を割り当てる。「自分から見た敵味方」ではなく
   「誰の情報か」を色で示すため、両者の画面で同じ色になる。
   自分の側は画面下＋「あなた」の印で区別する。 */

[data-color="0"] { --pc: var(--p0); --pc-lite: var(--p0-lite); --pc-deep: var(--p0-deep); --pc-soft: var(--p0-soft); }
[data-color="1"] { --pc: var(--p1); --pc-lite: var(--p1-lite); --pc-deep: var(--p1-deep); --pc-soft: var(--p1-soft); }

.pchip {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-weight: 900; color: var(--pc-deep, var(--ink));
  background: var(--pc-soft, var(--paper-2));
  border: var(--bw-thin) solid var(--pc-deep, var(--ink));
  border-radius: var(--r-pill);
  padding: 3px var(--s3) 3px 5px;
  min-width: 0;
}
.pchip__icon {
  width: 22px; height: 22px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--pc, var(--ink));
  border: 2px solid var(--pc-deep, var(--ink));
  color: #fff;
  line-height: 1;
}
.pchip__icon svg { width: 12px; height: 12px; display: block; }
.pchip__name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-sm);
}
.pchip__you {
  flex: none;
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .08em;
  padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--pc-deep, var(--ink));
  color: #fff;
}

.pchip__tag {
  flex: none; font-style: normal;
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .06em;
  color: var(--pc-deep, var(--text-dim)); opacity: .75;
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Noto Sans JP", system-ui, sans-serif;
}
/* まだ来ていない席。待っていることが見て分かるように、ゆっくり息をさせる。 */
.pchip--wait {
  color: var(--text-faint);
  background: transparent;
  border-color: var(--text-faint);
  border-style: dashed;
  /* 相手の名前より一段小さく。空席は「まだ何も無い」ことを言う枠なので、
     ここを本文と同じ大きさにすると、VS の行が折れて席が縦に離れてしまう。 */
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .02em;
  padding: 6px var(--s3);
  animation: waiting 2.4s var(--ease) infinite;
}
@keyframes waiting {
  0%, 100% { opacity: .5; }
  50%      { opacity: 1; }
}

/* ---------- 結果 ---------- */

.result {
  margin: auto 0;
  display: flex; flex-direction: column; gap: var(--s4);
  text-align: center;
  padding: var(--s6) var(--s4);
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-3), var(--cast);
}
/* かち／まけ の隣に、目が次に行く先を置く。
   前は大きな 2 文字のあと数字が 3 つ並ぶだけで、
   何がよかったのか・何が足りなかったのかが読めなかった。 */
.result__head { display: flex; align-items: center; gap: var(--s5); text-align: left; }
.result__side { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s2); }
.result__verdict {
  margin: 0;
  font-size: clamp(3rem, 15vw, 4.9rem);
  letter-spacing: .05em;
  line-height: 1.06;
  flex: none;
  -webkit-text-stroke: .13em var(--ink);
  paint-order: stroke fill;
}
.result.is-win  .result__verdict { color: var(--go);  filter: drop-shadow(0 6px 0 var(--go-deep)); }
.result.is-lose .result__verdict { color: var(--p1); filter: drop-shadow(0 6px 0 var(--p1-deep)); }
.result__reason { margin: 0; color: var(--text-dim); font-size: var(--fs-md); line-height: 1.8; font-weight: 800; }
.result__reason b { color: var(--gold-deep); }

/* 主役の数字。この対戦のあいだずっと「あと ◯ 文字」と数えてきた目標そのものなので、
   決着でもいちばん大きい数として置く。ふたりで対戦には勝ち筋が無いので出ない。 */
.killstat {
  display: flex; align-items: center; gap: var(--s3);
  border: var(--bw-thin) solid var(--go-deep);
  border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--go) 9%, var(--paper));
  padding: var(--s2) var(--s4);
}
.killstat[hidden] { display: none !important; }
/* 負けた画面で緑の枠が主張すると、届かなかった数を誇っているように見える。
   数は残したまま、枠と字の色だけ引く（どこまで行けたかは、それでも読める）。 */
.result.is-lose .killstat { border-color: var(--ink-soft); background: var(--paper-2); }
.result.is-lose .killstat__k { color: var(--text-dim); }
.result.is-lose .killstat__n b { color: var(--ink); }
.killstat__n {
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900; line-height: 1; flex: none;
  display: flex; align-items: baseline; gap: 2px;
  font-variant-numeric: tabular-nums;
}
.killstat__n b { font-size: 2.7rem; color: var(--go-deep); }
.killstat__n small { font-size: 1.2rem; color: var(--text-dim); }
.killstat__n i { font-style: normal; }
.killstat__b { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.killstat__k { font-size: var(--fs-xs); letter-spacing: .1em; color: var(--go-deep); font-weight: 900; }
.killstat__bar {
  position: relative;
  height: 15px; border-radius: var(--r-pill);
  border: var(--bw-thin) solid var(--ink);
  background: var(--sunken);
  overflow: hidden;
  box-shadow: inset 0 2px 0 rgba(35,43,69,.12);
}
.killstat__fill {
  position: absolute; inset: 0 auto 0 0;
  background: var(--go);
  box-shadow: inset 0 4px 0 rgba(255,255,255,.38);
}
/* 決着したときの盤面。「どれだけ削り合ったか」がそのまま絵になる。
   列は minmax(0, 1fr)。既定の 1fr は「中身より狭くならない」ので、
   見出しの「なまえ／81 分の N」が縮まず、狭い画面で横にはみ出す。 */
.result__boards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
.rboard {
  display: flex; flex-direction: column; gap: var(--s2); align-items: center;
  background: var(--paper-2);
  border: var(--bw-thin) solid var(--pc, var(--ink));
  border-radius: var(--r-sm);
  padding: var(--s3) var(--s2);
  box-shadow: 0 3px 0 var(--pc-deep, var(--ink));
}
.rboard__head {
  display: flex; align-items: center; gap: var(--s2);
  width: 100%; min-width: 0; justify-content: space-between;
  font-size: var(--fs-sm);
}
.rboard__head .pchip { min-width: 0; }
.rboard__head .board__hp { flex: none; }
.rboard .kbd--watch { --cell-foe: 24px; --key-h-foe: 24px; gap: 8px; }
.rboard .kbd--watch .kbd__grid { gap: 4px; }
.rboard .key { border-width: 1.5px; border-radius: 5px; }
/* 広い画面では盤そのものを見せる。削れた文字の一覧は狭い画面用なので出さない
   （下の @media が、この 2 つを入れ替える）。 */
.rboard > .rboard__summary { display: none; }

.result__chain {
  display: flex; flex-wrap: wrap; gap: var(--s1); justify-content: center;
  max-height: 22dvh; overflow-y: auto;
}
.result__chain .log__word { max-width: none; }
/* 次にすることは 1 つだけ大きく出す。共有もやめるも、
   「もう一戦」を探すときの邪魔にならない大きさに落とす。 */
.result__actions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s2);
}
.result__actions #rematchBtn { grid-column: 1 / -1; }
.btn--sub { font-size: var(--fs-sm); color: var(--text-dim); box-shadow: var(--lift-1); }
.btn--sub:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 0 0 var(--ink); }

/* ---------- 戦績 ---------- */

.stats { margin: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
.stats__cell {
  background: var(--paper-2);
  border: var(--bw-thin) solid var(--ink);
  border-radius: var(--r-sm);
  padding: var(--s3) var(--s1);
  text-align: center;
  box-shadow: var(--lift-1);
  /* 見出しが 2 行に折れる枠があると、そこだけ数の高さがずれる。
     数を枠の底に揃えて、3 つの数が同じ高さに並ぶようにする。 */
  display: flex; flex-direction: column; justify-content: flex-end; gap: 2px;
}
.stats__k {
  display: block; font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .06em; line-height: 1.35;
}
.stats__v {
  font-size: 1.7rem; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* 「手」「字」「勝」などの単位は本文の書体で出す。
   見出し書体は必要な字だけに絞ってあるので、絞っていない字を
   混ぜると勝手に代替書体になって不揃いに見える。 */
.stats__v small {
  font-size: .5em;
  color: var(--text-dim);
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Noto Sans JP", system-ui, sans-serif;
  font-weight: 800;
  margin-left: 1px;
}

/* ============================================================
   演出の重ね板
   弾・破片・数字はここに置く。盤面の中に足すと、
   はみ出しやスクロールで切れてしまう。
   ============================================================ */

.fxlayer {
  position: fixed; inset: 0; z-index: 45;
  pointer-events: none;
  overflow: hidden;
}
/* Canvas UI の流体層。盤面の字を消さない濃さに抑え、光として重ねる。
   対戦以外の画面では出さない（流し残りがタイトルや結果に映り込まないように）。 */
.fxlayer canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* もとは暗い地に光を足す screen 合成だった。明るい地では白飛びするだけなので、
     multiply にして「色の濃い影」として重ねる。 */
  opacity: .28;
  mix-blend-mode: multiply;
  transition: opacity var(--t-beat) var(--ease);
}
.fxlayer:not([data-screen="battle"]) canvas { opacity: 0; }

/* 飛んでいく文字（攻撃の弾） */
.fxbullet {
  position: fixed;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border-radius: 9px;
  font-family: 'Display', system-ui, sans-serif;
  font-size: 17px; line-height: 1;
  font-weight: 900;
  color: #fff;
  background: var(--bc, var(--p0));
  border: 2.5px solid var(--ink);
  text-shadow: 0 1.5px 0 rgba(0,0,0,.28);
  box-shadow: 0 3px 0 rgba(35,43,69,.35), inset 0 2px 0 rgba(255,255,255,.45);
  will-change: transform, opacity;
}
/* 破片 */
.fxshard {
  position: fixed;
  width: 6px; height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 2px;
  background: var(--bc, var(--p1));
  box-shadow: 0 0 0 1.5px rgba(35,43,69,.55);
  will-change: transform, opacity;
}
/* 飛び出す数字（−2 など） */
.fxfloat {
  position: fixed;
  transform: translate(-50%, -50%);
  font-family: 'Display', system-ui, sans-serif;
  font-size: 1.7rem; line-height: 1;
  font-weight: 900;
  color: var(--bc, var(--danger));
  -webkit-text-stroke: 5px var(--ink);
  paint-order: stroke fill;
  white-space: nowrap;
  will-change: transform, opacity;
}
/* 着弾の輪 */
.fxring {
  position: fixed;
  width: 20px; height: 20px;
  margin: -10px 0 0 -10px;
  border-radius: 50%;
  border: 3px solid var(--bc, var(--p0));
  will-change: transform, opacity;
}

/* 画面全体のいろ被せ。被弾と破壊の重さを体で分からせる */
.flashlayer {
  position: fixed; inset: 0; z-index: 44;
  pointer-events: none;
  opacity: 0;
}
.flashlayer.is-edge {
  background: radial-gradient(120% 90% at 50% 50%, transparent 52%, var(--fc, var(--danger)) 130%);
}

/* ---------- 全画面通知 ----------
   大事な進行変更（先攻決定・決着・進行交代）を見逃さないように、
   一瞬だけ画面全体を使って知らせる。押さなくても消える。 */

.announce {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: rgba(255,253,246,.82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: var(--s6);
  text-align: center;
  pointer-events: none;
}
.announce[hidden] { display: none; }
.announce__title {
  margin: 0;
  font-size: clamp(2.2rem, 11vw, 4.4rem);
  letter-spacing: .05em; line-height: 1.1;
  color: var(--gold);
  -webkit-text-stroke: .13em var(--ink);
  paint-order: stroke fill;
  filter: drop-shadow(0 6px 0 var(--ink));
}
.announce__sub {
  margin: var(--s4) 0 0; color: var(--ink);
  font-size: var(--fs-md); font-weight: 900; letter-spacing: .04em;
}
.announce.is-mine .announce__title { color: var(--p0); filter: drop-shadow(0 6px 0 var(--p0-deep)); }
.announce.is-foe  .announce__title { color: var(--p1); filter: drop-shadow(0 6px 0 var(--p1-deep)); }

/* ---------- シート（ルール・設定） ---------- */

.sheet {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: end center;
  background: rgba(35,43,69,.42);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.sheet[hidden] { display: none; }
.sheet__panel {
  width: 100%; max-width: 560px;
  max-height: 88dvh;
  display: flex; flex-direction: column;
  background: var(--paper);
  border: var(--bw) solid var(--ink);
  border-bottom: none;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  animation: sheetIn var(--t-beat) var(--ease-back) both;
}
/* 開くときの立ち上がり。開いた／閉じたが動きで分かる */
.sheet { animation: sheetFade var(--t-quick) var(--ease) both; }
@keyframes sheetFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheetIn {
  from { transform: translateY(22px) scale(.97); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
.sheet__panel--short {
  border-radius: var(--r-lg); margin: auto var(--s3);
  border-bottom: var(--bw) solid var(--ink);
  box-shadow: var(--lift-3);
}
.sheet__head {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4);
  border-bottom: var(--bw-thin) solid var(--ink);
}
.sheet__title { margin: 0; font-size: var(--fs-lg); font-weight: 900; }
.sheet__head .btn--icon { margin-left: auto; }
.sheet__body {
  padding: var(--s4) var(--s4) calc(var(--s5) + env(safe-area-inset-bottom));
  overflow-y: auto;
  font-size: var(--fs-md); line-height: 1.9;
  color: var(--text-dim);
  font-weight: 700;
}
.sheet__body--center { text-align: center; display: flex; flex-direction: column; gap: var(--s3); }
.sudden-death-sheet .sheet__panel { border: var(--bw) solid var(--ink); border-top: 8px solid var(--gold); width: calc(100% - 2 * var(--s3)); }
.sudden-death-sheet__eyebrow { color: var(--ink); font-size: var(--fs-sm); font-weight: 800; }
.sudden-death-sheet strong { color: var(--ink); background: var(--sand); padding-inline: .2em; }
.sudden-death-badge { margin: 0; color: var(--ink); background: var(--sand); border-radius: var(--r-sm); font-size: var(--fs-xs); text-align: center; }
.sheet__body h3 {
  margin: var(--s5) 0 var(--s2);
  font-size: var(--fs-xs); color: var(--gold-deep);
  letter-spacing: .16em; font-weight: 900;
}
.sheet__body h3:first-child { margin-top: 0; }
.sheet__body ul { margin: 0; padding-left: 1.25em; }
.sheet__body li { margin-bottom: var(--s1); }
.sheet__body b { color: var(--ink); }

/* ---------- これまでのことば（シート） ----------
   古い順に上から並べる。しりとりは前の語の終わりが次の語の頭になるので、
   上から下へ読めば、つながりかたがそのまま追える。 */
.logsheet { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.logsheet__empty { color: var(--text-dim); font-size: var(--fs-sm); text-align: center; padding: var(--s4) 0; }
.logsheet__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 2px var(--s3);
  padding: var(--s2) var(--s3);
  border: var(--bw-thin) solid var(--pc, var(--ink));
  border-radius: var(--r-sm);
  background: var(--paper);
  box-shadow: 0 2px 0 var(--pc, var(--ink));
}
/* 自分の手と相手の手は、席の色と左の余白で見分ける。
   狭い画面では左右に振り分けても幅が足りず、どちらの列かが読めなくなる。 */
.logsheet__item[data-side="foe"] { margin-left: var(--s4); }
.logsheet__item[data-side="me"]  { margin-right: var(--s4); }
.logsheet__who {
  grid-column: 1; grid-row: 1;
  color: var(--pc-deep, var(--text-dim));
  font-size: var(--fs-xs); font-weight: 900; letter-spacing: .06em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.logsheet__item .log__word {
  grid-column: 1; grid-row: 2;
  justify-self: start;
  border: none; box-shadow: none; background: none; padding: 0;
  font-size: var(--fs-lg);
  white-space: normal;
}
/* 攻撃になった字は席の色で塗る。シートの地の文用に .sheet__body b が
   色を持っているので、ここで名指しして取り返す（同じ強さだと後勝ちで負ける）。 */
.logsheet__item .log__word b { color: var(--pc, var(--p0)); }
.logsheet__note {
  grid-column: 2; grid-row: 1 / span 2;
  color: var(--text-dim);
  font-size: var(--fs-xs); font-weight: 800; letter-spacing: .04em;
  text-align: right;
  white-space: nowrap;
}

/* 対戦中でも今の設定が分かるように、シートの先頭に出す */
.live-settings {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--s2); margin-bottom: var(--s2);
}
.live-settings__item {
  background: var(--paper-2); border: var(--bw-thin) solid var(--ink);
  border-radius: var(--r-sm); padding: var(--s2) var(--s3);
  box-shadow: var(--lift-1);
}
.live-settings__k {
  display: block; font-size: var(--fs-xs); color: var(--text-dim);
  font-weight: 900; letter-spacing: .1em;
}
.live-settings__v {
  font-family: 'Display', system-ui, sans-serif;
  font-weight: 900;
  font-size: 1.15rem; color: var(--ink);
}

.prompt__icon { margin: 0; font-size: 2.8rem; color: var(--p0); line-height: 1; }
.prompt__actions { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s2); }

/* ---------- 切り替えスイッチ ---------- */

.toggle {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) 0;
  cursor: pointer;
  min-height: 48px;
}
.toggle__label { flex: 1; font-weight: 900; color: var(--ink); }
.toggle input { position: absolute; opacity: 0; pointer-events: none; }
.toggle__track {
  width: 54px; height: 32px; flex: none;
  border-radius: var(--r-pill);
  background: var(--sunken);
  border: var(--bw-thin) solid var(--ink);
  position: relative;
  box-shadow: inset 0 2px 0 rgba(35,43,69,.12);
  transition: background var(--t-quick), border-color var(--t-quick);
}
.toggle__knob {
  position: absolute; top: 3px; left: 3px;
  width: 21px; height: 21px; border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--ink);
  transition: transform var(--t-quick) var(--ease-back), background var(--t-quick);
}
.toggle input:checked + .toggle__track { background: var(--p0); }
.toggle input:checked + .toggle__track .toggle__knob { transform: translateX(22px); }
.toggle input:focus-visible + .toggle__track { outline: 3px solid var(--gold); outline-offset: 3px; }

/* ---------- PR枠 ----------
   対戦中には出さない。タイトルと結果だけ。
   広告タグを貼るときは data-slot="promo" の中に入れる。 */

.promo {
  border: var(--bw-thin) dashed var(--text-faint);
  border-radius: var(--r-sm);
  min-height: 60px;
  display: grid; place-items: center;
  color: var(--text-faint);
  font-size: var(--fs-xs);
  overflow: hidden;
}
.promo[hidden] { display: none; }

/* ---------- 接続状態 ---------- */

.conn {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--s3) + env(safe-area-inset-bottom));
  background: var(--danger);
  border: var(--bw-thin) solid var(--ink);
  color: #fff;
  font-size: var(--fs-sm); font-weight: 900;
  padding: var(--s2) var(--s4);
  border-radius: var(--r-pill);
  z-index: 50;
  box-shadow: var(--lift-2);
  display: flex;
  align-items: center;
  gap: var(--s3);
}
.conn[hidden] { display: none; }
.conn__retry {
  appearance: none;
  border: 2px solid #fff;
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--danger);
  font: inherit;
  font-size: var(--fs-xs);
  font-weight: 900;
  padding: var(--s1) var(--s3);
  cursor: pointer;
}
.conn__retry[hidden] { display: none; }

/* ---------- テスト用 ----------
   画面の操作を邪魔しない隅に置き、既定では畳んでおく。 */

.devtools {
  position: fixed; left: var(--s2); bottom: calc(var(--s2) + env(safe-area-inset-bottom));
  z-index: 80;
  display: flex; flex-direction: column; gap: var(--s1); align-items: flex-start;
  font-size: var(--fs-xs);
}
.devtools[hidden] { display: none; }
.devtools__toggle {
  min-height: 30px; padding: var(--s1) var(--s3);
  background: var(--paper);
  border: 2px solid var(--warn-deep); color: var(--warn-deep);
  border-radius: var(--r-pill); font: inherit; font-weight: 900;
  cursor: pointer;
}
.devtools__body {
  background: var(--paper);
  border: 2px solid var(--warn-deep);
  border-radius: 10px;
  padding: var(--s2);
  display: flex; flex-direction: column; gap: var(--s1);
  max-width: 190px;
}
.devtools__body[hidden] { display: none; }
.devtools__title { color: var(--warn-deep); font-weight: 900; letter-spacing: .08em; }
.devtools .btn { min-height: 30px; padding: var(--s1) var(--s2); font-size: var(--fs-xs); }

/* ---------- 案内ページ ---------- */

.doc { max-width: 720px; margin: 0 auto; width: 100%; }
.doc__body { line-height: 2; color: var(--text-dim); font-weight: 700; }
.doc__body h2 {
  margin: var(--s6) 0 var(--s2); font-size: var(--fs-lg); color: var(--ink); font-weight: 900;
  padding-bottom: var(--s2); border-bottom: var(--bw-thin) solid var(--ink);
}
.doc__body h2:first-child { margin-top: 0; }
.doc__body p { margin: 0 0 var(--s3); }
.doc__body ul { margin: 0 0 var(--s3); padding-left: 1.35em; }
.doc__body li { margin-bottom: var(--s1); }
.doc__body b { color: var(--ink); }
.doc__body a { color: var(--p0-deep); }
.doc__back { margin-top: var(--s6); text-align: center; }
.doc__back .btn { text-decoration: none; display: inline-block; }

/* ============================================================
   広い画面（PC 基準のレイアウトはここから）
   ============================================================ */

@media (min-width: 860px) {
  .screen { max-width: 1180px; margin: 0 auto; width: 100%; padding: var(--s6); }

  /* --- タイトル：看板 → 遊び方 → 入口 の順に縦へ積む。
         横に 2 段組みにすると、遊び方か入口のどちらかが必ず折り返しの下に落ちる。 --- */
  .screen--title {
    max-width: 1120px; gap: var(--s3);
    padding: var(--s4) var(--s6);
  }
  .title-fx { padding: 18px 28px 18px; }
  /* 題名が 2 行になったぶん、看板の背が高くなる。ここを詰めないと、
     いちばん押してほしい 2 つのボタンが 860px の画面で折り返しの下に落ちる。 */
  .screen--title .logo { font-size: clamp(2.6rem, 4.3vw, 3.5rem); }

  /* シートは広い画面では中央のカードにする。下辺に貼りつくのは縦画面の作法 */
  .sheet { place-items: center; }
  .sheet__panel { border-radius: var(--r-lg); max-height: 84dvh; max-width: 620px; }

  /* --- ロビー：左に「この対戦がどうなるか」の要約、右に設定 --- */
  .screen--lobby { max-width: 1080px; justify-content: center; }
  .lobby {
    display: grid; grid-template-columns: 440px minmax(0, 1fr);
    align-items: start; gap: var(--s4);
  }
  .lobby__who { padding: var(--s4) var(--s5); gap: var(--s4); }
  .lobby__setup { padding: var(--s4) var(--s5); }
  /* 設定の枠は左の要約より背が高い。始めるボタンを枠の底に貼り付けておくと、
     設定を出し入れしてもボタンの位置が動かない。 */
  .lobby__setup #startBtn { margin-top: auto; }

  /* --- 先攻決め：左にお題と入力、右に文字盤。対戦と同じ読み方にする --- */
  .screen--minigame { max-width: 1000px; justify-content: center; }
  .mg {
    display: grid;
    grid-template-columns: minmax(280px, 380px) minmax(0, auto);
    align-items: center;
    justify-content: center;
    gap: var(--s8);
  }
  .mg__lead { gap: var(--s3); }
  .mg__play { gap: var(--s3); align-items: stretch; }
  .mg__puzzle { font-size: 1.45rem; padding: var(--s6) var(--s5); }
  .mg .kbd { justify-content: center; }

  /* ============ 対戦：左＝自分 / 中央＝盤外の情報 / 右＝相手 ============
     攻撃はいつも左から右へ飛ぶ。どちらが殴ったのかが体で分かる。 */
  :root {
    --cell: 40px;
    --cell-foe: 30px;
    --gap: 5px;
  }
  .screen--battle { max-width: 1320px; padding: var(--s5) var(--s6); }

  .btl {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(268px, 1fr) minmax(0, auto);
    grid-template-rows: auto minmax(0, 1fr);
    justify-content: center;
    column-gap: var(--s6);
    row-gap: var(--s4);
  }
  /* 場所の指定は必ず .btl の直下に限る。
     .arena や .board は他のページ（dev/preview.html）にも出てくるので、
     裸のセレクタで置き場所を決めると、そこで重なって壊れる。 */
  .btl > .btl__bar { grid-column: 1 / -1; }
  .btl > .board--me  { grid-column: 1; grid-row: 2; }
  .btl > .arena      { grid-column: 2; grid-row: 2; }
  .btl > .board--foe { grid-column: 3; grid-row: 2; }

  .vs { display: flex; }

  /* 盤面まわり。手番でない側は板を机に沈めて、いま動くほうを立たせる */
  .btl > .board { padding: var(--s4); transition: transform var(--t-beat) var(--ease), box-shadow var(--t-beat) var(--ease); }
  .btl[data-turn="me"]  .board--me,
  .btl[data-turn="foe"] .board--foe {
    box-shadow: 0 6px 0 var(--pc-deep), 0 0 0 5px color-mix(in oklab, var(--pc) 30%, transparent), var(--cast);
  }
  .btl[data-turn="foe"] .board--me,
  .btl[data-turn="me"]  .board--foe {
    transform: translateY(3px);
    box-shadow: 0 3px 0 var(--pc-deep);
  }

  .dock__hint { display: block; }

  /* 入力は必ず盤面の下端に置く。手番が変わっても場所が動かないようにする。 */
  .board--me .dock { margin-top: auto; padding-top: var(--s3); }
  .board--foe .board__note { margin-top: auto; padding-top: var(--s3); }
  .board__head { font-size: var(--fs-md); }

  .arena { padding: var(--s4) var(--s3); gap: var(--s3); }
  .arena__turn { font-size: 1.15rem; }
  .dial { width: 148px; height: 148px; }
  .dial__char { font-size: 3.9rem; }
  /* 経過の枠の高さは決め打ちにする。ここを内容まかせにすると、
     手が進むたびに中央の列が伸びて、左の列の「ことばを出す」が下がっていく。
     枠は動かさず、あふれたぶんは枠の中だけでスクロールさせる。 */
  .log { flex: 1 1 auto; max-height: clamp(130px, 26vh, 280px); }

  /* 決着：2 枚の盤を大きく見せたいので、板そのものを広げる */
  /* margin:auto を入れた時点で幅は中身なりになるので、width も明示する。
     そうしないと板が中身の分だけ縮み、盤を大きくしても板ごと痩せてしまう。 */
  .screen--result .result { width: 100%; max-width: 980px; margin: auto; padding: var(--s6) var(--s8); }
  /* 「もう一戦」だけを大きく。残りは同じ行に小さく並べる */
  .result__actions { grid-template-columns: minmax(0, 1fr) 150px 150px 130px; }
  .result__actions #rematchBtn { grid-column: auto; }
}

/* もっと広いとき。盤面を少しだけ大きくして、真ん中に余白を持たせる */
@media (min-width: 1280px) and (min-height: 860px) {
  :root { --cell: 44px; --cell-foe: 34px; }
  .dial { width: 164px; height: 164px; }
  .dial__char { font-size: 4.3rem; }
}

/* ---------- 縦が短い画面 ----------
   対戦画面はスクロールさせない。「ことばを出す」が画面外にあると、
   15秒の勝負では致命的なので、縦に余裕がないぶんはキーを縮めて詰める。 */

@media (min-width: 860px) and (max-height: 820px) {
  :root { --cell: 34px; --cell-foe: 26px; --gap: 4px; }
  .screen--battle { padding: var(--s3) var(--s5); }
  .btl { row-gap: var(--s3); }
  .board { padding: var(--s3); }
  .dial { width: 116px; height: 116px; }
  .dial__char { font-size: 3rem; }
  .arena { gap: var(--s2); }
}
@media (min-width: 860px) and (max-height: 700px) {
  :root { --cell: 29px; --cell-foe: 22px; --gap: 3px; }
  .dial { width: 98px; height: 98px; }
  .dial__char { font-size: 2.5rem; }
  .word-slot { min-height: 46px; }
  .btl__bar { min-height: 32px; }
}

/* ---------- 狭い画面（縦持ち） ----------
   同じ部品を縦に積み替える。相手・中央・自分の順で、下へ行くほど自分のもの。

   ここでの制約はただ一つ、「ことばを出す」を画面の外に出さないこと。
   15 秒の勝負でスクロールを強いるのは致命的なので、
   縦の余裕に合わせてキーを縮めて詰める。下の段ほど厳しい端末向け。 */

@media (max-width: 859px) {
  /* --- タイトル：3 コマも 2 つの入口も縦に積む。
         横に並べたままだと 1 枚が 110px ほどになり、どちらも読めない札になる。 --- */
  .how  { grid-template-columns: minmax(0, 1fr); }
  .enter { grid-template-columns: minmax(0, 1fr); }
  .title-fx { padding: var(--s4) var(--s3); }
  /* 縦に積むと入口の札 2 枚が並ばないので、床に貼り付ける意味がなくなる。
     ボタンは説明のすぐ下に置いて、札 1 枚を短くする。 */
  .way .btn--lg { margin-top: 0; }
  .title-links { margin-top: var(--s1); }

  /* --- ロビー：2 人ぶんの席が横に収まらないので縦に積む。
         横のまま折り返すと VS だけが 1 行目の右端に残って、
         どちらとどちらが戦うのかが読めなくなる。 --- */
  .who__row { flex-direction: column; align-items: flex-start; gap: var(--s1); }
  .vsmark { align-self: center; }

  /* --- 決着：かち／まけ を上、読むものを下に積む --- */
  .result__head { flex-direction: column; gap: var(--s3); text-align: center; }
  .result__side { width: 100%; }
  .killstat { padding: var(--s2) var(--s3); }
  .killstat__n b { font-size: 2.2rem; }

  /* 高さは 100dvh を「下限」にする。以前はここを height + overflow: hidden で
     固定していたので、収まらない端末では画面外にはみ出したぶんが
     切り落とされ、いちばん下の「ことばを出す」に指が届かなくなっていた。
     下のキーの高さが画面なりに縮むので、ふつうは 1 画面に収まる。
     それでも足りない端末では、ページごとスクロールして届く。 */
  .screen--battle {
    min-height: 100dvh;
    gap: var(--s2);
  }
  .btl { gap: 6px; }
  /* 手数（「6手目」）は狭い画面では出さない。VS の名前もここでは隠しているので、
     この帯は札 1 枚のために 32px を使っているだけになる。帯ごと外して、
     その高さを中央の一行（何を削られたか）に回す。手数は決着の画面で見られる。 */
  .btl > .btl__bar   { display: none; }
  /* 上から「相手 → 中央の情報 → 自分と入力」。HTML の並び（自分が先）とは違うので、
     ここで明示的に組み替える。指の届く下側を自分の操作に空ける。 */
  .btl > .board--foe { order: 1; }
  .btl > .arena      { order: 2; }
  .btl > .board--me  { order: 3; }
  .board--foe .kbd--watch,
  .board--foe .board__note { display: none; }
  .board--foe { flex: none; }
  .foe-summary {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-height: 34px;
    padding: 7px 9px;
    border: 2px solid var(--pc-deep);
    border-radius: 10px;
    background: color-mix(in oklab, var(--pc-soft) 52%, var(--paper));
  }
  .foe-summary__empty {
    margin: 0;
    color: var(--text-dim);
    font-size: var(--fs-xs);
    font-weight: 800;
    line-height: 1.5;
  }
  .foe-summary__row {
    display: grid;
    grid-template-columns: 22px auto minmax(0, 1fr);
    gap: 7px;
    align-items: start;
    min-width: 0;
  }
  .damage-icon {
    position: relative;
    width: 21px;
    height: 18px;
    border: 2px solid var(--ink);
    border-radius: 5px;
    background: linear-gradient(180deg, var(--pc-lite), var(--pc));
    box-shadow: 0 2px 0 var(--pc-deep);
  }
  .damage-icon::after {
    content: "";
    position: absolute;
    inset: 1px;
    background: var(--crack-1) center / cover no-repeat;
  }
  .foe-summary__row[data-damage="2"] .damage-icon::after { background-image: var(--crack-2); }
  .foe-summary__row[data-damage="broken"] .damage-icon {
    background: var(--sunken-2);
    border-color: var(--ink-soft);
    box-shadow: inset 0 3px 0 rgba(0,0,0,.14);
  }
  .foe-summary__row[data-damage="broken"] .damage-icon::after { background-image: var(--crack-x); }
  .foe-summary__label {
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 900;
    line-height: 18px;
    white-space: nowrap;
  }
  .foe-summary__chars {
    min-width: 0;
    color: var(--ink);
    font-size: var(--fs-sm);
    font-weight: 900;
    line-height: 18px;
    white-space: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .foe-summary__chars::-webkit-scrollbar { display: none; }
  .foe-aim {
    align-items: center;
    gap: 7px;
    min-width: 0;
  }
  .foe-aim:not([hidden]) { display: flex; }
  .foe-aim__label {
    flex: none;
    color: var(--go-deep);
    font-size: 10px;
    font-weight: 900;
    letter-spacing: .03em;
  }
  .foe-aim__chars { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
  .foe-aim__char {
    display: grid;
    place-items: center;
    min-width: 25px;
    height: 25px;
    padding-inline: 5px;
    border: 2px solid var(--go-deep);
    border-radius: 7px;
    background: var(--paper);
    color: var(--ink);
    font-size: var(--fs-sm);
    font-weight: 900;
    box-shadow: 0 2px 0 var(--go-deep);
  }
  .foe-aim__char.is-dead {
    border-style: dashed;
    border-color: var(--ink-soft);
    color: var(--text-faint);
    box-shadow: none;
  }
  /* 結果の 2 枚の盤。狭い画面ではキーが 11px の粒になり、
     どの字が削れたのかまったく読めない。盤はやめて、対戦中の相手と同じ
     「削れた文字だけの一覧」に差し替える。2 枚は縦に積む
     （横に並べたままだと 1 枚 150px ほどで、文字の列が読めないため）。 */
  .result__boards { grid-template-columns: minmax(0, 1fr); }
  .rboard { padding: var(--s2) var(--s1); }
  .rboard .kbd--watch { display: none; }
  /* 結果は中央そろえの画面だが、字の一覧だけは左そろえにする。
     中央そろえだと行ごとに頭の位置がずれて、目で追えなくなる。 */
  .rboard > .rboard__summary { display: flex; width: 100%; text-align: left; }
  /* 対戦中は「いま増えた字」を横スクロールで流すが、結果は読み切るものなので折り返す。 */
  .rboard__summary .foe-summary__chars { white-space: normal; overflow-x: visible; }
  /* 盤 1 枚が 150px ほどしかないので、名前と「81 分の ◯◯」を横に並べると
     「あなた」の印が数の上に乗る。ここだけ 2 段にして、どちらも読めるようにする。 */
  .rboard__head { font-size: var(--fs-xs); flex-direction: column; gap: 2px; justify-content: center; }
  .rboard__head .board__hp { margin-left: 0; }
  /* 盤 1 枚ぶんの幅に名前と「あなた」の印を両方収める。
     印を縮めないと、先に名前のほうが「ば…」まで削られてしまう。 */
  .rboard__head .pchip { max-width: 100%; }
  .rboard__head .pchip__name { font-size: var(--fs-xs); }
  .rboard__head .pchip__you { font-size: 9px; padding: 1px 6px; letter-spacing: 0; }
  /* 3 つ並べると「結果を共有」が 2 行に折れる。字を一段落として 1 行に収める。 */
  .result__actions .btn--sub { font-size: var(--fs-xs); padding-inline: var(--s1); }
  .board { gap: 6px; padding: var(--s2); }
  .board--me { margin-top: auto; }
  /* 知らせの帯もここでは細くする。この帯が厚いぶんだけ、
     いちばん下の「ことばを出す」が画面の外へ押し出される。 */
  .dock__alert { font-size: var(--fs-xs); padding-inline: var(--s2); }
  /* かなの表 2 枚のあいだ。広い画面ほど空けなくても、切れ目は伝わる。 */
  .kbd { gap: 7px; }
  .kbd--watch { gap: 5px; }
  /* 名前が長いと「81 分の 81」が 2 行に折れて盤の背が伸びる。折らない。 */
  .board__hp, .board__spare { white-space: nowrap; }
  .pchip { min-width: 0; flex: 0 1 auto; }
  /* 中央の情報は格子にまとめる。縦に積むと、それだけで画面の1/4を使ってしまう。
     上段は「輪 ｜ だれの番か・のこり秒 ｜ 経過ボタン」、
     下段いっぱいに「直前の一手」の札。 */
  .arena {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--s3);
    row-gap: 4px;
    padding: var(--s2) var(--s3);
    text-align: left;
    /* 縮ませない。この板は overflow: hidden なので、縮められると
       いちばん下の「直前の一手」の札が途中で切れて読めなくなる。 */
    flex: none;
  }
  .arena__turn { grid-column: 2; grid-row: 1; font-size: var(--fs-md); text-align: left; }
  .dial        { grid-column: 1; grid-row: 1 / span 2; }
  .dial__meta  { grid-column: 2 / -1; grid-row: 2; }
  .strike      { grid-column: 1 / -1; grid-row: 3; }
  /* 経過（鎖）は置く高さが無い。代わりに、右上のボタンから読めるようにする。 */
  .arena .log { display: none; }
  .log-open {
    display: inline-flex;
    grid-column: 3; grid-row: 1;
    align-self: center;
    min-height: 32px; min-width: 6.2em;
    padding: 4px var(--s2);
    font-size: var(--fs-xs);
    font-variant-numeric: tabular-nums;
  }
  /* 直前の一手は、feedback の一行ではなく札そのもので出す。
     「◯を削られた」だけでは、相手が何ということばを出したのかが分からず、
     しりとりをしている手応えが残らない。札には、だれの手か・ことば・
     削れた字の 3 つが入っているので、一行ぶんの高さで足りる。 */
  /* 目には出さないが、読み上げには残す。この一行は aria-live で
     「いま何が起きたか」を伝える窓口なので、display: none で消すと
     画面を見ずに遊んでいる人に結果が届かなくなる。 */
  .arena .feedback {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .strike {
    flex-direction: row;
    align-items: center;
    gap: var(--s2);
    width: 100%;
    padding: 3px var(--s2);
    border-radius: var(--r-sm);
    box-shadow: 0 3px 0 var(--strike-color, var(--p0));
    /* ことばだけは削らない。長い語で押し出されるのは右のひとことのほう。 */
    overflow-x: auto;
    scrollbar-width: none;
  }
  .strike::-webkit-scrollbar { display: none; }
  .strike__who { flex: none; max-width: 7em; font-size: 10px; padding: 1px 7px; letter-spacing: 0; }
  .strike__word { flex: none; font-size: 1.3rem; }
  .strike__tag {
    flex: 1 1 auto; min-width: 0;
    text-align: right; letter-spacing: .04em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* 帯の背は削らない。行の高さを決めているのは横に並ぶ「あと ◯ 文字」のほうなので、
     ここを細くしても縦は 1px も稼げず、縁 2.5px に挟まれた塗りが消えるだけになる。 */
  .hpbar__track { height: 11px; }
  .dial__cap { display: none; }    /* 輪の中の字を見れば分かる */
  .dial { width: 96px; height: 96px; }
  .dial__char { font-size: 2.5rem; }
  .board__hp b { font-size: 1.5em; }
}

/* ふつうの縦持ち（iPhone 相当）。ここが基準。
   横は使えるので幅いっぱいに広げ、詰まっている高さのほうだけを削る。 */
@media (max-width: 859px) and (max-height: 920px) {
  :root {
    --gap: 3px;
    --cell: clamp(22px, calc((min(100vw, 430px) - 20px - 9 * var(--gap)) / 10), 32px);
    --key-h: 28px;
  }
  /* 対戦のキーの高さだけは、段ではなく画面の高さから連続で決める。
     段（28px → 23px）で切り替えていたころは、その段のあいだの高さ
     （727px の端末など）でどちらの値も収まらず、盤の下側が画面の外へ出ていた。

     --btl-fixed は「キー 10 段を除いた対戦画面の高さ」。
     ここから残りを 10 で割ったものが 1 段ぶんになる。
     相手の要約が 2・3 行に増えるぶんは、その行数ぶんを足して引く。 */
  .btl {
    --btl-fixed: 535px;
    --key-h: clamp(17px, calc((100dvh - var(--btl-fixed)) / 10), 30px);
  }
  /* キーが平たくなるぶん、輪郭と角丸も一段細くする。
     22px の高さに 2.5px の縁を回すと、面より縁のほうが太く見える。 */
  .key { border-width: 2px; border-radius: 7px; }
  .btl__bar { min-height: 32px; }
  /* 板の下に落とす硬い影のぶん、いちばん下の板が画面からはみ出す。
     下の余白でそのぶんを持つ。 */
  .screen--battle {
    padding: max(var(--s2), env(safe-area-inset-top)) var(--s3)
             calc(var(--s2) + env(safe-area-inset-bottom));
  }
  .board__head { font-size: var(--fs-xs); }
  .board__hp b { font-size: 1.5em; }
  .dial { width: 68px; height: 68px; }
  .dial__char { font-size: 1.8rem; -webkit-text-stroke-width: 4px; }
  .dial::before { inset: 5px; border-width: 2px; box-shadow: 0 3px 0 var(--ink); }
  .dial circle { stroke-width: 9; }
  .word-slot { min-height: 42px; }
  .word-slot__ch { font-size: 1.25rem; }
  .dock { gap: 6px; }
  .dock__actions .btn { min-height: 48px; }
  /* 耐久3で要約が2・3行に増えても、送信操作は画面内に残す。 */
  .btl[data-foe-rows="2"] { --btl-fixed: 561px; }
  .btl[data-foe-rows="3"] { --btl-fixed: 587px; }
}

/* 背の低い端末。ここから先は削るしかない。

   境目を 720px から 800px へ上げてある。720〜800px の端末（Pixel 5 の 727、
   iPhone 8 Plus の 736 など）に上の造りのまま入ってもらうと、
   残ったぶんで割ったキーが 20px まで潰れる。「のこり◯秒」の数字を落として
   キーを 30px 残すほうが、指で押す盤としては確実に良い
   （残り時間は輪の減りかたで見える。押せない盤は取り返しがつかない）。 */
@media (max-width: 859px) and (max-height: 800px) {
  :root {
    --gap: 2px;
    --cell: clamp(20px, calc((min(100vw, 430px) - 16px - 9 * var(--gap)) / 10), 30px);
    --key-h: 23px;
  }
  .btl { --btl-fixed: 436px; }
  /* 背の低い端末では、直前の一手の札を輪の右（のこり秒を消した跡）へ入れる。
     一段下に置くと、それだけで 40px ぶん盤の高さを食う。 */
  .arena { row-gap: 2px; }
  .strike { grid-column: 2 / -1; grid-row: 2; padding: 2px var(--s2); }
  .strike__word { font-size: 1.1rem; }
  .strike__who { font-size: 9px; max-width: 6.5em; }
  .strike__tag { font-size: 10px; }
  .kbd { gap: 5px; }
  .screen--battle {
    padding: max(6px, env(safe-area-inset-top)) var(--s2)
             calc(6px + env(safe-area-inset-bottom));
  }
  .btl { gap: 4px; }
  .board { gap: 4px; }
  .btl__bar { min-height: 28px; }
  .board__hp b { font-size: 1.3em; }
  .hpbar__track { height: 9px; }
  .hpbar__num b { font-size: 1.3em; }
  .dial { width: 56px; height: 56px; }
  .dial__char { font-size: 1.5rem; }
  .dial__meta { display: none; }   /* 輪の減りかたで見る */
  .word-slot { min-height: 38px; }
  .word-slot__ch { font-size: 1.1rem; }
  .screen--battle .feedback { min-height: 1.15em; font-size: var(--fs-xs); }
  .dock__alert { padding-block: 0; border-width: 2px; }
  .dock__actions .btn { min-height: 44px; padding: var(--s2) var(--s3); }
  .foe-summary { gap: 3px; padding: 5px 7px; }
  .foe-summary__row { grid-template-columns: 20px auto minmax(0, 1fr); gap: 5px; }
  .damage-icon { width: 19px; height: 16px; }
  .foe-summary__label, .foe-summary__chars { line-height: 16px; }
  .foe-aim__char { min-width: 22px; height: 21px; }
  .btl[data-foe-rows="2"] { --btl-fixed: 458px; }
  .btl[data-foe-rows="3"] { --btl-fixed: 480px; }
}

/* 先攻決めも同じ考えで詰める */
@media (max-width: 859px) and (max-height: 800px) {
  .mg { gap: var(--s3); }
  .mg__puzzle { padding: var(--s4); font-size: var(--fs-lg); }
  .mg__note { display: none; }
}

/* ---------- 動きを減らす設定 ---------- */

/* ---------- 動きを減らす設定 ----------
   位置と大きさの変化はやめる。それでも情報は落ちない ----
   あと何回耐えるかは水面の高さ、やられた回数はひび、
   盤ぜんたいの残りは「81 分の ◯◯」の数、いま狙っている先は輪の色と形が、
   どれも動かずに示しているため。 */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .fxlayer, .flashlayer { display: none; }
  /* 押したときの沈み込みも切る。ただし押せることは分かるようにしたいので、
     段差は残したまま、動かさないだけにする。 */
  .btn:hover:not(:disabled), .btn:active:not(:disabled),
  .key:hover:not(:disabled), .key:active:not(:disabled),
  .seg:active:not(:disabled) { transform: none; }
}

/* 手元で複数端末から試すときの注意書き */
.hint--warn { color: var(--gold-deep); }
/* コピーできない環境向けに、長押しで選べるようにする要素 */
.selectable {
  user-select: all; -webkit-user-select: all;
  display: inline-block;
  margin-top: var(--s1);
  padding: var(--s1) var(--s2);
  background: var(--paper-2);
  border: 2px solid var(--ink);
  border-radius: 8px;
  color: var(--gold-deep);
  font-size: var(--fs-sm);
  font-weight: 800;
  word-break: break-all;
}
