<m-prompt
  id="tb-icb-prompt"
  message="Play Ice Wordle. Guess the 5-letter word with FROST-style feedback. Use RESET to restart or NEW for another puzzle."
  placeholder="FROST"
  prefill="FROST"
  debug="false"
>
  <m-model
    id="tb-icb-board-model"
    src="/assets/tb_ice_wordle_board_downloads.glb"
    x="0"
    y="0.96"
    z="4.04"
    rx="-90"
    sx="8"
    sy="8"
    sz="8"
  ></m-model>
<m-cube id="tb-icb-slab-0-0" x="-2.1" y="1.56" z="-2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-0-0" x="-2.1" y="1.68" z="-2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-0-1" x="-1.05" y="1.56" z="-2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-0-1" x="-1.05" y="1.68" z="-2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-0-2" x="0" y="1.56" z="-2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-0-2" x="0" y="1.68" z="-2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-0-3" x="1.05" y="1.56" z="-2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-0-3" x="1.05" y="1.68" z="-2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-0-4" x="2.1" y="1.56" z="-2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-0-4" x="2.1" y="1.68" z="-2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-1-0" x="-2.1" y="1.56" z="-1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-1-0" x="-2.1" y="1.68" z="-1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-1-1" x="-1.05" y="1.56" z="-1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-1-1" x="-1.05" y="1.68" z="-1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-1-2" x="0" y="1.56" z="-1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-1-2" x="0" y="1.68" z="-1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-1-3" x="1.05" y="1.56" z="-1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-1-3" x="1.05" y="1.68" z="-1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-1-4" x="2.1" y="1.56" z="-1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-1-4" x="2.1" y="1.68" z="-1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-2-0" x="-2.1" y="1.56" z="-0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-2-0" x="-2.1" y="1.68" z="-0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-2-1" x="-1.05" y="1.56" z="-0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-2-1" x="-1.05" y="1.68" z="-0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-2-2" x="0" y="1.56" z="-0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-2-2" x="0" y="1.68" z="-0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-2-3" x="1.05" y="1.56" z="-0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-2-3" x="1.05" y="1.68" z="-0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-2-4" x="2.1" y="1.56" z="-0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-2-4" x="2.1" y="1.68" z="-0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-3-0" x="-2.1" y="1.56" z="0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-3-0" x="-2.1" y="1.68" z="0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-3-1" x="-1.05" y="1.56" z="0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-3-1" x="-1.05" y="1.68" z="0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-3-2" x="0" y="1.56" z="0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-3-2" x="0" y="1.68" z="0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-3-3" x="1.05" y="1.56" z="0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-3-3" x="1.05" y="1.68" z="0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-3-4" x="2.1" y="1.56" z="0.54" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-3-4" x="2.1" y="1.68" z="0.54" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-4-0" x="-2.1" y="1.56" z="1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-4-0" x="-2.1" y="1.68" z="1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-4-1" x="-1.05" y="1.56" z="1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-4-1" x="-1.05" y="1.68" z="1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-4-2" x="0" y="1.56" z="1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-4-2" x="0" y="1.68" z="1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-4-3" x="1.05" y="1.56" z="1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-4-3" x="1.05" y="1.68" z="1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-4-4" x="2.1" y="1.56" z="1.62" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-4-4" x="2.1" y="1.68" z="1.62" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-5-0" x="-2.1" y="1.56" z="2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-5-0" x="-2.1" y="1.68" z="2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-5-1" x="-1.05" y="1.56" z="2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-5-1" x="-1.05" y="1.68" z="2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-5-2" x="0" y="1.56" z="2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-5-2" x="0" y="1.68" z="2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-5-3" x="1.05" y="1.56" z="2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-5-3" x="1.05" y="1.68" z="2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
<m-cube id="tb-icb-slab-5-4" x="2.1" y="1.56" z="2.7" width="0.78" height="0.2" depth="0.78" color="#8bd6ea" opacity="0.9" visible="false"></m-cube>
<m-label id="tb-icb-cell-5-4" x="2.1" y="1.68" z="2.7" rx="-90" width="0.78" height="0.78" font-size="78" alignment="center" color="#1b2f3a" font-color="#eafaff" emissive="0" visible="false" content=""></m-label>
  <m-label id="tb-icb-notice" x="0" y="2.05" z="4.85" rx="-24" width="7.2" height="0.48" font-size="20" alignment="center" color="#0b2334" font-color="#f5fbff" emissive="0" visible="false" content=""></m-label>
