Custom caret position misaligned on web page

I found this cool demo website that emulated a terminal. So, naturally I copy-pasted it into my editor to toy around with it. I understand the code and how it works well enough. However, I discovered a small but annoying visual error. The longer the line your typing on gets the more misaligned the caret will be when trying to reposition to the left with the left arrow key. Example below.

misaligned caret

This is where the caret should be.

enter image description here

I have tried multiple different font-sizes and monospaced fonts to no avail. The differing font-sizes simply made the alignment worse. I even tried measure the character widths with no success. The individual characters would all be the same size but multiple characters together would somehow be smaller than predicted. I have also tried messing with the offset in caret.js, nothing seems to work. So, I am thinking this is probably a styling issue?

The reason I say this is because you are typing into a textarea, but it is position off screen and each character is copied into a span element with each keystroke. So, any suggestions, solutions, or even alternatives would be much appreciated. I have provided the relevant files below. Command.js is just a file with a bunch of strings and Main.js shouldn’t be necessary here. If anyone feels otherwise let me and I will provide it as well.

Index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Terminal</title>
        <link rel="stylesheet" type="text/css" media="screen" href="css/style.css" />
    </head>
    <body>
        <div id="terminal">
            <a id="before"></a>
        </div>
        <div id="command" onclick="$('texter').focus();">
            <textarea
                type="text"
                id="texter"
                onkeyup="typeIt(this, event)"
                onkeydown="typeIt(this, event); 
                        moveIt(this.value.length, event)"
                onkeypress="typeIt(this, event);"
                autofocus
            ></textarea>
            <div id="liner">
                <span id="typer"></span><b class="cursor" id="cursor">L</b>
            </div>
        </div>
        <script src="js/command.js"></script>
        <script src="js/caret.js"></script>
        <script src="js/main.js"></script>
    </body>
</html>

Style.css

body {
    margin: 0;
    padding: 15px 20px 15px 20px;
    min-height: 99%;
    width: 99%;
    min-width: 550px;
    color: #519975;
    background: #211D1B;
    font-family: cursor, monospace, monospace !important;
    font-size: 16px !important;
    overflow-x: hidden;
}
::selection {
    color: #211830;
    background-color: #519975;
}
::-moz-selection {
    color: #211830;
    background-color: #519975;
}
textarea {
    left: -1000px;
    position: absolute;
}
b {
    font-weight: bold;
    text-decoration: underline;
}

/* Cursor Start */
.cursor {
    /* font-size: 13px; */
    color: #4fa5a8;
    background-color: #4fa5a8;
    position: relative;
    opacity: 1;
    height: 1.5em;
    width: 10px;
    max-width: 10px;
    transform: translateY(5px);
    overflow: hidden;
    text-indent: -5px;
    display: inline-block;
    text-decoration: blink;
    animation: blinker 1.3s linear infinite;
    /*border: #4c01c4;
    border-radius: 5px;
    border-style: dotted;*/
}
@keyframes blinker {
    50% {
      opacity: 0;
    }
}
#command {
    cursor: text;
    height: 50px;
    color: #73ABAD;
    /*border: #4c01c4;
    border-radius: 5px;
    border-style: dotted;*/
}
#liner {
    line-height: 1.4em;
    animation: show 0.5s ease forwards;
    animation-delay: 0.5s;
    opacity: 0;
    /*letter-spacing: 0.05em;*/
    /*border: #01bec4;
    border-radius: 5px;
    border-style: dotted;*/
}
#liner::before {
    color: #519975;
    content: "visitor:~$";
}
#liner.password::before {
    content: "Password:";
}
@keyframes show {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
}
/* Cursor End */
  
p {
    display: block;
    line-height: 1.3em;
    margin: 0;
    overflow: hidden;
    white-space: nowrap;
    /*letter-spacing: 0.05em;*/
    animation: typing 0.5s steps(30, end);
}
.no-animation {
    animation: typing 0 steps(30, end);
}
.margin {
    margin-left: 20px;
}
@keyframes typing {
    from {
      width: 0;
    }
    to {
      width: 100%;
    }
}
.index {
    color: #DCDCCC;
}
.color2 {
    color: #B89076;
}
.command {
    color: #73ABAD;
    text-shadow: 0 0 5px #73ABAD; 
}
.neon {
    color: #b29b6e;
    text-shadow: 0 0 7.5px #b29b6e; 
}
.error {
    color: #B89076;
}
.white {
    color: #fff;
}
.inherit, a {
    color: #9C8394;
}
a {
    text-decoration: inherit;
}
a:hover {
    background: #73ABAD;
    color: #211830;
}
a:focus {
    outline: 0;
}

Caret.js

function $(elid) {
    return document.getElementById(elid);
  }
  
var cursor;
window.onload = init;

function init() {
  cursor = $("cursor");
  cursor.style.left = "0px";
}

function nl2br(txt) {
  return txt.replace(/n/g, '');
}

var audio2 = new Audio("audio/chat_type1.wav")
audio2.volume = 0.75;

function typeIt(from, e) {
  e = e || window.event;
  var w = $("typer");
  var tw = from.value;
  if (!pw){
    audio2.play();
    w.innerHTML = nl2br(tw);
  }
}

function moveIt(count, e) {
  console.log(count);
  e = e || window.event;
  var keycode = e.keyCode || e.which;
  if (keycode == 37 && parseInt(cursor.style.left) >= (0 - ((count - 1) * 10))) {
    console.log(parseInt(cursor.style.left));
    cursor.style.left = parseInt(cursor.style.left) - 10 + "px";
  } else if (keycode == 39 && (parseInt(cursor.style.left) + 10) <= 0) {
    cursor.style.left = parseInt(cursor.style.left) + 10 + "px";
  }
}

function alert(txt) {
  console.log(txt);
}