X O - Curated Themes
Game History
Recent Games
```### **2. `style.css` (External CSS)**All CSS rules have been moved to this external file. There is limited room for reduction here without changing the design, as the styles are complex and handle many different themes and states. However, moving it to a separate file makes the HTML much cleaner.```css
/* CSS Variables for Theming */
:root {
--bg-light: #FFF9E8;
--grid-line-color: #77ddc7;
--accent-x: #ffb7c5;
--accent-o: #87ceeb;
--highlighter: #ffd1a4;
--text-color: #5D4037;
--shadow-color: #5D4037;
--cell-bg: rgba(255, 249, 232, 0.8);
--input-bg: #fff;
--line-thickness: 8px;
--font-title: 'Fredoka One', cursive;
--font-body: 'Nunito', sans-serif;
--slider-primary-color: #ffd1a4;
--text-color-soft: #a1887f;
--ui-element-bg: rgba(93, 64, 55, 0.05);
--ui-element-border: rgba(93, 64, 55, 0.1);
}/* --- Themes --- */
body.theme-ocean {
--bg-light: #d8eefe; --grid-line-color: #3b8ea5; --accent-x: #f59e6c;
--accent-o: #46b9a8; --highlighter: #f9d48b; --text-color: #0b3954;
--shadow-color: #0b3954; --cell-bg: rgba(216, 238, 254, 0.8);
}
body.theme-sunset {
--bg-light: #fbe6e8; --grid-line-color: #ff8a8a; --accent-x: #8a79a9;
--accent-o: #ffc482; --highlighter: #f7b2ad; --text-color: #4a4063;
--shadow-color: #4a4063; --cell-bg: rgba(251, 230, 232, 0.8);
}
body.theme-wood {
--bg-light: #EAE0D5; --grid-line-color: #5E3023; --accent-x: #A98743;
--accent-o: #659B5E; --highlighter: #C6AC8F; --text-color: #3C2A21;
--shadow-color: #3C2A21; --cell-bg: rgba(234, 224, 213, 0.8);
}
body.theme-marbles {
--bg-light: #F0F0F0; --grid-line-color: #4A4A4A; --accent-x: #3498DB;
--accent-o: #E74C3C; --highlighter: #F1C40F; --text-color: #2C3E50;
--shadow-color: #2C3E50; --cell-bg: rgba(240, 240, 240, 0.8);
}
body.theme-moonlight,
body.theme-volcano,
body.theme-galaxy {
--shadow-color: transparent; --input-bg: #2c3e50; --text-color-soft: #b0c4de;
--ui-element-bg: rgba(237, 242, 244, 0.1); --ui-element-border: rgba(237, 242, 244, 0.2);
}
body.theme-moonlight {
--bg-light: #0e1a2b; --grid-line-color: #8d99ae; --accent-x: #ade8f4;
--accent-o: #edf2f4; --highlighter: #48cae4; --text-color: #ffffff;
--cell-bg: rgba(14, 26, 43, 0.8);
}
body.theme-volcano {
--bg-light: #1C1C1C; --grid-line-color: #FF4500; --accent-x: #FFD700;
--accent-o: #B22222; --highlighter: #FFA500; --text-color: #FFFFFF;
--cell-bg: rgba(28, 28, 28, 0.8); --input-bg: #333333;
}
body.theme-galaxy {
--bg-light: #000020; --grid-line-color: #9A4FE8; --accent-x: #00FFFF;
--accent-o: #FF00FF; --highlighter: #FFFFFF; --text-color: #FFFFFF;
--cell-bg: rgba(0, 0, 32, 0.8); --input-bg: #101030;
}/* --- Generic Dark Mode --- */
body.dark-mode {
--bg-light: #1a1a2e; --highlighter: #ffc107; --text-color: #e0e0e0;
--shadow-color: #e0e0e0; --cell-bg: rgba(40, 42, 60, 0.8);
--input-bg: #2f2f4e; --text-color-soft: #9a9ab0;
--ui-element-bg: rgba(224, 224, 224, 0.1); --ui-element-border: rgba(224, 224, 224, 0.2);
}
body.dark-mode.theme-ocean { --grid-line-color: #5c9eaf; }
body.dark-mode.theme-sunset { --grid-line-color: #f7b2ad; }
body.dark-mode.theme-wood { --grid-line-color: #C6AC8F; }
body.dark-mode.theme-marbles { --grid-line-color: #aaaaaa; }/* --- General Styles --- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { height: 100%; }
body {
background-color: var(--bg-light);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: var(--font-body);
color: var(--text-color);
padding: 15px;
user-select: none;
overflow-y: auto;
transition: background-color: 0.4s ease, color: 0.4s ease;
}
main {
width: 100%;
max-width: 900px;
display: flex;
justify-content: center;
align-items: center;
z-index: 2;
padding: 20px 0;
}/* --- UI Controls --- */
.theme-controls-left, .theme-controls-right, .board-size-controls, .exit-control { position: fixed; z-index: 100; }
.theme-controls-left { top: 20px; left: 20px; }
.theme-controls-right { top: 20px; right: 20px; }
.board-size-controls { bottom: 20px; left: 20px; }
.exit-control { bottom: 20px; right: 20px; }.theme-button {
width: 50px;
height: 50px;
background-color: var(--ui-element-bg);
border: 2px solid var(--ui-element-border);
border-radius: 50%;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease;
font-size: 1.5rem;
}
.theme-button:disabled { cursor: not-allowed; opacity: 0.5; }
.theme-button:hover:not(:disabled) { transform: scale(1.1); }
#theme-toggle-button svg {
width: 24px;
height: 24px;
position: absolute;
transition: all 0.4s ease;
color: var(--highlighter);
}
#theme-toggle-button .sun-icon { opacity: 1; transform: scale(1) rotate(0deg); }
#theme-toggle-button .moon-icon { opacity: 0; transform: scale(0) rotate(-90deg); }
body.dark-mode:not(.theme-moonlight):not(.theme-volcano):not(.theme-galaxy) #theme-toggle-button .sun-icon,
body.theme-moonlight #theme-toggle-button .sun-icon,
body.theme-volcano #theme-toggle-button .sun-icon,
body.theme-galaxy #theme-toggle-button .sun-icon {
opacity: 0;
transform: scale(0) rotate(90deg);
}
body.dark-mode:not(.theme-moonlight):not(.theme-volcano):not(.theme-galaxy) #theme-toggle-button .moon-icon,
body.theme-moonlight #theme-toggle-button .moon-icon,
body.theme-volcano #theme-toggle-button .moon-icon,
body.theme-galaxy #theme-toggle-button .moon-icon {
opacity: 1;
transform: scale(1) rotate(0deg);
}/* --- Background Animations --- */
#background-animations { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; }
.sticker { position: absolute; bottom: -150px; display: block; animation: floatUp 10s linear infinite; }
.sticker svg { width: 100%; height: 100%; display: block; filter: drop-shadow(4px 4px 6px rgba(0, 0, 0, 0.1)); }
@keyframes floatUp {
0% { transform: translateY(0) rotate(0deg); opacity: 1; }
100% { transform: translateY(-120vh) rotate(360deg); opacity: 0; }
}/* --- Page Management --- */
.page { display: none; flex-direction: column; align-items: center; text-align: center; width: 100%; }
.page.active { display: flex; }/* --- Start Page & Logo Styles --- */
#start-page, #intro-page { gap: 20px; }
.game-title {
font-family: 'Style Script', cursive;
font-size: clamp(6rem, 25vmin, 9.5rem);
font-weight: 400;
color: var(--text-color);
text-shadow: 0 0 10px var(--accent-x), 0 0 25px var(--accent-o);
transition: all 0.4s ease;
animation: logo-fade-in 1.5s ease-out 0.5s forwards;
opacity: 0;
}
@keyframes logo-fade-in {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}/* --- Menu & Button Styles --- */
.start-options { display: flex; flex-direction: column; align-items: center; width: 100%; gap: 15px; }
.start-button {
font-family: var(--font-body);
font-weight: 700;
font-size: clamp(1rem, 4vmin, 1.25rem);
padding: 15px 30px;
border: 3px solid var(--shadow-color);
background: var(--highlighter);
color: var(--text-color);
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
max-width: 380px;
border-radius: 50px;
box-shadow: 0 4px 0 0 var(--shadow-color);
}
.start-button:hover { transform: translateY(2px); box-shadow: 0 2px 0 0 var(--shadow-color); }
body.dark-mode .start-button,
body.theme-moonlight .start-button,
body.theme-volcano .start-button,
body.theme-galaxy .start-button { color: #0e1a2b; }.rule-options-container {
width: 100%;
max-width: 380px;
border: 3px solid var(--highlighter);
border-radius: 20px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 15px;
box-shadow: 0 0 15px -5px var(--highlighter);
}.board-size-controls, .exit-control { display: none; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
body.on-start-page .board-size-controls, body.on-start-page .exit-control { display: block; opacity: 1; pointer-events: auto; }
#toggle-board-size-options { font-size: 1rem; font-family: var(--font-title); }
#exit-button svg { width: 24px; height: 24px; color: var(--text-color); }
.board-size-controls .sub-options-container { position: absolute; bottom: 110%; left: 0; width: 240px; background-color: var(--cell-bg); border: 2px solid var(--ui-element-border); border-radius: 15px; padding: 10px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); }
#go-to-history-button { padding: 12px 25px; font-size: clamp(0.9rem, 3.5vmin, 1.15rem); max-width: 240px; align-self: center; }.sub-options-container { display: none; width: 100%; max-width: 380px; text-align: center; flex-direction: column; align-items: center; gap: 15px; margin-top: 10px; transition: all 0.3s ease; }
.sub-options-container.show { display: flex; }
.sub-options-container .start-button, .difficulty-container .start-button { background-color: var(--cell-bg); border-color: var(--text-color); }
.sub-options-container .start-button:hover, .difficulty-container .start-button:hover { opacity: 0.8; }body.dark-mode .sub-options-container .start-button,
body.dark-mode .difficulty-container .start-button:not(.play-bot-button),
body.theme-moonlight .sub-options-container .start-button,
body.theme-moonlight .difficulty-container .start-button:not(.play-bot-button),
body.theme-volcano .sub-options-container .start-button,
body.theme-volcano .difficulty-container .start-button:not(.play-bot-button),
body.theme-galaxy .sub-options-container .start-button,
body.theme-galaxy .difficulty-container .start-button:not(.play-bot-button) {
background-color: var(--ui-element-bg); border-color: var(--grid-line-color); color: var(--grid-line-color); box-shadow: none;
}
body.dark-mode .sub-options-container .start-button:hover,
body.dark-mode .difficulty-container .start-button:not(.play-bot-button):hover,
body.theme-moonlight .sub-options-container .start-button:hover,
body.theme-moonlight .difficulty-container .start-button:not(.play-bot-button):hover,
body.theme-volcano .sub-options-container .start-button:hover,
body.theme-volcano .difficulty-container .start-button:not(.play-bot-button):hover,
body.theme-galaxy .sub-options-container .start-button:hover,
body.theme-galaxy .difficulty-container .start-button:not(.play-bot-button):hover {
background-color: var(--grid-line-color); color: var(--bg-light); opacity: 1;
}.start-button.active-option {
background-color: var(--grid-line-color) !important;
color: var(--bg-light) !important;
opacity: 1 !important;
transform: translateY(2px);
box-shadow: 0 2px 0 0 var(--shadow-color) !important;
}body.dark-mode .play-bot-button,
body.theme-moonlight .play-bot-button,
body.theme-volcano .play-bot-button,
body.theme-galaxy .play-bot-button { background-color: var(--highlighter); border-color: var(--highlighter); color: var(--bg-light); }
body.dark-mode .play-bot-button:hover,
body.theme-moonlight .play-bot-button:hover,
body.theme-volcano .play-bot-button:hover,
body.theme-galaxy .play-bot-button:hover { background-color: var(--accent-x); border-color: var(--accent-x); }.board-size-options { flex-direction: row; gap: 10px; margin-top: 0; }
.board-size-options .start-button { font-size: 0.9rem; padding: 10px 0; width: 100%; }
.player-name-input {
font-family: var(--font-body);
font-weight: 700;
font-size: clamp(1rem, 4vmin, 1.25rem);
padding: 12px 20px;
width: 100%;
max-width: 380px;
background-color: var(--input-bg);
border: 3px solid var(--ui-element-border);
color: var(--text-color);
text-align: center;
margin-bottom: 5px;
border-radius: 50px;
transition: all 0.4s ease;
}
.player-name-input:focus { outline: none; border-color: var(--grid-line-color); }
.player-name-input.player-o-input { margin-bottom: 10px; }
.player-name-input::placeholder { color: var(--text-color); opacity: 0.6; font-weight: 400; }/* --- Difficulty Slider --- */
.difficulty-container {
display: none;
width: 100%;
max-width: 380px;
text-align: center;
flex-direction: column;
align-items: center;
gap: 15px;
margin-top: 10px;
padding: 25px;
background: var(--cell-bg);
border-radius: 30px;
border: 3px solid var(--slider-primary-color);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
transition: all 0.4s ease;
}
.difficulty-container.show { display: flex; }
.difficulty-label { font-family: var(--font-title); font-size: 2.5rem; color: var(--slider-primary-color); text-shadow: none; transition: color 0.5s ease; }
.slider-container { width: 85%; }
.slider-container p { color: var(--text-color-soft); margin-top: 10px; font-size: 0.9rem; }
input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 20px; background: var(--ui-element-bg); border-radius: 20px; cursor: pointer; outline: none; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 40px; height: 40px; background: var(--highlighter); border-radius: 50%; border: 4px solid var(--slider-primary-color); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); transition: all 0.4s ease; }
.play-bot-button { background-color: var(--slider-primary-color); border-color: var(--shadow-color); }/* --- Game Page Styles --- */
#game-page { container-type: inline-size; }
.game-wrapper { width: 100%; max-width: min(80vh, 80svh); display: flex; flex-direction: column; gap: 15px; }
.game-header { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; width: 100%; }
.game-screen-logo { font-family: 'Style Script', cursive; font-size: clamp(3.5rem, 18cqi, 5rem); font-weight: 400; color: var(--text-color); text-shadow: 0 0 5px var(--accent-x), 0 0 15px var(--accent-o); line-height: 1; }
.turn-indicator { font-family: var(--font-title); font-size: clamp(1.2rem, 6cqi, 1.8rem); display: flex; justify-content: center; align-items: center; gap: 12px; height: 3rem; }
.turn-indicator .turn-icon { font-size: clamp(1.5rem, 7.5cqi, 2rem); }
.back-button, .restart-button { font-size: clamp(1.8rem, 10cqi, 2.5rem); cursor: pointer; transition: all 0.2s ease-in-out; padding: 10px; background: none; border: none; color: var(--text-color); }
.back-button:hover, .restart-button:hover { transform: scale(1.1); }
.board { display: grid; grid-template-columns: repeat(var(--board-size, 3), 1fr); grid-template-rows: repeat(var(--board-size, 3), 1fr); width: 100%; aspect-ratio: 1 / 1; position: relative; gap: var(--line-thickness); background-color: var(--grid-line-color); border-radius: 30px; overflow: hidden; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); transition: background-color 0.4s ease; }
.board.locked { pointer-events: none; }
#winning-line-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.cell { cursor: pointer; display: flex; justify-content: center; align-items: center; position: relative; background-color: var(--cell-bg); transition: background-color 0.4s ease; }
.cell .symbol { font-family: var(--font-title); font-size: var(--symbol-size); font-weight: normal; line-height: 1; animation: symbol-glow-in 0.5s ease-out; transition: all 0.3s ease-out; text-shadow: 4px 4px 0px rgba(93, 64, 55, 0.15); }
body.dark-mode .cell .symbol, body.theme-moonlight .cell .symbol, body.theme-volcano .cell .symbol, body.theme-galaxy .cell .symbol { text-shadow: none; }
body.theme-galaxy .cell.x .symbol, body.theme-galaxy .cell.o .symbol { text-shadow: 0 0 10px currentColor; }
.cell.x .symbol { color: var(--accent-x); }
.cell.o .symbol { color: var(--accent-o); }
.cell.is-fading .symbol { opacity: 0.3; text-shadow: none; }/* --- Winning Line Styles --- */
.winning-line { position: absolute; height: clamp(8px, 3.25cqi, 18px); background-color: var(--highlighter); border-radius: 20px; border: 4px solid var(--shadow-color); z-index: 10; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); transform-origin: center; animation: draw-line 0.7s ease-out forwards; }
.board[style*="--board-size: 6;"] .winning-line, .board[style*="--board-size: 9;"] .winning-line, .board[style*="--board-size: 11;"] .winning-line { height: clamp(6px, 1.8cqi, 12px); border-width: 3px; }
body.theme-moonlight .winning-line, body.theme-volcano .winning-line, body.theme-galaxy .winning-line { border-width: 2px; box-shadow: 0 0 10px var(--highlighter); }
@keyframes draw-line {
from { width: 0; }
to { width: var(--width); }
}/* --- Scoreboard & Footer --- */
.score-footer { display: grid; grid-template-columns: 1fr 1fr; width: 100%; margin-top: 20px; border: 4px solid var(--grid-line-color); border-radius: 20px; overflow: hidden; transition: border-color: 0.4s ease; }
.score-box { text-align: center; padding: 8px 12px; }
#player-x-score-box { border-right: 4px solid var(--grid-line-color); transition: border-color 0.4s ease; }
.score-box .label { font-size: clamp(0.8rem, 4cqi, 1.1rem); font-weight: 700; }
.score-box .score { font-family: var(--font-title); font-size: clamp(1.8rem, 7cqi, 2.5rem); font-weight: normal; }
#player-x-score-box .score { color: var(--accent-x); }
#player-o-score-box .score { color: var(--accent-o); }/* --- Themes & History Pages --- */
#themes-page, #history-page, #recent-games-page { gap: 20px; }
.page-title { font-family: var(--font-title); font-size: clamp(2.5rem, 10vmin, 3.5rem); color: var(--grid-line-color); }
.themes-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 15px; width: 100%; }
.theme-preview-button { background-color: var(--cell-bg); border: 3px solid var(--ui-element-border); border-radius: 20px; padding: 15px; cursor: pointer; transition: all 0.2s ease; text-align: center; }
.theme-preview-button:hover { transform: translateY(-5px); box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1); }
.theme-preview-button.active { border-color: var(--highlighter); box-shadow: 0 0 0 3px var(--highlighter); }
.theme-preview-button * { pointer-events: none; }
.theme-name { font-weight: 700; margin-bottom: 10px; font-size: 1.1rem; color: var(--text-color); }
.color-swatches { display: flex; justify-content: center; gap: 5px; }
.swatch { width: 25px; height: 25px; border-radius: 50%; border: 2px solid rgba(0, 0, 0, 0.1); }/* --- History Page --- */
.history-board-size-section { width: 100%; margin-bottom: 30px; }
.history-board-size-section > h1 { font-family: var(--font-title); font-size: 2.2rem; color: var(--highlighter); margin-bottom: 15px; padding-bottom: 10px; border-bottom: 4px solid var(--ui-element-border); }
.history-grid-container { width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 20px; }
.history-section h2 { font-size: 1.8rem; margin-bottom: 10px; color: var(--text-color-soft); }
.history-stats-container { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }
.history-column { background-color: var(--cell-bg); padding: 15px; border-radius: 20px; border: 3px solid var(--ui-element-border); display: flex; flex-direction: column; gap: 10px; }
.history-column > h3 { font-family: var(--font-title); font-size: 1.3rem; color: var(--grid-line-color); border-bottom: 3px solid var(--ui-element-border); padding-bottom: 8px; margin-bottom: 5px; white-space: nowrap; }
.player-stats-container { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 100%; }
.player-stat-box h4 { font-family: var(--font-title); font-size: 2.2rem; margin-bottom: 8px; }
.player-stat-box h4.player-x { color: var(--accent-x); }
.player-stat-box h4.player-o { color: var(--accent-o); }
.stat-line { display: flex; justify-content: space-between; font-size: 1rem; margin-bottom: 5px; }
.stat-line .value { font-weight: 700; }
.draw-stat-line { text-align: center; margin-top: 10px; padding-top: 10px; border-top: 3px solid var(--ui-element-border); grid-column: 1 / -1; }
.history-buttons { display: flex; flex-direction: column; gap: 15px; width: 100%; max-width: 380px; margin-top: 10px; }
#clear-history-button { background-color: var(--accent-x); }/* --- Recent Games Page --- */
#recent-games-page { max-width: 600px; }
.recent-games-list { list-style: none; width: 100%; display: flex; flex-direction: column; gap: 12px; }
.recent-games-list li { background-color: var(--cell-bg); padding: 15px; border-radius: 15px; border: 3px solid var(--ui-element-border); text-align: left; }
.log-result { font-weight: 700; font-size: 1.1rem; margin-bottom: 5px; }
.log-details { font-size: 0.9rem; color: var(--text-color-soft); }/* --- Animations & Responsive --- */
@keyframes symbol-glow-in { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(1); } }@media (max-width: 480px) {
body { padding: 10px; }
.theme-controls-left { top: 10px; left: 10px; }
.theme-controls-right { top: 10px; right: 10px; }
.board-size-controls { bottom: 10px; left: 10px; }
.exit-control { bottom: 10px; right: 10px; }
.game-title { font-size: clamp(4.5rem, 25vmin, 9.5rem); }
.start-button { padding: 12px 20px; }
.rule-options-container { padding: 15px; }
.themes-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.history-grid-container { grid-template-columns: 1fr; }
.game-wrapper { gap: 10px; }
.score-footer { margin-top: 10px; }
}
@media (max-height: 500px) and (orientation: landscape) {
#start-page, #intro-page { gap: 10px; }
.game-title { font-size: clamp(3rem, 25vh, 5rem); }
main { padding: 10px 0; }
}