モモ企画お馴染みの花絵柄・柴犬をモチーフに作成したスロットです。このスロットはゲームとして多少は遊べると思いますが、本来はゲームソースの説明が主旨となります。従って、このソースをベースに、更にアレンジして頂くことを目的としています。

仕様
1. 縦・横・斜めの一致
2. 画像一致条件によるボーナスコイン
3. 特定絵柄によるコイン数の増減
4. ゲームリセットボタン
5. 獲得倍数の入力(ハズレ減算・当たりに応じた倍数計算)

6. キャンバス内、スタート&ストップ
7. コイン数0で終了(ゲームセット)

8. 画像一致で、ライン上にカラーボーダー点滅表示
9. 1億コイン獲得でハイスコア表示後、ゲームセット※表示しているハイスコア以下は保存なし
10.ハイスコア削除ボタン
11.1億コイン獲得で、キャンバス内アクション画像表示

12.横ライン2画像一致で加算(重複含む)
13.INFO:案内表示ボタン

細かい仕様は実際のデモ画面のINFOで確認して下さい

多少アレンジした4×4クロススロット見たい方はご自由にどうぞ。

ファイル構成
index.html script.js style.css  画像格納ファイルassets ファイルパスは環境に合わせて下さい
画像 0.png~23.pngまでの24画像 600px正方形 参考使用画像 花の写真素材屋
使用画像ダウンロード assets.zip

ソースコードは、ある程度の動作確認をしております。コードをコピペで使用しても構いませんが、動作の不具合やバグなどが確認された場合、使用された方の自己責任で適切な修正・追加をお願いします。

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name=viewport content="width=device-width,initial-scale=1.0">
  <title>4列スロット(4×4)</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <canvas id="slotCanvas"></canvas>
   <div class="ui">
    <label>獲得倍数<input id="betInput" type="number" min="1" step="5"  value="1" style="width:90px;"></label>
  <p>🎯 <span class="coin-label">COIN</span> <span id="coinDisplay">200</span></p>
  <button id="resetButton">RESET</button>
  </div>
  <!-- スコア表示領域 -->
<div id="legendaryScoreWrapper">
  <span id="legendaryScore">Legendary Score: ----</span>
  <button id="clearLegendaryScore">✖️ DELETE</button>
  <button id="openGuide" class="open-button">📘 INFO</button>
</div>
<div id="gameGuide" class="guide-box">
  <button id="closeGuide" class="close-button"></button>
  <h2>🎰 ゲーム案内</h2>
  <h3><font color="Yellow">画像を揃えるとコインが獲得できるゲームです</font></h3>
  <ul>
    <li>当たり条件:縦・横・斜め(クロス)の各画像一致</li>
    <li>獲得倍数:設定数値に応じた当たりの報酬</li>
    <li>COIN:取得したコイン数</li>
    <li>Legendary Score: ハイスコアの表示</li>
    <li>RESET:ゲーム初期状態に戻す</li>
    <li>DELETE:ハイスコアの削除</li>
    <li>スタートは画像表示画面をクリック&タップ</li>
    <li>ストップは各4列の任意の位置でクリック&タップ</li>
    <li>1億以上のコインを獲得するとゲーム終了(ハイスコア表示)</li>
    <li>ハイスコアの更新は現在の数値以上で更新(初期は表示)</li>
    <li>横列2画像一致で50(重複画像加算)</li>
    <li><font color="pink">当たりボーナス(画像一致)の条件:</font>横10万・      斜め(クロス)20万・縦30万 バラ 100万
       パラソルの下にいる犬たち 60万 アジサイ(BAR) ボーナスなし 柴犬-10万 P・T・Y画像は全てのライン共通 -5万</li>
    <li>INF:この案内表示</li>
      <h3><font color="#ff0099">1億超えて終了したら貴方は神!!</font></h3>
  </ul>
</div>
  <script src="script.js"></script>
