/* ui/style.css — コネクトパズルの画面スタイル
   色はすべて app.js が theme.js から注入する CSS 変数を使う。
   このファイルに生の色コードを書かない。
   寸法は画面幅に応じて伸びる (4K等の大画面で小さく見えないように)。 */

* { box-sizing: border-box; }

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

/* --- ページ遷移 --------------------------------------------------------
   サイトの他ページ (css/style.css) と揃える。別HTMLへ移る一瞬に
   ブラウザ既定の白が見えるのを防ぎ、対応ブラウザではクロスフェードする。
   フォールバック色は theme.decor.base と同値: JS が CSS 変数を注入する前の
   初回描画で使われる (変数だけだと最初の一瞬が白くなる) */
/* scrollbar-gutter: スクロールバーの有無でヘッダーが左右にずれるのを防ぐ */
html { background: var(--deco-base, #23421F); scrollbar-gutter: stable; }

@view-transition { navigation: auto; }

/* 中身は動かさず即座に差し替える (他ページと同じ扱い)。ヘッダーは据え置き */
#app { view-transition-name: page-content; }

::view-transition-old(root),
::view-transition-new(root),
::view-transition-old(page-content),
::view-transition-new(page-content) { animation: none; }

:root {
  /* 基準文字サイズ: 画面幅に応じて 17px〜26px。以降の em/rem がこれに追従する */
  --fs: clamp(17px, 0.9vw + 12px, 26px);
  --gap: calc(var(--fs) * 0.6);
  --radius: calc(var(--fs) * 0.6);
}

body {
  background: var(--deco-base);
  color: var(--bar-value);
  font-family: "Zen Kaku Gothic New", "Hiragino Sans", "Yu Gothic", sans-serif;
  font-size: var(--fs);
  line-height: 1.7;
}

.num { font-variant-numeric: tabular-nums; font-family: "Outfit", sans-serif; }

/* 背景層: 情報を持たない飾り。すべての下に敷く */
#decor { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
#decor svg { display: block; }

/* ---- サイト共通ヘッダー ----
   サイト (racrewe-site/css/style.css) と同じ見た目をここで再現する。
   ゲーム単体で配信してもロゴ・タブが崩れないよう、依存を持たせない。
   サイト側のヘッダー意匠を変えたときは、ここと img/racrewe-logo-header.svg も揃える */
.site-header {
  position: relative;
  z-index: 2;
  background: var(--site-bg);
  border-bottom: 1px solid var(--site-line);
  view-transition-name: site-header; /* 他ページと同名にして据え置きに見せる */
}
.site-header .header-inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 24px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}
.site-logo { display: flex; align-items: center; flex: none; }
.site-logo img { height: 56px; width: auto; max-width: none; display: block; }

.tab-nav { display: flex; gap: 32px; }
.tab-nav a {
  font-size: 16px;
  font-weight: 500;
  color: var(--site-text);
  text-decoration: none;
  white-space: nowrap;
  padding: 8px 0;
  border-bottom: 2px solid transparent;
}
.tab-nav a:hover { color: var(--site-accent); }
/* 太字 (font-weight) にすると文字幅が変わり、タブを切り替えるたびに隣がずれる。
   影を重ねる書き方なら幅が変わらない (サイト側 css/style.css と同じ手当て) */
.tab-nav a[aria-current="page"] {
  color: var(--site-accent);
  border-bottom-color: var(--site-accent);
  text-shadow: 0.4px 0 0 currentColor, -0.4px 0 0 currentColor;
}

@media (max-width: 1000px) {
  /* ロゴ2倍(幅400px)とタブが同居できない幅からは等倍へ */
  .site-logo img { height: 28px; }
  .site-header .header-inner { height: 72px; }
}
@media (max-width: 520px) {
  .site-header .header-inner {
    height: auto;
    padding: 16px;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  .tab-nav { gap: 16px; }
  .tab-nav a { font-size: 14px; }
}

#app {
  position: relative;
  z-index: 1;
  width: min(100%, calc(var(--board-cap, 440px) + var(--fs) * 2));
  margin: 0 auto;
  padding: calc(var(--fs) * 0.8) calc(var(--fs) * 0.7) calc(var(--fs) * 3);
}

/* ---- 見出し ---- */

.page-head { padding: calc(var(--fs) * 0.4) 0 0; }
.page-head .back {
  color: var(--bar-label);
  text-decoration: none;
  font-size: 0.85em;
}
.page-head .back:hover { color: var(--bar-value); }
.page-head h1 {
  margin: 0.2em 0 0.1em;
  font-size: 1.7em;
  color: var(--bar-value);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.page-head .lead { margin: 0; color: var(--bar-label); font-size: 0.9em; }

/* 遊び方の一文 (問題一覧・あそびかたの両画面) は目的そのものなので大きく強く出す
   (.page-head .lead より詳細度を上げないと効かない) */
.page-head .howto-lead {
  margin-top: 0.3em;
  font-size: 1.45em;
  font-weight: 700;
  color: var(--bar-value);
  letter-spacing: 0.02em;
}

/* ---- あそびかたの帯 ---- */

.howto-banner {
  display: flex;
  align-items: baseline;
  gap: var(--gap);
  margin-top: calc(var(--fs) * 1.1);
  padding: calc(var(--fs) * 0.7) calc(var(--fs) * 0.9);
  border: 2px solid var(--bar-label);
  border-radius: var(--radius);
  text-decoration: none;
  background: var(--panel);
}
.howto-banner:hover { background: var(--deco-line); }
.howto-title { font-size: 1.15em; font-weight: 700; color: var(--bar-value); }
.howto-sub { font-size: 0.8em; color: var(--bar-label); }

/* ---- 難易度ごとの区画 ---- */

.diff-section { margin-top: calc(var(--fs) * 1.4); }

.diff-heading {
  display: inline-block;
  margin: 0 0 calc(var(--fs) * 0.5);
  padding: 0.15em 0.9em;
  border-radius: 999px;
  font-size: 0.95em;
  font-weight: 700;
  letter-spacing: 0.1em;
}
[data-diff="beginner"] .diff-heading { background: var(--diff-beginner); color: var(--diff-beginner-text); }
[data-diff="intermediate"] .diff-heading { background: var(--diff-intermediate); color: var(--diff-intermediate-text); }
[data-diff="advanced"] .diff-heading { background: var(--diff-advanced); color: var(--diff-advanced-text); }
[data-diff="expert"] .diff-heading { background: var(--diff-expert); color: var(--diff-expert-text); }

/* 難易度ラベルの右に添える断り書き (上級以上の候補非表示) */
.diff-note {
  margin-left: 0.7em;
  font-size: 1.05em;
  font-weight: 700;
  color: var(--bar-value);
}

.puzzle-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: calc(var(--fs) * 0.45);
}

.puzzle-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--fs) * 2.8);
  border: 2px solid var(--deco-line);
  border-radius: var(--radius);
  background: var(--panel); /* 背景の飾りを透けさせない (数字の可読性) */
  color: var(--bar-value);
  text-decoration: none;
  font-size: 1.15em;
  font-weight: 500;
}
.puzzle-cell:hover { border-color: var(--bar-value); }

