{"id":1652,"date":"2025-01-08T19:40:10","date_gmt":"2025-01-08T18:40:10","guid":{"rendered":"https:\/\/palanteinc.de\/?page_id=1652"},"modified":"2026-10-28T09:27:26","modified_gmt":"2026-10-28T08:27:26","slug":"tonnapoki","status":"publish","type":"page","link":"https:\/\/palanteinc.de\/en\/webgames\/tonnapoki\/","title":{"rendered":"TonnaPoki"},"content":{"rendered":"\n<div style=\"height:120px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div id=\"palapoki\">\n  <!-- A: Navigation & Info -->\n  <div class=\"zone zone-a\" aria-label=\"Navigation und Spielinfo\">\n    <!-- Zur\u00fcck -->\n    <a href=\"https:\/\/palanteinc.de\/en\/webgames\/\" class=\"nav-btn\">ZUR\u00dcCK<\/a>\n\n    <!-- Neu -->\n    <button class=\"nav-btn\">NEU<\/button>\n\n    <!-- Strikes -->\n    <div class=\"strikes\">\n      <div class=\"strike\"><\/div>\n      <div class=\"strike\"><\/div>\n      <div class=\"strike\"><\/div>\n    <\/div>\n\n    <!-- Zeit -->\n    <div class=\"status\">ZEIT: 00:00<\/div>\n\n    <!-- Profilbild -->\n    <div class=\"profile\">\n      <img decoding=\"async\" src=\"https:\/\/via.placeholder.com\/36\" alt=\"Profil\" \/>\n    <\/div>\n  <\/div>\n\n  <!-- B: Spielfeld -->\n  <div class=\"zone zone-b\" aria-label=\"Spielfeld\">\n    <div id=\"board\" role=\"grid\" aria-label=\"Palapoki Feld\"><\/div>\n  <\/div>\n\n  <!-- C: Zahlen\/Icons -->\n  <div class=\"zone zone-c\" aria-label=\"Symbolauswahl\">\n    <div id=\"pad\" class=\"pad\">\n      <!-- 9 Symbole: beliebig austauschbar -->\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc36\">\ud83d\udc36<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc31\">\ud83d\udc31<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83e\udd8a\">\ud83e\udd8a<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc3b\">\ud83d\udc3b<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc3c\">\ud83d\udc3c<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc28\">\ud83d\udc28<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc2f\">\ud83d\udc2f<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83e\udd81\">\ud83e\udd81<\/button>\n      <button class=\"pad-btn\" data-icon=\"\ud83d\udc35\">\ud83d\udc35<\/button>\n    <\/div>\n  <\/div>\n\n  <!-- D: Bedienelemente -->\n  <div class=\"zone zone-d\" aria-label=\"Bedienelemente\">\n    <button class=\"ui-btn\" id=\"notesToggle\" title=\"Notizen umschalten\">\u270e<\/button>\n    <button class=\"ui-btn\" id=\"erase\" title=\"L\u00f6schen\">\u232b<\/button>\n    <button class=\"ui-btn\" id=\"hint\" title=\"Hinweis\">\ud83d\udca1<\/button>\n    <button class=\"ui-btn\" id=\"check\" title=\"Pr\u00fcfen\">\u2713<\/button>\n  <\/div>\n<\/div>\n\n<script>\n(() => {\n  \/\/ --- Grund-Setup ---\n  const boardEl = document.getElementById('board');\n  const errorsEl = document.getElementById('errors');\n  const timeEl = document.getElementById('time');\n  const padBtns = Array.from(document.querySelectorAll('.pad-btn'));\n  const eraseBtn = document.getElementById('erase');\n  const notesToggle = document.getElementById('notesToggle');\n\n  const SIZE = 9; \/\/ 9x9 Sudoku\n  let currentIcon = null;\n  let notesMode = false;\n  let errors = 0;\n\n  \/\/ Map Zahl->Icon entsprechend Reihenfolge im Pad\n  const icons = padBtns.map(b => b.dataset.icon);\n\n\/\/ --- NEW: load a real Sudoku puzzle on start ---\n\/\/ '.' means empty; digits 1..9 are givens\nconst PUZZLE = \"53..7....6..195....98....6.8...6...34..8.3..17...2...6....6..8....419..5....8..79\";\n\nconst idx = (r,c) => r*SIZE + c;\n\n\/\/ Build the board from an 81-char string\nfunction buildBoard(puzzleStr){\n  boardEl.innerHTML = \"\";\n  for(let r=0;r<SIZE;r++){\n    for(let c=0;c<SIZE;c++){\n      const ch = puzzleStr[idx(r,c)];\n      const cell = document.createElement('button');\n      cell.className = 'cell';\n      cell.setAttribute('data-r', r);\n      cell.setAttribute('data-c', c);\n      cell.setAttribute('role','gridcell');\n      cell.title = `Feld ${r+1},${c+1}`;\n\n      \/\/ Prefill givens (lock them)\n      if(ch !== '.'){\n        const icon = icons[Number(ch)-1];  \/\/ map 1..9 -> your pad icon order\n        cell.textContent = icon ?? '';\n        cell.classList.add('prefilled');\n        cell.disabled = true;\n      }\n\n      boardEl.appendChild(cell);\n    }\n  }\n}\n\n\/\/ Call once on load\nbuildBoard(PUZZLE);\n\n  \/\/ Auswahl im Pad\n  padBtns.forEach(btn=>{\n    btn.addEventListener('click', ()=>{\n      padBtns.forEach(b=>b.classList.remove('active'));\n      btn.classList.add('active');\n      currentIcon = btn.dataset.icon;\n    });\n  });\n\n  \/\/ Erase\n  eraseBtn.addEventListener('click', ()=>{\n    currentIcon = null;\n    padBtns.forEach(b=>b.classList.remove('active'));\n  });\n\n  \/\/ Notes (Platzhalter \u2013 nur visueller Toggle)\n  notesToggle.addEventListener('click', ()=>{\n    notesMode = !notesMode;\n    notesToggle.classList.toggle('active', notesMode);\n  });\n\n  \/\/ Klick auf Zelle\n  boardEl.addEventListener('click', (e)=>{\n    const cell = e.target.closest('.cell');\n    if(!cell || cell.classList.contains('prefilled')) return;\n\n    if(currentIcon){\n      cell.textContent = currentIcon;\n      cell.classList.add('selected');\n    }else{\n      \/\/ L\u00f6schen, wenn kein Icon aktiv\n      cell.textContent = '';\n      cell.classList.remove('selected');\n    }\n  });\n\n  \/\/ Mini-Timer\n  let secs = 0;\n  setInterval(()=>{\n    secs++;\n    const m = String(Math.floor(secs\/60)).padStart(2,'0');\n    const s = String(secs%60).padStart(2,'0');\n    timeEl.textContent = `${m}:${s}`;\n  }, 1000);\n})();\n<\/script>\n\n\n\n<style>\n\/* ================= Base Layout ================= *\/\n#palapoki{\n  box-sizing:border-box;\n  margin:0 auto;\n  padding:12px;\n  display:grid;\n  gap:1em;\n  border-radius:16px;\n  width:100%;\n  max-width:980px;\n  height: 80vh;\n  max-height: 800px;\n  justify-content: center;\n  align-content: center;\n}\n\n\/* Panels\/Zones *\/\n.zone{\n  background: rgba(255, 255, 255, 0.6);\n  border-radius:12px;\n  padding:10px;\n  flex: 1 1 auto;\n}\n\n\/* ================= A & D: Responsive toolbars ================= *\/\n\/* Shared: left\/right buffer + responsive fill with gaps *\/\n.zone-a, .zone-d{\n  --item-min: 110px;          \/* min target width per item before wrapping *\/\n  display:flex;\n  align-items:center;\n  gap:12px;\n  padding:10px 14px;          \/* subtle left\/right buffer *\/\n  flex-wrap:wrap;              \/* graceful wrapping when space is tight *\/\n}\n\n\/* Make primary buttons stretch to fill evenly *\/\n.zone-a .nav-btn{ flex: 1 1 var(--item-min); }\n.zone-d .ui-btn{  flex: 1 1 var(--item-min); }\n\n\/* Keep utility items compact *\/\n.zone-a .strikes,\n.zone-a .status,\n.zone-a .profile{\n  flex: 0 1 auto;\n}\n\n\/* Keep profile pushed to the far end when space allows *\/\n.zone-a .profile{ margin-left:auto; }\n\n\/* Buttons fill their flex box cleanly *\/\n.nav-btn, .ui-btn{\n  width:100%;\n  max-width:100%;\n  border-radius:8px;\n}\n\n\/* Status pill (unchanged look) *\/\n.status{\n  font-weight:600;\n  padding:2px 8px;\n  border:1px solid #ddd;\n  border-radius:8px;\n}\n\n\/* Strikes *\/\n.strikes{ display:flex; gap:6px; }\n.strike{\n  width:18px; height:18px;\n  border:1px solid #000;\n  background:#fff;\n  border-radius:4px;\n}\n.strike.used{ background:#ccc; }\n\n\/* Profile image *\/\n.profile img{\n  width:36px; height:36px;\n  border-radius:50%;\n  object-fit:cover;\n}\n\n\/* ================= Board ================= *\/\n.zone-b{ padding:14px; }\n\n#board{\n  aspect-ratio: 1 \/ 1;\n  width: 100%;  margin: 0 auto;\n  height: auto;\n  max-height: 60%;\n  display: grid;\n  grid-template-columns: repeat(9, 1fr);\n  grid-template-rows: repeat(9, 1fr);\n  border: 2px solid #000;\n  border-radius: 8px;\n  overflow: hidden;\n  margin: 0 auto;\n}\n\n.cell{\n  display:flex; align-items:center; justify-content:center;\n  font-size: calc( (min(90vw, 60vh) \/ 9) * 0.75 ); \/* ~75% of a cell *\/\n  line-height: 1;            \/* avoid extra vertical metrics *\/\n  user-select:none;\n  border:1px solid #bbb;\n  cursor:pointer;\n}\n.cell:focus{ outline:2px solid #0b72b766; outline-offset:-3px; }\n.cell.prefilled{ background:#f6f7fb; font-weight:700; cursor:default; }\n.cell.selected{ background:#e7f2ff; }\n\n\/* 3\u00d73 block lines *\/\n.cell[data-r=\"2\"], .cell[data-r=\"5\"]{ border-bottom:3px solid #000; }\n.cell[data-c=\"2\"], .cell[data-c=\"5\"]{ border-right:3px solid #000; }\n\n\/* ================= Pad ================= *\/\n.pad{\n  display:flex;\n  gap:8px;\n  align-items:stretch;\n  justify-content:space-between;\n  overflow-x:auto;              \/* allow scroll on narrow screens *\/\n  -webkit-overflow-scrolling: touch;\n  scroll-snap-type: x proximity;\/* nicer snap while scrolling *\/\n  padding-bottom:2px;           \/* avoid scrollbar overlap *\/\n}\n.pad-btn{\n  flex: 0 0 auto;               \/* keep in one row *\/\n  width: clamp(44px, 6vw, 64px);\/* responsive size *\/\n  aspect-ratio: 1 \/ 1;          \/* keeps each button square *\/\n  display:grid; place-items:center;\n  font-size: clamp(20px, 4.5vw, 28px);\n  line-height:1;\n  padding:0;                    \/* square = no extra padding *\/\n  border-radius:10px;\n  background:#fff;\n  cursor:pointer;\n  scroll-snap-align:center;     \/* align on snap *\/\n}\n.pad-btn.active{\n  box-shadow:0 0 0 3px #0b72b7 inset;\n}\n\n\/* ================= Desktop ================= *\/\n@media (min-width:900px){\n  #palapoki{ width:60vw; }\n  .zone-c .pad{ grid-template-columns:repeat(3, 1fr); }\n}\n\n\/* ================= Mobile ================= *\/\n@media (max-width: 899.98px){\n  #palapoki{\n    background:#fff !important;\n    border:none !important;\n    border-radius:0 !important;\n    box-shadow:none !important;\n  }\n\n  \/* Toolbars: slightly tighter + smaller min item *\/\n  .zone-a, .zone-d{\n    --item-min: 90px;\n    gap:10px;\n    padding:8px 10px;\n  }\n\n  .ui-btn{ padding:8px 10px; font-size:14px; }\n  .status{ font-size:12px; padding:2px 6px; }\n\n  \/* Example nav button visuals (optional \u2013 keep or adjust) *\/\n  .nav-btn{\n    background:#d8d8d8;\n    border-radius:8px;\n    padding:8px 10px;\n    font-size:14px;\n    font-weight:600;\n    cursor:pointer;\n    text-decoration:none;\n    color:#000;\n  }\n  .nav-btn:hover{ background:#f2f2f2; }\n\n  \/* Board tighter on mobile *\/\n  .zone-b{ padding:6px; }\n  #board{\n    width:100%;\n    max-width:90vw;     \/* not wider than viewport *\/\n    max-height:55vh;    \/* slightly smaller cap to fit toolbars *\/\n    height:auto;\n    margin:0 auto;\n  }\n  .cell{ font-size: clamp(14px, 5vw, 22px); }\n\n  \/* Pad as horizontal bar with snap *\/\n  .zone-c{ padding:6px 4px; }\n  .zone-c .pad{\n    grid-auto-flow:column;\n    grid-auto-columns:minmax(48px,1fr);\n    gap:6px;\n    overflow-x:auto;\n    scroll-snap-type:x mandatory;\n  }\n  .zone-c .pad .pad-btn{\n    padding:8px; font-size:20px; scroll-snap-align:center;\n  }\n}\n<\/style>\n","protected":false},"excerpt":{"rendered":"<p>ZUR\u00dcCK NEU ZEIT: 00:00 \ud83d\udc36 \ud83d\udc31 \ud83e\udd8a \ud83d\udc3b \ud83d\udc3c \ud83d\udc28 \ud83d\udc2f \ud83e\udd81 \ud83d\udc35 \u270e \u232b \ud83d\udca1 \u2713<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1032,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1652","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/pages\/1652","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/comments?post=1652"}],"version-history":[{"count":1,"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/pages\/1652\/revisions"}],"predecessor-version":[{"id":1653,"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/pages\/1652\/revisions\/1653"}],"up":[{"embeddable":true,"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/pages\/1032"}],"wp:attachment":[{"href":"https:\/\/palanteinc.de\/en\/wp-json\/wp\/v2\/media?parent=1652"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}