</body>
</html>
JS
const COLS = 4, ROWS = 4, cellSize = 120;
let canvas = document.getElementById('slotCanvas');
let ctx = canvas.getContext('2d');
canvas.width = COLS * cellSize;
canvas.height = ROWS * cellSize;
canvas.style.borderColor = "#0066ff";//canvasボーダー
const markerColors = {normal: "#5fbefdff"};//キャンバス内マークcolor
let offsetY = Array(COLS).fill(0);
let spinning = Array(COLS).fill(false);
let reels = Array.from({ length: COLS }, () => Array.from({ length: ROWS }, () => Math.floor(Math.random() * 24)));
let images = [], imagesLoaded = 0;
let coin = 200; //初期コイン
let spinSpeed = 20; //スピード調整
let isGameOver = false;
let spinSpeedArray = Array(COLS).fill(24);
let stopCount = 0;
let snapping = Array(COLS).fill(false);
let snapTarget = Array(COLS).fill(0);
const totalStops = COLS;

//======24画像========
    for (let i = 0; i < 24; i++) {
      const img = new Image();
      img.src = `../assets/${i}.png`;//===任意のアドレス=======
      img.onload = () => {
        imagesLoaded++;
        if (imagesLoaded === 24) drawReels();
      };
      images.push(img);
    }

function drawReels(state = "normal") {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 🎰 画像描画
  for (let col = 0; col < COLS; col++) {
    for (let row = 0; row < ROWS; row++) {
      const x = col * cellSize;
      const y = row * cellSize + offsetY[col];
      const img = images[reels[col][row]];
      ctx.drawImage(img, x, y % canvas.height, cellSize, cellSize);
    }
  }

  // 🧱 仕切り線
  ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
  ctx.lineWidth = 2;
  for (let i = 1; i < COLS; i++) {
    const x = i * cellSize;
    ctx.beginPath();
    ctx.moveTo(x, 0);
    ctx.lineTo(x, canvas.height);
    ctx.stroke();
  }

  // 🟨 マーカー描画(状態に応じた色)
  drawFrameMarkers(markerColors[state]);
}
//=========呼び出し=============
window.addEventListener("DOMContentLoaded", () => {
  initializeCoin();
  updateCoinDisplay();
  updateLegendaryScoreDisplay();
});

//=======canvasクリック==========
canvas.addEventListener("click", () => {
  setBetInputEnabled(false);
  if (isGameOver) {
    coin = 200;
    document.getElementById("coinDisplay").textContent = coin;
    document.getElementById("betInput").value = 1;
    isGameOver = false;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawReels();
  }
});
//=======canvasタッチ==========
let touchEventHappened = false;

canvas.addEventListener("touchstart", (e) => {
  e.preventDefault();
  setBetInputEnabled(false);

  if (isGameOver) {
    coin = 200;
    isGameOver = false;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawReels();
    return;
  }

  const rect = canvas.getBoundingClientRect();
  const x = e.touches[0].clientX - rect.left;
  const touchedCol = Math.floor(x / cellSize);

  if (spinning.every(s => s === false) && snapping.every(s => s === false)) {
    spinning = spinning.map(() => true);
    spinSpeedArray = spinSpeedArray.map(() => 4);
    offsetY = offsetY.map(() => 0);
    stopCount = 0;
    requestAnimationFrame(spinStep);
    return;
  }

  if (touchedCol >= 0 && touchedCol < COLS && spinning[touchedCol] === true) {
    spinning[touchedCol] = "stopping";
  }
}, { passive: false });