/* クリア済みは難易度色で塗る (色でも進捗が分かる) */
[data-diff="beginner"] .puzzle-cell.is-cleared { background: var(--diff-beginner); border-color: var(--diff-beginner); color: var(--diff-beginner-text); }
[data-diff="intermediate"] .puzzle-cell.is-cleared { background: var(--diff-intermediate); border-color: var(--diff-intermediate); color: var(--diff-intermediate-text); }
[data-diff="advanced"] .puzzle-cell.is-cleared { background: var(--diff-advanced); border-color: var(--diff-advanced); color: var(--diff-advanced-text); }
[data-diff="expert"] .puzzle-cell.is-cleared { background: var(--diff-expert); border-color: var(--diff-expert); color: var(--diff-expert-text); }

.puzzle-cell .best {
  position: absolute;
  bottom: 0.1em;
  right: 0.4em;
  font-size: 0.55em;
  opacity: 0.85;
}

/* ---- プレイ画面 ---- */

.info-bar {
  display: flex;
  align-items: center;
  gap: calc(var(--fs) * 0.5);
  flex-wrap: wrap;
  padding: calc(var(--fs) * 0.5) 0;
}
.info-bar .label { color: var(--bar-label); font-size: 0.8em; }
.info-bar .value { color: var(--bar-value); font-size: 1.25em; font-weight: 700; }
.info-bar .spacer { flex: 1; }

