Spaces:
Running
Running
| <html lang="fa" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>مار و پله | Snakes & Ladders</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| /* ============================================ | |
| CSS CUSTOM PROPERTIES & DESIGN TOKENS | |
| ============================================ */ | |
| :root { | |
| /* Color Palette - Minimal & Elegant */ | |
| --primary: #4A6FA5; | |
| --primary-dark: #166088; | |
| --primary-light: #6B8CBE; | |
| --background: #F8F9FA; | |
| --surface: #FFFFFF; | |
| --text-primary: #2D3047; | |
| --text-secondary: #6C757D; | |
| --success: #6BA368; | |
| --warning: #E54B4B; | |
| --accent-purple: #8B5CF6; | |
| --accent-orange: #F59E0B; | |
| /* Shadows - Soft & Layered */ | |
| --shadow-sm: 0 1px 2px rgba(45, 48, 71, 0.05); | |
| --shadow-md: 0 4px 6px -1px rgba(45, 48, 71, 0.1), 0 2px 4px -1px rgba(45, 48, 71, 0.06); | |
| --shadow-lg: 0 10px 15px -3px rgba(45, 48, 71, 0.1), 0 4px 6px -2px rgba(45, 48, 71, 0.05); | |
| --shadow-xl: 0 20px 25px -5px rgba(45, 48, 71, 0.1), 0 10px 10px -5px rgba(45, 48, 71, 0.04); | |
| --shadow-dice: 0 8px 16px rgba(74, 111, 165, 0.3); | |
| /* Spacing Scale */ | |
| --space-xs: 0.25rem; | |
| --space-sm: 0.5rem; | |
| --space-md: 1rem; | |
| --space-lg: 1.5rem; | |
| --space-xl: 2rem; | |
| --space-2xl: 3rem; | |
| /* Border Radius */ | |
| --radius-sm: 8px; | |
| --radius-md: 12px; | |
| --radius-lg: 16px; | |
| --radius-xl: 24px; | |
| --radius-full: 9999px; | |
| /* Transitions */ | |
| --transition-fast: 150ms ease; | |
| --transition-normal: 250ms ease; | |
| --transition-slow: 400ms ease; | |
| /* Typography */ | |
| --font-family: 'Vazirmatn', system-ui, -apple-system, sans-serif; | |
| } | |
| /* Dark Mode Variables */ | |
| [data-theme="dark"] { | |
| --background: #1a1a2e; | |
| --surface: #16213e; | |
| --text-primary: #e94560; | |
| --text-secondary: #a0a0a0; | |
| --primary: #e94560; | |
| --primary-dark: #c73e54; | |
| --primary-light: #ff6b6b; | |
| } | |
| /* ============================================ | |
| RESET & BASE STYLES | |
| ============================================ */ | |
| *, *::before, *::after { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| html { | |
| font-size: 16px; | |
| scroll-behavior: smooth; | |
| } | |
| body { | |
| font-family: var(--font-family); | |
| background: var(--background); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| line-height: 1.6; | |
| overflow-x: hidden; | |
| } | |
| /* ============================================ | |
| UTILITY CLASSES | |
| ============================================ */ | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: var(--space-lg); | |
| } | |
| .flex { | |
| display: flex; | |
| } | |
| .flex-col { | |
| flex-direction: column; | |
| } | |
| .items-center { | |
| align-items: center; | |
| } | |
| .justify-center { | |
| justify-content: center; | |
| } | |
| .gap-sm { gap: var(--space-sm); } | |
| .gap-md { gap: var(--space-md); } | |
| .gap-lg { gap: var(--space-lg); } | |
| .text-center { text-align: center; } | |
| /* ============================================ | |
| HEADER & BRANDING | |
| ============================================ */ | |
| .header { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| z-index: 100; | |
| background: rgba(248, 249, 250, 0.95); | |
| backdrop-filter: blur(10px); | |
| border-bottom: 1px solid rgba(74, 111, 165, 0.1); | |
| padding: var(--space-md) var(--space-lg); | |
| } | |
| [data-theme="dark"] .header { | |
| background: rgba(22, 33, 62, 0.95); | |
| } | |
| .header-content { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .logo { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-sm); | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| color: var(--primary); | |
| } | |
| .logo-icon { | |
| width: 40px; | |
| height: 40px; | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| border-radius: var(--radius-md); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 1.25rem; | |
| } | |
| .built-with { | |
| font-size: 0.75rem; | |
| color: var(--text-secondary); | |
| text-decoration: none; | |
| padding: var(--space-xs) var(--space-md); | |
| background: var(--surface); | |
| border-radius: var(--radius-full); | |
| box-shadow: var(--shadow-sm); | |
| transition: all var(--transition-fast); | |
| } | |
| .built-with:hover { | |
| color: var(--primary); | |
| box-shadow: var(--shadow-md); | |
| transform: translateY(-1px); | |
| } | |
| /* Theme Toggle */ | |
| .theme-toggle { | |
| background: var(--surface); | |
| border: none; | |
| width: 44px; | |
| height: 44px; | |
| border-radius: var(--radius-full); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: var(--shadow-sm); | |
| transition: all var(--transition-fast); | |
| } | |
| .theme-toggle:hover { | |
| box-shadow: var(--shadow-md); | |
| transform: scale(1.05); | |
| } | |
| /* ============================================ | |
| SCREEN MANAGEMENT | |
| ============================================ */ | |
| .screen { | |
| display: none; | |
| min-height: 100vh; | |
| padding-top: 80px; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| .screen.active { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ============================================ | |
| HOME SCREEN | |
| ============================================ */ | |
| .home-screen { | |
| justify-content: center; | |
| align-items: center; | |
| text-align: center; | |
| } | |
| .hero { | |
| max-width: 600px; | |
| } | |
| .hero-title { | |
| font-size: clamp(2.5rem, 8vw, 4rem); | |
| font-weight: 800; | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: var(--space-md); | |
| line-height: 1.2; | |
| } | |
| .hero-subtitle { | |
| font-size: 1.125rem; | |
| color: var(--text-secondary); | |
| margin-bottom: var(--space-2xl); | |
| } | |
| .game-preview { | |
| width: 200px; | |
| height: 200px; | |
| margin: 0 auto var(--space-2xl); | |
| position: relative; | |
| } | |
| .preview-board { | |
| width: 100%; | |
| height: 100%; | |
| background: var(--surface); | |
| border-radius: var(--radius-lg); | |
| box-shadow: var(--shadow-xl); | |
| display: grid; | |
| grid-template-columns: repeat(5, 1fr); | |
| grid-template-rows: repeat(5, 1fr); | |
| gap: 4px; | |
| padding: var(--space-md); | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translateY(0); } | |
| 50% { transform: translateY(-10px); } | |
| } | |
| .preview-cell { | |
| background: linear-gradient(135deg, var(--primary-light), var(--primary)); | |
| border-radius: var(--radius-sm); | |
| opacity: 0.3; | |
| } | |
| .preview-cell:nth-child(3n) { | |
| opacity: 0.6; | |
| } | |
| /* ============================================ | |
| BUTTONS | |
| ============================================ */ | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: var(--space-sm); | |
| padding: var(--space-md) var(--space-xl); | |
| font-family: var(--font-family); | |
| font-size: 1rem; | |
| font-weight: 600; | |
| border: none; | |
| border-radius: var(--radius-lg); | |
| cursor: pointer; | |
| transition: all var(--transition-fast); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .btn::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(135deg, transparent, rgba(255,255,255,0.2), transparent); | |
| transform: translateX(-100%); | |
| transition: transform 0.5s; | |
| } | |
| .btn:hover::before { | |
| transform: translateX(100%); | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| color: white; | |
| box-shadow: var(--shadow-dice); | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 12px 24px rgba(74, 111, 165, 0.4); | |
| } | |
| .btn-secondary { | |
| background: var(--surface); | |
| color: var(--text-primary); | |
| box-shadow: var(--shadow-md); | |
| } | |
| .btn-secondary:hover { | |
| background: var(--background); | |
| transform: translateY(-2px); | |
| } | |
| .btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| transform: none ; | |
| } | |
| /* ============================================ | |
| SETUP SCREEN | |
| ============================================ */ | |
| .setup-card { | |
| background: var(--surface); | |
| border-radius: var(--radius-xl); | |
| padding: var(--space-2xl); | |
| box-shadow: var(--shadow-lg); | |
| max-width: 500px; | |
| width: 100%; | |
| } | |
| .setup-title { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| margin-bottom: var(--space-lg); | |
| text-align: center; | |
| } | |
| .form-group { | |
| margin-bottom: var(--space-lg); | |
| } | |
| .form-label { | |
| display: block; | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| color: var(--text-secondary); | |
| margin-bottom: var(--space-sm); | |
| } | |
| .form-input { | |
| width: 100%; | |
| padding: var(--space-md); | |
| font-family: var(--font-family); | |
| font-size: 1rem; | |
| border: 2px solid rgba(74, 111, 165, 0.1); | |
| border-radius: var(--radius-md); | |
| background: var(--background); | |
| color: var(--text-primary); | |
| transition: all var(--transition-fast); | |
| } | |
| .form-input:focus { | |
| outline: none; | |
| border-color: var(--primary); | |
| box-shadow: 0 0 0 3px rgba(74, 111, 165, 0.1); | |
| } | |
| .player-inputs { | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--space-md); | |
| } | |
| .player-input-row { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-md); | |
| padding: var(--space-md); | |
| background: var(--background); | |
| border-radius: var(--radius-md); | |
| transition: all var(--transition-fast); | |
| } | |
| .player-input-row.active { | |
| background: linear-gradient(135deg, rgba(74, 111, 165, 0.1), rgba(74, 111, 165, 0.05)); | |
| border: 2px solid var(--primary); | |
| } | |
| .player-color { | |
| width: 32px; | |
| height: 32px; | |
| border-radius: var(--radius-full); | |
| flex-shrink: 0; | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .player-color-1 { background: linear-gradient(135deg, #4A6FA5, #166088); } | |
| .player-color-2 { background: linear-gradient(135deg, #E54B4B, #C73E54); } | |
| .player-color-3 { background: linear-gradient(135deg, #6BA368, #4A7A47); } | |
| .player-color-4 { background: linear-gradient(135deg, #8B5CF6, #6D28D9); } | |
| .player-count-selector { | |
| display: flex; | |
| gap: var(--space-sm); | |
| justify-content: center; | |
| margin-bottom: var(--space-lg); | |
| } | |
| .count-btn { | |
| width: 48px; | |
| height: 48px; | |
| border-radius: var(--radius-md); | |
| border: 2px solid rgba(74, 111, 165, 0.2); | |
| background: var(--surface); | |
| font-size: 1.25rem; | |
| font-weight: 700; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| transition: all var(--transition-fast); | |
| } | |
| .count-btn:hover, .count-btn.active { | |
| border-color: var(--primary); | |
| background: var(--primary); | |
| color: white; | |
| } | |
| /* ============================================ | |
| GAME SCREEN | |
| ============================================ */ | |
| .game-layout { | |
| display: grid; | |
| grid-template-columns: 1fr; | |
| gap: var(--space-lg); | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: var(--space-lg); | |
| } | |
| @media (min-width: 1024px) { | |
| .game-layout { | |
| grid-template-columns: 280px 1fr 280px; | |
| align-items: start; | |
| } | |
| } | |
| /* Game Board */ | |
| .board-container { | |
| position: relative; | |
| aspect-ratio: 1; | |
| max-width: 600px; | |
| margin: 0 auto; | |
| width: 100%; | |
| } | |
| .game-board { | |
| display: grid; | |
| grid-template-columns: repeat(10, 1fr); | |
| grid-template-rows: repeat(10, 1fr); | |
| gap: 2px; | |
| width: 100%; | |
| height: 100%; | |
| background: var(--surface); | |
| border-radius: var(--radius-lg); | |
| padding: var(--space-md); | |
| box-shadow: var(--shadow-xl); | |
| position: relative; | |
| } | |
| .cell { | |
| position: relative; | |
| border-radius: var(--radius-sm); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: clamp(0.625rem, 2vw, 0.875rem); | |
| font-weight: 500; | |
| color: var(--text-secondary); | |
| transition: all var(--transition-fast); | |
| overflow: hidden; | |
| } | |
| /* Checkerboard pattern */ | |
| .cell:nth-child(even) { | |
| background: rgba(74, 111, 165, 0.05); | |
| } | |
| .cell:nth-child(odd) { | |
| background: rgba(74, 111, 165, 0.02); | |
| } | |
| /* Special cells */ | |
| .cell.ladder-start { | |
| background: linear-gradient(135deg, rgba(107, 163, 104, 0.2), rgba(107, 163, 104, 0.1)); | |
| } | |
| .cell.ladder-end { | |
| background: linear-gradient(135deg, rgba(107, 163, 104, 0.3), rgba(107, 163, 104, 0.2)); | |
| } | |
| .cell.snake-start { | |
| background: linear-gradient(135deg, rgba(229, 75, 75, 0.2), rgba(229, 75, 75, 0.1)); | |
| } | |
| .cell.snake-end { | |
| background: linear-gradient(135deg, rgba(229, 75, 75, 0.1), rgba(229, 75, 75, 0.05)); | |
| } | |
| .cell-content { | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* Snake and Ladder SVG overlays */ | |
| .board-overlay { | |
| position: absolute; | |
| inset: var(--space-md); | |
| pointer-events: none; | |
| z-index: 10; | |
| } | |
| .snake-path, .ladder-path { | |
| fill: none; | |
| stroke-width: 4; | |
| stroke-linecap: round; | |
| } | |
| .snake-path { | |
| stroke: var(--warning); | |
| filter: drop-shadow(0 2px 4px rgba(229, 75, 75, 0.3)); | |
| } | |
| .ladder-path { | |
| stroke: var(--success); | |
| filter: drop-shadow(0 2px 4px rgba(107, 163, 104, 0.3)); | |
| } | |
| .ladder-rung { | |
| stroke: var(--success); | |
| stroke-width: 2; | |
| } | |
| /* Player Tokens */ | |
| .token { | |
| position: absolute; | |
| width: clamp(20px, 5vw, 32px); | |
| height: clamp(20px, 5vw, 32px); | |
| border-radius: 50%; | |
| transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| z-index: 20; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.2); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: clamp(10px, 2.5vw, 14px); | |
| color: white; | |
| font-weight: 700; | |
| } | |
| .token::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: 50%; | |
| border: 2px solid rgba(255,255,255,0.5); | |
| } | |
| .token-player-1 { background: linear-gradient(135deg, #4A6FA5, #166088); } | |
| .token-player-2 { background: linear-gradient(135deg, #E54B4B, #C73E54); } | |
| .token-player-3 { background: linear-gradient(135deg, #6BA368, #4A7A47); } | |
| .token-player-4 { background: linear-gradient(135deg, #8B5CF6, #6D28D9); } | |
| .token.moving { | |
| z-index: 30; | |
| transform: scale(1.2); | |
| } | |
| /* Side Panels */ | |
| .side-panel { | |
| background: var(--surface); | |
| border-radius: var(--radius-xl); | |
| padding: var(--space-lg); | |
| box-shadow: var(--shadow-lg); | |
| } | |
| .panel-title { | |
| font-size: 1rem; | |
| font-weight: 600; | |
| color: var(--text-secondary); | |
| margin-bottom: var(--space-md); | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| /* Player Info Cards */ | |
| .player-card { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-md); | |
| padding: var(--space-md); | |
| border-radius: var(--radius-md); | |
| margin-bottom: var(--space-sm); | |
| transition: all var(--transition-fast); | |
| border: 2px solid transparent; | |
| } | |
| .player-card.active { | |
| background: linear-gradient(135deg, rgba(74, 111, 165, 0.1), rgba(74, 111, 165, 0.05)); | |
| border-color: var(--primary); | |
| box-shadow: var(--shadow-md); | |
| } | |
| .player-card.winner { | |
| background: linear-gradient(135deg, rgba(107, 163, 104, 0.2), rgba(107, 163, 104, 0.1)); | |
| border-color: var(--success); | |
| } | |
| .player-avatar { | |
| width: 48px; | |
| height: 48px; | |
| border-radius: var(--radius-full); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.25rem; | |
| color: white; | |
| font-weight: 700; | |
| flex-shrink: 0; | |
| } | |
| .player-info { | |
| flex: 1; | |
| } | |
| .player-name { | |
| font-weight: 600; | |
| margin-bottom: var(--space-xs); | |
| } | |
| .player-stats { | |
| font-size: 0.875rem; | |
| color: var(--text-secondary); | |
| } | |
| .player-position { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| color: var(--primary); | |
| } | |
| /* Dice Section */ | |
| .dice-section { | |
| text-align: center; | |
| } | |
| .dice-container { | |
| width: 120px; | |
| height: 120px; | |
| margin: 0 auto var(--space-lg); | |
| perspective: 600px; | |
| } | |
| .dice { | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| transform-style: preserve-3d; | |
| transition: transform 0.6s ease; | |
| } | |
| .dice.rolling { | |
| animation: rollDice 0.6s ease; | |
| } | |
| @keyframes rollDice { | |
| 0% { transform: rotateX(0) rotateY(0) rotateZ(0); } | |
| 25% { transform: rotateX(360deg) rotateY(180deg) rotateZ(90deg); } | |
| 50% { transform: rotateX(720deg) rotateY(360deg) rotateZ(180deg); } | |
| 75% { transform: rotateX(1080deg) rotateY(540deg) rotateZ(270deg); } | |
| 100% { transform: rotateX(1440deg) rotateY(720deg) rotateZ(360deg); } | |
| } | |
| .dice-face { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| background: var(--surface); | |
| border-radius: var(--radius-lg); | |
| box-shadow: var(--shadow-lg), inset 0 0 20px rgba(0,0,0,0.05); | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| grid-template-rows: repeat(3, 1fr); | |
| padding: 16px; | |
| backface-visibility: hidden; | |
| } | |
| .dice-face::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: var(--radius-lg); | |
| background: linear-gradient(135deg, transparent 40%, rgba(255,255,255,0.4) 50%, transparent 60%); | |
| } | |
| .dot { | |
| width: 20px; | |
| height: 20px; | |
| background: var(--text-primary); | |
| border-radius: 50%; | |
| align-self: center; | |
| justify-self: center; | |
| box-shadow: inset 0 2px 4px rgba(0,0,0,0.3); | |
| } | |
| /* Dice face positions */ | |
| .dice-face:nth-child(1) { transform: translateZ(60px); } | |
| .dice-face:nth-child(2) { transform: rotateY(90deg) translateZ(60px); } | |
| .dice-face:nth-child(3) { transform: rotateY(180deg) translateZ(60px); } | |
| .dice-face:nth-child(4) { transform: rotateY(-90deg) translateZ(60px); } | |
| .dice-face:nth-child(5) { transform: rotateX(90deg) translateZ(60px); } | |
| .dice-face:nth-child(6) { transform: rotateX(-90deg) translateZ(60px); } | |
| /* Dot positions for each face */ | |
| .dice-face[data-face="1"] .dot:nth-child(1) { grid-area: 2 / 2; } | |
| .dice-face[data-face="2"] .dot:nth-child(1) { grid-area: 1 / 1; } | |
| .dice-face[data-face="2"] .dot:nth-child(2) { grid-area: 3 / 3; } | |
| .dice-face[data-face="3"] .dot:nth-child(1) { grid-area: 1 / 1; } | |
| .dice-face[data-face="3"] .dot:nth-child(2) { grid-area: 2 / 2; } | |
| .dice-face[data-face="3"] .dot:nth-child(3) { grid-area: 3 / 3; } | |
| .dice-face[data-face="4"] .dot:nth-child(1) { grid-area: 1 / 1; } | |
| .dice-face[data-face="4"] .dot:nth-child(2) { grid-area: 1 / 3; } | |
| .dice-face[data-face="4"] .dot:nth-child(3) { grid-area: 3 / 1; } | |
| .dice-face[data-face="4"] .dot:nth-child(4) { grid-area: 3 / 3; } | |
| .dice-face[data-face="5"] .dot:nth-child(1) { grid-area: 1 / 1; } | |
| .dice-face[data-face="5"] .dot:nth-child(2) { grid-area: 1 / 3; } | |
| .dice-face[data-face="5"] .dot:nth-child(3) { grid-area: 2 / 2; } | |
| .dice-face[data-face="5"] .dot:nth-child(4) { grid-area: 3 / 1; } | |
| .dice-face[data-face="5"] .dot:nth-child(5) { grid-area: 3 / 3; } | |
| .dice-face[data-face="6"] .dot:nth-child(1) { grid-area: 1 / 1; } | |
| .dice-face[data-face="6"] .dot:nth-child(2) { grid-area: 1 / 3; } | |
| .dice-face[data-face="6"] .dot:nth-child(3) { grid-area: 2 / 1; } | |
| .dice-face[data-face="6"] .dot:nth-child(4) { grid-area: 2 / 3; } | |
| .dice-face[data-face="6"] .dot:nth-child(5) { grid-area: 3 / 1; } | |
| .dice-face[data-face="6"] .dot:nth-child(6) { grid-area: 3 / 3; } | |
| .turn-indicator { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: var(--space-sm); | |
| padding: var(--space-md); | |
| background: var(--background); | |
| border-radius: var(--radius-md); | |
| margin-bottom: var(--space-md); | |
| } | |
| .turn-dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| animation: pulse 1.5s ease infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); opacity: 1; } | |
| 50% { transform: scale(1.2); opacity: 0.7; } | |
| } | |
| /* Move History */ | |
| .history-list { | |
| max-height: 300px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--space-sm); | |
| } | |
| .history-item { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--space-sm); | |
| padding: var(--space-sm); | |
| background: var(--background); | |
| border-radius: var(--radius-sm); | |
| font-size: 0.875rem; | |
| animation: slideIn 0.3s ease; | |
| } | |
| @keyframes slideIn { | |
| from { opacity: 0; transform: translateX(-20px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| .history-dice { | |
| width: 24px; | |
| height: 24px; | |
| background: var(--surface); | |
| border-radius: var(--radius-sm); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: 700; | |
| font-size: 0.75rem; | |
| box-shadow: var(--shadow-sm); | |
| } | |
| /* ============================================ | |
| MODALS & OVERLAYS | |
| ============================================ */ | |
| .modal-overlay { | |
| position: fixed; | |
| inset: 0; | |
| background: rgba(45, 48, 71, 0.8); | |
| backdrop-filter: blur(4px); | |
| display: none; | |
| align-items: center; | |
| justify-content: center; | |
| z-index: 1000; | |
| padding: var(--space-lg); | |
| } | |
| .modal-overlay.active { | |
| display: flex; | |
| animation: fadeIn 0.3s ease; | |
| } | |
| .modal { | |
| background: var(--surface); | |
| border-radius: var(--radius-xl); | |
| padding: var(--space-2xl); | |
| max-width: 400px; | |
| width: 100%; | |
| text-align: center; | |
| box-shadow: var(--shadow-xl); | |
| animation: scaleIn 0.3s ease; | |
| } | |
| @keyframes scaleIn { | |
| from { transform: scale(0.9); opacity: 0; } | |
| to { transform: scale(1); opacity: 1; } | |
| } | |
| .modal-icon { | |
| width: 80px; | |
| height: 80px; | |
| margin: 0 auto var(--space-lg); | |
| border-radius: var(--radius-full); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 2.5rem; | |
| } | |
| .modal-icon.win { | |
| background: linear-gradient(135deg, rgba(107, 163, 104, 0.2), rgba(107, 163, 104, 0.1)); | |
| } | |
| .modal-icon.snake { | |
| background: linear-gradient(135deg, rgba(229, 75, 75, 0.2), rgba(229, 75, 75, 0.1)); | |
| } | |
| .modal-icon.ladder { | |
| background: linear-gradient(135deg, rgba(107, 163, 104, 0.2), rgba(107, 163, 104, 0.1)); | |
| } | |
| .modal-title { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| margin-bottom: var(--space-sm); | |
| } | |
| .modal-message { | |
| color: var(--text-secondary); | |
| margin-bottom: var(--space-xl); | |
| } | |
| /* ============================================ | |
| ANIMATIONS & EFFECTS | |
| ============================================ */ | |
| .confetti { | |
| position: fixed; | |
| width: 10px; | |
| height: 10px; | |
| animation: confetti-fall 3s ease-out forwards; | |
| z-index: 1001; | |
| } | |
| @keyframes confetti-fall { | |
| 0% { | |
| transform: translateY(-100vh) rotate(0deg); | |
| opacity: 1; | |
| } | |
| 100% { | |
| transform: translateY(100vh) rotate(720deg); | |
| opacity: 0; | |
| } | |
| } | |
| /* Snake bite effect */ | |
| .snake-bite { | |
| animation: shake 0.5s ease; | |
| } | |
| @keyframes shake { | |
| 0%, 100% { transform: translateX(0); } | |
| 25% { transform: translateX(-10px) rotate(-5deg); } | |
| 75% { transform: translateX(10px) rotate(5deg); } | |
| } | |
| /* Ladder climb effect */ | |
| .ladder-climb { | |
| animation: bounce 0.6s ease; | |
| } | |
| @keyframes bounce { | |
| 0%, 100% { transform: scale(1); } | |
| 50% { transform: scale(1.2); } | |
| } | |
| /* ============================================ | |
| RESPONSIVE DESIGN | |
| ============================================ */ | |
| @media (max-width: 1023px) { | |
| .game-layout { | |
| grid-template-columns: 1fr; | |
| } | |
| .side-panel { | |
| order: 2; | |
| } | |
| .board-container { | |
| order: 1; | |
| } | |
| .dice-section { | |
| order: 3; | |
| } | |
| .players-panel { | |
| display: grid; | |
| grid-template-columns: repeat(2, 1fr); | |
| gap: var(--space-sm); | |
| } | |
| .player-card { | |
| margin-bottom: 0; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .container { | |
| padding: var(--space-md); | |
| } | |
| .setup-card { | |
| padding: var(--space-lg); | |
| } | |
| .player-count-selector { | |
| flex-wrap: wrap; | |
| } | |
| .players-panel { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| /* ============================================ | |
| UTILITY ANIMATIONS | |
| ============================================ */ | |
| .fade-enter { | |
| animation: fadeEnter 0.3s ease; | |
| } | |
| @keyframes fadeEnter { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* Scrollbar styling */ | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: var(--background); | |
| border-radius: var(--radius-full); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--primary-light); | |
| border-radius: var(--radius-full); | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--primary); | |
| } | |
| /* Selection colors */ | |
| ::selection { | |
| background: var(--primary); | |
| color: white; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Header --> | |
| <header class="header"> | |
| <div class="header-content"> | |
| <div class="logo"> | |
| <div class="logo-icon">🐍</div> | |
| <span>مار و پله</span> | |
| </div> | |
| <div class="flex gap-md items-center"> | |
| <button class="theme-toggle" id="themeToggle" title="تغییر تم"> | |
| <span id="themeIcon">🌙</span> | |
| </button> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Home Screen --> | |
| <section class="screen home-screen active" id="homeScreen"> | |
| <div class="hero"> | |
| <div class="game-preview"> | |
| <div class="preview-board"> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| <div class="preview-cell"></div> | |
| </div> | |
| </div> | |
| <h1 class="hero-title">مار و پله</h1> | |
| <p class="hero-subtitle">بازی کلاسیک با طراحی مینیمال و مدرن. آمادهاید برای چالش؟</p> | |
| <button class="btn btn-primary" onclick="showSetup()"> | |
| <span>▶</span> | |
| شروع بازی | |
| </button> | |
| </div> | |
| </section> | |
| <!-- Setup Screen --> | |
| <section class="screen" id="setupScreen"> | |
| <div class="setup-card"> | |
| <h2 class="setup-title">تنظیمات بازی</h2> | |
| <div class="form-group"> | |
| <label class="form-label">تعداد بازیکنان</label> | |
| <div class="player-count-selector"> | |
| <button class="count-btn active" data-count="2" onclick="setPlayerCount(2)">2</button> | |
| <button class="count-btn" data-count="3" onclick="setPlayerCount(3)">3</button> | |
| <button class="count-btn" data-count="4" onclick="setPlayerCount(4)">4</button> | |
| </div> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">نام بازیکنان</label> | |
| <div class="player-inputs" id="playerInputs"> | |
| <!-- Generated by JS --> | |
| </div> | |
| </div> | |
| <button class="btn btn-primary" style="width: 100%;" onclick="startGame()"> | |
| <span>🎮</span> | |
| شروع بازی | |
| </button> | |
| </div> | |
| </section> | |
| <!-- Game Screen --> | |
| <section class="screen" id="gameScreen"> | |
| <div class="game-layout"> | |
| <!-- Left Panel - Players --> | |
| <div class="side-panel"> | |
| <h3 class="panel-title">بازیکنان</h3> | |
| <div class="players-panel" id="playersPanel"> | |
| <!-- Generated by JS --> | |
| </div> | |
| </div> | |
| <!-- Center - Game Board --> | |
| <div class="board-container"> | |
| <div class="game-board" id="gameBoard"> | |
| <!-- Cells generated by JS --> | |
| </div> | |
| <svg class="board-overlay" id="boardOverlay"> | |
| <!-- Snakes and ladders drawn by JS --> | |
| </svg> | |
| <div id="tokensContainer"> | |
| <!-- Tokens generated by JS --> | |
| </div> | |
| </div> | |
| <!-- Right Panel - Dice & History --> | |
| <div class="side-panel"> | |
| <h3 class="panel-title">نوبت بازی</h3> | |
| <div class="dice-section"> | |
| <div class="turn-indicator" id="turnIndicator"> | |
| <div class="turn-dot" id="turnDot"></div> | |
| <span id="turnText">نوبت بازیکن ۱</span> | |
| </div> | |
| <div class="dice-container"> | |
| <div class="dice" id="dice"> | |
| <div class="dice-face" data-face="1"> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="dice-face" data-face="2"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="dice-face" data-face="3"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="dice-face" data-face="4"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="dice-face" data-face="5"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="dice-face" data-face="6"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <button class="btn btn-primary" id="rollBtn" onclick="rollDice()" style="width: 100%;"> | |
| <span>🎲</span> | |
| پرتاب تاس | |
| </button> | |
| </div> | |
| <h3 class="panel-title" style="margin-top: var(--space-lg);">تاریخچه حرکات</h3> | |
| <div class="history-list" id="historyList"> | |
| <!-- Generated by JS --> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Modals --> | |
| <div class="modal-overlay" id="gameModal"> | |
| <div class="modal"> | |
| <div class="modal-icon" id="modalIcon">🏆</div> | |
| <h3 class="modal-title" id="modalTitle">عنوان</h3> | |
| <p class="modal-message" id="modalMessage">پیام</p> | |
| <button class="btn btn-primary" id="modalBtn" onclick="closeModal()" style="width: 100%;"> | |
| ادامه | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| /* ============================================ | |
| GAME CONFIGURATION & STATE | |
| ============================================ */ | |
| const CONFIG = { | |
| boardSize: 100, | |
| gridSize: 10, | |
| snakes: { | |
| 16: 6, // Snake 1 | |
| 47: 26, // Snake 2 | |
| 49: 11, // Snake 3 | |
| 62: 19, // Snake 4 | |
| 64: 60, // Snake 5 | |
| 87: 24, // Snake 6 | |
| 93: 73, // Snake 7 | |
| 95: 75, // Snake 8 | |
| 98: 78 // Snake 9 | |
| }, | |
| ladders: { | |
| 4: 14, // Ladder 1 | |
| 9: 31, // Ladder 2 | |
| 21: 42, // Ladder 3 | |
| 28: 84, // Ladder 4 | |
| 36: 44, // Ladder 5 | |
| 51: 67, // Ladder 6 | |
| 71: 91, // Ladder 7 | |
| 80: 100 // Ladder 8 | |
| } | |
| }; | |
| let gameState = { | |
| players: [], | |
| currentPlayer: 0, | |
| isRolling: false, | |
| isMoving: false, | |
| gameOver: false, | |
| history: [] | |
| }; | |
| let playerCount = 2; | |
| /* ============================================ | |
| THEME MANAGEMENT | |
| ============================================ */ | |
| const themeToggle = document.getElementById('themeToggle'); | |
| const themeIcon = document.getElementById('themeIcon'); | |
| let isDark = false; | |
| themeToggle.addEventListener('click', () => { | |
| isDark = !isDark; | |
| document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light'); | |
| themeIcon.textContent = isDark ? '☀️' : '🌙'; | |
| localStorage.setItem('theme', isDark ? 'dark' : 'light'); | |
| }); | |
| // Load saved theme | |
| const savedTheme = localStorage.getItem('theme'); | |
| if (savedTheme === 'dark') { | |
| isDark = true; | |
| document.documentElement.setAttribute('data-theme', 'dark'); | |
| themeIcon.textContent = '☀️'; | |
| } | |
| /* ============================================ | |
| SCREEN NAVIGATION | |
| ============================================ */ | |
| function showScreen(screenId) { | |
| document.querySelectorAll |