← back to Games Agentabrams

games/wordle/AbramsWordle.aa

478 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Abrams Wordle</title>
<style>
  :root {
    --bg:#0a0e14; --ink:#e5e7eb; --muted:#8b97a7;
    --tile:#141b25; --tile-border:#2a3441;
    --green:#2fbf71; --yellow:#e0b23a; --gray:#3a4655;
    --key:#28323f; --key-ink:#dbe3ec;
    --neon:#7dd3fc;
  }
  * { box-sizing:border-box; margin:0; padding:0; -webkit-tap-highlight-color:transparent; }
  html,body { height:100%; }
  body {
    background:radial-gradient(1200px 600px at 50% -10%, #16202e, var(--bg));
    color:var(--ink); font:15px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
    display:flex; flex-direction:column; align-items:center;
    min-height:100%; gap:10px; padding:12px 10px; overscroll-behavior:none;
    touch-action:manipulation; user-select:none; -webkit-user-select:none;
  }
  h1 {
    font-size:15px; letter-spacing:.34em; text-transform:uppercase;
    color:var(--neon); font-weight:700; text-align:center;
    text-shadow:0 0 12px rgba(125,211,252,.35);
  }
  .hud { display:flex; gap:8px; align-items:stretch; flex-wrap:wrap; justify-content:center; }
  .stat { background:var(--tile); border:1px solid var(--tile-border); border-radius:10px; padding:5px 10px; text-align:center; min-width:58px; }
  .stat .k { font-size:9px; letter-spacing:.12em; text-transform:uppercase; color:var(--muted); }
  .stat .v { font-size:17px; font-weight:700; font-variant-numeric:tabular-nums; }
  .btn {
    padding:7px 14px; border-radius:10px; border:1px solid var(--tile-border);
    background:var(--tile); color:#cbd5e1; cursor:pointer; font-size:13px; font-weight:600;
  }
  .btn:active { transform:scale(.96); }

  #board { display:grid; grid-template-rows:repeat(6,1fr); gap:6px; margin-top:2px; }
  .brow { display:grid; grid-template-columns:repeat(5,1fr); gap:6px; }
  .tile {
    width:52px; height:52px; border:2px solid var(--tile-border);
    border-radius:8px; display:flex; align-items:center; justify-content:center;
    font-weight:800; font-size:26px; text-transform:uppercase; color:var(--ink);
    background:transparent; transition:transform .08s ease, border-color .12s ease;
  }
  .tile.filled { border-color:#4a586b; }
  .tile.pop { animation:pop .12s ease; }
  @keyframes pop { 0%{transform:scale(1)} 50%{transform:scale(1.12)} 100%{transform:scale(1)} }
  .tile.flip { animation:flip .5s ease forwards; }
  @keyframes flip {
    0% { transform:rotateX(0); }
    45% { transform:rotateX(90deg); }
    55% { transform:rotateX(90deg); }
    100% { transform:rotateX(0); }
  }
  .tile.g { background:var(--green); border-color:var(--green); color:#062015; box-shadow:0 0 14px rgba(47,191,113,.4); }
  .tile.y { background:var(--yellow); border-color:var(--yellow); color:#241a03; box-shadow:0 0 14px rgba(224,178,58,.35); }
  .tile.x { background:var(--gray); border-color:var(--gray); color:#cdd6e0; }
  .brow.shake { animation:shake .4s ease; }
  @keyframes shake {
    0%,100%{transform:translateX(0)} 20%{transform:translateX(-7px)}
    40%{transform:translateX(7px)} 60%{transform:translateX(-5px)} 80%{transform:translateX(5px)}
  }

  #msg { height:20px; font-size:13px; font-weight:600; color:var(--neon); letter-spacing:.02em; text-align:center; }

  #kb { display:flex; flex-direction:column; gap:6px; width:100%; max-width:500px; margin-top:2px; }
  .krow { display:flex; gap:5px; justify-content:center; }
  .key {
    flex:1 1 auto; min-width:0; height:50px; border-radius:7px; border:0;
    background:var(--key); color:var(--key-ink); font-weight:700; font-size:14px;
    text-transform:uppercase; cursor:pointer; display:flex; align-items:center; justify-content:center;
    transition:transform .06s ease, background .12s ease;
  }
  .key.wide { flex:1.5 1 auto; font-size:11px; letter-spacing:.04em; }
  .key:active { transform:scale(.93); }
  .key.g { background:var(--green); color:#062015; }
  .key.y { background:var(--yellow); color:#241a03; }
  .key.x { background:var(--gray); color:#9aa6b3; }

  .overlay {
    position:fixed; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:10px; text-align:center; background:rgba(6,10,16,.86); backdrop-filter:blur(3px); z-index:10; padding:20px;
  }
  .overlay.hide { display:none; }
  .tag { font-size:11px; color:var(--neon); letter-spacing:.24em; text-transform:uppercase; }
  .big { font-size:26px; font-weight:800; }
  .word { font-size:20px; font-weight:800; letter-spacing:.18em; text-transform:uppercase; color:var(--green); }
  .sub { font-size:13px; color:var(--muted); max-width:280px; }
  button.play { margin-top:6px; padding:11px 26px; border:0; border-radius:999px; cursor:pointer;
    background:linear-gradient(180deg,#7dd3fc,#38bdf8); color:#03202e; font-weight:800; font-size:14px; }
  .ostats { display:flex; gap:14px; margin-top:6px; }
  .ostats .k { font-size:9px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
  .ostats .v { font-size:20px; font-weight:800; }

  @media (max-width:380px){
    .tile{ width:46px; height:46px; font-size:22px; }
    .key{ height:46px; }
    h1{ letter-spacing:.24em; }
  }
</style>
</head>
<body>
  <h1>Abrams Wordle</h1>
  <div class="hud">
    <div class="stat"><div class="k">Played</div><div class="v" id="sPlayed">0</div></div>
    <div class="stat"><div class="k">Win %</div><div class="v" id="sWin">0</div></div>
    <div class="stat"><div class="k">Streak</div><div class="v" id="sStreak">0</div></div>
    <div class="stat"><div class="k">Max</div><div class="v" id="sMax">0</div></div>
    <button class="btn" id="newBtn">New</button>
  </div>
  <div id="board"></div>
  <div id="msg"></div>
  <div id="kb"></div>

  <div class="overlay hide" id="ov">
    <div class="tag" id="ovTag">Result</div>
    <div class="big" id="ovTitle"></div>
    <div class="word" id="ovWord"></div>
    <div class="sub" id="ovSub"></div>
    <div class="ostats">
      <div><div class="k">Played</div><div class="v" id="oPlayed">0</div></div>
      <div><div class="k">Win %</div><div class="v" id="oWin">0</div></div>
      <div><div class="k">Streak</div><div class="v" id="oStreak">0</div></div>
      <div><div class="k">Max</div><div class="v" id="oMax">0</div></div>
    </div>
    <button class="play" id="playBtn">New game</button>
  </div>

<script>
(function () {
  "use strict";

  // ---- Answer words (common 5-letter solutions) ----
  var ANSWERS = ["about","above","abuse","actor","acute","admit","adopt","adult","after","again","agent","agree","ahead","alarm","album","alert","alike","alive","allow","alone","along","alter","among","anger","angle","angry","apart","apple","apply","arena","argue","arise","array","aside","asset","audio","audit","avoid","award","aware","badly","baker","bases","basic","beach","began","begin","being","below","bench","billy","birth","black","blame","blank","blast","blind","block","blood","board","boost","booth","bound","brain","brand","brass","brave","bread","break","breed","brief","bring","broad","broke","brown","brush","build","built","buyer","cable","calif","carry","catch","cause","chain","chair","chaos","charm","chart","chase","cheap","check","chest","chief","child","china","chose","civil","claim","class","clean","clear","click","climb","clock","close","cloud","coach","coast","could","count","court","cover","craft","crash","crazy","cream","crime","cross","crowd","crown","crude","curve","cycle","daily","dance","dated","dealt","death","debut","delay","depth","doing","doubt","dozen","draft","drama","drank","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","favor","fence","fever","fewer","field","fifth","fifty","fight","final","first","fixed","flame","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","grain","grand","grant","grass","grave","great","green","gross","group","grown","guard","guess","guest","guide","happy","harsh","heart","heavy","hence","henry","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","lives","local","logic","loose","lower","lucky","lunch","lying","magic","major","maker","march","maria","match","maybe","mayor","meant","medal","media","metal","meter","might","minor","minus","mixed","model","money","month","moral","motor","mount","mouse","mouth","moved","movie","music","needs","never","newly","night","noise","north","noted","novel","nurse","occur","ocean","offer","often","order","other","ought","paint","panel","paper","party","peace","penny","peter","phase","phone","photo","piano","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","realm","rebel","refer","relax","reply","right","rigid","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","shine","shirt","shock","shoot","short","shown","sight","silly","since","sixth","sixty","sized","skill","sleep","slide","small","smart","smile","smith","smoke","snake","snowy","solid","solve","sorry","sound","south","space","spare","speak","speed","spend","spent","split","spoke","sport","staff","stage","stake","stand","start","state","steam","steel","steep","steer","stern","stick","still","stock","stone","stood","store","storm","story","strip","stuck","study","stuff","style","sugar","suite","super","sweet","table","taken","taste","taxes","teach","teeth","terry","texas","thank","theft","their","theme","there","these","thick","thing","think","third","those","three","threw","throw","thumb","tiger","tight","timer","title","today","topic","total","touch","tough","tower","track","trade","trail","train","treat","trend","trial","tribe","trick","tried","tries","truck","truly","trunk","trust","truth","twice","under","undue","union","unity","until","upper","upset","urban","usage","usual","valid","value","video","virus","visit","vital","voice","waste","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","zesty","chalk","chart","chord","churn","cider","cliff","cloak","clone","clown","coral","couch","cough","cramp","crank","crate","crept","crisp","crook","daisy","dandy","dodge","donor","drift","drown","dwarf","ebony","elbow","ember","evoke","exile","fable","fairy","fancy","feast","ferry","fetch","fiber","fjord","flask","flint","float","flock","flora","flour","flung","folly","forge","frost","gauge","gecko","ghost","gland","gleam","glide","glint","gloom","glory","gloss","grasp","grill","grind","groan","grove","gruff","habit","haste","hazel","hedge","hinge","hoard","hobby","honey","humid","hunch","hutch","icing","igloo","ivory","jelly","jewel","jolly","joust","kiosk","kneel","knock","lapse","larva","latch","lemon","liver","llama","lobby","lodge","loyal","lyric","manor","maple","marsh","medic","melon","mercy","merge","merit","mirth","mocha","moist","mound","mourn","mucky","mummy","nasty","navel","nerve","niche","noble","nudge","oaken","olive","onset","opera","orbit","organ","otter","ozone","pansy","parka","pasta","patch","pause","peach","pearl","pecan","perch","petal","piety","pixel","plaid","pluck","plumb","plume","plush","poise","polar","porch","posse","pouch","prank","prawn","preen","prism","probe","prong","prune","pupil","quail","quake","qualm","quart","quash","quell","query","quest","quill","quilt","quota","quote","rabid","ranch","raven","razor","realm","rerun","resin","rhino","ridge","rinse","risky","roast","robot","rogue","rowdy","ruddy","rugby","salsa","salty","sandy","sassy","sauna","savor","scald","scalp","scarf","scoff","scold","scoop","scorn","scout","scowl","scrap","scrub","seize","serum","sever","sewer","shack","shade","shady","shaft","shale","shame","shard","shawl","shear","sheen","sheep","sheer","shied","shiny","shoal","shone","shore","shorn","showy","shrub","shrug","shuck","siege","sieve","skate","skimp","skunk","slack","slain","slang","slant","slash","slate","sleek","sleet","slept","slick","slime","sling","slink","slope","slosh","sloth","slump","slung","slunk","slush","smash","smear","smelt","smirk","snack","snail","snare","sneak","sneer","snort","snout","snowy","soggy","solar","sonic","sooty","sound","spade","spank","spawn","spear","speck","spell","spice","spicy","spied","spike","spiky","spine","spiny","spire","spite","splat","spoof","spool","spoon","spore","sprig","spurn","spurt","squad","squat","squid","stack","stage","staid","stain","stair","stalk","stall","stamp","stank","stare","stash","steak","stead","steed","stink","stint","stirs","stoke","stole","stomp","stony","stool","stoop","stork","stout","stove","stown","strap","straw","stray","strum","strut","stump","stung","stunk","stunt","suave","surge","swamp","swash","swath","swear","sweat","swell","swept","swift","swine","swing","swirl","swoon","swoop","sword","swore","sworn","swung","syrup","tabby","tacit","taffy","tally","talon","tango","tardy","tarot","taunt","tawny","tease","tepid","thick","thigh","thong","thorn","those","throb","throw","thump","tibia","tidal","tiger","tilde","timid","tipsy","toast","today","toddy","token","tonal","tonic","topaz","torch","torso","total","touch","towel","tower","toxic","toxin","trace","tract","trail","tramp","trash","trawl","tread","treat","tress","triad","trill","tripe","troll","troop","trout","trove","truce","tulip","tumor","tunic","turbo","tutor","tweak","tweed","twine","twirl","twist","udder","ulcer","ultra","umbra","uncle","undid","unfit","unify","unlit","unmet","untie","upend","upper","usher","utter","vague","valor","vapor","vault","vegan","venom","verse","verve","vigor","villa","viper","vivid","vixen","vodka","vogue","vouch","vowel","wafer","wager","wagon","waist","waltz","waste","weary","weave","wedge","weedy","weigh","weird","whale","wharf","wheat","which","whiff","whine","whirl","whisk","white","whoop","whorl","widow","wield","wince","windy","wiser","witch","wooly","woozy","world","wrath","wreak","wreck","wrest","wring","wrist","wrote","yacht","yearn","yeast","yield","yodel","yokel","young","yummy","zebra","zesty","zonal"];

  // ---- Additional allowed guesses (common valid words, not usually answers) ----
  var EXTRA = ["aback","abbey","abbot","abhor","abide","abled","abode","aboil","abort","about","abyss","ached","aches","acids","acres","acrid","addle","adept","adieu","adobe","affix","afire","afoot","afoul","agape","agile","aging","agora","ahold","aisle","alarm","alder","alert","algae","alias","alibi","alien","align","alkyl","allay","alley","allot","aloft","aloof","aloud","altar","amass","amaze","amber","amble","amend","amiss","amity","ample","amply","amuse","angel","anime","anion","ankle","annex","annoy","antic","antsy","aorta","aphid","aptly","arbor","ardor","areas","arena","argon","aroma","arose","arrow","arson","ascot","ashen","ashes","aspen","aspic","assay","aster","astir","atlas","atoll","atone","attic","augur","aunts","avail","avast","avert","avian","await","awake","aware","awash","awful","awoke","axial","axiom","axion","azure","bacon","badge","badly","bagel","baggy","baked","baker","baler","balls","balmy","banal","banjo","barge","baron","basil","basin","baste","bathe","baton","batty","bawdy","bayou","beach","beady","beard","beast","befit","began","begat","beget","begin","begun","being","belch","belie","belle","belly","below","bench","beret","berry","berth","beset","betel","bevel","bezel","bicep","biddy","bigot","bilge","billy","binge","biome","birch","birth","bison","bitty","black","blade","blame","bland","blank","blare","blast","blaze","bleak","bleat","bleed","bleep","blend","bless","blimp","blind","blink","bliss","blitz","bloat","block","bloke","blond","blood","bloom","blown","bluff","blunt","blurb","blurt","blush","board","boast","bobby","boded","bogey","boggy","bongo","bonus","booby","boost","booth","booty","booze","borax","borne","bosom","bossy","botch","bough","boule","bound","bowel","boxer","brace","braid","brain","brake","brand","brash","brass","brave","bravo","brawl","brawn","bread","break","breed","briar","bribe","brick","bride","brine","bring","brink","briny","brisk","broad","broil","broke","brood","brook","broom","broth","brown","brunt","brush","brute","buddy","budge","buggy","bugle","build","built","bulge","bulky","bully","bunch","bunny","burly","burnt","burst","bushy","butte","buxom","buyer","bylaw","cabal","cabby","cabin","cable","cacao","cache","cacti","caddy","cadet","cagey","cairn","camel","cameo","canal","candy","canny","canoe","canon","caper","caput","carat","cargo","carol","carry","carve","caste","catch","cater","catty","caulk","cause","cavil","cease","cedar","cello","chafe","chaff","chain","chair","chalk","champ","chant","chaos","chard","charm","chart","chase","chasm","cheap","cheat","check","cheek","cheer","chess","chest","chick","chide","chief","child","chili","chill","chime","china","chirp","chock","choir","choke","chord","chore","chose","chuck","chump","chunk","churn","chute","cider","cigar","cinch","circa","civet","civic","civil","clack","claim","clamp","clang","clank","clash","clasp","class","clean","clear","cleat","cleft","clerk","click","cliff","climb","cling","clink","cloak","clock","clone","close","cloth","cloud","clout","clove","clown","cluck","clued","clump","clung","coach","coast","cobra","cocoa","colon","color","comet","comfy","comic","comma","conch","condo","conic","copse","coral","corny","couch","cough","could","count","coupe","court","coven","cover","covet","covey","cower","coyly","crack","craft","cramp","crane","crank","crash","crass","crate","crave","crawl","craze","crazy","creak","cream","credo","creed","creek","creep","creme","crepe","crept","cress","crest","crick","cried","crier","crime","crimp","crisp","croak","crock","crony","crook","croon","cross","croup","crowd","crown","crude","cruel","crumb","crump","crush","crust","crypt","cubic","cumin","curio","curly","curry","curse","curve","curvy","cutie","cyber","cycle","cynic","daddy","daily","dairy","daisy","dally","dance","dandy","datum","daunt","dealt","death","debit","debug","debut","decal","decay","decor","decoy","decry","defer","deign","deity","delta","delve","demon","demur","denim","dense","depot","depth","derby","deter","detox","devil","diary","dicey","digit","dilly","dimly","diner","dingo","dingy","diode","dirge","dirty","disco","ditch","ditto","ditty","diver","dizzy","dodge","dodgy","dogma","doing","dolly","donor","donut","dopey","doubt","dough","dowdy","dowel","downy","dowry","dozen","draft","drain","drake","drama","drank","drape","drawl","drawn","dread","dream","dress","dried","drier","drift","drill","drink","drive","droit","droll","drone","drool","droop","dross","drove","drown","druid","drunk","dryer","dryly","duchy","dully","dummy","dumpy","dunce","dusky","dusty","dutch","duvet","dwarf","dwell","dwelt","dying","eager","eagle","early","earth","easel","eaten","eater","ebony","eclat","edict","edify","eerie","egret","eight","eject","eking","elate","elbow","elder","elect","elegy","elfin","elide","elite","elope","elude","email","embed","ember","emcee","emote","empty","enact","endow","enema","enemy","enjoy","ennui","ensue","enter","entry","envoy","epoch","epoxy","equal","equip","erase","erect","erode","error","erupt","essay","ester","ether","ethic","ethos","etude","evade","event","every","evict","evoke","exact","exalt","excel","exert","exile","exist","expel","extol","extra","exult","fable","facet","faint","fairy","faith","false","fancy","farce","fatal","fatty","fault","fauna","favor","feast","fecal","feign","fella","felon","femur","fence","feral","ferry","fetal","fetch","fetid","fever","fewer","fiber","fibre","ficus","field","fiend","fiery","fifth","fifty","fight","filet","filly","filmy","filth","final","finch","finer","first","fishy","fixer","fizzy","fjord","flack","flail","flair","flake","flaky","flame","flank","flare","flash","flask","fleck","fleet","flesh","flick","flier","fling","flint","flirt","float","flock","flood","floor","flora","floss","flour","flout","flown","fluff","fluid","fluke","flume","flung","flush","flute","foamy","focal","focus","foggy","foist","folio","folly","foray","force","forge","forgo","forte","forth","forty","forum","found","foyer","frail","frame","frank","fraud","freak","freed","freer","fresh","friar","fried","frill","frisk","fritz","frock","frond","front","frost","froth","frown","froze","fruit","fudge","fugue","fully","fumes","fungi","funky","funny","furor","furry","fussy","fuzzy","gaffe","gaily","gamer","gamma","gamut","gassy","gaudy","gauge","gaunt","gauze","gavel","gawky","gayer","gayly","gazer","gecko","geeky","geese","genie","genre","ghost","ghoul","giant","giddy","gipsy","girly","girth","given","giver","gizmo","glade","gland","glare","glass","glaze","gleam","glean","glide","glint","gloat","globe","gloom","glory","gloss","glove","glyph","gnash","gnome","godly","going","golem","golly","gonad","goner","goody","gooey","goofy","goose","gorge","gouge","gourd","grace","grade","graft","grail","grain","grand","grant","grape","graph","grasp","grass","grate","grave","gravy","graze","great","greed","green","greet","grief","grill","grime","grimy","grind","gripe","groan","groin","groom","grope","gross","group","grout","grove","growl","grown","gruel","gruff","grunt","guard","guava","guess","guest","guide","guild","guile","guilt","guise","gulch","gully","gumbo","gummy","guppy","gusto","gusty","gypsy","habit","hairy","halve","handy","happy","hardy","harem","harpy","harsh","haste","hasty","hatch","hater","haunt","haute","haven","havoc","hazel","heady","heard","heart","heath","heave","heavy","hedge","hefty","heist","helix","hello","hence","heron","hilly","hinge","hippo","hippy","hitch","hoard","hobby","hoist","holly","homer","honey","honor","horde","horny","horse","hotel","hotly","hound","house","hovel","hover","howdy","human","humid","humor","humph","humus","hunch","hunky","hurry","husky","hussy","hutch","hydro","hyena","hymen","hyper","icily","icing","ideal","idiom","idiot","idler","idyll","igloo","iliac","image","imbue","impel","imply","inane","inbox","incur","index","inept","inert","infer","ingot","inlay","inlet","inner","input","inter","intro","ionic","irate","irony","islet","issue","itchy","ivory","jaunt","jazzy","jelly","jerky","jetty","jewel","jiffy","joint","joist","joker","jolly","joust","judge","juice","juicy","jumbo","jumpy","junta","junto","juror","kappa","karma","kayak","kebab","khaki","kinky","kiosk","kitty","knack","knave","knead","kneed","kneel","knelt","knife","knock","knoll","known","koala","krill","label","labor","laden","ladle","lager","lance","lanky","lapel","lapse","larva","laser","lasso","latch","later","lathe","laugh","layer","leach","leafy","leaky","leant","leapt","learn","lease","leash","least","leave","ledge","leech","leery","lefty","legal","leggy","lemon","lemur","leper","level","lever","libel","liege","light","liken","lilac","limbo","limit","linen","liner","lingo","lipid","lithe","liver","livid","llama","loamy","loath","lobby","local","locus","lodge","lofty","logic","login","loopy","loose","lorry","loser","louse","lousy","lover","lower","lowly","loyal","lucid","lucky","lumen","lumpy","lunar","lunch","lunge","lupus","lurch","lurid","lusty","lying","lymph","lynch","lyric","macaw","macho","macro","madam","madly","mafia","magic","magma","maize","major","maker","mambo","mamma","mammy","manga","mange","mango","mangy","mania","manic","manly","manor","maple","march","marge","marry","marsh","mason","masse","match","matey","mauve","maxim","maybe","mayor","mealy","meant","meaty","mecca","medal","media","medic","melee","melon","mercy","merge","merit","merry","metal","meter","metro","micro","midge","midst","might","milky","mimic","mince","miner","minim","minor","minty","minus","mirth","miser","missy","mocha","modal","model","modem","mogul","moist","molar","moldy","money","month","moody","moose","moral","moron","morph","mossy","motel","motif","motor","motto","moult","mound","mount","mourn","mouse","mousy","mouth","moved","mover","movie","mower","mucky","mucus","muddy","mulch","mummy","munch","mural","murky","mushy","music","musky","musty","myrrh","nadir","naive","nanny","nasal","nasty","natal","naval","navel","needy","neigh","nerdy","nerve","never","newer","newly","nicer","niche","niece","night","ninja","ninny","ninth","noble","nobly","noise","noisy","nomad","noose","north","nosey","notch","noted","novel","nudge","nurse","nutty","nylon","nymph","oaken","obese","occur","ocean","octal","octet","odder","oddly","offal","offer","often","olden","older","olive","ombre","omega","onion","onset","opera","opine","opium","optic","orbit","order","organ","other","otter","ought","ounce","outdo","outer","outgo","ovary","ovate","overt","ovine","ovoid","owing","owner","oxide","ozone","paddy","pagan","paint","paler","palsy","panel","panic","pansy","paper","parer","parka","parry","parse","party","pasta","paste","pasty","patch","patio","patsy","patty","pause","payee","payer","peace","peach","pearl","pecan","pedal","penal","pence","penne","penny","perch","peril","perky","pesky","pesto","petal","petty","phase","phone","phony","photo","piano","picky","piece","piety","piggy","pilot","pinch","piney","pinky","pinto","piper","pique","pitch","pithy","pivot","pixel","pixie","pizza","place","plaid","plain","plait","plane","plank","plant","plate","plaza","plead","pleat","plied","plier","pluck","plumb","plume","plump","plunk","plush","poesy","point","poise","poker","polar","polka","polyp","pooch","poppy","porch","poser","posit","posse","pouch","pound","pouty","power","prank","prawn","preen","press","preen","price","prick","pride","pried","prime","primo","primp","print","prior","prism","privy","prize","probe","prone","prong","proof","prose","proud","prove","prowl","proxy","prude","prune","psalm","pubic","pudgy","puffy","pulpy","pulse","punch","pupal","pupil","puppy","puree","purer","purge","purse","pushy","putty","pygmy","quack","quail","quake","qualm","quark","quart","quash","quasi","queen","queer","quell","query","quest","queue","quick","quiet","quill","quilt","quirk","quite","quota","quote","quoth","rabbi","rabid","racer","radar","radii","radio","rainy","raise","rajah","rally","ralph","ramen","ranch","randy","range","rapid","rarer","raspy","ratio","ratty","raven","rayon","razor","reach","react","ready","realm","rearm","rebar","rebel","rebus","rebut","recap","recur","recut","reedy","refer","refit","regal","rehab","reign","relax","relay","relic","remit","renal","renew","repay","repel","reply","rerun","reset","resin","retch","retro","retry","reuse","revel","revue","rhino","rhyme","rider","ridge","rifle","right","rigid","rigor","rinse","ripen","riper","risen","riser","risky","rival","river","rivet","roach","roast","robin","robot","rocky","rodeo","roger","rogue","roomy","roost","rotor","rouge","rough","round","rouse","route","rowdy","royal","ruddy","ruder","rugby","ruler","rumba","rumor","rupee","rural","rusty","sadly","safer","saint","salad","sally","salon","salsa","salty","salve","salvo","sandy","saner","sappy","sassy","satin","satyr","sauce","saucy","sauna","saute","savor","savoy","savvy","scald","scale","scalp","scaly","scamp","scant","scare","scarf","scary","scene","scent","scion","scoff","scold","scone","scoop","scope","score","scorn","scour","scout","scowl","scram","scrap","scree","screw","scrub","scrum","scuba","sedan","seedy","segue","seize","semen","sense","sepia","serif","serum","serve","setup","seven","sever","sewer","shack","shade","shady","shaft","shake","shaky","shale","shall","shalt","shame","shank","shape","shard","share","shark","sharp","shave","shawl","shear","sheen","sheep","sheer","sheet","sheik","shelf","shell","shied","shift","shine","shiny","shire","shirk","shirt","shoal","shock","shone","shook","shoot","shore","shorn","short","shout","shove","shown","showy","shrew","shrub","shrug","shuck","shunt","shush","shyly","siege","sieve","sight","sigma","silky","silly","since","sinew","singe","siren","sissy","sixth","sixty","skate","skier","skiff","skill","skimp","skirt","skulk","skull","skunk","slack","slain","slang","slant","slash","slate","slave","sleek","sleep","sleet","slept","slice","slick","slide","slime","slimy","sling","slink","sloop","slope","slosh","sloth","slump","slung","slunk","slurp","slush","slyly","smack","small","smart","smash","smear","smell","smelt","smile","smirk","smite","smith","smock","smoke","smoky","smote","snack","snail","snake","snaky","snare","snarl","sneak","sneer","snide","sniff","snipe","snoop","snore","snort","snout","snowy","snuck","snuff","soapy","sober","soggy","solar","solid","solve","sonar","sonic","sooth","sooty","sorry","sound","south","sowed","space","spade","spank","spare","spark","spasm","spawn","speak","spear","speck","speed","spell","spelt","spend","spent","sperm","spice","spicy","spied","spiel","spike","spiky","spill","spilt","spine","spiny","spire","spite","splat","split","spoil","spoke","spoof","spook","spool","spoon","spore","sport","spout","spray","spree","sprig","spume","spunk","spurn","spurt","squad","squat","squib","squid","stack","staff","stage","staid","stain","stair","stake","stale","stalk","stall","stamp","stand","stank","stare","stark","start","stash","state","stave","stead","steak","steal","steam","steed","steel","steep","steer","stein","stern","stick","stiff","still","stilt","sting","stink","stint","stock","stoic","stoke","stole","stomp","stone","stony","stood","stool","stoop","store","stork","storm","story","stout","stove","strap","straw","stray","strip","strut","stuck","study","stuff","stump","stung","stunk","stunt","style","suave","sugar","suing","suite","sulky","sully","sumac","sunny","super","surer","surge","surly","sushi","swami","swamp","swash","swath","swear","sweat","sweep","sweet","swell","swept","swift","swill","swine","swing","swirl","swish","swoon","swoop","sword","swore","sworn","swung","synod","syrup","tabby","table","taboo","tacit","tacky","taffy","taint","taken","taker","tally","talon","tamer","tango","tangy","taper","tapir","tardy","tarot","taste","tasty","tatty","taunt","tawny","teach","teary","tease","teddy","teeth","tempo","tenet","tenor","tense","tenth","tepee","tepid","terra","terse","testy","thank","theft","their","theme","there","these","theta","thick","thief","thigh","thing","think","third","thong","thorn","those","three","threw","throb","throw","thrum","thumb","thump","thyme","tiara","tibia","tidal","tiger","tight","tilde","timer","timid","tipsy","titan","tithe","title","toast","today","toddy","token","tonal","tonga","tonic","tooth","topaz","topic","torch","torso","torus","total","totem","touch","tough","towel","tower","toxic","toxin","trace","track","tract","trade","trail","train","trait","tramp","trash","trawl","tread","treat","trend","triad","trial","tribe","trice","trick","tried","tripe","trite","troll","troop","trope","trout","trove","truce","truck","truer","truly","trump","trunk","truss","trust","truth","tryst","tubal","tuber","tulip","tulle","tumor","tunic","turbo","tutor","twang","tweak","tweed","tweet","twice","twine","twirl","twist","twixt","tying","udder","ulcer","ultra","umbra","uncle","uncut","under","undid","undue","unfed","unfit","unify","union","unite","unity","unlit","unmet","unset","untie","until","unwed","unzip","upend","upper","upset","urban","urine","usage","usher","using","usual","usurp","utile","utter","vague","valet","valid","valor","value","valve","vapid","vapor","vault","vaunt","vegan","venom","venue","verge","verse","verso","verve","vicar","video","vigil","vigor","villa","vinyl","viola","viper","viral","virus","visit","visor","vista","vital","vivid","vixen","vocal","vodka","vogue","voice","voila","vomit","voter","vouch","vowel","vying","wacky","wafer","wager","wagon","waist","waive","waltz","warty","waste","watch","water","waver","waxen","weary","weave","wedge","weedy","weigh","weird","welch","welsh","whack","whale","wharf","wheat","wheel","whelp","where","which","whiff","while","whine","whiny","whirl","whisk","white","whole","whoop","whorl","whose","widen","wider","widow","width","wield","wight","willy","wimpy","wince","winch","windy","wiser","wispy","witch","witty","woken","woman","women","woody","wooer","wooly","woozy","wordy","world","worry","worse","worst","worth","would","wound","woven","wrack","wrath","wreak","wreck","wrest","wring","wrist","write","wrong","wrote","wrung","wryly","yacht","yearn","yeast","yield","yodel","yokel","young","youth","zebra","zesty","zonal"];

  // Build validity set (deduped, 5-letter, lowercase)
  var VALID = {};
  var i, w;
  var ans = [];
  var seen = {};
  for (i = 0; i < ANSWERS.length; i++) {
    w = String(ANSWERS[i]).toLowerCase();
    if (w.length === 5 && /^[a-z]{5}$/.test(w)) {
      VALID[w] = 1;
      if (!seen[w]) { seen[w] = 1; ans.push(w); }
    }
  }
  for (i = 0; i < EXTRA.length; i++) {
    w = String(EXTRA[i]).toLowerCase();
    if (w.length === 5 && /^[a-z]{5}$/.test(w)) VALID[w] = 1;
  }
  var ANSWER_POOL = ans;

  // ---- State ----
  var ROWS = 6, COLS = 5;
  var STORE_KEY = "abrams-wordle-stats";
  var target = "", row = 0, col = 0, cur = "", over = false, busy = false;
  var boardEl, msgEl, kbEl;
  var tiles = [];     // tiles[r][c]
  var keyEls = {};    // letter -> key element
  var keyState = {};  // letter -> best status 0 none, 1 x, 2 y, 3 g

  function loadStats() {
    var s = { played:0, wins:0, streak:0, max:0 };
    try {
      var raw = localStorage.getItem(STORE_KEY);
      if (raw) {
        var p = JSON.parse(raw);
        if (p && typeof p === "object") {
          s.played = p.played|0; s.wins = p.wins|0;
          s.streak = p.streak|0; s.max = p.max|0;
        }
      }
    } catch (e) {}
    return s;
  }
  function saveStats(s) {
    try { localStorage.setItem(STORE_KEY, JSON.stringify(s)); } catch (e) {}
  }
  var stats = loadStats();

  function renderStats() {
    var pct = stats.played ? Math.round(stats.wins / stats.played * 100) : 0;
    setText("sPlayed", stats.played);
    setText("sWin", pct);
    setText("sStreak", stats.streak);
    setText("sMax", stats.max);
    setText("oPlayed", stats.played);
    setText("oWin", pct);
    setText("oStreak", stats.streak);
    setText("oMax", stats.max);
  }
  function setText(id, v) {
    var el = document.getElementById(id);
    if (el) el.textContent = String(v);
  }

  function buildBoard() {
    boardEl.innerHTML = "";
    tiles = [];
    for (var r = 0; r < ROWS; r++) {
      var rowEl = document.createElement("div");
      rowEl.className = "brow";
      var rowTiles = [];
      for (var c = 0; c < COLS; c++) {
        var t = document.createElement("div");
        t.className = "tile";
        rowEl.appendChild(t);
        rowTiles.push(t);
      }
      boardEl.appendChild(rowEl);
      tiles.push(rowTiles);
    }
  }

  var KB_ROWS = ["qwertyuiop", "asdfghjkl", "zxcvbnm"];
  function buildKeyboard() {
    kbEl.innerHTML = "";
    keyEls = {};
    for (var r = 0; r < KB_ROWS.length; r++) {
      var rowEl = document.createElement("div");
      rowEl.className = "krow";
      if (r === 2) {
        rowEl.appendChild(makeKey("ENTER", "enter", true));
      }
      var letters = KB_ROWS[r];
      for (var c = 0; c < letters.length; c++) {
        var ch = letters.charAt(c);
        var k = makeKey(ch, ch, false);
        keyEls[ch] = k;
        rowEl.appendChild(k);
      }
      if (r === 2) {
        rowEl.appendChild(makeKey("DEL", "backspace", true));
      }
      kbEl.appendChild(rowEl);
    }
  }
  function makeKey(label, action, wide) {
    var b = document.createElement("button");
    b.className = "key" + (wide ? " wide" : "");
    b.textContent = label;
    b.setAttribute("data-action", action);
    b.setAttribute("type", "button");
    return b;
  }

  function newGame() {
    target = ANSWER_POOL[Math.floor(Math.random() * ANSWER_POOL.length)];
    row = 0; col = 0; cur = ""; over = false; busy = false;
    keyState = {};
    buildBoard();
    for (var k in keyEls) {
      if (keyEls.hasOwnProperty(k)) keyEls[k].className = "key";
    }
    setMsg("");
    hideOverlay();
  }

  function setMsg(m) { if (msgEl) msgEl.textContent = m || ""; }

  function flashMsg(m) {
    setMsg(m);
    if (flashMsg._t) clearTimeout(flashMsg._t);
    flashMsg._t = setTimeout(function () { setMsg(""); }, 1400);
  }

  function addLetter(ch) {
    if (over || busy) return;
    if (cur.length >= COLS) return;
    var t = tiles[row][cur.length];
    t.textContent = ch;
    t.classList.add("filled", "pop");
    (function (tt) { setTimeout(function () { tt.classList.remove("pop"); }, 130); })(t);
    cur += ch;
  }

  function delLetter() {
    if (over || busy) return;
    if (cur.length === 0) return;
    cur = cur.slice(0, -1);
    var t = tiles[row][cur.length];
    t.textContent = "";
    t.classList.remove("filled");
  }

  function shakeRow() {
    var rowEl = boardEl.children[row];
    if (!rowEl) return;
    rowEl.classList.add("shake");
    setTimeout(function () { rowEl.classList.remove("shake"); }, 420);
  }

  function scoreGuess(guess, answer) {
    // returns array of "g"/"y"/"x"
    var res = ["x","x","x","x","x"];
    var counts = {};
    var a, gch;
    for (var j = 0; j < COLS; j++) {
      a = answer.charAt(j);
      counts[a] = (counts[a] || 0) + 1;
    }
    for (j = 0; j < COLS; j++) {
      if (guess.charAt(j) === answer.charAt(j)) {
        res[j] = "g";
        counts[guess.charAt(j)]--;
      }
    }
    for (j = 0; j < COLS; j++) {
      if (res[j] === "g") continue;
      gch = guess.charAt(j);
      if (counts[gch] > 0) {
        res[j] = "y";
        counts[gch]--;
      }
    }
    return res;
  }

  var RANK = { "x":1, "y":2, "g":3 };
  function updateKey(ch, st) {
    var prev = keyState[ch] || 0;
    if (RANK[st] > prev) {
      keyState[ch] = RANK[st];
      var el = keyEls[ch];
      if (el) {
        el.classList.remove("g", "y", "x");
        el.classList.add(st);
      }
    }
  }

  function submit() {
    if (over || busy) return;
    if (cur.length < COLS) { flashMsg("Not enough letters"); shakeRow(); return; }
    var guess = cur;
    if (!VALID[guess]) { flashMsg("Not in word list"); shakeRow(); return; }

    busy = true;
    var res = scoreGuess(guess, target);
    var rowTiles = tiles[row];
    var thisRow = row;

    for (var c = 0; c < COLS; c++) {
      (function (c) {
        setTimeout(function () {
          var t = rowTiles[c];
          t.classList.add("flip");
          setTimeout(function () {
            t.classList.add(res[c]);
            updateKey(guess.charAt(c), res[c]);
          }, 250);
          setTimeout(function () { t.classList.remove("flip"); }, 500);
        }, c * 180);
      })(c);
    }

    var total = (COLS - 1) * 180 + 520;
    setTimeout(function () {
      finishRow(guess, res, thisRow);
    }, total);
  }

  function finishRow(guess, res, guessRow) {
    var won = true;
    for (var c = 0; c < COLS; c++) { if (res[c] !== "g") { won = false; break; } }

    if (won) {
      over = true; busy = false;
      recordResult(true);
      showOverlay(true, guessRow + 1);
      return;
    }

    row++;
    cur = "";
    if (row >= ROWS) {
      over = true; busy = false;
      recordResult(false);
      showOverlay(false, 0);
    } else {
      busy = false;
    }
  }

  function recordResult(won) {
    stats.played++;
    if (won) {
      stats.wins++;
      stats.streak++;
      if (stats.streak > stats.max) stats.max = stats.streak;
    } else {
      stats.streak = 0;
    }
    saveStats(stats);
    renderStats();
  }

  var WIN_MSGS = ["Genius","Magnificent","Impressive","Splendid","Great","Phew"];
  function showOverlay(won, guessNum) {
    var ov = document.getElementById("ov");
    setText("ovTag", won ? "You win" : "Out of guesses");
    setText("ovTitle", won ? (WIN_MSGS[Math.min(guessNum - 1, WIN_MSGS.length - 1)] || "Nice") : "So close");
    setText("ovWord", target);
    setText("ovSub", won
      ? ("Solved in " + guessNum + (guessNum === 1 ? " guess" : " guesses"))
      : "Better luck next round");
    renderStats();
    ov.classList.remove("hide");
  }
  function hideOverlay() {
    var ov = document.getElementById("ov");
    ov.classList.add("hide");
  }

  // ---- Input ----
  function handleAction(action) {
    if (action === "enter") submit();
    else if (action === "backspace") delLetter();
    else if (action.length === 1 && action >= "a" && action <= "z") addLetter(action);
  }

  function onKeydown(e) {
    if (e.ctrlKey || e.metaKey || e.altKey) return;
    var key = e.key;
    if (key === "Enter") { e.preventDefault(); handleAction("enter"); }
    else if (key === "Backspace") { e.preventDefault(); handleAction("backspace"); }
    else if (key && key.length === 1) {
      var lc = key.toLowerCase();
      if (lc >= "a" && lc <= "z") { e.preventDefault(); handleAction(lc); }
    }
  }

  function onKbClick(e) {
    var el = e.target;
    while (el && el !== kbEl && !el.getAttribute) el = el.parentNode;
    if (!el || el === kbEl) return;
    var action = el.getAttribute && el.getAttribute("data-action");
    if (action) {
      e.preventDefault();
      handleAction(action);
    }
  }

  function init() {
    boardEl = document.getElementById("board");
    msgEl = document.getElementById("msg");
    kbEl = document.getElementById("kb");

    buildBoard();
    buildKeyboard();
    renderStats();
    newGame();

    document.addEventListener("keydown", onKeydown);
    kbEl.addEventListener("click", onKbClick);

    var newBtn = document.getElementById("newBtn");
    if (newBtn) newBtn.addEventListener("click", function () { newGame(); });
    var playBtn = document.getElementById("playBtn");
    if (playBtn) playBtn.addEventListener("click", function () { newGame(); });
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})();
</script>
</body>
</html>