.diff-chip {
  padding: 0.1em 0.8em;
  border-radius: 999px;
  font-size: 0.8em;
  font-weight: 700;
}
.diff-chip[data-diff="beginner"] { background: var(--diff-beginner); color: var(--diff-beginner-text); }
.diff-chip[data-diff="intermediate"] { background: var(--diff-intermediate); color: var(--diff-intermediate-text); }
.diff-chip[data-diff="advanced"] { background: var(--diff-advanced); color: var(--diff-advanced-text); }
.diff-chip[data-diff="expert"] { background: var(--diff-expert); color: var(--diff-expert-text); }

.info-bar button,
#clear-panel button,
.demo-actions button,
.demo-actions .btn-link {
  background: transparent;
  color: var(--bar-value);
  border: 2px solid var(--deco-line);
  border-radius: calc(var(--fs) * 0.4);
  padding: 0.35em 0.9em;
  font-size: 0.85em;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
}
.info-bar button:hover:not(:disabled),
#clear-panel button:hover,
.demo-actions button:hover,
.demo-actions .btn-link:hover { border-color: var(--bar-value); }
.info-bar button:disabled { opacity: 0.35; cursor: default; }
.info-bar .back-link {
  color: var(--bar-label);
  text-decoration: none;
  font-size: 0.85em;
}
.info-bar .back-link:hover { color: var(--bar-value); }

#board-wrap, #demo-wrap { display: flex; justify-content: center; padding: calc(var(--fs) * 0.3) 0 var(--gap); }

/* 盤面サイズはここで完結させる:
   コンテナ幅いっぱい・大画面での上限 (--board-cap)・画面高さ由来の上限の最小。
   下限を割る幅では横スクロールさせず全体を縮小する */
/* 盤面と、その上に重ねるクリア演出。幅は親が持ち、盤はいっぱいに描く */
.board-stage {
  position: relative;
  width: min(100%, var(--board-cap, 440px), calc(100vh - 200px));
  line-height: 0;
}

#board {
  display: block;
  width: 100%;
  height: auto;
}

/* クリア時: 盤面が光る */
.board-stage.is-cleared #board {
  animation: board-glow 900ms ease-out 2;
  filter: drop-shadow(0 0 calc(var(--fs) * 0.5) var(--clear-glow));
}
@keyframes board-glow {
  0%, 100% { filter: drop-shadow(0 0 calc(var(--fs) * 0.5) var(--clear-glow)); }
  45% { filter: drop-shadow(0 0 calc(var(--fs) * 1.6) var(--clear-glow)); }
}

/* クリア時: 盤面の中央に大きく出す */
#clear-banner {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}
/* display を指定すると hidden 属性 (display:none) が効かなくなるので打ち消す */
#clear-banner[hidden] { display: none; }

