Index: main/trunk/model-interfaces-dev/atea/js/asr/asr-controller.js
===================================================================
--- main/trunk/model-interfaces-dev/atea/js/asr/asr-controller.js	(revision 35304)
+++ main/trunk/model-interfaces-dev/atea/js/asr/asr-controller.js	(revision 35305)
@@ -6,5 +6,6 @@
 import { TranscribeService, TranscriptionError, TranscriptionModel, TranscriptionMetadata } from "./TranscribeModule.js";
 
-class TranscriptionViewModel {
+class TranscriptionViewModel
+{
     /**
      * Initialises a new instance of the {@link TranscriptionViewModel} class.
@@ -40,4 +41,26 @@
 }
 
+class TranscriptionViewFailure
+{
+    /**
+     * 
+     * @param {String} fileName The name of the file for which this failure occured.
+     * @param {String} message The reason for this failure.
+     */
+    constructor(fileName, message) {
+        /** @type {String} The UUID of this failure. */
+        this.id = UUID.generate();
+
+        /** @type {String | null} The name of the file for which this failure occured. */
+        this.fileName = fileName;
+
+        /** @type {String} The reason for the failure. */
+        this.message = message;
+
+        /** @type {Boolean} Gets or sets a value indicating if this transcription view has been deleted. */
+        this.isDeleted = false;
+    }
+}
+
 /** @type {HTMLAudioElement} */
 var EL_AUDIO_TRANSCRIPTION_AUDIO;
@@ -188,7 +211,8 @@
             /** @type {Map<String, TranscriptionViewModel>} */
             transcriptions: new Map(),
-            /** @type {Map<String, TranscriptionError>} */
+            /** @type {Map<String, TranscriptionViewFailure>} */
             failures: new Map(),
             showCharDisplay: false,
+            enableTextEditing: false,
             /** @type {{id: String, url: String} | null} Gets the ID of the transcription for which the audio is currently loaded */
             currentlyLoadedAudio: null,
@@ -200,8 +224,12 @@
         playAudioFile(transcriptionId, startTime = 0)
         {
-            if (startTime < 0)
-            {
+            if (this.enableTextEditing && startTime != -1) { // Check the start time to know if we've been triggered by a word click
+                return;
+            }
+
+            // A value of -1 indicates that the play button has been used.
+            // Any other causes of negative time values, for whatever unknown reason, are silently corrected
+            if (startTime < 0) {
                 startTime = 0;
-                console.warn("Cannot start audio playback at a time of less than zero.");
             }
 
@@ -223,5 +251,6 @@
         },
         removeFailure(id) {
-            this.failures.delete(id);
+            this.failures.get(id).isDeleted = true;
+            delay(550).then(() => this.failures.delete(id));
         },
         getChars(transcriptionId)
@@ -248,5 +277,5 @@
         currentAudioTime(newValue)
         {
-            // TODO: Replace with more efficient search. Even binary would be a significant improvment for longer transcriptions.
+            // TODO: Replace with more efficient search. Even binary would be a significant improvement for longer transcriptions.
             const t = this.transcriptions.get(this.currentlyLoadedAudio.id);
 
@@ -297,5 +326,5 @@
     AudioUploadVM.isTranscribing = true;
     
-    await delay(200); // TODO: Remove - UI testing purposes only
+    // await delay(200); // TODO: Remove - UI testing purposes only
     
     // Transcribe each audio file in batches.
@@ -307,5 +336,6 @@
             {
                 if (!t.success) {
-                    TranscriptionsListVM.failures.set(UUID.generate(), new TranscriptionError(t.log, t.file_name));
+                    let failure = new TranscriptionViewFailure(t.file_name, t.log);
+                    TranscriptionsListVM.failures.set(failure.id, failure);
                 }
                 else {
@@ -326,5 +356,6 @@
         console.error("Failed to transcribe files");
         console.error(e);
-        TranscriptionsListVM.failures.set(UUID.generate(), e);
+        let failure = new TranscriptionViewFailure(e.fileName, e.message);
+        TranscriptionsListVM.failures.set(failure.id, failure);
     }
     
@@ -367,5 +398,5 @@
                 word: lastWord,
                 startTime: currStartTime,
-                endTime: transcription.metadata[transcription.metadata.length].start_time,
+                endTime: transcription.metadata[transcription.metadata.length - 1].start_time,
                 shouldHighlight: false
             });
Index: main/trunk/model-interfaces-dev/atea/style/asr.scss
===================================================================
--- main/trunk/model-interfaces-dev/atea/style/asr.scss	(revision 35304)
+++ main/trunk/model-interfaces-dev/atea/style/asr.scss	(revision 35305)
@@ -28,7 +28,7 @@
 
 .transform-slideout {
-    -webkit-transition-duration: 0.5s;
-    -moz-transition-duration: 0.5s;
-    transition-duration: 0.5s;
+    -webkit-transition-duration: 0.4s;
+    -moz-transition-duration: 0.4s;
+    transition-duration: 0.4s;
 
     transform: translate(100%, 0);
@@ -102,5 +102,4 @@
     display: flex;
 
-    font: var(--monospace-font);
     padding-top: 1em;
 
@@ -116,15 +115,28 @@
 }
 
-.transcription__word {
+.transcription__word-highlight {
+    background-color: rgba(255, 255, 0, 0.4);
+}
+
+.transcription__word-container {
+    font: var(--monospace-font);
     display: inline-block;
     margin-bottom: 1em;
 
     &:hover {
-        background-color: rgba(255, 255, 0, 0.4)
-    }
-}
-
-.yellow {
-    background-color: rgba(255, 255, 0, 0.4);
+        @extend .transcription__word-highlight;
+    }
+}
+
+.transcription__word {
+    font: var(--monospace-font);
+    display: inline;
+    background: transparent;
+    width: auto;
+    border: none;
+
+    &:disabled {
+        color: black;
+    }
 }
 
Index: main/trunk/model-interfaces-dev/atea/style/material.scss
===================================================================
--- main/trunk/model-interfaces-dev/atea/style/material.scss	(revision 35304)
+++ main/trunk/model-interfaces-dev/atea/style/material.scss	(revision 35305)
@@ -168,5 +168,5 @@
     }
 
-    &:active {
+    &:active, &:focus {
         border-bottom: 1px solid var(--primary-bg-color);
         
Index: main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl
===================================================================
--- main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl	(revision 35304)
+++ main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl	(revision 35305)
@@ -81,12 +81,16 @@
                 <ul class="transcription__list">
                     <!-- Displays any failed transcriptions -->
-                    <li v-for="[key, value] in failures">
+                    <li v-for="[id, failure] in failures">
+                        <xsl:attribute name="v-bind:class">
+                            <xsl:text disable-output-escaping="yes">{ 'transform-slideout': failure.isDeleted }</xsl:text>
+                        </xsl:attribute>
+
                         <div class="transcription__error-container card">
                             <div>
-                                Failed to transcribe <i v-if="value.file">{{ value.fileName }}</i><br/>
-                                <span v-if="value.message">Reason: {{ value.message }}</span>
+                                Failed to transcribe <i v-if="failure.file">{{ failure.fileName }}</i><br/>
+                                <span v-if="failure.message">Reason: {{ failure.message }}</span>
                             </div>
                             
-                            <button class="btn-fab theme-flat" v-on:click="removeFailure(key)">
+                            <button class="btn-fab theme-flat" v-on:click="removeFailure(id)">
                                 <span class="material-icons">&#xE14C;</span> <!-- clear -->
                             </button>
@@ -117,24 +121,27 @@
                             <div class="transcription__word-list" v-if="transcription.isExpanded">
                                 <div class="transcription__word-list__controls">
-                                    <button class="btn-fab" v-on:click="playAudioFile(id)" type="button">
+                                    <button class="btn-fab" v-on:click="playAudioFile(id, -1)" type="button">
                                         <span class="material-icons">play_arrow</span>
                                     </button>
 
-                                    <input type="checkbox" v-model="showCharDisplay" />
+                                    <input type="checkbox" v-model="showCharDisplay" title="Show characters" />
+
+                                    <input type="checkbox" v-model="enableTextEditing" title="Enable text editing" />
                                 </div>
                                 
                                 <ul class="transcription__list">
                                     <li v-if="!showCharDisplay">
-                                        <span v-for="word in transcription.words" class="transcription__word"
+                                        <div v-for="word in transcription.words" class="transcription__word-container"
                                             v-on:click="playAudioFile(id, word.startTime)">
                                             <xsl:attribute name="v-bind:class">
-                                                <xsl:text disable-output-escaping="yes">{ yellow: word.shouldHighlight }</xsl:text>
+                                                <xsl:text disable-output-escaping="yes">{ 'transcription__word-highlight': word.shouldHighlight }</xsl:text>
                                             </xsl:attribute>
 
-                                            {{ word.word }}
-                                        </span>
+                                            <input type="text" v-bind:size="word.word.length - 1" v-model="word.word" class="transcription__word"
+                                                v-bind:disabled="!enableTextEditing" />
+                                        </div>
                                     </li>
                                     <li v-if="showCharDisplay">
-                                        <span v-for="char in getChars(id)" class="transcription__word"
+                                        <span v-for="char in getChars(id)" class="transcription__word-container"
                                               v-on:click="playAudioFile(id, char.startTime)">
                                             {{ char.char }}
