initial commit
This commit is contained in:
845
mines.css
Normal file
845
mines.css
Normal file
@@ -0,0 +1,845 @@
|
|||||||
|
/* ===== CSS VARIABLES ===== */
|
||||||
|
:root {
|
||||||
|
/* Main Palette - Elegant & Subdued */
|
||||||
|
--bg-primary: #0d0d12;
|
||||||
|
--bg-secondary: #14141c;
|
||||||
|
--bg-tertiary: #1c1c28;
|
||||||
|
--bg-card: #1a1a24;
|
||||||
|
--bg-card-hover: #222230;
|
||||||
|
|
||||||
|
/* Text Colors */
|
||||||
|
--text-primary: #f5f5f7;
|
||||||
|
--text-secondary: #a0a0b0;
|
||||||
|
--text-muted: #606070;
|
||||||
|
|
||||||
|
/* Accent Colors */
|
||||||
|
--gold: #c9a962;
|
||||||
|
--gold-light: #e0c887;
|
||||||
|
--gold-dark: #a08840;
|
||||||
|
|
||||||
|
/* Green - RARE ACCENT (only for wins/success) */
|
||||||
|
--green-accent: #2d9469;
|
||||||
|
--green-light: #3db87f;
|
||||||
|
--green-glow: rgba(45, 148, 105, 0.3);
|
||||||
|
|
||||||
|
/* Danger */
|
||||||
|
--red: #c44545;
|
||||||
|
--red-light: #e05555;
|
||||||
|
--red-glow: rgba(196, 69, 69, 0.4);
|
||||||
|
|
||||||
|
/* UI Elements */
|
||||||
|
--border-color: #2a2a3a;
|
||||||
|
--border-light: #3a3a4a;
|
||||||
|
|
||||||
|
/* Tile States */
|
||||||
|
--tile-bg: linear-gradient(145deg, #252535, #1e1e2a);
|
||||||
|
--tile-hover: linear-gradient(145deg, #2a2a3c, #232332);
|
||||||
|
--tile-revealed-safe: linear-gradient(145deg, #1a2e25, #152520);
|
||||||
|
--tile-revealed-mine: linear-gradient(145deg, #2e1a1a, #251515);
|
||||||
|
|
||||||
|
/* Shadows */
|
||||||
|
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||||
|
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);
|
||||||
|
--shadow-gold: 0 0 20px rgba(201, 169, 98, 0.2);
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--font-display: 'Playfair Display', Georgia, serif;
|
||||||
|
--font-body: 'Inter', -apple-system, sans-serif;
|
||||||
|
|
||||||
|
/* Sizing */
|
||||||
|
--grid-size: 5;
|
||||||
|
--tile-size: 70px;
|
||||||
|
--tile-gap: 8px;
|
||||||
|
|
||||||
|
/* Transitions */
|
||||||
|
--transition-fast: 0.15s ease;
|
||||||
|
--transition-normal: 0.25s ease;
|
||||||
|
--transition-slow: 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== RESET & BASE ===== */
|
||||||
|
*, *::before, *::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-body);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== LAYOUT ===== */
|
||||||
|
.casino-container {
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== HEADER ===== */
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px 30px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: var(--gold);
|
||||||
|
text-shadow: var(--shadow-gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
background: linear-gradient(135deg, var(--gold-light), var(--gold));
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-display {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== MAIN GAME AREA ===== */
|
||||||
|
.game-area {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 280px 1fr 240px;
|
||||||
|
gap: 24px;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== PANELS ===== */
|
||||||
|
.controls-panel,
|
||||||
|
.history-panel {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-section {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-section:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== INPUT STYLES ===== */
|
||||||
|
.input-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-input-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
overflow: hidden;
|
||||||
|
transition: border-color var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-input-group:focus-within {
|
||||||
|
border-color: var(--gold-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.currency-symbol {
|
||||||
|
padding: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-input {
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 12px 8px;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-input::-webkit-outer-spin-button,
|
||||||
|
.bet-input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-buttons {
|
||||||
|
display: flex;
|
||||||
|
border-left: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
padding: 12px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-btn:hover {
|
||||||
|
background: var(--bg-card-hover);
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bet-btn:first-child {
|
||||||
|
border-right: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== MINES SELECTOR ===== */
|
||||||
|
.mines-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-btn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-btn:hover {
|
||||||
|
background: var(--bg-card-hover);
|
||||||
|
border-color: var(--gold-dark);
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-value {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--gold);
|
||||||
|
min-width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-range {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-range input[type="range"] {
|
||||||
|
flex: 1;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-range input[type="range"]::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: var(--gold);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mines-range input[type="range"]::-webkit-slider-thumb:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== STATS SECTION ===== */
|
||||||
|
.stats-section {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 16px !important;
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-right: -8px;
|
||||||
|
width: calc(100% + 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-row:not(:last-child) {
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.multiplier {
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== PAYOUT SECTION ===== */
|
||||||
|
.payout-section {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-multiplier,
|
||||||
|
.potential-win {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payout-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payout-value {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.payout-value.win-value {
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== ACTION BUTTONS ===== */
|
||||||
|
.action-section {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn {
|
||||||
|
background: linear-gradient(135deg, var(--gold), var(--gold-dark));
|
||||||
|
color: var(--bg-primary);
|
||||||
|
box-shadow: var(--shadow-gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn:hover:not(:disabled) {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 24px rgba(201, 169, 98, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn:active:not(:disabled) {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cashout-btn {
|
||||||
|
background: linear-gradient(135deg, var(--green-accent), #257a55);
|
||||||
|
color: var(--text-primary);
|
||||||
|
box-shadow: 0 4px 16px var(--green-glow);
|
||||||
|
animation: pulse-green 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cashout-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 24px var(--green-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-green {
|
||||||
|
0%, 100% { box-shadow: 0 4px 16px var(--green-glow); }
|
||||||
|
50% { box-shadow: 0 4px 24px rgba(45, 148, 105, 0.5); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== GAME GRID ===== */
|
||||||
|
.grid-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-wrapper {
|
||||||
|
position: relative;
|
||||||
|
padding: 24px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(var(--grid-size), var(--tile-size));
|
||||||
|
grid-template-rows: repeat(var(--grid-size), var(--tile-size));
|
||||||
|
gap: var(--tile-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
width: var(--tile-size);
|
||||||
|
height: var(--tile-size);
|
||||||
|
background: var(--tile-bg);
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 28px;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(135deg, rgba(255,255,255,0.05), transparent);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile:hover:not(.revealed):not(.disabled) {
|
||||||
|
background: var(--tile-hover);
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
border-color: var(--border-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile:active:not(.revealed):not(.disabled) {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.revealed {
|
||||||
|
cursor: default;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.revealed.safe {
|
||||||
|
background: var(--tile-revealed-safe);
|
||||||
|
border-color: var(--green-accent);
|
||||||
|
animation: reveal-safe 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.revealed.safe .tile-icon {
|
||||||
|
color: var(--green-light);
|
||||||
|
text-shadow: 0 0 10px var(--green-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.revealed.mine {
|
||||||
|
background: var(--tile-revealed-mine);
|
||||||
|
border-color: var(--red);
|
||||||
|
animation: reveal-mine 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.revealed.mine .tile-icon {
|
||||||
|
color: var(--red-light);
|
||||||
|
text-shadow: 0 0 10px var(--red-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.show-mine {
|
||||||
|
background: var(--tile-revealed-mine);
|
||||||
|
border-color: rgba(196, 69, 69, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile.show-mine .tile-icon {
|
||||||
|
color: var(--red);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes reveal-safe {
|
||||||
|
0% { transform: scale(0.8); opacity: 0; }
|
||||||
|
50% { transform: scale(1.1); }
|
||||||
|
100% { transform: scale(1); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes reveal-mine {
|
||||||
|
0% { transform: scale(0.8) rotate(-10deg); opacity: 0; }
|
||||||
|
30% { transform: scale(1.2) rotate(5deg); }
|
||||||
|
60% { transform: scale(0.95) rotate(-2deg); }
|
||||||
|
100% { transform: scale(1) rotate(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile-icon {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid Overlay */
|
||||||
|
.grid-overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(13, 13, 18, 0.9);
|
||||||
|
border-radius: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.revealed-counter {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== HISTORY PANEL ===== */
|
||||||
|
.history-panel {
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-empty {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 14px;
|
||||||
|
border-left: 3px solid var(--border-color);
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item:hover {
|
||||||
|
background: var(--bg-card-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item.win {
|
||||||
|
border-left-color: var(--green-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item.loss {
|
||||||
|
border-left-color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-bet {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-result {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item.win .history-result {
|
||||||
|
color: var(--green-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item.loss .history-result {
|
||||||
|
color: var(--red-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-details {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== MODAL ===== */
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
animation: modal-fade-in 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes modal-fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 48px;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
animation: modal-scale-in 0.4s ease;
|
||||||
|
min-width: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.win {
|
||||||
|
border-color: var(--green-accent);
|
||||||
|
box-shadow: 0 0 60px var(--green-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.loss {
|
||||||
|
border-color: var(--red);
|
||||||
|
box-shadow: 0 0 60px var(--red-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes modal-scale-in {
|
||||||
|
from { transform: scale(0.8); opacity: 0; }
|
||||||
|
to { transform: scale(1); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-icon {
|
||||||
|
font-size: 64px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.win .modal-title {
|
||||||
|
color: var(--green-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.loss .modal-title {
|
||||||
|
color: var(--red-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-amount {
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.win .modal-amount {
|
||||||
|
color: var(--green-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.loss .modal-amount {
|
||||||
|
color: var(--red-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-btn {
|
||||||
|
background: linear-gradient(135deg, var(--gold), var(--gold-dark));
|
||||||
|
color: var(--bg-primary);
|
||||||
|
border: none;
|
||||||
|
padding: 14px 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== UTILITIES ===== */
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== SCROLLBAR ===== */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--border-light);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== RESPONSIVE ===== */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.game-area {
|
||||||
|
grid-template-columns: 260px 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-panel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.game-area {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls-panel {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--tile-size: 60px;
|
||||||
|
--tile-gap: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
:root {
|
||||||
|
--tile-size: 50px;
|
||||||
|
--tile-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.casino-container {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-wrapper {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
133
mines.html
Normal file
133
mines.html
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="pl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Mines - Elegant Casino</title>
|
||||||
|
<link rel="stylesheet" href="mines.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="casino-container">
|
||||||
|
<!-- Header -->
|
||||||
|
<header class="header">
|
||||||
|
<div class="logo">
|
||||||
|
<span class="logo-icon">◆</span>
|
||||||
|
<span class="logo-text">MINES</span>
|
||||||
|
</div>
|
||||||
|
<div class="balance-display">
|
||||||
|
<span class="balance-label">Balance</span>
|
||||||
|
<span class="balance-value" id="balance">$1,000.00</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Main Game Area -->
|
||||||
|
<main class="game-area">
|
||||||
|
<!-- Left Panel - Controls -->
|
||||||
|
<aside class="controls-panel">
|
||||||
|
<div class="panel-section">
|
||||||
|
<label class="input-label">Bet Amount</label>
|
||||||
|
<div class="bet-input-group">
|
||||||
|
<span class="currency-symbol">$</span>
|
||||||
|
<input type="number" id="bet-amount" class="bet-input" value="10" min="1" step="1">
|
||||||
|
<div class="bet-buttons">
|
||||||
|
<button class="bet-btn" data-action="half">½</button>
|
||||||
|
<button class="bet-btn" data-action="double">2×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-section">
|
||||||
|
<label class="input-label">Number of Mines</label>
|
||||||
|
<div class="mines-selector">
|
||||||
|
<button class="mines-btn" id="mines-decrease">−</button>
|
||||||
|
<span class="mines-value" id="mines-count">3</span>
|
||||||
|
<button class="mines-btn" id="mines-increase">+</button>
|
||||||
|
</div>
|
||||||
|
<div class="mines-range">
|
||||||
|
<span>1</span>
|
||||||
|
<input type="range" id="mines-slider" min="1" max="24" value="3">
|
||||||
|
<span>24</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-section stats-section">
|
||||||
|
<div class="stat-row">
|
||||||
|
<span class="stat-label">Tiles</span>
|
||||||
|
<span class="stat-value" id="tiles-info">25 (5×5)</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-row">
|
||||||
|
<span class="stat-label">Safe Tiles</span>
|
||||||
|
<span class="stat-value" id="safe-tiles">22</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-row">
|
||||||
|
<span class="stat-label">Next Multiplier</span>
|
||||||
|
<span class="stat-value multiplier" id="next-multiplier">×1.14</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-section payout-section">
|
||||||
|
<div class="current-multiplier">
|
||||||
|
<span class="payout-label">Current Multiplier</span>
|
||||||
|
<span class="payout-value" id="current-multiplier">×1.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="potential-win">
|
||||||
|
<span class="payout-label">Potential Win</span>
|
||||||
|
<span class="payout-value win-value" id="potential-win">$0.00</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-section action-section">
|
||||||
|
<button class="action-btn start-btn" id="start-btn">
|
||||||
|
<span class="btn-icon">▶</span>
|
||||||
|
Start Round
|
||||||
|
</button>
|
||||||
|
<button class="action-btn cashout-btn hidden" id="cashout-btn">
|
||||||
|
<span class="btn-icon">$</span>
|
||||||
|
Cash Out
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Center - Game Grid -->
|
||||||
|
<section class="grid-container">
|
||||||
|
<div class="grid-wrapper">
|
||||||
|
<div class="game-grid" id="game-grid">
|
||||||
|
<!-- Tiles will be generated by JS -->
|
||||||
|
</div>
|
||||||
|
<div class="grid-overlay hidden" id="grid-overlay">
|
||||||
|
<div class="overlay-content">
|
||||||
|
<span class="overlay-icon" id="overlay-icon">💎</span>
|
||||||
|
<span class="overlay-text" id="overlay-text">Place your bet and start!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="revealed-counter">
|
||||||
|
<span id="revealed-count">0</span> / <span id="total-safe">22</span> tiles revealed
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Right Panel - History -->
|
||||||
|
<aside class="history-panel">
|
||||||
|
<h3 class="panel-title">Round History</h3>
|
||||||
|
<div class="history-list" id="history-list">
|
||||||
|
<div class="history-empty">No rounds played yet</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Result Modal -->
|
||||||
|
<div class="modal hidden" id="result-modal">
|
||||||
|
<div class="modal-content" id="modal-content">
|
||||||
|
<div class="modal-icon" id="modal-icon">💎</div>
|
||||||
|
<h2 class="modal-title" id="modal-title">You Won!</h2>
|
||||||
|
<p class="modal-amount" id="modal-amount">$125.00</p>
|
||||||
|
<p class="modal-subtitle" id="modal-subtitle">×2.50 multiplier</p>
|
||||||
|
<button class="modal-btn" id="modal-close">Continue</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="mines.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
384
mines.js
Normal file
384
mines.js
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
/**
|
||||||
|
* MINES - Casino Game
|
||||||
|
* Elegant browser-based Mines game simulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MinesGame {
|
||||||
|
constructor(config = {}) {
|
||||||
|
// Grid configuration (easily changeable)
|
||||||
|
this.gridSize = config.gridSize || 5;
|
||||||
|
this.totalTiles = this.gridSize * this.gridSize;
|
||||||
|
|
||||||
|
// Game state
|
||||||
|
this.balance = 1000;
|
||||||
|
this.bet = 10;
|
||||||
|
this.minesCount = 3;
|
||||||
|
this.isPlaying = false;
|
||||||
|
this.revealedCount = 0;
|
||||||
|
this.currentMultiplier = 1.0;
|
||||||
|
this.minePositions = [];
|
||||||
|
this.history = [];
|
||||||
|
|
||||||
|
// DOM Elements
|
||||||
|
this.elements = {
|
||||||
|
balance: document.getElementById('balance'),
|
||||||
|
betInput: document.getElementById('bet-amount'),
|
||||||
|
minesCount: document.getElementById('mines-count'),
|
||||||
|
minesSlider: document.getElementById('mines-slider'),
|
||||||
|
minesDecrease: document.getElementById('mines-decrease'),
|
||||||
|
minesIncrease: document.getElementById('mines-increase'),
|
||||||
|
tilesInfo: document.getElementById('tiles-info'),
|
||||||
|
safeTiles: document.getElementById('safe-tiles'),
|
||||||
|
nextMultiplier: document.getElementById('next-multiplier'),
|
||||||
|
currentMultiplier: document.getElementById('current-multiplier'),
|
||||||
|
potentialWin: document.getElementById('potential-win'),
|
||||||
|
startBtn: document.getElementById('start-btn'),
|
||||||
|
cashoutBtn: document.getElementById('cashout-btn'),
|
||||||
|
gameGrid: document.getElementById('game-grid'),
|
||||||
|
gridOverlay: document.getElementById('grid-overlay'),
|
||||||
|
overlayIcon: document.getElementById('overlay-icon'),
|
||||||
|
overlayText: document.getElementById('overlay-text'),
|
||||||
|
revealedCount: document.getElementById('revealed-count'),
|
||||||
|
totalSafe: document.getElementById('total-safe'),
|
||||||
|
historyList: document.getElementById('history-list'),
|
||||||
|
modal: document.getElementById('result-modal'),
|
||||||
|
modalContent: document.getElementById('modal-content'),
|
||||||
|
modalIcon: document.getElementById('modal-icon'),
|
||||||
|
modalTitle: document.getElementById('modal-title'),
|
||||||
|
modalAmount: document.getElementById('modal-amount'),
|
||||||
|
modalSubtitle: document.getElementById('modal-subtitle'),
|
||||||
|
modalClose: document.getElementById('modal-close')
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.updateGridCSS();
|
||||||
|
this.createGrid();
|
||||||
|
this.bindEvents();
|
||||||
|
this.updateUI();
|
||||||
|
this.showOverlay('💎', 'Place your bet and start!');
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGridCSS() {
|
||||||
|
document.documentElement.style.setProperty('--grid-size', this.gridSize);
|
||||||
|
this.elements.tilesInfo.textContent = `${this.totalTiles} (${this.gridSize}×${this.gridSize})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
createGrid() {
|
||||||
|
this.elements.gameGrid.innerHTML = '';
|
||||||
|
for (let i = 0; i < this.totalTiles; i++) {
|
||||||
|
const tile = document.createElement('div');
|
||||||
|
tile.className = 'tile disabled';
|
||||||
|
tile.dataset.index = i;
|
||||||
|
tile.innerHTML = '<span class="tile-icon"></span>';
|
||||||
|
this.elements.gameGrid.appendChild(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEvents() {
|
||||||
|
// Bet input
|
||||||
|
this.elements.betInput.addEventListener('input', (e) => {
|
||||||
|
this.bet = Math.max(1, parseFloat(e.target.value) || 1);
|
||||||
|
this.updateUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bet buttons (half/double)
|
||||||
|
document.querySelectorAll('.bet-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const action = btn.dataset.action;
|
||||||
|
if (action === 'half') {
|
||||||
|
this.bet = Math.max(1, Math.floor(this.bet / 2));
|
||||||
|
} else if (action === 'double') {
|
||||||
|
this.bet = Math.min(this.balance, this.bet * 2);
|
||||||
|
}
|
||||||
|
this.elements.betInput.value = this.bet;
|
||||||
|
this.updateUI();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mines selector
|
||||||
|
this.elements.minesDecrease.addEventListener('click', () => {
|
||||||
|
this.minesCount = Math.max(1, this.minesCount - 1);
|
||||||
|
this.elements.minesSlider.value = this.minesCount;
|
||||||
|
this.updateUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.elements.minesIncrease.addEventListener('click', () => {
|
||||||
|
this.minesCount = Math.min(this.totalTiles - 1, this.minesCount + 1);
|
||||||
|
this.elements.minesSlider.value = this.minesCount;
|
||||||
|
this.updateUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.elements.minesSlider.addEventListener('input', (e) => {
|
||||||
|
this.minesCount = parseInt(e.target.value);
|
||||||
|
this.updateUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update slider max based on grid size
|
||||||
|
this.elements.minesSlider.max = this.totalTiles - 1;
|
||||||
|
|
||||||
|
// Start button
|
||||||
|
this.elements.startBtn.addEventListener('click', () => this.startRound());
|
||||||
|
|
||||||
|
// Cashout button
|
||||||
|
this.elements.cashoutBtn.addEventListener('click', () => this.cashOut());
|
||||||
|
|
||||||
|
// Modal close
|
||||||
|
this.elements.modalClose.addEventListener('click', () => this.hideModal());
|
||||||
|
|
||||||
|
// Tile clicks
|
||||||
|
this.elements.gameGrid.addEventListener('click', (e) => {
|
||||||
|
const tile = e.target.closest('.tile');
|
||||||
|
if (tile && this.isPlaying && !tile.classList.contains('revealed') && !tile.classList.contains('disabled')) {
|
||||||
|
this.revealTile(parseInt(tile.dataset.index));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate multiplier based on mines count and revealed tiles
|
||||||
|
* Formula: Each safe reveal increases multiplier based on probability
|
||||||
|
* The fewer safe tiles remaining, the higher the reward
|
||||||
|
*/
|
||||||
|
calculateMultiplier(revealed) {
|
||||||
|
if (revealed === 0) return 1.0;
|
||||||
|
|
||||||
|
const safeTiles = this.totalTiles - this.minesCount;
|
||||||
|
let multiplier = 1.0;
|
||||||
|
|
||||||
|
// House edge (around 3%)
|
||||||
|
const houseEdge = 0.97;
|
||||||
|
|
||||||
|
for (let i = 0; i < revealed; i++) {
|
||||||
|
const remainingTiles = this.totalTiles - i;
|
||||||
|
const remainingSafe = safeTiles - i;
|
||||||
|
// Fair odds * house edge
|
||||||
|
const stepMultiplier = (remainingTiles / remainingSafe) * houseEdge;
|
||||||
|
multiplier *= stepMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.round(multiplier * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNextMultiplier() {
|
||||||
|
return this.calculateMultiplier(this.revealedCount + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUI() {
|
||||||
|
// Update mines count display
|
||||||
|
this.elements.minesCount.textContent = this.minesCount;
|
||||||
|
|
||||||
|
// Update safe tiles count
|
||||||
|
const safeTiles = this.totalTiles - this.minesCount;
|
||||||
|
this.elements.safeTiles.textContent = safeTiles;
|
||||||
|
this.elements.totalSafe.textContent = safeTiles;
|
||||||
|
|
||||||
|
// Update multipliers
|
||||||
|
this.elements.currentMultiplier.textContent = `×${this.currentMultiplier.toFixed(2)}`;
|
||||||
|
this.elements.nextMultiplier.textContent = `×${this.getNextMultiplier().toFixed(2)}`;
|
||||||
|
|
||||||
|
// Update potential win
|
||||||
|
const potentialWin = this.bet * this.currentMultiplier;
|
||||||
|
this.elements.potentialWin.textContent = this.formatCurrency(potentialWin);
|
||||||
|
|
||||||
|
// Update revealed count
|
||||||
|
this.elements.revealedCount.textContent = this.revealedCount;
|
||||||
|
|
||||||
|
// Update balance
|
||||||
|
this.elements.balance.textContent = this.formatCurrency(this.balance);
|
||||||
|
|
||||||
|
// Update start button state
|
||||||
|
this.elements.startBtn.disabled = this.bet > this.balance || this.bet <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatCurrency(amount) {
|
||||||
|
return '$' + amount.toLocaleString('en-US', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
showOverlay(icon, text) {
|
||||||
|
this.elements.overlayIcon.textContent = icon;
|
||||||
|
this.elements.overlayText.textContent = text;
|
||||||
|
this.elements.gridOverlay.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
hideOverlay() {
|
||||||
|
this.elements.gridOverlay.classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
generateMinePositions() {
|
||||||
|
const positions = [];
|
||||||
|
while (positions.length < this.minesCount) {
|
||||||
|
const pos = Math.floor(Math.random() * this.totalTiles);
|
||||||
|
if (!positions.includes(pos)) {
|
||||||
|
positions.push(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
startRound() {
|
||||||
|
if (this.bet > this.balance) return;
|
||||||
|
|
||||||
|
// Deduct bet from balance
|
||||||
|
this.balance -= this.bet;
|
||||||
|
|
||||||
|
// Reset game state
|
||||||
|
this.isPlaying = true;
|
||||||
|
this.revealedCount = 0;
|
||||||
|
this.currentMultiplier = 1.0;
|
||||||
|
this.minePositions = this.generateMinePositions();
|
||||||
|
|
||||||
|
// Update UI
|
||||||
|
this.hideOverlay();
|
||||||
|
this.elements.startBtn.classList.add('hidden');
|
||||||
|
this.elements.cashoutBtn.classList.remove('hidden');
|
||||||
|
|
||||||
|
// Reset all tiles
|
||||||
|
document.querySelectorAll('.tile').forEach(tile => {
|
||||||
|
tile.className = 'tile';
|
||||||
|
tile.querySelector('.tile-icon').textContent = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable bet controls during game
|
||||||
|
this.elements.betInput.disabled = true;
|
||||||
|
this.elements.minesSlider.disabled = true;
|
||||||
|
this.elements.minesDecrease.disabled = true;
|
||||||
|
this.elements.minesIncrease.disabled = true;
|
||||||
|
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
revealTile(index) {
|
||||||
|
const tile = document.querySelectorAll('.tile')[index];
|
||||||
|
const icon = tile.querySelector('.tile-icon');
|
||||||
|
|
||||||
|
if (this.minePositions.includes(index)) {
|
||||||
|
// Hit a mine - GAME OVER
|
||||||
|
tile.classList.add('revealed', 'mine');
|
||||||
|
icon.textContent = '💣';
|
||||||
|
this.endRound(false);
|
||||||
|
} else {
|
||||||
|
// Safe tile
|
||||||
|
tile.classList.add('revealed', 'safe');
|
||||||
|
icon.textContent = '💎';
|
||||||
|
this.revealedCount++;
|
||||||
|
this.currentMultiplier = this.calculateMultiplier(this.revealedCount);
|
||||||
|
this.updateUI();
|
||||||
|
|
||||||
|
// Check if all safe tiles are revealed
|
||||||
|
const safeTiles = this.totalTiles - this.minesCount;
|
||||||
|
if (this.revealedCount >= safeTiles) {
|
||||||
|
this.cashOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cashOut() {
|
||||||
|
if (!this.isPlaying) return;
|
||||||
|
|
||||||
|
const winnings = this.bet * this.currentMultiplier;
|
||||||
|
this.balance += winnings;
|
||||||
|
this.endRound(true, winnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
endRound(isWin, winnings = 0) {
|
||||||
|
this.isPlaying = false;
|
||||||
|
|
||||||
|
// Reveal all mines
|
||||||
|
this.minePositions.forEach(pos => {
|
||||||
|
const tile = document.querySelectorAll('.tile')[pos];
|
||||||
|
if (!tile.classList.contains('revealed')) {
|
||||||
|
tile.classList.add('show-mine');
|
||||||
|
tile.querySelector('.tile-icon').textContent = '💣';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable all tiles
|
||||||
|
document.querySelectorAll('.tile').forEach(tile => {
|
||||||
|
tile.classList.add('disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-enable controls
|
||||||
|
this.elements.betInput.disabled = false;
|
||||||
|
this.elements.minesSlider.disabled = false;
|
||||||
|
this.elements.minesDecrease.disabled = false;
|
||||||
|
this.elements.minesIncrease.disabled = false;
|
||||||
|
|
||||||
|
// Update buttons
|
||||||
|
this.elements.cashoutBtn.classList.add('hidden');
|
||||||
|
this.elements.startBtn.classList.remove('hidden');
|
||||||
|
|
||||||
|
// Add to history
|
||||||
|
this.addToHistory(isWin, winnings);
|
||||||
|
|
||||||
|
// Show result modal
|
||||||
|
this.showResultModal(isWin, winnings);
|
||||||
|
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
showResultModal(isWin, winnings) {
|
||||||
|
this.elements.modalContent.className = 'modal-content ' + (isWin ? 'win' : 'loss');
|
||||||
|
|
||||||
|
if (isWin) {
|
||||||
|
this.elements.modalIcon.textContent = '💎';
|
||||||
|
this.elements.modalTitle.textContent = 'You Won!';
|
||||||
|
this.elements.modalAmount.textContent = '+' + this.formatCurrency(winnings);
|
||||||
|
this.elements.modalSubtitle.textContent = `×${this.currentMultiplier.toFixed(2)} multiplier • ${this.revealedCount} tiles revealed`;
|
||||||
|
} else {
|
||||||
|
this.elements.modalIcon.textContent = '💣';
|
||||||
|
this.elements.modalTitle.textContent = 'Mine Hit!';
|
||||||
|
this.elements.modalAmount.textContent = '-' + this.formatCurrency(this.bet);
|
||||||
|
this.elements.modalSubtitle.textContent = `${this.revealedCount} tiles revealed before explosion`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.elements.modal.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
hideModal() {
|
||||||
|
this.elements.modal.classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
addToHistory(isWin, winnings) {
|
||||||
|
const historyItem = {
|
||||||
|
isWin,
|
||||||
|
bet: this.bet,
|
||||||
|
winnings: isWin ? winnings : -this.bet,
|
||||||
|
multiplier: this.currentMultiplier,
|
||||||
|
mines: this.minesCount,
|
||||||
|
revealed: this.revealedCount
|
||||||
|
};
|
||||||
|
|
||||||
|
this.history.unshift(historyItem);
|
||||||
|
if (this.history.length > 20) this.history.pop();
|
||||||
|
|
||||||
|
this.renderHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHistory() {
|
||||||
|
if (this.history.length === 0) {
|
||||||
|
this.elements.historyList.innerHTML = '<div class="history-empty">No rounds played yet</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.elements.historyList.innerHTML = this.history.map(item => `
|
||||||
|
<div class="history-item ${item.isWin ? 'win' : 'loss'}">
|
||||||
|
<div class="history-bet">Bet: ${this.formatCurrency(item.bet)}</div>
|
||||||
|
<div class="history-result">${item.isWin ? '+' : ''}${this.formatCurrency(item.winnings)}</div>
|
||||||
|
<div class="history-details">×${item.multiplier.toFixed(2)} • ${item.mines} mines • ${item.revealed} revealed</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize game when DOM is loaded
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// You can change grid size here: 5, 6, 7, etc.
|
||||||
|
window.minesGame = new MinesGame({ gridSize: 5 });
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user