/* クリア時の花吹雪 */
#confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: calc(var(--fs) * 0.9);
}
.petal {
  position: absolute;
  top: -10%;
  width: 0.55em;
  height: 0.85em;
  border-radius: 60% 40% 55% 45%;
  opacity: 0;
  animation-name: petal-fall;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
/* 落下は top で動かす。transform の % は自分の大きさ基準になり、
   盤面の高さぶん落ちてくれないため */
@keyframes petal-fall {
  0% { top: -8%; transform: translateX(0) rotate(0deg); opacity: 0; }
  12% { opacity: 1; }
  85% { opacity: 1; }
  100% { top: 106%; transform: translateX(var(--drift)) rotate(var(--spin)); opacity: 0; }
}
#clear-banner span {
  padding: 0.3em 1.1em;
  border: 4px solid var(--callout-border);
  border-radius: var(--radius);
  background: var(--callout-bg);
  color: var(--callout-text);
  box-shadow: 0 10px 30px var(--callout-shadow);
  font-size: 2.6em;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.12em;
  /* 飛び出して少し見せたあと、静かに消える */
  animation: clear-pop-fade 3s cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
}
@keyframes clear-pop {
  from { transform: scale(0.4); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
@keyframes clear-pop-fade {
  0% { transform: scale(0.4); opacity: 0; }
  14% { transform: scale(1); opacity: 1; }
  70% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 0; }
}
#clear-banner .num { font-size: 1.5em; margin-right: 0.1em; }

/* ランク到達の告知 (置ける場所が出なくなる難易度に入ったとき) */
#rank-notice {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--callout-shadow);
  border-radius: calc(var(--fs) * 0.9);
}
#rank-notice[hidden] { display: none; }

.rank-notice-box {
  max-width: 82%;
  padding: 1em 1.2em;
  border: 4px solid var(--callout-border);
  border-radius: var(--radius);
  background: var(--callout-bg);
  color: var(--callout-text);
  box-shadow: 0 10px 30px var(--callout-shadow);
  text-align: center;
  line-height: 1.5;
  animation: clear-pop 320ms cubic-bezier(0.2, 1.5, 0.4, 1);
}
.rank-notice-box p {
  margin: 0 0 0.7em;
  font-size: 1.2em;
  font-weight: 700;
}
.rank-notice-box button {
  border: 3px solid var(--callout-border);
  border-radius: calc(var(--fs) * 0.4);
  background: transparent;
  color: var(--callout-text);
  padding: 0.35em 1.4em;
  font-size: 0.95em;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}

/* コネクタの濃淡 (自分の網につながっているか) はなめらかに変える。
   1手で何本も同時に反転することがあり、瞬間的に切り替わると
   盤面が別物に入れ替わったように見えてしまうため */
.conn { transition: opacity 320ms ease; }

/* デモ盤も本編と同じ 7×7。幅は親 (.demo-stage) が持ち、盤はそれいっぱいに描く */
#demo-board {
  display: block;
  height: auto;
  width: 100%;
}

/* 盤面の下に出す「ラクルゥの記録」(その問題の最短手数) */
.record-row {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap; /* 狭い画面では顔と文字が上下に分かれる */
  gap: calc(var(--fs) * 0.5);
  margin-top: calc(var(--fs) * 0.2);
}

.record-face {
  /* 幅が足りない画面でも溢れないよう上限を掛ける。
     height を auto にしないと HTML の height 属性 (512) が残って縦長になる */
  width: min(calc(var(--fs) * 7.8), 30vw);
  height: auto;
  aspect-ratio: 1;
  border-radius: calc(var(--fs) * 0.9);
  border: 3px solid var(--bar-label);
  background: var(--callout-bg);
  object-fit: cover;
  flex-shrink: 0;
}

.record-line {
  margin: 0;
  color: var(--bar-value);
  font-size: min(1.8em, 6vw); /* 狭い画面でも一行に収まる大きさまで落とす */
  font-weight: 700;
  line-height: 1.3;
  white-space: nowrap; /* 「3 手」で折り返させない */
}
.record-line .num {
  font-size: 1.6em;
  margin: 0 0.1em;
}

