Guess my word!

Guess my word clone. http://simbase.org/gmw/gmw.html

HTML

<h1>Guess my word!</h1>

<div id="guesses" class="hidden">Your guesses so far:
    <ol id="guesses-list"></ol>
</div>

<p id="valid-guess" class="hidden centered">My word is <span id="result-relative">relative</span> "<span id="result-word">xxx</span>".</p>

<p id="invalid-guess" class="hidden centered">I couldn't find "<span id="invalid-word"></span>" in my dictionary. Remember, you're only allowed to guess words.</p>

<div id="win-game" class="hidden centered">
    <p>Well done! You guessed it in <span id="win-time"></span>, using <span id="win-guesses"></span> guesses.</p>
    <p><button id="win-new-game">New game!</button></p>
</div>

<div id="lose-game" class="hidden centered">
    <p>Oh well. My word was <a id="lose-word"></a>.</p>
    <p><button id="lose-new-game">New game!</button></p>
</div>

<form id="interface">
    <label>What is your guess? <input id="input-word" type="text" autofocus></input></label> <input id="btn-guess" type="submit" value="Guess"></input> <button id="btn-giveup">I give up! Tell me!</button>
</form>

<hr>

<div><p>Programmed quick and dirtily by kaoD!</p>
    
<p>Blatant clone of <a href="http://simbase.org/gmw/gmw.html">http://simbase.org/gmw/gmw.html</a></p>

<p>Thanks to <a href="https://jsonp.afeld.me/">https://jsonp.afeld.me/</a> for its public CORS proxy and <a href="http://www.cs.duke.edu/~ola/ap/linuxwords">http://www.cs.duke.edu/~ola/ap/linuxwords</a> for the wordlist.</p></div>

CSS

html, body {
    width: 100%;
}

.hidden {
    display: none;
}

.centered {
    text-align: center;
}

.after {
    color: blue;
}

.before {
    color: red;
}

#interface {
    margin-bottom: 1.5em;
}

JavaScript

var getRandWord = (function() {
    var URL = encodeURIComponent('http://www.cs.duke.edu/~ola/ap/linuxwords');
    var words = undefined;

    return function getRandWord(callback) {
        if (typeof words === "undefined") {
            $.get('https://jsonp.afeld.me/?url=' + URL, function(data){
                words = data.split('\n').filter(function (word) {
                    return word[0] >= 'a' && word[0] <= 'z';
                });
                var rand = Math.floor(Math.random() * words.length);
                callback(words, words[rand]);
            });
        } else {
            var rand = Math.floor(Math.random() * words.length);
            callback(words, words[rand]);
        }
    }
})();

function timeString(msecs) {
    var totalSecs = Math.floor(msecs / 1000);
    
    var secs = totalSecs % 60;
    var mins = Math.floor(totalSecs / 60) % 60;
    var hrs = Math.floor(totalSecs / 3600);
    
    var strHrs = "";
    if (hrs >= 10) {
        strHrs = hrs + ":";
    } else if (hrs > 0) {
        strHrs = "0" + hrs + ":";
    }
    
    var strMins = "";
    if (mins >= 10) {
        strMins = mins + ":";
    } else {
        strMins = "0" + mins + ":";
    }
    
    var strSecs = "";
    if (secs >= 10) {
        strSecs = secs;
    } else {
        strSecs = "0" + secs;
    }
    
    return strHrs + strMins + strSecs;
}

$(function() {
    var DICTIONARY_URL = 'http://www.merriam-webster.com/dictionary/';
    
    var $guesses = $('#guesses');
    var $guesses_list = $('#guesses-list');
    var $result_relative = $('#result-relative');
    var $result_word = $('#result-word');
    var $valid_guess = $('#valid-guess');
    var $invalid_guess = $('#invalid-guess');
    var $invalid_word = $('#invalid-word');
    
    var $win_game = $('#win-game');
    var $win_time = $('#win-time');
    var $win_guesses = $('#win-guesses');
    var $win_new_game = $('#win-new-game');
    
    var $lose_game = $('#lose-game');
    var $lose_word =...