//========= 通常のスロット停止処理==============
function spinStep() {
  let needsAnimation = false;
  for (let col = 0; col < COLS; col++) {
    if (spinning[col] === true) {
      offsetY[col] += spinSpeed;
      if (offsetY[col] >= cellSize) {
        offsetY[col] -= cellSize;
        reels[col].pop();
        reels[col].unshift(Math.floor(Math.random() * 24));
      }
      needsAnimation = true;
} else if (spinning[col] === "stopping") {

  offsetY[col] += spinSpeedArray[col];

  if (offsetY[col] >= cellSize) {
    offsetY[col] -= cellSize;
    reels[col].pop();
    reels[col].unshift(Math.floor(Math.random() * 24));
  }
  needsAnimation = true;
    spinning[col] = false;

// 🎯 即停止:offsetYをリセット
  offsetY[col] = 0;
  stopCount++;
// 🎯 全リール停止かつ吸着完了を確認
if (spinning.every(s => s === false) && snapping.every(s => s === false)) {
  setBetInputEnabled(true);
  requestAnimationFrame(() => {
    drawReels();
    const matchedLines = getMatchedLines(reels);
    const bet = parseInt(document.getElementById("betInput").value, 10) || 1;
    if (matchedLines.length > 0) {
      blinkLines(matchedLines);
      matchedLines.forEach(line => {
        console.log(`Applying reward for: ${line.type}, symbol: ${line.symbol}`);
        const coinBefore = getCoin();
        applyMatchReward(line.type, bet, line.symbol);
        const coinAfter = getCoin();
        console.log(`Coin before: ${coinBefore}, after: ${coinAfter}`);
      });
    } else {//====ハズレ減算===========
      const currentCoin = getCoin();
      const updatedCoin = Math.max(0, currentCoin - bet);
      setCoin(updatedCoin);
      drawReels();
    }
// ✅ ここで判定・保存(条件付き)
const finalCoin = getCoin();
const currentLegendary = parseInt(localStorage.getItem("legendaryCoin"), 10) || 0;

if (finalCoin >= 100_000_000 && finalCoin > currentLegendary) {
  showLegendaryAnimation();
  localStorage.setItem("legendaryCoin", finalCoin);
  updateLegendaryScoreDisplay(); // ← 表示更新
}
  });
}
    needsAnimation = true;
      }
    }
    drawReels();
  if (getCoin() === 0) {//======コイン0処理=======
    showGameOverMessage(ctx);
    isGameOver = true;
  }

  if (needsAnimation) requestAnimationFrame(spinStep);
}
//======スコア更新==================
function updateCoinDisplay() {
  const coin = getCoin();
  const display = document.getElementById("coinDisplay");
  if (display) display.textContent = coin.toLocaleString();
}
//======スピン中操作=================
canvas.addEventListener("click", (e) => {
  if (touchEventHappened) {
    touchEventHappened = false;
    return;
  }

  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const clickedCol = Math.floor(x / cellSize);

  if (spinning.every(s => s === false) && snapping.every(s => s === false)) {
    spinning = spinning.map(() => true);
    spinSpeedArray = spinSpeedArray.map(() => 4);
    offsetY = offsetY.map(() => 0);
    stopCount = 0;
    requestAnimationFrame(spinStep);
    return;
  }

  if (clickedCol >= 0 && clickedCol < COLS && spinning[clickedCol] === true) {
    spinning[clickedCol] = "stopping";
  }
});

//================================
function normalizeReels(reels) {
  const normalized = reels.map(col => {
    const newCol = Array.isArray(col) ? [...col] : [];
    while (newCol.length < ROWS) {
      newCol.push(Math.floor(Math.random() * 24));
    }
    return newCol;
  });
  return normalized;
}

//====================ラインマッチ=======================
function getMatchedLines(reels) {
  const normalizedReels = normalizeReels(reels);
  const lines = [];

  // 横揃い
  for (let row = 0; row < reels[0].length; row++) {
    const symbol = reels[0][row];
    if (reels[1][row] === symbol && reels[2][row] === symbol && reels[3][row] === symbol) {
      lines.push({
        type: "row",
        index: row,
        symbol: symbol
      });
    }
  }

  // 縦揃い
  for (let col = 0; col < COLS; col++) {
    const symbol = normalizedReels[col][0];
    if (symbol !== undefined && normalizedReels[col].every(v => v === symbol)) {
      lines.push({
        type: "col",
        index: col,
        symbol: symbol
      });
    }
  }

  // 斜め揃い(左上→右下)
  const diag1Symbol = normalizedReels[0][0];
  if (
    diag1Symbol !== undefined &&
    normalizedReels.every((reel, i) => reel[i] === diag1Symbol)
  ) {
    lines.push({
      type: "diag1",
      symbol: diag1Symbol
    });
  }

  // 斜め揃い(右上→左下)
  const diag2Symbol = normalizedReels[COLS - 1][0];
  if (
    diag2Symbol !== undefined &&
    normalizedReels.every((_, i) => {
      const col = COLS - 1 - i;
      return normalizedReels[col][i] === diag2Symbol;
    })
  ) {
    lines.push({
      type: "diag2",
      symbol: diag2Symbol
    });
  }

  return lines;
}