</m-prompt>
<script>

(function () {
  const ROWS = 6;
  const COLS = 5;
  const WORDS = ["FROST", "GLACE", "SHARD", "CRANE", "NORTH", "SPARK"];
  const COLORS = {
exact: "#1f8f61",
present: "#b8962f",
miss: "#263744",
empty: "#1b2f3a"
  };
  const FONTS = {
exact: "#eafff7",
present: "#061827",
miss: "#d7e8ef",
empty: "#eafaff"
  };

  const prompt = document.getElementById("tb-icb-prompt");
  const notice = document.getElementById("tb-icb-notice");
  let noticeTimer = null;
  let puzzleIndex = 0;
  let currentRow = 0;
  let finished = false;
  let lastPromptKey = "";
  let lastPromptAt = 0;

  function debug(message) {
try {
  if (typeof console !== "undefined" && console && typeof console.log === "function") {
    console.log(String(message));
  }
} catch (error) {
  // Debug output must never break gameplay.
}
  }

  function setText(el, text) {
if (el) el.setAttribute("content", String(text));
  }

  function clearNoticeTimer() {
if (!noticeTimer) return;
const clearTimer =
  typeof clearTimeout === "function"
    ? clearTimeout
    : typeof window !== "undefined" && typeof window.clearTimeout === "function"
      ? window.clearTimeout.bind(window)
      : null;
if (clearTimer) clearTimer(noticeTimer);
noticeTimer = null;
  }

  function showNotice(message, kind) {
if (!notice) return;
clearNoticeTimer();
setText(notice, message);
notice.setAttribute("visible", "true");
if (kind === "error") {
  notice.setAttribute("color", "#220711");
  notice.setAttribute("font-color", "#ffb7ce");
  notice.setAttribute("emissive", "0");
} else if (kind === "success") {
  notice.setAttribute("color", "#062317");
  notice.setAttribute("font-color", "#b8ffe5");
  notice.setAttribute("emissive", "0");
} else {
  notice.setAttribute("color", "#0b2334");
  notice.setAttribute("font-color", "#f5fbff");
  notice.setAttribute("emissive", "0");
}
const setTimer =
  typeof setTimeout === "function"
    ? setTimeout
    : typeof window !== "undefined" && typeof window.setTimeout === "function"
      ? window.setTimeout.bind(window)
      : null;
if (setTimer) {
  noticeTimer = setTimer(function () {
    notice.setAttribute("visible", "false");
  }, 3600);
}
  }

  function clean(value) {
return String(value || "").toUpperCase().replace(/[^A-Z0-9 ]/g, " ").replace(/\s+/g, " ").trim();
  }

  function firstString() {
for (let i = 0; i < arguments.length; i += 1) {
  const value = arguments[i];
  if (typeof value === "string" && value.trim()) return value;
  if (typeof value === "number") return String(value);
}
return "";
  }

  function readPromptValue(event) {
const detail = event && event.detail ? event.detail : {};
const value = firstString(
  detail.value,
  detail.text,
  detail.prompt,
  detail.input,
  detail.message,
  detail.result,
  event && event.value,
  event && event.text,
  typeof event === "string" ? event : ""
);
if (value) return value;
if (prompt && typeof prompt.getAttribute === "function") {
  return firstString(prompt.getAttribute("value"), prompt.getAttribute("text"));
}
return "";
  }

  function isDuplicatePrompt(rawValue) {
const key = clean(rawValue);
const now = typeof Date !== "undefined" && Date && typeof Date.now === "function" ? Date.now() : 0;
if (key && key === lastPromptKey && now && lastPromptAt && now - lastPromptAt < 750) {
  return true;
}
lastPromptKey = key;
lastPromptAt = now;
return false;
  }

  function currentSecret() {
return WORDS[puzzleIndex % WORDS.length];
  }

  function cell(row, col) {
return document.getElementById("tb-icb-cell-" + row + "-" + col);
  }

  function clearBoard() {
for (let row = 0; row < ROWS; row += 1) {
  for (let col = 0; col < COLS; col += 1) {
    const el = cell(row, col);
    if (!el) continue;
    el.setAttribute("content", "");
    el.setAttribute("visible", "false");
    el.setAttribute("color", COLORS.empty);
    el.setAttribute("font-color", FONTS.empty);
  }
}
currentRow = 0;
finished = false;
  }

  function resetPuzzle(advance) {
if (advance) puzzleIndex = (puzzleIndex + 1) % WORDS.length;
clearBoard();
showNotice("Puzzle " + (puzzleIndex + 1) + ". Guess 5 letters. Try FROST.", "info");
debug("ice-wordle reset: " + currentSecret());
  }

  function parseGuess(rawValue) {
const value = clean(rawValue);
if (!value) return { error: "Type a 5-letter word." };
if (value === "RESET" || value === "CLEAR") return { reset: true };
if (value === "NEW" || value === "NEXT") return { next: true };
const tokens = value.split(" ");
let guess = "";
for (const token of tokens) {
  if (token === "GUESS" || token === "WORD" || token === "TRY") continue;
  if (/^[A-Z]{5}$/.test(token)) {
    guess = token;
    break;
  }
}
if (!guess) return { error: "Use a 5-letter word. Example: GUESS FROST." };
return { guess };
  }

  function scoreGuess(guess, secret) {
const result = Array(COLS).fill("miss");
const remaining = {};
for (let i = 0; i < COLS; i += 1) {
  if (guess[i] === secret[i]) {
    result[i] = "exact";
  } else {
    remaining[secret[i]] = (remaining[secret[i]] || 0) + 1;
  }
}
for (let i = 0; i < COLS; i += 1) {
  if (result[i] === "exact") continue;
  const letter = guess[i];
  if (remaining[letter] > 0) {
    result[i] = "present";
    remaining[letter] -= 1;
  }
}
return result;
  }

  function showGuess(guess, result) {
for (let col = 0; col < COLS; col += 1) {
  const el = cell(currentRow, col);
  if (!el) continue;
  const state = result[col];
  el.setAttribute("content", guess[col]);
  el.setAttribute("visible", "true");
  el.setAttribute("color", COLORS[state] || COLORS.miss);
  el.setAttribute("font-color", FONTS[state] || FONTS.miss);
  el.setAttribute("emissive", "0");
}
  }

  function handlePrompt(event) {
try {
  const rawValue = readPromptValue(event);
  if (isDuplicatePrompt(rawValue)) return;
  const parsed = parseGuess(rawValue);
  debug("ice-wordle prompt: " + String(rawValue || ""));

  if (parsed.reset) {
    resetPuzzle(false);
    return;
  }
  if (parsed.next) {
    resetPuzzle(true);
    return;
  }
  if (parsed.error) {
    showNotice(parsed.error, "error");
    debug("ice-wordle error: " + parsed.error);
    return;
  }
  if (finished) {
    showNotice("Puzzle finished. Type NEW or RESET.", "info");
    return;
  }
  if (currentRow >= ROWS) {
    finished = true;
    showNotice("No guesses left. Answer was " + currentSecret() + ". Type NEW.", "error");
    return;
  }

  const secret = currentSecret();
  const result = scoreGuess(parsed.guess, secret);
  showGuess(parsed.guess, result);
  const exactCount = result.filter(function (state) { return state === "exact"; }).length;
  const presentCount = result.filter(function (state) { return state === "present"; }).length;
  currentRow += 1;

  if (parsed.guess === secret) {
    finished = true;
    showNotice("Solved " + secret + " in " + currentRow + "/6. Type NEW.", "success");
    debug("ice-wordle solved: " + secret);
    return;
  }

  if (currentRow >= ROWS) {
    finished = true;
    showNotice("Answer was " + secret + ". Type NEW for another.", "error");
    debug("ice-wordle lost: " + secret);
    return;
  }

  showNotice(parsed.guess + ": " + exactCount + " HIT, " + presentCount + " NEAR. Guess " + (currentRow + 1) + "/6.", "info");
  debug("ice-wordle move: " + parsed.guess + " hit=" + exactCount + " near=" + presentCount);
} catch (error) {
  const message = error && error.message ? error.message : "Prompt handler failed.";
  showNotice("Command error: " + message, "error");
  debug("ice-wordle exception: " + message);
}
  }

  if (prompt) {
prompt.addEventListener("prompt", handlePrompt);
prompt.addEventListener("submit", handlePrompt);
  }
  resetPuzzle(false);
})();

</script>
