diff --git a/public/redirect.js b/public/redirect.js
index 96697a4..21622ce 100644
--- a/public/redirect.js
+++ b/public/redirect.js
@@ -1,6 +1,6 @@
// Device Detection and Redirect
(function() {
- // Check if we're already on the correct page
+ // Check current page
const currentPage = window.location.pathname.split('/').pop() || 'index.html'
// Check if we've already redirected (prevent infinite loops)
@@ -9,16 +9,28 @@
return
}
- // Detect mobile device
- const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
- || window.innerWidth < 768
+ // Detect device type
+ const width = window.innerWidth
+ const isMobileDevice = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
+ const isTabletDevice = /iPad|Android/i.test(navigator.userAgent) && !isMobileDevice
- // Only redirect if needed
- if (isMobile && currentPage !== 'mobile.html') {
+ let targetPage = null
+
+ // Determine target page based on device and screen size
+ if (width < 600 || (isMobileDevice && width < 768)) {
+ // Mobile: < 600px or mobile device < 768px
+ targetPage = 'mobile.html'
+ } else if (width >= 600 && width < 1024) {
+ // Tablet: 600-1024px
+ targetPage = 'tablet.html'
+ } else {
+ // Desktop: >= 1024px
+ targetPage = 'index.html'
+ }
+
+ // Redirect if needed
+ if (currentPage !== targetPage) {
sessionStorage.setItem('hasRedirected', 'true')
- window.location.href = 'mobile.html'
- } else if (!isMobile && currentPage === 'mobile.html') {
- sessionStorage.setItem('hasRedirected', 'true')
- window.location.href = 'index.html'
+ window.location.href = targetPage
}
})()
diff --git a/public/tablet.css b/public/tablet.css
new file mode 100644
index 0000000..810349e
--- /dev/null
+++ b/public/tablet.css
@@ -0,0 +1,442 @@
+/* Tablet-Optimized Styles */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ height: 100vh;
+ overflow: hidden;
+}
+
+.tablet-container {
+ width: 100vw;
+ height: 100vh;
+ background: white;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+/* Header */
+.tablet-header {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ color: white;
+ padding: 12px 20px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ flex-shrink: 0;
+}
+
+.menu-btn {
+ background: rgba(255,255,255,0.2);
+ border: none;
+ color: white;
+ width: 44px;
+ height: 44px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.menu-btn:hover {
+ background: rgba(255,255,255,0.3);
+}
+
+.header-center {
+ text-align: center;
+}
+
+.header-center h1 {
+ font-size: 22px;
+ font-weight: 700;
+ margin-bottom: 2px;
+}
+
+.level {
+ font-size: 14px;
+ font-weight: 600;
+ opacity: 0.9;
+}
+
+.header-right {
+ display: flex;
+ gap: 12px;
+}
+
+.stat {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ background: rgba(255,255,255,0.2);
+ padding: 8px 14px;
+ border-radius: 20px;
+ font-weight: 600;
+ font-size: 16px;
+}
+
+/* Main Content - Side by Side Layout */
+.main-content {
+ flex: 1;
+ display: flex;
+ overflow: hidden;
+ background: #f8f9fa;
+}
+
+/* Grid Area (Left) */
+.grid-area {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ padding: 15px;
+ overflow: hidden;
+}
+
+.progress-bar-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 15px;
+ flex-shrink: 0;
+}
+
+.progress-bar {
+ flex: 1;
+ height: 10px;
+ background: #e9ecef;
+ border-radius: 5px;
+ overflow: hidden;
+}
+
+.progress-fill {
+ height: 100%;
+ background: linear-gradient(90deg, #48bb78, #38a169);
+ width: 0%;
+ transition: width 0.3s ease;
+}
+
+.progress-text {
+ font-size: 14px;
+ font-weight: 600;
+ color: #4a5568;
+ min-width: 50px;
+}
+
+.grid-section {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+ background: white;
+ border-radius: 12px;
+ padding: 15px;
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+}
+
+.grid-wrapper {
+ display: grid;
+ background: #a0aec0;
+ padding: 6px;
+ border-radius: 8px;
+ gap: 2px;
+}
+
+.grid-cell {
+ background: white;
+ border: 1px solid #cbd5e0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ font-weight: bold;
+}
+
+.grid-cell.clue-cell {
+ background: linear-gradient(135deg, #4a5568, #2d3748);
+ color: white;
+ padding: 3px;
+ font-size: 9px;
+ font-weight: 600;
+ line-height: 1.2;
+ text-align: left;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+.clue-text {
+ font-size: 9px;
+ line-height: 1.2;
+ word-wrap: break-word;
+ width: 100%;
+}
+
+.arrow {
+ position: absolute;
+ color: #4299e1;
+ font-weight: bold;
+ font-size: 16px;
+}
+
+.arrow-right {
+ right: 3px;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.grid-cell.blocked-cell {
+ background: #2d3748;
+ border-color: #2d3748;
+}
+
+.grid-cell.input-cell {
+ background: white;
+ transition: all 0.2s;
+}
+
+.grid-cell.input-cell:hover {
+ background: #f7fafc;
+ border-color: #4299e1;
+}
+
+.grid-cell.input-cell.active {
+ background: #ebf8ff;
+ border-color: #3182ce;
+ box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.3);
+}
+
+.grid-cell.correct {
+ background: #c6f6d5;
+ border-color: #48bb78;
+}
+
+.grid-cell.incorrect {
+ background: #fed7d7;
+ border-color: #f56565;
+}
+
+.grid-cell input {
+ width: 100%;
+ height: 100%;
+ border: none;
+ background: transparent;
+ text-align: center;
+ font-weight: bold;
+ color: #2d3748;
+ text-transform: uppercase;
+ font-size: inherit;
+ outline: none;
+}
+
+/* Controls Sidebar (Right) */
+.controls-sidebar {
+ width: 180px;
+ background: white;
+ padding: 15px;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ border-left: 1px solid #e9ecef;
+ flex-shrink: 0;
+}
+
+.control-btn {
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ color: white;
+ border: none;
+ border-radius: 12px;
+ padding: 16px 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 6px;
+ cursor: pointer;
+ font-weight: 600;
+ font-size: 14px;
+ transition: all 0.3s;
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
+}
+
+.control-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
+}
+
+.control-btn:active {
+ transform: translateY(0);
+}
+
+.control-btn i {
+ font-size: 24px;
+}
+
+.control-btn.primary {
+ background: linear-gradient(135deg, #48bb78, #38a169);
+}
+
+.control-btn.hint {
+ background: linear-gradient(135deg, #ed8936, #dd6b20);
+}
+
+/* Side Menu */
+.side-menu {
+ position: fixed;
+ top: 0;
+ left: -280px;
+ width: 280px;
+ height: 100vh;
+ background: white;
+ box-shadow: 2px 0 15px rgba(0,0,0,0.2);
+ transition: left 0.3s ease;
+ z-index: 1000;
+}
+
+.side-menu.active {
+ left: 0;
+}
+
+.menu-header {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ color: white;
+ padding: 20px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.close-menu {
+ background: none;
+ border: none;
+ color: white;
+ font-size: 24px;
+ cursor: pointer;
+}
+
+.menu-items {
+ padding: 15px 0;
+}
+
+.menu-item {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ padding: 15px 20px;
+ border: none;
+ background: none;
+ width: 100%;
+ text-align: left;
+ cursor: pointer;
+ font-size: 16px;
+ transition: background 0.2s;
+}
+
+.menu-item:hover {
+ background: #f8f9fa;
+}
+
+.menu-item i {
+ width: 20px;
+ color: #4facfe;
+}
+
+/* Modals */
+.modal {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0,0,0,0.6);
+ z-index: 2000;
+ justify-content: center;
+ align-items: center;
+ padding: 20px;
+}
+
+.modal.active {
+ display: flex;
+}
+
+.modal-content {
+ background: white;
+ border-radius: 20px;
+ padding: 30px;
+ text-align: center;
+ max-width: 400px;
+ width: 100%;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
+}
+
+.success-icon {
+ font-size: 64px;
+ color: #48bb78;
+ margin-bottom: 16px;
+}
+
+.modal-content h2 {
+ color: #2d3748;
+ margin-bottom: 10px;
+ font-size: 24px;
+}
+
+.modal-content h3 {
+ color: #2d3748;
+ margin-bottom: 16px;
+ font-size: 20px;
+}
+
+.modal-content p {
+ color: #4a5568;
+ margin-bottom: 20px;
+ font-size: 16px;
+}
+
+.modal-btns {
+ display: flex;
+ gap: 10px;
+ margin-top: 20px;
+}
+
+.btn-primary {
+ background: linear-gradient(135deg, #48bb78, #38a169);
+ color: white;
+ border: none;
+ border-radius: 10px;
+ padding: 14px 24px;
+ cursor: pointer;
+ font-weight: 600;
+ font-size: 16px;
+ flex: 1;
+ transition: transform 0.2s;
+}
+
+.btn-secondary {
+ background: #e2e8f0;
+ color: #4a5568;
+ border: none;
+ border-radius: 10px;
+ padding: 14px 24px;
+ cursor: pointer;
+ font-weight: 600;
+ font-size: 16px;
+ flex: 1;
+ transition: transform 0.2s;
+}
+
+.btn-primary:hover,
+.btn-secondary:hover {
+ transform: scale(1.02);
+}
diff --git a/public/tablet.html b/public/tablet.html
new file mode 100644
index 0000000..22c7d9d
--- /dev/null
+++ b/public/tablet.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+ Kruiswoord Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Gefeliciteerd!
+
+50 Munten | +1 Hint
+
+
+
+
+
+
+
+
Hint Gebruiken?
+
Kost 1 hint
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tablet.js b/public/tablet.js
new file mode 100644
index 0000000..fd4392f
--- /dev/null
+++ b/public/tablet.js
@@ -0,0 +1,464 @@
+// Tablet-Optimized Crossword Game
+class TabletCrosswordGame {
+ constructor() {
+ this.currentLevel = 1
+ this.coins = 100
+ this.hints = 3
+ this.currentPuzzle = null
+ this.userAnswers = {}
+ this.selectedCell = null
+ this.gridElement = document.getElementById('crosswordGrid')
+
+ this.init()
+ }
+
+ init() {
+ this.loadPuzzle(this.currentLevel)
+ this.setupEventListeners()
+ this.updateUI()
+ }
+
+ setupEventListeners() {
+ document.getElementById('menuBtn').addEventListener('click', () => {
+ document.getElementById('sideMenu').classList.add('active')
+ })
+ document.getElementById('closeMenu').addEventListener('click', () => {
+ document.getElementById('sideMenu').classList.remove('active')
+ })
+
+ document.getElementById('checkBtn').addEventListener('click', () => this.checkAnswers())
+ document.getElementById('clearBtn').addEventListener('click', () => this.clearGrid())
+ document.getElementById('hintBtn').addEventListener('click', () => this.showHintModal())
+ document.getElementById('skipBtn').addEventListener('click', () => this.skipPuzzle())
+
+ document.getElementById('useHintBtn').addEventListener('click', () => this.useHint())
+ document.getElementById('cancelHintBtn').addEventListener('click', () => this.hideHintModal())
+ document.getElementById('nextBtn').addEventListener('click', () => this.nextPuzzle())
+
+ document.getElementById('dailyPuzzle').addEventListener('click', () => {
+ this.showFeedback('Dagelijkse puzzel komt binnenkort!')
+ document.getElementById('sideMenu').classList.remove('active')
+ })
+ document.getElementById('levelSelect').addEventListener('click', () => {
+ this.showFeedback('Niveau selectie komt binnenkort!')
+ document.getElementById('sideMenu').classList.remove('active')
+ })
+ }
+
+ loadPuzzle(level) {
+ if (typeof DUTCH_PUZZLES !== 'undefined') {
+ this.currentPuzzle = DUTCH_PUZZLES[`level${level}`] || DUTCH_PUZZLES.level1
+ }
+
+ this.userAnswers = {}
+ this.renderGrid()
+ this.updateProgress()
+ this.updateUI()
+ }
+
+ renderGrid() {
+ if (!this.currentPuzzle) return
+
+ const grid = this.currentPuzzle.grid
+ const words = this.currentPuzzle.words
+
+ this.gridElement.innerHTML = ''
+
+ const rows = grid.length
+ const cols = Math.max(...grid.map(row => row.length)) + 1
+
+ // Tablet-specific calculation - fill available space
+ const cellSize = this.calculateCellSize(rows, cols)
+
+ this.gridElement.style.gridTemplateColumns = `repeat(${cols}, ${cellSize}px)`
+ this.gridElement.style.gridTemplateRows = `repeat(${rows}, ${cellSize}px)`
+
+ // Create grid cells
+ for (let row = 0; row < rows; row++) {
+ for (let col = 0; col < cols; col++) {
+ if (col === 0) {
+ const clueData = this.getClueForRow(row, words)
+ this.gridElement.appendChild(this.createClueCell(clueData, cellSize))
+ } else {
+ const gridCol = col - 1
+ const cellValue = grid[row]?.[gridCol] || '#'
+ this.gridElement.appendChild(this.createCell(cellValue, row, gridCol, words, cellSize))
+ }
+ }
+ }
+
+ this.attachCellListeners()
+ }
+
+ calculateCellSize(rows, cols) {
+ // Tablet layout: sidebar is 180px, header is ~70px, progress is ~50px, padding is 30px each side
+ const headerHeight = 70
+ const progressHeight = 50
+ const sidebarWidth = 180
+ const padding = 60 // 15px on each side x2
+
+ const availableHeight = window.innerHeight - headerHeight - progressHeight - padding
+ const availableWidth = window.innerWidth - sidebarWidth - padding
+
+ const maxFromHeight = Math.floor(availableHeight / rows)
+ const maxFromWidth = Math.floor(availableWidth / cols)
+
+ let cellSize = Math.min(maxFromHeight, maxFromWidth)
+
+ // Tablet range: 50-90px for good visibility and touch
+ cellSize = Math.max(50, Math.min(90, cellSize))
+
+ return cellSize
+ }
+
+ getClueForRow(row, words) {
+ return words.find(w => w.direction === 'horizontal' && w.startRow === row)
+ }
+
+ createClueCell(clueData, cellSize) {
+ const cell = document.createElement('div')
+ cell.className = 'grid-cell clue-cell'
+ cell.style.width = `${cellSize}px`
+ cell.style.height = `${cellSize}px`
+
+ if (clueData) {
+ const text = document.createElement('div')
+ text.className = 'clue-text'
+ text.textContent = clueData.clue
+
+ const arrow = document.createElement('div')
+ arrow.className = 'arrow arrow-right'
+ arrow.textContent = '→'
+
+ cell.appendChild(text)
+ cell.appendChild(arrow)
+ } else {
+ cell.classList.add('blocked-cell')
+ }
+
+ return cell
+ }
+
+ createCell(value, row, col, words, cellSize) {
+ const cell = document.createElement('div')
+ cell.className = 'grid-cell'
+ cell.style.width = `${cellSize}px`
+ cell.style.height = `${cellSize}px`
+ cell.dataset.row = row
+ cell.dataset.col = col
+
+ if (value === '#') {
+ const clueData = this.getClueAtPosition(row, col, words)
+ if (clueData) {
+ cell.classList.add('clue-cell')
+
+ const text = document.createElement('div')
+ text.className = 'clue-text'
+ text.textContent = clueData.clue
+
+ const arrow = document.createElement('div')
+ arrow.className = 'arrow arrow-right'
+ arrow.textContent = '→'
+
+ cell.appendChild(text)
+ cell.appendChild(arrow)
+ } else {
+ cell.classList.add('blocked-cell')
+ }
+ } else {
+ cell.classList.add('input-cell')
+ const input = document.createElement('input')
+ input.type = 'text'
+ input.maxLength = 1
+ input.dataset.row = row
+ input.dataset.col = col
+
+ const fontSize = Math.max(20, Math.min(36, cellSize * 0.5))
+ input.style.fontSize = `${fontSize}px`
+
+ const key = `${row}-${col}`
+ if (this.userAnswers[key]) {
+ input.value = this.userAnswers[key]
+ }
+
+ cell.appendChild(input)
+ }
+
+ return cell
+ }
+
+ getClueAtPosition(row, col, words) {
+ for (const word of words) {
+ if (word.direction === 'horizontal' && word.startRow === row && word.startCol - 1 === col) {
+ return word
+ }
+ }
+ return null
+ }
+
+ attachCellListeners() {
+ const inputs = this.gridElement.querySelectorAll('input')
+
+ inputs.forEach(input => {
+ input.addEventListener('input', (e) => this.handleInput(e))
+ input.addEventListener('focus', (e) => this.selectCell(e.target))
+ input.addEventListener('click', (e) => this.selectCell(e.target))
+ })
+
+ // Keyboard navigation
+ document.addEventListener('keydown', (e) => this.handleKeyboard(e))
+ }
+
+ handleInput(e) {
+ const input = e.target
+ const value = input.value.toUpperCase()
+ input.value = value
+
+ const row = parseInt(input.dataset.row)
+ const col = parseInt(input.dataset.col)
+ const key = `${row}-${col}`
+
+ this.userAnswers[key] = value
+
+ if (value && value.length === 1) {
+ this.moveToNextCell(input)
+ }
+
+ this.updateProgress()
+ }
+
+ selectCell(input) {
+ document.querySelectorAll('.grid-cell.input-cell').forEach(cell => {
+ cell.classList.remove('active')
+ })
+ input.parentElement.classList.add('active')
+ this.selectedCell = input
+ }
+
+ moveToNextCell(currentInput) {
+ const inputs = Array.from(this.gridElement.querySelectorAll('input'))
+ const currentIndex = inputs.indexOf(currentInput)
+
+ if (currentIndex !== -1 && currentIndex < inputs.length - 1) {
+ const nextInput = inputs[currentIndex + 1]
+ nextInput.focus()
+ }
+ }
+
+ handleKeyboard(e) {
+ if (!this.selectedCell) return
+
+ const inputs = Array.from(this.gridElement.querySelectorAll('input'))
+ const currentIndex = inputs.indexOf(this.selectedCell)
+
+ if (currentIndex === -1) return
+
+ switch (e.key) {
+ case 'ArrowRight':
+ if (currentIndex < inputs.length - 1) {
+ inputs[currentIndex + 1].focus()
+ }
+ e.preventDefault()
+ break
+ case 'ArrowLeft':
+ if (currentIndex > 0) {
+ inputs[currentIndex - 1].focus()
+ }
+ e.preventDefault()
+ break
+ case 'Backspace':
+ if (!this.selectedCell.value && currentIndex > 0) {
+ inputs[currentIndex - 1].focus()
+ }
+ break
+ }
+ }
+
+ checkAnswers() {
+ let correct = 0
+ let total = 0
+
+ const inputs = this.gridElement.querySelectorAll('input')
+ inputs.forEach(input => {
+ const row = parseInt(input.dataset.row)
+ const col = parseInt(input.dataset.col)
+ const userAnswer = input.value.toUpperCase()
+ const correctAnswer = this.getCorrectAnswer(row, col)
+
+ if (correctAnswer) {
+ total++
+ const cell = input.parentElement
+ if (userAnswer === correctAnswer) {
+ correct++
+ cell.classList.add('correct')
+ cell.classList.remove('incorrect')
+ } else if (userAnswer) {
+ cell.classList.add('incorrect')
+ cell.classList.remove('correct')
+ }
+ }
+ })
+
+ const percentage = total > 0 ? Math.round((correct / total) * 100) : 0
+
+ if (percentage === 100) {
+ this.showSuccess()
+ } else {
+ this.showFeedback(`${correct}/${total} correct (${percentage}%)`)
+ }
+ }
+
+ getCorrectAnswer(row, col) {
+ for (const word of this.currentPuzzle.words) {
+ if (word.direction === 'horizontal') {
+ if (word.startRow === row && col >= word.startCol && col < word.startCol + word.answer.length) {
+ return word.answer[col - word.startCol]
+ }
+ } else if (word.direction === 'vertical') {
+ if (word.startCol === col && row >= word.startRow && row < word.startRow + word.answer.length) {
+ return word.answer[row - word.startRow]
+ }
+ }
+ }
+ return null
+ }
+
+ clearGrid() {
+ if (confirm('Alles wissen?')) {
+ this.userAnswers = {}
+ const inputs = this.gridElement.querySelectorAll('input')
+ inputs.forEach(input => {
+ input.value = ''
+ input.parentElement.classList.remove('correct', 'incorrect')
+ })
+ this.updateProgress()
+ this.showFeedback('Gewist')
+ }
+ }
+
+ showHintModal() {
+ if (this.hints <= 0) {
+ this.showFeedback('Geen hints meer!')
+ return
+ }
+ document.getElementById('hintModal').classList.add('active')
+ }
+
+ hideHintModal() {
+ document.getElementById('hintModal').classList.remove('active')
+ }
+
+ useHint() {
+ if (this.hints <= 0) return
+
+ const inputs = Array.from(this.gridElement.querySelectorAll('input'))
+ const emptyInputs = inputs.filter(input => !input.value)
+
+ if (emptyInputs.length === 0) {
+ this.showFeedback('Alles al ingevuld!')
+ this.hideHintModal()
+ return
+ }
+
+ const randomInput = emptyInputs[Math.floor(Math.random() * emptyInputs.length)]
+ const row = parseInt(randomInput.dataset.row)
+ const col = parseInt(randomInput.dataset.col)
+ const correctAnswer = this.getCorrectAnswer(row, col)
+
+ if (correctAnswer) {
+ randomInput.value = correctAnswer
+ this.userAnswers[`${row}-${col}`] = correctAnswer
+
+ this.hints--
+ this.updateUI()
+ this.updateProgress()
+ this.showFeedback('Letter onthuld!')
+ this.hideHintModal()
+ }
+ }
+
+ showSuccess() {
+ this.coins += 50
+ this.hints += 1
+ this.updateUI()
+ document.getElementById('successModal').classList.add('active')
+ }
+
+ nextPuzzle() {
+ document.getElementById('successModal').classList.remove('active')
+ this.currentLevel++
+ this.loadPuzzle(this.currentLevel)
+ this.showFeedback(`Niveau ${this.currentLevel}`)
+ }
+
+ skipPuzzle() {
+ if (confirm('Overslaan?')) {
+ this.currentLevel++
+ this.loadPuzzle(this.currentLevel)
+ this.showFeedback('Overgeslagen')
+ }
+ }
+
+ updateProgress() {
+ const inputs = this.gridElement.querySelectorAll('input')
+ let filled = 0
+ let total = 0
+
+ inputs.forEach(input => {
+ total++
+ if (input.value) filled++
+ })
+
+ const progress = total > 0 ? Math.round((filled / total) * 100) : 0
+ document.getElementById('progressFill').style.width = `${progress}%`
+ document.getElementById('progressText').textContent = `${progress}%`
+ }
+
+ updateUI() {
+ document.getElementById('coinsCount').textContent = this.coins
+ document.getElementById('hintsCount').textContent = this.hints
+ document.getElementById('levelNum').textContent = this.currentLevel
+ }
+
+ showFeedback(message) {
+ const feedback = document.createElement('div')
+ feedback.style.cssText = `
+ position: fixed;
+ top: 90px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: rgba(0,0,0,0.85);
+ color: white;
+ padding: 12px 24px;
+ border-radius: 24px;
+ font-size: 16px;
+ font-weight: 600;
+ z-index: 9999;
+ animation: fadeInOut 2.5s ease;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
+ `
+ feedback.textContent = message
+ document.body.appendChild(feedback)
+
+ setTimeout(() => {
+ feedback.remove()
+ }, 2500)
+ }
+}
+
+// Animation
+const style = document.createElement('style')
+style.textContent = `
+ @keyframes fadeInOut {
+ 0% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
+ 15% { opacity: 1; transform: translateX(-50%) translateY(0); }
+ 85% { opacity: 1; transform: translateX(-50%) translateY(0); }
+ 100% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
+ }
+`
+document.head.appendChild(style)
+
+// Initialize
+document.addEventListener('DOMContentLoaded', () => {
+ new TabletCrosswordGame()
+})