//==============ラインブリンクボーダー====================
let isBlinking = false;

function blinkLines(lines) {
  isBlinking = true;
  let blinkCount = 0;
  const maxBlinks = 6;

  const interval = setInterval(() => {
    drawReels(); // 通常描画

    ctx.lineWidth = 8;
    ctx.strokeStyle = (blinkCount % 2 === 0) ? "#f0f" : "#0ff";

    for (const line of lines) {
      ctx.beginPath();
      if (line.type === "row") {
        const y = line.index * cellSize + cellSize / 2;
        ctx.moveTo(0, y);
        ctx.lineTo(canvas.width, y);
      } else if (line.type === "col") {
        const x = line.index * cellSize + cellSize / 2;
        ctx.moveTo(x, 0);
        ctx.lineTo(x, canvas.height);
      } else if (line.type === "diag1") {
        ctx.moveTo(0, 0);
        ctx.lineTo(canvas.width, canvas.height);
      } else if (line.type === "diag2") {
        ctx.moveTo(canvas.width, 0);
        ctx.lineTo(0, canvas.height);
      }
      ctx.stroke();
    }

    blinkCount++;
    if (blinkCount >= maxBlinks) {
      clearInterval(interval);
      drawReels(); // 最後に通常描画
      isBlinking = false;
    }
  }, 500);
}

//==============ラインマーク===========================
function drawFrameMarkers(color = markerColors.normal) {
  const markerSize = 10;
  const margin = 0;
  ctx.fillStyle = color;

  // ◀ 左端 → 内向き三角形
  for (let row = 0; row < ROWS; row++) {
    const y = row * cellSize + cellSize / 2;
    ctx.beginPath();
    ctx.moveTo(margin + markerSize, y);
    ctx.lineTo(margin, y - markerSize / 2);
    ctx.lineTo(margin, y + markerSize / 2);
    ctx.closePath();
    ctx.fill();
  }

  // ▶ 右端 → 左向き
  for (let row = 0; row < ROWS; row++) {
    const y = row * cellSize + cellSize / 2;
    ctx.beginPath();
    ctx.moveTo(canvas.width - margin - markerSize, y);
    ctx.lineTo(canvas.width - margin, y - markerSize / 2);
    ctx.lineTo(canvas.width - margin, y + markerSize / 2);
    ctx.closePath();
    ctx.fill();
  }

  // ▲ 上端 → 下向き
  for (let col = 0; col < COLS; col++) {
    const x = col * cellSize + cellSize / 2;
    ctx.beginPath();
    ctx.moveTo(x, margin + markerSize);
    ctx.lineTo(x - markerSize / 2, margin);
    ctx.lineTo(x + markerSize / 2, margin);
    ctx.closePath();
    ctx.fill();
  }

  // ▼ 下端 → 上向き
  for (let col = 0; col < COLS; col++) {
    const x = col * cellSize + cellSize / 2;
    ctx.beginPath();
    ctx.moveTo(x, canvas.height - margin - markerSize);
    ctx.lineTo(x - markerSize / 2, canvas.height - margin);
    ctx.lineTo(x + markerSize / 2, canvas.height - margin);
    ctx.closePath();
    ctx.fill();
  }

  // 🔶 四隅 → 斜め向き三角形(角の語り部)
  // ⬉ 左上(↘向き)
  ctx.beginPath();
  ctx.moveTo(margin, margin + markerSize);
  ctx.lineTo(margin + markerSize, margin);
  ctx.lineTo(margin + markerSize, margin + markerSize);
  ctx.closePath();
  ctx.fill();

  // ⬈ 右上(↙向き)
  ctx.beginPath();
  ctx.moveTo(canvas.width - margin, margin + markerSize);
  ctx.lineTo(canvas.width - margin - markerSize, margin);
  ctx.lineTo(canvas.width - margin - markerSize, margin + markerSize);
  ctx.closePath();
  ctx.fill();

  // ⬋ 左下(↗向き)
  ctx.beginPath();
  ctx.moveTo(margin, canvas.height - margin - markerSize);
  ctx.lineTo(margin + markerSize, canvas.height - margin);
  ctx.lineTo(margin + markerSize, canvas.height - margin - markerSize);
  ctx.closePath();
  ctx.fill();

  // ⬊ 右下(↖向き)
  ctx.beginPath();
  ctx.moveTo(canvas.width - margin, canvas.height - margin - markerSize);
  ctx.lineTo(canvas.width - margin - markerSize, canvas.height - margin);
  ctx.lineTo(canvas.width - margin - markerSize, canvas.height - margin - markerSize);
  ctx.closePath();
  ctx.fill();
}
const betInput = document.getElementById("betInput");
const coinDisplay = document.getElementById("coinDisplay");

