<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LexiCold - Daily Word Hacker</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&family=Inter:wght@400;600;800&display=swap');
:root {
--bg: #050505;
--glass-bg: rgba(20, 20, 20, 0.75);
--border: rgba(255, 255, 255, 0.1);
--neon-green: #99d160;
--neon-blue: #4db8ff;
--hot: #e74c3c;
--warm: #f39c12;
--cold: #3498db;
--text: #eee;
--font-mono: 'JetBrains Mono', monospace;
--font-sans: 'Inter', sans-serif;
}
body, html { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: var(--font-sans); height: 100%; overflow-x: hidden; }
.game-wrapper {
display: grid; grid-template-columns: 1fr 350px; gap: 20px;
max-width: 1200px; margin: 40px auto; padding: 0 20px;
}
.glass-panel {
background: var(--glass-bg); backdrop-filter: blur(15px); border: 1px solid var(--border);
border-radius: 16px; padding: 25px; box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
h1 { font-family: var(--font-mono); font-size: 2rem; color: #fff; margin: 0 0 5px 0; text-shadow: 0 0 10px rgba(153, 209, 96, 0.4); }
.sub-text { color: #888; font-size: 0.95rem; margin: 0 0 20px 0; }
/* Game UI */
.hud { display: flex; justify-content: space-between; font-family: var(--font-mono); color: var(--neon-green); margin-bottom: 20px; padding: 10px; background: rgba(0,0,0,0.4); border-radius: 8px; border: 1px solid var(--border); }
.input-group { display: flex; gap: 10px; margin-bottom: 20px; }
.input-group input { flex: 1; background: rgba(0,0,0,0.6); border: 2px solid var(--border); color: #fff; padding: 15px; border-radius: 10px; font-size: 1.2rem; font-family: var(--font-mono); text-transform: uppercase; outline: none; transition: 0.2s;}
.input-group input:focus { border-color: var(--neon-blue); box-shadow: 0 0 15px rgba(77, 184, 255, 0.2); }
.btn { background: var(--neon-green); color: #000; font-weight: 800; border: none; padding: 0 25px; border-radius: 10px; cursor: pointer; transition: 0.2s; font-family: var(--font-sans); text-transform: uppercase; }
.btn:hover { filter: brightness(1.1); transform: translateY(-2px); }
.btn:active { transform: scale(0.95); }
.btn-hint { background: transparent; border: 1px solid var(--warm); color: var(--warm); padding: 10px 15px; border-radius: 8px; cursor: pointer; font-weight: bold; margin-bottom: 20px; width: 100%; transition: 0.2s;}
.btn-hint:hover { background: rgba(243, 156, 18, 0.1); }
/* Guesses History */
.guess-log { display: flex; flex-direction: column; gap: 8px; max-height: 400px; overflow-y: auto; padding-right: 10px; }
.guess-log::-webkit-scrollbar { width: 5px; }
.guess-log::-webkit-scrollbar-thumb { background: #444; border-radius: 5px; }
.guess-row { display: flex; justify-content: space-between; align-items: center; padding: 12px 15px; background: rgba(0,0,0,0.3); border: 1px solid var(--border); border-radius: 8px; font-family: var(--font-mono); font-weight: bold; animation: popIn 0.3s ease forwards;}
.g-word { font-size: 1.1rem; color: #fff; text-transform: uppercase; }
.g-dir { color: #888; font-size: 0.8rem; }
.g-temp { padding: 4px 10px; border-radius: 6px; font-size: 0.8rem; }
.temp-hot { background: rgba(231, 76, 60, 0.2); color: var(--hot); border: 1px solid var(--hot); }
.temp-warm { background: rgba(243, 156, 18, 0.2); color: var(--warm); border: 1px solid var(--warm); }
.temp-cold { background: rgba(52, 152, 219, 0.2); color: var(--cold); border: 1px solid var(--cold); }
/* Leaderboard */
.leaderboard h2 { font-family: var(--font-mono); font-size: 1.2rem; border-bottom: 1px dashed var(--border); padding-bottom: 10px; margin-top: 0; color: var(--neon-blue); }
.lb-row { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,0.05); font-size: 0.9rem; }
.lb-user { font-weight: bold; }
.lb-score { font-family: var(--font-mono); color: var(--neon-green); }
.modal-overlay { display: none; position: fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.9); z-index: 100; justify-content:center; align-items:center; }
.modal { background: var(--glass-bg); border: 1px solid var(--neon-green); padding: 40px; border-radius: 16px; text-align: center; max-width: 400px; box-shadow: 0 0 40px rgba(153,209,96,0.3); }
@keyframes popIn { 0% { transform: scale(0.9); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
@media (max-width: 900px) {
.game-wrapper { grid-template-columns: 1fr; padding: 10px; margin: 10px auto;}
.glass-panel { padding: 20px; }
.input-group { flex-direction: column; }
.btn { padding: 15px; }
}
</style>
</head>
<body>
<div class="game-wrapper">
<!-- Main Game Area -->
<div class="glass-panel">
<h1>LexiCold [Daily]</h1>
<p class="sub-text">Guess the 5-letter word. The dictionary is alphabetical. We'll tell you if your guess is "Before" or "After" the target word, and how close you are!</p>
<div class="hud">
<div>Score: <span id="scoreDisplay">10000</span></div>
<div>Guesses: <span id="guessCount">0</span></div>
<div>Time: <span id="timerDisplay">0s</span></div>
</div>
<button id="hintBtn" class="btn-hint" onclick="useHint()">Cost: 500 Pts - Reveal a letter hint</button>
<div id="hintDisplay" style="color:var(--warm); font-weight:bold; text-align:center; margin-bottom:15px; font-family:var(--font-mono); letter-spacing:3px;"></div>
<form id="guessForm" class="input-group" onsubmit="handleGuess(event)">
<input type="text" id="guessInput" maxlength="5" minlength="5" placeholder="Enter 5 letter word..." required autocomplete="off" autofocus>
<button type="submit" class="btn">HACK</button>
</form>
<div class="guess-log" id="guessLog">
<!-- Guesses inject here -->
</div>
</div>
<!-- Leaderboard Area -->
<div class="glass-panel leaderboard">
<h2><span style="opacity:0.5;">///</span> DAILY LEADERBOARD</h2>
<div id="lbContainer">
<div style="text-align:center; color:#888; padding: 20px 0;">Loading network data...</div>
</div>
</div>
</div>
<!-- Victory Modal -->
<div class="modal-overlay" id="victoryModal">
<div class="modal">
<h1 style="color:var(--neon-green); margin-bottom:10px;">MAINFRAME HACKED</h1>
<p style="color:#ccc; font-size:1.1rem;">You found the daily word: <strong id="v-word" style="color:#fff;">WORD</strong></p>
<div style="font-family:var(--font-mono); font-size:1.5rem; color:var(--neon-green); margin: 20px 0;">Score: <span id="v-score">0</span></div>
<p style="font-size:0.85rem; color:#888;">Time: <span id="v-time">0</span>s | Guesses: <span id="v-guesses">0</span></p>
<div id="save-status" style="margin-top:20px; font-size:0.9rem; font-weight:bold; color:var(--neon-blue);"></div>
</div>
</div>
<script>
// Embedded Dictionary (Sorted Alphabetically)
const dictionary = [
"abide","about","above","abuse","actor","acute","admit","adopt","adult","after","again","agent","agree","ahead","alarm","album","alert","alien","align","alike","alive","allow","alone","along","alter","among","angel","anger","angle","angry","apart","apple","apply","arena","argue","arise","array","asset","audio","audit","avoid","award","aware","badly","baker","bases","basic","basis","beach","began","begin","begun","being","below","bench","billy","birth","black","blame","blind","block","blood","board","boost","booth","bound","brain","brand","bread","break","breed","brief","bring","broad","brown","build","built","buyer","cable","calif","carry","catch","cause","chain","chair","chart","chase","cheap","check","chest","chief","child","china","choir","civil","claim","class","clean","clear","click","clock","close","coach","coast","count","court","cover","craft","crash","cream","crime","cross","crowd","crown","curve","cycle","daily","dance","dated","dealt","death","debut","delay","depth","doing","doubt","dozen","draft","drama","drawn","dream","dress","drill","drink","drive","drove","dying","eager","early","earth","eight","elite","empty","enemy","enjoy","enter","entry","equal","error","event","every","exact","exist","extra","faith","false","fault","fiber","field","fifth","fifty","fight","final","first","fixed","flash","fleet","floor","fluid","focus","force","forth","forty","forum","found","frame","frank","fraud","fresh","front","fruit","fully","funny","giant","given","glass","globe","going","grace","grade","grand","grant","grass","great","green","gross","group","grown","guard","guess","guest","guide","happy","harry","heart","heavy","hence","night","horse","hotel","house","human","ideal","image","index","inner","input","issue","japan","jimmy","joint","jones","judge","known","label","large","laser","later","laugh","layer","learn","lease","least","leave","legal","level","lewis","light","limit","links","local","logic","loose","lower","lucky","lunch","magic","major","maker","march","match","mayor","meant","media","metal","might","minor","minus","mixed","model","money","month","moral","motor","mount","mouse","mouth","movie","music","needs","never","newly","night","noise","north","noted","novel","nurse","occur","ocean","offer","often","order","other","ought","paint","panel","paper","party","peace","peter","phase","phone","photo","piece","pilot","pitch","place","plain","plane","plant","plate","point","pound","power","press","price","pride","prime","print","prior","prize","proof","proud","prove","queen","quick","quiet","quite","radio","raise","range","rapid","ratio","reach","ready","refer","right","rival","river","robin","roger","roman","rough","round","route","royal","rural","scale","scene","scope","score","sense","serve","seven","shall","shape","share","sharp","sheet","shelf","shell","shift","shirt","shock","shoot","short","shown","sight","since","sixth","sixty","sized","skill","sleep","slide","small","smart","smile","smith","smoke","solid","solve","sorry","sound","south","space","spare","speak","speed","spend","spent","split","spoke","sport","staff","stage","stake","stand","start","state","steam","steel","stick","still","stock","stone","stood","store","storm","story","strip","stuck","study","stuff","style","sugar","suite","super","sweet","table","taken","taste","taxes","teach","teeth","texas","thank","theft","their","theme","there","these","thick","thing","think","third","those","three","threw","throw","tight","times","tired","title","today","topic","total","touch","tough","tower","track","trade","train","treat","trend","trial","tried","tries","truck","truly","trust","truth","twice","under","undue","union","unity","until","upper","upset","urban","usage","usual","valid","value","video","virus","visit","vital","voice","watch","water","wheel","where","which","while","white","whole","whose","woman","women","world","worry","worse","worst","worth","would","wound","write","wrong","wrote","yield","young","youth","zebra"
];
// Seed Random Generator for Daily Word
function getDailyWord() {
const today = new Date();
const seedStr = today.getUTCFullYear() + "" + today.getUTCMonth() + "" + today.getUTCDate();
// Simple string hash to number
let hash = 0;
for (let i = 0; i < seedStr.length; i++) {
hash = ((hash << 5) - hash) + seedStr.charCodeAt(i);
hash |= 0;
}
hash = Math.abs(hash);
const index = hash % dictionary.length;
return dictionary[index];
}
const targetWord = getDailyWord();
const targetIndex = dictionary.indexOf(targetWord);
// API Route pointing back to the ISACC2 root
const API_URL = '/daily_word_api.php';
// Game State
let guesses = 0;
let score = 10000;
let timeElapsed = 0;
let timerInterval = null;
let gameActive = true;
let hintsUsed = 0;
// Setup initial hints display (_____ )
let hintArray = ["_", "_", "_", "_", "_"];
function startTimer() {
if (!timerInterval) {
timerInterval = setInterval(() => {
if (gameActive) {
timeElapsed++;
document.getElementById('timerDisplay').innerText = timeElapsed + 's';
score -= 5; // Time penalty
updateScoreDisplay();
}
}, 1000);
}
}
function updateScoreDisplay() {
if(score < 0) score = 0;
document.getElementById('scoreDisplay').innerText = score;
}
function useHint() {
if (!gameActive) return;
if (hintsUsed >= 5) {
alert("No more hints available!");
return;
}
hintArray[hintsUsed] = targetWord[hintsUsed].toUpperCase();
document.getElementById('hintDisplay').innerText = hintArray.join(" ");
score -= 500; // Hint penalty
hintsUsed++;
updateScoreDisplay();
startTimer(); // Enforce timer start
}
function handleGuess(e) {
e.preventDefault();
if (!gameActive) return;
startTimer(); // Start timer on first guess
const inputEl = document.getElementById('guessInput');
const guess = inputEl.value.toLowerCase().trim();
inputEl.value = '';
if (guess.length !== 5) return;
const guessIndex = dictionary.indexOf(guess);
if (guessIndex === -1) {
alert("Word not found in dictionary! Try a more common word.");
return;
}
guesses++;
document.getElementById('guessCount').innerText = guesses;
if (guess === targetWord) {
triggerVictory();
return;
}
// Calculate Feedback
score -= 100; // Guess penalty
updateScoreDisplay();
const distance = Math.abs(targetIndex - guessIndex);
let tempClass = 'temp-cold';
let tempText = 'COLD ❄️';
if (distance <= 10) { tempClass = 'temp-hot'; tempText = 'HOT 🔥'; }
else if (distance <= 40) { tempClass = 'temp-warm'; tempText = 'WARM ☀️'; }
let direction = guessIndex < targetIndex ? 'Target is AFTER ⬇️' : 'Target is BEFORE ⬆️';
const log = document.getElementById('guessLog');
const row = document.createElement('div');
row.className = 'guess-row';
row.innerHTML = `
<div>
<div class="g-word">${guess}</div>
<div class="g-dir">${direction}</div>
</div>
<div class="g-temp ${tempClass}">${tempText}</div>
`;
log.prepend(row);
}
function triggerVictory() {
gameActive = false;
clearInterval(timerInterval);
const finalScore = score;
document.getElementById('v-word').innerText = targetWord.toUpperCase();
document.getElementById('v-score').innerText = finalScore;
document.getElementById('v-time').innerText = timeElapsed;
document.getElementById('v-guesses').innerText = guesses;
document.getElementById('victoryModal').style.display = 'flex';
// Submit score to ISACC2 Mainframe
document.getElementById('save-status').innerText = "Uploading to Mainframe...";
fetch(API_URL + '?action=submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ score: finalScore, time: timeElapsed, guesses: guesses })
})
.then(res => res.json())
.then(data => {
if(data.error) {
document.getElementById('save-status').innerText = "Not logged in. Play as guest.";
document.getElementById('save-status').style.color = "#888";
} else {
document.getElementById('save-status').innerText = "Score Saved to Leaderboard!";
loadLeaderboard(); // Refresh background LB
}
}).catch(err => {
document.getElementById('save-status').innerText = "Save failed. Offline mode.";
document.getElementById('save-status').style.color = "#e74c3c";
});
}
// Leaderboard logic
function loadLeaderboard() {
fetch(API_URL + '?action=leaderboard')
.then(res => res.json())
.then(data => {
const container = document.getElementById('lbContainer');
if (data.leaders && data.leaders.length > 0) {
let html = '';
data.leaders.forEach((l, index) => {
let color = l.user_color || '#fff';
html += `
<div class="lb-row">
<span class="lb-user" style="color:${color}">${index + 1}. ${l.username}</span>
<span class="lb-score">${l.score} <span style="color:#666; font-size:0.75rem;">(${l.time_taken}s)</span></span>
</div>
`;
});
container.innerHTML = html;
} else {
container.innerHTML = '<div style="text-align:center; color:#666; padding: 20px 0;">No scores yet today. Be the first!</div>';
}
}).catch(err => {
document.getElementById('lbContainer').innerHTML = '<div style="text-align:center; color:#e74c3c; padding: 20px 0;">Failed to load network.</div>';
});
}
// Init
document.getElementById('hintDisplay').innerText = hintArray.join(" ");
loadLeaderboard();
</script>
</body>
</html>