/* 詰み表示: 控えめに、操作は塞がない */
#notice {
  margin: var(--gap) auto 0;
  padding: 0.6em 1em;
  border: 2px dashed var(--bar-label);
  border-radius: var(--radius);
  color: var(--bar-value);
  font-size: 0.85em;
  text-align: center;
}

#clear-panel {
  margin: var(--gap) auto 0;
  padding: calc(var(--fs) * 0.9);
  border: 2px solid var(--bar-label);
  border-radius: var(--radius);
  background: var(--deco-base);
  text-align: center;
}
#clear-panel h2 { margin: 0 0 0.3em; font-size: 1.5em; color: var(--bar-value); }
#clear-panel p { margin: 0 0 0.7em; color: var(--bar-label); font-size: 1.25em; font-weight: 700; }
#clear-panel p .num { color: var(--bar-value); font-size: 1.5em; font-weight: 700; margin: 0 0.1em; }
#clear-panel .actions { display: flex; gap: var(--gap); justify-content: center; flex-wrap: wrap; }

/* ---- あそびかたデモ ---- */

/* 盤面に重ねる説明。手順で使わない下半分に置く */
.demo-stage {
  position: relative;
  width: min(100%, var(--board-cap, 440px), calc(100vh - 300px));
  line-height: 0;
}

/* 説明のふきだし。上向きの三角で「盤面のここについての説明」だと示す */
#demo-caption {
  position: absolute;
  left: 50%;
  top: 63%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 88%;
  margin: 0;
  padding: 0.5em 1.1em;
  border: 3px solid var(--callout-border);
  border-radius: var(--radius);
  background: var(--callout-bg);
  color: var(--callout-text);
  box-shadow: 0 6px 18px var(--callout-shadow);
  text-align: center;
  font-size: 1.15em;
  font-weight: 700;
  line-height: 1.5;
  pointer-events: none;
}

#demo-caption::before,
#demo-caption::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 0;
  height: 0;
  transform: translateX(-50%);
  border-left: 13px solid transparent;
  border-right: 13px solid transparent;
}
#demo-caption::before { top: -16px; border-bottom: 16px solid var(--callout-border); }
#demo-caption::after { top: -11px; border-bottom: 16px solid var(--callout-bg); }
.demo-actions {
  display: flex;
  gap: var(--gap);
  justify-content: center;
  align-items: center;
  margin-top: var(--gap);
}

/* 「つぎへ」は押してほしいボタンなので目立たせる */
#btn-demo-next {
  font-size: 1.05em;
  font-weight: 700;
  padding: 0.45em 1.6em;
  border-color: var(--bar-value);
}
#btn-demo-next:disabled { opacity: 0.35; cursor: default; }

.demo-cursor { pointer-events: none; transition: transform 700ms cubic-bezier(0.4, 0, 0.2, 1); }
.demo-cursor.is-clicking path { transform: scale(0.8); transform-origin: 0 0; }

/* 動かせないコネクタを押したときの空振り表現 (カーソルが小刻みに震える) */
.demo-cursor-inner.is-shaking { animation: demo-shake 300ms linear 3; }
@keyframes demo-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px) rotate(-4deg); }
  75% { transform: translateX(3px) rotate(4deg); }
}

.boot-error { position: relative; z-index: 1; text-align: center; padding: 2em; }

/* 版数表示 (リロード反映の確認用) */
#build {
  position: fixed;
  bottom: 0.4em;
  right: 0.6em;
  z-index: 2;
  color: var(--bar-value);
  opacity: 0.9;
  font-size: 1.1em;
  font-weight: 700;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .demo-cursor { transition: none; }
  .demo-cursor-inner.is-shaking { animation: none; }
  .conn { transition: none; }
  .petal { animation: none !important; }
  #clear-banner span { animation: none !important; }
  /* ページ遷移の動きも切る (疑似要素なので個別に指定が要る) */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