//==================入力制限============================
betInput.addEventListener("input", () => {
  let value = betInput.value.trim();

  // 数値かつ整数か判定
  if (!/^\d+$/.test(value)) {
    betInput.value = ""; // 無効な入力は消去
    return;
  }

  let bet = parseInt(value, 10);
  let coin = parseInt(coinDisplay.textContent.replace(/,/g, ""), 10);
  betInput.max = coin;
  // コイン数を超えたら最大値に制限
  if (bet > coin) {
    betInput.value = coin;
  }
});

//=============ゲームオーバーメッセージ==================
function showGameOverMessage(ctx) {
  ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#fff";
  ctx.font = "bold 32px sans-serif";
  ctx.textAlign = "center";
  ctx.fillText("コインが尽きました", canvas.width / 2, canvas.height / 2 - 20);
  ctx.font = "24px sans-serif";
  ctx.fillText("リセットでリプレイです", canvas.width / 2, canvas.height / 2 + 20);
}

//=================リセット============================
document.getElementById("resetButton").addEventListener("click", () => {
  // 🪙 コインとベットの初期化
  coin = 200;
  localStorage.setItem("coin", 200);
  document.getElementById("coinDisplay").textContent = coin;
  document.getElementById("betInput").value = 1;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawReels();
  // 🎭 状態フラグの初期化
  isGameOver = false;
  isSpinning = false;
});
window.addEventListener("keydown", function (e) {
  if ((e.key === "F5") || (e.ctrlKey && e.key === "r")) {
    e.preventDefault();
  }
});

//==============リロード表示============================
function getCoin() {
  return parseInt(localStorage.getItem("coin") || "200", 10);
}
function setCoin(value) {
  localStorage.setItem("coin", value);
  updateCoinDisplay(); // 表示更新
}
function initializeCoin() {
  if (!localStorage.getItem("coin")) {
    localStorage.setItem("coin", "200");
  }
}

//=================スコア減算===========================
function applyMatchReward(type, bet, symbol) {
  const coin = getCoin();

  // 横2画像一致だけは独立処理
if (type === "row2_left" || type === "row2_center" || type === "row2_right") {
  const updatedCoin = getCoin() + 50;
  setCoin(updatedCoin);
  updateCoinDisplay();
  return;
}

  let rewardMultiplier = 0;
  switch (type) {
    case "horizontal":
    case "row":
      rewardMultiplier = 100_000;
      break;
    case "diagonal":
    case "diag1":
    case "diag2":
      rewardMultiplier = 200_000;
      break;
    case "col":
    case "vertical":
    case "column":
      rewardMultiplier = 300_000;
      break;
    default:
      rewardMultiplier = 0;
  }

  // 絵柄による固定報酬
  let symbolBonus = 0;
  switch (symbol) {
    case 3:
      symbolBonus = 1_000_000;
      break;
    case 23:
      symbolBonus = 500_000;
      break;
    case 17:
      symbolBonus = -100_000;
      bet = 0;
      break;
    case 16:
      symbolBonus = 0;
      bet = 0;
      break;
    case 20:
    case 21:
    case 22:
      symbolBonus = -50_000;
      bet = 0;
      break;
    default:
      symbolBonus = 0;
  }

  const reward = rewardMultiplier * bet + symbolBonus;
  const updatedCoin = Math.max(0, coin + reward - bet);
  setCoin(updatedCoin);
  updateCoinDisplay();
}

//=================入力非表示===========================
function setBetInputEnabled(enabled) {
  const input = document.getElementById("betInput");
  if (input) input.disabled = !enabled;
}

//==================ハイスコア処理=======================
function updateLegendaryScoreDisplay() {
  const legendaryValue = localStorage.getItem("legendaryCoin");
  const scoreElement = document.getElementById("legendaryScore");

  if (legendaryValue && scoreElement) {
    const numericValue = parseInt(legendaryValue, 10);
    scoreElement.textContent = `Legendary Score: ${numericValue.toLocaleString()}`;
  }
}
document.getElementById("clearLegendaryScore").addEventListener("click", () => {
  localStorage.removeItem("legendaryCoin");

  const scoreElement = document.getElementById("legendaryScore");
  if (scoreElement) {
    scoreElement.textContent = "Legendary Score: ----";
  }
});

//================ゲームセット演出========================
function showLegendaryAnimation() {
  const img = new Image();
  img.src = '../assets/23_1.png';//===任意のアドレス=======

  img.onload = () => {
    const startTime = performance.now();

    function animate(time) {
      const elapsed = time - startTime;
      const progress = elapsed / 5000;

      ctx.clearRect(0, 0, canvas.width, canvas.height);

      let alpha = 1;
      if (progress < 0.2) {
        alpha = progress / 0.2;
      } else if (progress > 0.8) {
        alpha = 1 - (progress - 0.8) / 0.2;
      }

      ctx.globalAlpha = alpha;

      const scale = 1 + progress;
      const floatY = -progress * 100;
      const offsetX = Math.sin(elapsed / 200) * 10;
      const offsetY = Math.cos(elapsed / 300) * 10;

      const imgWidth = img.width * scale;
      const imgHeight = img.height * scale;

      const x = canvas.width / 2 - imgWidth / 2 + offsetX;
      const y = canvas.height / 2 - imgHeight / 2 + offsetY + floatY;

      ctx.drawImage(img, x, y, imgWidth, imgHeight);
      ctx.globalAlpha = 1;

      if (elapsed < 5000) {
        requestAnimationFrame(animate);
      } else {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 文言を描画(canvas上)
        const message = "その瞬間、伝説は静かに舞い上がり、記憶の空に溶けていった。";
  ctx.font = "20px serif";
  ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
  ctx.textAlign = "center";
  ctx.textBaseline = "top";

  const maxWidth = canvas.width * 0.8;
  const lineHeight = 28;
  const x = canvas.width / 2;
  const y = canvas.height / 2 - lineHeight; // 上に少しずらす

drawWrappedText(ctx, message, x, y, maxWidth, lineHeight);
      }
    }

    requestAnimationFrame(animate);
  };
}

function drawWrappedText(ctx, text, x, y, maxWidth, lineHeight) {
  const words = text.split(/(\s||)/); // 区切りで分割
  let line = "";
  let lines = [];

  for (let i = 0; i < words.length; i++) {
    const testLine = line + words[i];
    const testWidth = ctx.measureText(testLine).width;

    if (testWidth > maxWidth && line !== "") {
      lines.push(line);
      line = words[i];
    } else {
      line = testLine;
    }
  }
  lines.push(line);

  lines.forEach((l, i) => {
    ctx.fillText(l, x, y + i * lineHeight);
  });
}

//============INF=================
  const openBtn = document.getElementById('openGuide');
  const closeBtn = document.getElementById('closeGuide');
  const guideBox = document.getElementById('gameGuide');
  openBtn.addEventListener('click', () => {
    guideBox.style.display = 'block';
  });
  closeBtn.addEventListener('click', () => {
    guideBox.style.display = 'none';
  });
//=================================
CSS
body {
  background: #222;
  font-family: sans-serif;
  text-align: center;
  color: #e7e7e7;
}

html {
  touch-action: manipulation;
}

canvas {
  background: #111;
  display: block;
  margin: 1em auto;
  border: 4px solid #888;
  border-radius: 12px;
  box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);
}

.ui {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 452px; /* キャンバスと同じ幅 */
  padding: 10px 15px;
  margin: 10px auto;
  border: 2px solid #ccc;
  border-radius: 12px;
  background-color: #4e9217;
  font-family: "Segoe UI", sans-serif;
  box-shadow: 2px 2px 6px rgba(0,0,0,0.1);
}

.ui label,
.ui p {
  margin: 0;
  font-size: 16px;
}

/* COINだけサイズを変える */
.coin-label {
  font-size: 20px !important; /* 強制的に上書き */
  color: rgb(39, 39, 39);
  font-weight: bold;
}
#coinDisplay {
  font-size: 20px; /* お好みのサイズに調整 */
  font-weight: bold;
  color: #ff73e8; /* ゴールド系でコイン感 */
  text-shadow: 2px 1px 2px #272525;
}
.ui input {
  font-size: 18px;
  padding: 4px;
  border-radius: 6px;
  border: 1px solid #aaa;
}

.ui button {
  font-size: 16px;
  padding: 6px 12px;
  border-radius: 8px;
  border: none;
  background-color: #252ca3;
  color: white;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.ui button:hover {
  background-color: #38688f;
}

input[type="number"] {
  width: 120px;
  font-size:14px;

}

#legendaryScore {
    font-size: 18px;
    font-weight: bold;
    color: gold;
    text-shadow: 1px 1px 4px rgba(255,215,0,0.6);
    font-family: 'Cinzel', serif; /* 伝説感あるフォントもおすすめ */
  }

#clearLegendaryScore {
  font-size: 18px;
  margin-left: 8px;
  background: transparent;
  border: none;
  color: crimson;
  cursor: pointer;
  font-weight: bold;
}

#clearLegendaryScore:hover {
  text-decoration: underline;
}

/* 初期状態で非表示 */
#gameGuide {
  display: none;
  position: fixed; /* fixedで画面中央に固定 */
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%); /* 中央に寄せる */
  width: 430px;
  background: #353434;
  border: 2px solid #21e271;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  font-size: 14px;
  font-family: sans-serif;
  margin: 0 auto;
  opacity: 0.9;
  z-index: 100;
}
.open-button{
  cursor: pointer;
  font-size: 12px;
  padding: 2px 4px;
  background-color: #0078D4;
  color: white;
  text-shadow: 2px 1px 2px #272525;
  border: none;
  border-radius: 4px;
}
.close-button {
  cursor: pointer;
  font-size: 12px;
  padding: 8px 12px;
  margin: 8px;
  background-color: #0078D4;
  color: white;
  border: none;
  border-radius: 4px;
}

.close-button {
  float: right;
  background-color: #d40000;
  font-size: 18px;
  border-radius: 6px;
}
#gameGuide ul {
  list-style: none;         /* デフォルトの「・」を消す */
  padding-left: 0;          /* 左余白をなくす */
  margin: 10px;
}

#gameGuide li {
  position: relative;
  padding-left: 1.4em;      /* ▶の分だけ左に余白を作る */
  text-align: left;         /* テキストを左寄せ */
}

#gameGuide li::before {
  content: "▶";
  position: absolute;
  left: 0;                  /* 左端に固定 */
  color: #80ccff;              /* お好みで色調整 */
}

以上です・・・・・。