<p class="police">\s\n<<if $language eq "en">>\s\n<<if $suttonLives eq "True">>Sutton Emily Jeong was unable to provide details. She has since transferred to a university on the East Coast.<<endif>>\n\nIf you have information about the\nwhereabouts of Josie Il Kwon<<if $suttonLives eq "False">> or\nSutton Emily Jeong,<<endif>> please contact\nthe <a href="http://www.sub-q.com" target="_blank">official tip site</a>.\n<<elseif $language eq "kor">>\s\n<<if $suttonLives eq "True">>서튼 에밀리 정씨는 동부의 대학으로 편입했기 때문에, 자세한 정보를 주지못했습니다.<<endif>>\n\n조시 일 권씨와<<if $suttonLives eq "False">> 서튼 에밀리 정씨의<<endif>> 행방을 아시는 분은 부디 저희 사이트에 <a href="http://www.sub-q.com" target="_blank">연락해주시길 바랍니다</a>.\n<<endif>>\s\n</p>\s\n<<timedcontinue 4s>>\n[[Credits and How-Tos]]\n
<<playsound $notification 0.15>>\s
<<fadeoutsound $city_ambience_plain 0.10 2000>>\s\n<<set $currentLoops.splice($currentLoops.indexOf($city_ambience_plain),1)>>\s\n<<fadeinsound $city_ambience_crickets 0.10 2000>>\s\n<<set $currentLoops.splice($currentLoops.indexOf($city_ambience_crickets),1)>>\s
<<display "Notification">>\s
<<display "Notification">>\s
<<set $frame to 0>>\s\n<<set $sound = "no">>\s\n<<set $language = "en">>\s\n<<set $suttonLives to "False">>\s\n<<set $city_ambience_crickets = "audio/city_ambience_crickets.mp3">>\s\n<<set $city_ambience_plain = "audio/city_ambience_plain.mp3">>\s\n<<set $notification = "audio/notification.mp3">>\s\n<<set $barking = "audio/barking.mp3">>\s\n<<set $faucet = "audio/faucet.mp3">>\s\n<<set $sutton_footsteps = "audio/sutton_footsteps.mp3">>\s\n<<set $currentLoops = [$city_ambience_crickets]>>\s\n<<display "Style Changer">><<typical>>\s\n<img style="width:100%;max-width:613px;" src="centralImages/start.png">\n\nFor the best experience, read this story on a desktop computer with headphones.\nPlease choose to read in English or Korean below.\n<table width="450px"><tr><td class="align-right" width="30%">Sound?</td><td></td><td width="30%">음향?</td></tr>\n<tr><td class="align-right">On<br/>Off</td>\n<td class="align-center"><<radiobutton "$sound" "yes" checked>>\n<<radiobutton "$sound" "no">></td> \n<td>켜짐<br/>꺼짐</td></tr>\n<tr><td>CONTENT ADVISORY: possible flickering and startling content</td>\n<td></td>\n<td>내용 경고 : 깜박거림과 무서운 내용이 있을 수 있습니다</td>\n</tr>\n<tr><td>Estimated Duration?\n5 min</td><td></td><td>예상 상영시간?\n5 분</td></tr>\n<tr><td><div class="startButton"><center><<button [[Start|Frame00]]>><<set $language to "en">><<playsound "audio/lightswitch.mp3" 0.01>><</button>></center></div></td><td></td><td><div class="startButton"><center><<button [[시작|Frame00]]>><<set $language to "kor">><<playsound "audio/lightswitch.mp3" 0.01>><</button>></center></div></td></tr></table>\n\n[[Credits and How-Tos]]\n\n<h6>Text and images appear under a Creative Commons Attribution-NonCommercial-ShareAlike License.\nSound acquired from <a href="http://www.audiojungle.net" target="_blank">AudioJungle</a> for single-use license only.</h6>
<video width="100%" max-width="1280" autoplay>\s\n<source src="centralImages/frame_21.webm" type="video/webm">\s\n<source src="centralImages/frame_21.mp4" type="video/mp4">\s\n</video>\s
<<updatevolume $city_ambience_plain 0.45>>\s
<<set $typing to either("audio/typing2.mp3", "audio/typing1.mp3","audio/typing3.mp3","audio/typing4.mp3","audio/typing5.mp3","audio/typing6.mp3")>><<playsound $typing 0.25>>\s
<<if $language eq "en">>\s\nGPS on Sutton's mobile phone indicates she returned home at 9:46 PM\s\n<<elseif $language eq "kor">>\s\n서튼의 핸드폰 GPS는 그녀가9:46 PM에\n집에 도착하였음을 알린다.\s\n<<endif>>\s
<<display "SetLanguage">>\s\n<<timedreplace 9000ms>>\n<video width="100%" max-width="1280" autoplay>\s\n<source src="centralImages/frame_53.webm" type="video/webm">\s\n<source src="centralImages/frame_53.mp4" type="video/mp4">\s\n</video>\s\n<<timedreplace 500ms>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<becomes>><<display "RandomRun">><<endtimedreplace>>\s\n<<becomes>><<display "End">><<endtimedreplace>>\s
<<updatevolume $city_ambience_crickets 0.25>>\s
<<if $language eq "en">>\s\nHit and run reported three blocks north at Sedona and East Lancet.\s\n<<elseif $language eq "kor">>\s\n세도나와 이스트 란세트 교차로에서 북쪽으로 세 블록에서 떨어진 곳에서 뺑소니 사건이 일어났다.\s\n<<endif>>\s
<<if $language eq "en">>\s\nAt approximately 9:15 PM a neighbor two blocks south observed an adult white male standing outside her living room window. When her husband joined her, the man left.\s\n<<elseif $language eq "kor">>\s\n저녁 9시 15분쯤 남쪽으로 두 블록에 사는 이웃은 자신의 거실 창문 밖에 한 백인 남자가 서 있는 것을 보았다. 하지만 남편이 나타나자 그 남자는 떠났다.\s\n<<endif>>\s
<<if $language eq "en">>\s\n9:26 PM Sutton is tagged twice in an acquaintance's LookaHere photo feed. Determined to be coincidental.\s\n<<elseif $language eq "kor">>\s\n9:26 PM 서튼은 지인의 LookaHere 사진에 2번이나 태그되었다. 분명 우연이겠지.\s\n<<endif>>\s
<<display "Typing">>\s
<<display "SetLanguage">>\s\n<<display "volume controls">>\s\n<<set $fastContinue to ["1","12","13","14","15","16","17","19","24"]>>\s\n<<set $translatedFrames to ["2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "42"]>>\s\n<<set $captionImageFrames to ["14", "15", "18", "19", "25", "26", "31", "33", "35", "46"]>>\s\n<<set $captionTranslatedFrames to ["14", "15", "18", "19", "25", "26", "31", "33", "35", "46"]>>\s\n<<set $captionFrames to ["6", "8", "9", "11", "14", "38", "41"]>>\s\n<<set $audioFrames to ["1","2","3","4","5","6","10","11","12","13","16","17","18","19","21","24","27","29","30","31","33","35","40","41","42","47","52"]>>\s\n<<set $videoFrames to ["18","21","25"]>>\s\n<<set $frame to $frame + 1>>\s\n<<set $padding to "">>\s\n<<if $frame < 10>><<set $padding to "0">><<endif>>\s\n<<if $audioFrames.indexOf($frame + "") >= 0>><<set $audioPassage to "Audio" + $padding + $frame>><<if $sound eq "yes">><<display $audioPassage>><<endif>><<endif>>\s\n<<set $centralImagePath to "centralImages/frame_" + $padding + $frame>>\s\n<<if $videoFrames.indexOf($frame + "") >= 0>><<set $videoPassage = "Video"+$padding+$frame>>\s\n<<display $videoPassage>>\n<<else>>\s\n<<if $translatedFrames.indexOf($frame + "") >= 0>><<set $centralImagePath += "_" + $language>><<endif>>\s\n<<set $centralImagePath += ".png">>\s\n<div class="centralImage">[img[$centralImagePath]]</div>\n<<endif>>\s\n\n<<if $captionImageFrames.indexOf($frame + "") >= 0>>\s\n<<set $captionImagePath to "captionImages/caption" + $padding + $frame>>\s\n<<if $captionTranslatedFrames.indexOf($frame + "") >= 0>><<set $captionImagePath += "_" + $language>><<endif>>\s\n<<set $captionImagePath += ".png">>\s\n<div class="captionImage">[img[$captionImagePath]]</div>\n<<endif>>\s\n<<if $captionFrames.indexOf($frame + "") >= 0>>\s\n<<set $captionPassage to "Caption"+$padding+$frame>>\s\n<p class="police"><<display $captionPassage>></p>\s\n<<endif>>\s\n<<if $frame < 52>>[[$continueText|MainFrame]]<<else>>[[$continueText|Frame53]]<<endif>>\s
<<silently>>\n<<set $StyleChanger = \nfunction()\n{\n\n\tmacros['typical'] =\n\t{\n\t\thandler: function(){\n\t\t\tdocument.getElementsByTagName("body")[0].style.backgroundColor="008080";\n\t\t\t\n\t\t}\n\t\n\t};\n\n\tmacros['hiddenBar'] =\n\t{\n\t\thandler: function(){\n\t\t\tdocument.getElementById("ui-bar").style.display="none";\n\t\t\tdocument.getElementById("passages").style.border=0;\n\t\t}\n\t};\n}>>\n<<print $StyleChanger()>>\n<<endsilently>>
<<display "Notification">>\s
<h5>Dead Week - 데드 위크 (죽음의 주): 기말고사 바로 전 주</h5>\s
<<display "Notification">>\s
<<display "SetLanguage">>\s\n<<display "volume controls">>\s\n<p class="police">\s\n<<if $language eq "en">>\s\nThis account is based on phone records, computer logs, and eyewitness reports of the minutes before the incident. Names and identifying details have been changed.\n<<elseif $language eq "kor">>\s\n이 사건은 전화기록, 컴퓨터 로그 그리고 목격자의 증언을 기반으로 한다. 이 이야기에 나오는 이름은 모두 가명이다.\n<<endif>>\s\n</p>\s\n\n[[$continueText|MainFrame]]
<<stopsound $sutton_footsteps>><<display "TrafficCricketsLouder">>\s
<<playsound $sutton_footsteps 0.10>>\s\n<<timedcontinue 2s>>\s\n<<updatevolume $sutton_footsteps 0.15>>\s\n<<timedcontinue 2s>>\s\n<<updatevolume $sutton_footsteps 0.20>>\s\n<<timedcontinue 2s>>\s\n<<stopsound $sutton_footsteps>>\s
<<display "TrafficCricketsQuieter">>\s
<<display "SetLanguage">>\s\n<<display "volume controls">>\s\n<<display "Style Changer">><<hiddenBar>>\s\n<p class="police">\s\n<<if $language eq "en">>\s\nThe events that follow took place 2013 December 8 at 380 Sedona Ave,\nsouth of the University of California, Los Angeles.\n<<elseif $language eq "kor">>\s\n이 사건은 2014년 10월 28일 로스앤젤레스에 위치한 캘리포니아 대학교 서쪽에 있는 세도나 거리에서 일어난 일이다.\n<<endif>>\s\n</p>\s\n\n[[$continueText|Frame0]]\n
<<playsound "audio/bookClosing.mp3" 0.15>>
/*\nsqTwineSound HTML5 Sound Macro Suite\nCopyright 2014 Tory Hoke\n\nProgram URI: http://www.sub-q.com/plugins/sqTwineSound/\nDescription: Sound macros for Twine creations, including controls for volume, fade interval, and playing multiple tracks at once.\nVersion: 0.8.0\nAuthor: Tory Hoke\nAuthor URI: http://www.toryhoke.com\nLicense: GNU General Public License\nLicense URI: http://www.opensource.org/licenses/gpl-license.php\nRepository: https://github.com/AteYourLembas/sqTwineSound\nFAQ / Q & A: http://sub-q.com/questions (password: ThinkVast)\nBug Reports/Feature Requests: http://sub-q.com/forums/topic/what-would-you-like-to-see-sqtwinesound-do-that-its-not-doing/ (password: ThinkVast)\n\n sub-Q.com is password-protected while it's in beta (until January 2015.)\n Please kick the tires and report any issues with the website\n via the sub-Q.com Contact form.\n\n\nThis program based on:\nTwine: HTML5 sound macros by Leon Arnott of Glorious Trainwrecks\nthe source and influence of which appear under a Creative Commons CC0 1.0 Universal License\n\nThis program uses\n\n easeInOutSine()\n Copyright © 2001 Robert Penner\n All rights reserved.\n \n As distributed by Kirupa\n http://www.kirupa.com/forum/showthread.php?378287-Robert-Penner-s-Easing-Equations-in-Pure-JS-(no-jQuery)\n \n Open source under the BSD License. \n \n \n Redistribution and use in source and binary forms, with or without modification, \n are permitted provided that the following conditions are met:\n \n Redistributions of source code must retain the above copyright notice, this list of \n conditions and the following disclaimer.\n Redistributions in binary form must reproduce the above copyright notice, this list \n of conditions and the following disclaimer in the documentation and/or other materials \n provided with the distribution.\n \n Neither the name of the author nor the names of contributors may be used to endorse \n or promote products derived from this software without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY \n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED \n AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED \n OF THE POSSIBILITY OF SUCH DAMAGE. \n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n \nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\n*/\n\n(function () {\n version.extensions.soundMacros = {\n major: 0,\n minor: 8,\n revision: 0\n };\n\n var globalVolume = 1.0;\n var updateInterval = 10; //Update sound volume, etc. once every 10 ms\n var defaultOverlap = 1000; //Default track overlap is 1000 ms\n var minVolume = 0.01; // Minimum possible volume -- 0 is mute, so we want somethings slightly above that\n var soundInterval = 0.1; // Creates an interval of 1/10 creates ten stages of loudness. Used by quieter/louder. Feel free to tweak\n var fileExtensions = ["ogg", "mp3", "wav", "webm"]; // Acceptable file extensions for audio\n var clips = {};\n\n // Convenience vars\n var clipNameLabel = "Clip Name";\n var overlapLabel = "Overlap";\n var volumeProportionLabel = "Volume Proportion";\n var loopLabel = "Loop?";\n\n\n //------------ Robert Penner via Kirupa math methods ----------\n //-------------------------------------------------------------\n\n function easeInOutSine(currentIteration, startValue, changeInValue, totalIterations) {\n return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue;\n }\n\n\n //------------ End Math methods -------------------------------\n //-------------------------------------------------------------\n\n //------------- pausableTimeout ---------\n //--------------------------------------\n function pausableTimeout(func, params) {\n\n this.funcToRun = func;\n this.waitStartTime = -1;\n this.waitEndTime = -1;\n this.waitDuration = -1;\n\n this.activate = function(waitDuration) {\n\n if (this.pausedAt !== undefined) { this.waitDuration = this.timeRemaining(); }\n else if (waitDuration !== undefined) this.waitDuration = waitDuration;\n else if (this.waitDuration > -1 ) { console.log("Warning: No wait duration given to pausableTimeout. Using last specified one."); }\n else return; // Don't bother to start a loop with no wait duration\n\n this.waitStartTime = new Date().getTime();\n this.waitEndTime = new Date().getTime() + this.waitDuration;\n this.timeout = setTimeout(this.funcToRun, this.waitDuration, params);\n };\n\n this.deactivate = function() {\n this.pausedAt = this.timeElapsed();\n if (this.timeout !== undefined) clearTimeout(this.timeout);\n };\n\n this.stopAndClear = function() {\n if (this.pausedAt !== undefined) delete this.pausedAt;\n if (this.timeout !== undefined) { clearTimeout(this.timeout); delete this.timeout; }\n };\n\n this.timeElapsed = function() {\n return new Date().getTime() - this.waitStartTime;\n };\n\n this.timeRemaining = function() {\n if (this.pausedAt !== undefined) return this.waitDuration - this.pausedAt;\n return this.waitEndTime - new Date().getTime();\n };\n }\n //------------- /pausableTimeout --------\n //--------------------------------------\n\n\n //------------- sqAudio ----------------\n //--------------------------------------\n function sqAudio(fullPath, clipName, fileExt) {\n\n this.fullPath = fullPath;\n this.clipName = clipName; // Let a clip know its own name\n this.fileExt = fileExt;\n\n // Defaults\n this.volumeProportion = 1.0; // By default, full volume\n this.overlap = defaultOverlap; // By default, defaultOverlap ms\n this.isPlayable = false; // Assume audio is not playable\n this.looping = false; // Assume audio not looping\n this.alternate = false;\n this.mainAudio = new Audio();\n this.partnerAudio = new Audio();\n\n this.mainAudio.setAttribute("src", this.fullPath);\n if (this.mainAudio.canPlayType) {\n for (var i = -1; i < fileExtensions.length; i += 1) {\n if (i >= 0) fileExt = fileExtensions[i];\n if (this.mainAudio.canPlayType("audio/" + fileExt)) break;\n }\n if (i < fileExtensions.length) {\n this.mainAudio.interval = null;\n this.partnerAudio.setAttribute("src", this.fullPath);\n this.partnerAudio.interval = null;\n this.isPlayable = true;\n\n } else {\n console.log("Browser can't play '" + this.clipName + "'");\n }\n } \n\n // Convenience method for getting duration\n // TODO : protect this against audio not being loaded yet\n //\n this.getDuration = function () {\n\n return this.mainAudio.duration;\n };\n\n // Get what we consider the current audio track\n //\n this._getActiveAudio = function() {\n return (this.alternate) ? this.partnerAudio : this.mainAudio;\n };\n\n // Get what we consider the idle audio track\n //\n this._getIdleAudio = function() {\n return (this.alternate) ? this.mainAudio : this.partnerAudio;\n };\n\n\n\n // Perform fade on specified audio\n // Use ease\n //\n this.__fadeSound = function(audioObj, fadeIn) {\n\n var startVolume = fadeIn ? 0 : globalVolume * this.volumeProportion;\n var deltaVolume = globalVolume * this.volumeProportion * (fadeIn ? 1 : -1);\n\n //alert("__fadeSound! fadeIn " + fadeIn + ", globalVolume " + globalVolume + ", volProp " + this.volumeProportion + " startVol " + startVolume + " deltaVolume " + deltaVolume);\n\n // Handy vars for easing\n var totalIterations = this.overlap/updateInterval;\n var currentIteration = 1;\n\n audioObj.interval = setInterval(function() {\n\n //Use easing to prevent sound popping in or out\n //\n var desiredVolume = easeInOutSine(currentIteration, startVolume, deltaVolume, totalIterations);\n \n //alert("Well desiredVol is " + desiredVolume + " cos currIter " + currentIteration + " startVol " + startVolume + " delta vol " + deltaVolume + " total iter " + totalIterations);\n //This should never happen, but if it does, skip the fade\n if (isNaN(desiredVolume)) {\n audioObj.volume = startVolume + deltaVolume;\n console.log("There was a problem with the fade. Possibly overlap " + this.overlap + " is shorter than updateInterval " + updateInterval + "? ");\n } else {\n audioObj.volume = desiredVolume;\n }\n currentIteration += 1;\n \n if (audioObj.volume === (startVolume + deltaVolume)) { \n //alert("Grats! You reached your destination of " + audioObj.volume); \n clearInterval(audioObj.interval); \n }\n\n //This effectively stops the loop and poises the volume to be played again\n //That way the clip isn't needlessly looping when no one can hear it.\n if (audioObj.volume === 0) {\n audioObj.pause();\n audioObj.currentTime = 0;\n }\n }, updateInterval);\n\n };\n\n\n // Manages starting one loop before the last play has ended\n // and cross-fading the ends\n //\n this._crossfadeLoop = function(params) {\n\n var sqAudioObj = params[0];\n var currAudioObj = params[1];\n\n // Let loop expire if no longer looping\n //\n if (!sqAudioObj.looping) { return; }\n\n var nextAudioObj = sqAudioObj.alternate ? sqAudioObj.mainAudio : sqAudioObj.partnerAudio;\n sqAudioObj.alternate = !sqAudioObj.alternate;\n\n // Don't even bother with crossfade if there's no overlap\n if (sqAudioObj.overlap !== undefined && sqAudioObj.overlap > 1) {\n\n // fade out current sound\n //\n sqAudioObj._fadeSound(currAudioObj, false);\n\n // And fade in our partner\n //\n //nextAudioObj.volume = 0; \n //if (nextAudioObj.currentTime > 0) nextAudioObj.currentTime = 0;\n //nextAudioObj.play();\n sqAudioObj._fadeSound(nextAudioObj, true);\n\n }\n else {\n sqAudioObj.updateVolume(); \n nextAudioObj.currentTime = 0;\n nextAudioObj.play();\n }\n\n // Kick off the next timer to crossfade\n // Might as well garbage collect the old crossfadeTimeout, too.\n //\n //if (sqAudioObj.crossfadeTimeout !== undefined) { sqAudioObj.crossfadeTimeout.stopAndClear(); delete sqAudioObj.crossfadeTimeout; }\n //if (isNaN(sqAudioObj.getDuration())) { throwError("Can't loop because duration is not known (audio not loaded, probably not found.)"); return; }\n //sqAudioObj.crossfadeTimeout = new pausableTimeout(sqAudioObj._crossfadeLoop, [sqAudioObj, nextAudioObj]); \n //sqAudioObj.crossfadeTimeout.activate(sqAudioObj.getDuration()*1000-sqAudioObj.overlap);\n\n };\n\n\n this._fadeSound = function(activeAudioObj, fadeIn) {\n\n // Set the goal volume as a proportion of the global volume\n // (e.g. if global volume is 0.4, and volume proportion is 0.25, overall the goal volume is 0.1)\n //\n var goalVolume = globalVolume * this.volumeProportion;\n if (activeAudioObj.interval) clearInterval(activeAudioObj.interval);\n if (fadeIn) {\n if (activeAudioObj.currentTime > 0) activeAudioObj.currentTime = 0;\n activeAudioObj.volume = 0; \n this.loop();\n\n } else {\n\n if (!activeAudioObj.currentTime) return;\n activeAudioObj.volume = goalVolume;\n activeAudioObj.play();\n }\n this.__fadeSound(activeAudioObj, fadeIn);\n\n };\n\n\n // Fade sound on whatever the active audio is\n //\n this.fadeSound = function(fadeIn) {\n if (fadeIn) {\n this.stopAndClear();\n this.looping = true;\n }\n else this.looping = false;\n this._fadeSound(this._getActiveAudio(), fadeIn);\n };\n\n // Update volume proportion and volume of both audio clips\n //\n this.setVolumeProportion = function(volumeProportion) {\n this.volumeProportion = volumeProportion;\n };\n\n // Update volume of active audio clips (assumes vol proportion and global vol already set)\n //\n this.updateVolume = function() {\n\n //alert("about to set vol to " + globalVolume + " x " + this.volumeProportion);\n this._getActiveAudio().volume = globalVolume * this.volumeProportion;\n };\n\n // Play the current audio object and reactivate any paused timer\n //\n this.play = function(loop) {\n\n //If it's a loop we want, just loop and don't make a big deal out of it\n if (loop) this.loop();\n\n else {\n\n var activeAudioObj = this._getActiveAudio();\n if (activeAudioObj) { \n activeAudioObj.play();\n }\n }\n };\n\n // Pause whatever audio is currently playing and pause the timer, too\n //\n this.pause = function() {\n if (this.crossfadeTimeout !== undefined) this.crossfadeTimeout.deactivate();\n this._getActiveAudio().pause();\n };\n\n // Stop whatever audio is currently playing and dump the timer\n //\n this.stopAndClear = function() {\n var activeAudioObj = this._getActiveAudio();\n activeAudioObj.pause();\n if (activeAudioObj.currentTime > 0) activeAudioObj.currentTime = 0;\n if (this.crossfadeTimeout !== undefined) { this.crossfadeTimeout.stopAndClear(); delete this.crossfadeTimeout; }\n };\n\n\n // Loop the track\n //\n this.loop = function() {\n\n this.looping = true;\n var activeAudioObj = this._getActiveAudio();\n\n // Create new timeout if one does not already exist; otherwise just reuse the existing one\n //\n this.crossfadeTimeout = (this.crossfadeTimeout === undefined) ? new pausableTimeout(this._crossfadeLoop, [this, activeAudioObj]) : this.crossfadeTimeout; \n if (isNaN(this.getDuration())) { return throwError("Can't loop because duration is not known (audio not loaded, probably not found.)"); }\n this.crossfadeTimeout.activate((this.getDuration()*1000)-this.overlap);\n activeAudioObj.play();\n };\n\n\n }\n //------------ /sqAudio ----------------\n //--------------------------------------\n\n\n\n /***********************************************************\n * MAIN METHOD\n /***********************************************************\n /\n / Here be monsters. Proceed with caution.\n /\n */\n\n // Verify that the audio can be played in browser\n //\n function parseAudio(c) {\n\n var d = c.exec(div.innerHTML); // returns list of form ["url/to/audio.fileType",/to/audio,fileType]\n\n while(d) {\n if (d) {\n if (!clips.hasOwnProperty(d[1])) {\n\n var parser = document.createElement('a');\n parser.href = d[1].toString();\n var pathnameSubstrings = parser.pathname.split("/");\n var clipName = pathnameSubstrings[pathnameSubstrings.length-1];\n var sqAudioObj = new sqAudio(parser.href + "." + d[2].toString(), clipName, d[2].toString());\n if (sqAudioObj.isPlayable) { clips[clipName] = sqAudioObj;}\n }\n }\n d = c.exec(div.innerHTML); // yes, we could just do a do/while, but some envs don't like that\n }\n }\n\n // Parse all used audio file names\n // Use whatever store area element is available in the story format\n //\n var storeElement = (document.getElementById("store-area") ? document.getElementById("store-area") : document.getElementById("storeArea"));\n var div = storeElement.firstChild;\n while (div) {\n var b = String.fromCharCode(92);\n var q = '"';\n var re = "['" + q + "]([^" + q + "']*?)" + b + ".(" + fileExtensions.join("|") + ")['" + q + "]";\n parseAudio(new RegExp(re, "gi"));\n div = div.nextSibling;\n }\n /***********************************************************\n * END MAIN METHOD\n /***********************************************************/\n\n\n\n /***********************************************************\n * SUPPORTING FUNCTIONS FOR THE MACROS\n /***********************************************************\n /\n / Here be monsters.\n /\n */\n\n // Given the clipName, get the active soundtrack\n //\n function getSoundTrack(clipName) {\n clipName = cleanClipName(clipName.toString());\n if (!clips.hasOwnProperty(clipName)) { return throwError("Given clipName " + clipName + " does not exist in this project. Please check your variable names."); }\n return clips[clipName];\n\n }\n\n\n // Centralized function for sound fading\n //\n function fadeSound(clipName, fadeIn) {\n\n var soundtrack = getSoundTrack(clipName);\n if (soundtrack === "undefined") { return throwError("audio clip " + clipName + " not found"); } \n soundtrack.fadeSound(fadeIn);\n \n }\n\n\n // Adjust the volume of ALL audio in the page\n //\n function adjustVolume(direction) {\n\n // Note soundInterval and minVolume are declared globally (at top of the script)\n var maxVolume = 1.0; // This is native to JavaScript. Changing will cause unexpected behavior\n globalVolume = Math.max(minVolume, Math.min(maxVolume, globalVolume + (soundInterval * direction)));\n for (var soundIndex in clips) {\n if (clips.hasOwnProperty(soundIndex)) {\n clips[soundIndex].updateVolume();\n }\n }\n }\n\n // Common argument management\n // Because of the total expected arguments (one string, one float, one int, one boolean)\n // This method attempts to be forgiving of sequence. \n // Be advised if there were even one more argument, it probably couldn't be so forgiving anymore!\n //\n function manageCommonArgs(func, requiredArgs) {\n\n // Look at the list of available arguments, clean them up, and take the first one of each desired type:\n // Recreate the arguments as a list in required sequence [clipName, volumeProportion, overlap, loop]\n\n var clipName;\n var volumeProportion;\n var overlap;\n var loop;\n\n for (var i = 0; i < func.args.length; i++) {\n switch (typeof func.args[i]) {\n case "string" :\n if (clipName === undefined) clipName = func.args[i].toString();\n break;\n case "number" :\n var tempNum = parseFloat(func.args[i]);\n if (volumeProportion === undefined && tempNum <= 1.0) volumeProportion = tempNum;\n else if (overlap === undefined && tempNum >=updateInterval) overlap = tempNum; \n break;\n case "boolean" :\n if (loop === undefined) loop = func.args[i];\n break;\n }\n }\n\n for (var requiredArg in requiredArgs) {\n if (requiredArgs.hasOwnProperty(requiredArg)) {\n switch (requiredArg) {\n case clipNameLabel :\n if (clipName === undefined) { return throwError("No audio clip name specified."); } \n break;\n case volumeProportionLabel :\n if (volumeProportion === undefined || volumeProportion > 1.0 || volumeProportion < 0.0) { return throwError("No volume proportion specified (must be a decimal number no smaller than 0.0 and no bigger than 1.0.)"); }\n break;\n case overlapLabel :\n if (overlap === undefined) { return throwError("No fade duration specified (must be a number in milliseconds greater than + " + updateInterval + " ms.)"); }\n break;\n case loopLabel :\n if (loop === undefined) { return throwError("No loop flag provided (must be a boolean, aka true or false.)"); }\n break;\n }\n }\n }\n return [clipName, volumeProportion, overlap, loop];\n }\n\n // Get the clipName up to the . if a . exists, otherwise do no harm\n //\n function cleanClipName(clipName) {\n\n var parser = document.createElement('a');\n parser.href = clipName.toString();\n var pathnameSubstrings = parser.pathname.split("/");\n clipName = pathnameSubstrings[pathnameSubstrings.length-1];\n return clipName.lastIndexOf(".") > -1 ? clipName.slice(0, clipName.lastIndexOf(".")) : clipName;\n }\n\n\n /***********************************************************\n * END SUPPORTING FUNCTIONS FOR THE MACROS\n /***********************************************************/\n\n\n\n /***********************************************************\n /***********************************************************\n * MACROS\n /***********************************************************\n /***********************************************************\n */\n\n /* updatevolume\n \n Given a decimal between 0.0 and 1.0, \n updates the clip's volume proportion and the clip's actual volume\n \n */\n macros.add("updatevolume", {\n handler: function () {\n \n var args = manageCommonArgs(this, [clipNameLabel, volumeProportionLabel]);\n var soundtrack = getSoundTrack(this.args[0]);\n soundtrack.setVolumeProportion(args[1]);\n soundtrack.updateVolume();\n }\n });\n\n /** playsound \n\n This version of the macro lets you do a little bit of sound mixing.\n \n Parameters:\n\n REQUIRED: clipName \n OPTIONAL: decimal proportion of volume (0.0 being minimum/mute, and 1.0 being maximum/default)\n OPTIONAL: number of milliseconds to overlap/crossfade the loop (0 ms by default)\n OPTIONAL: true if you'd like to loop, false if no\n \n \n */\n macros.add("playsound", {\n handler : function () {\n\n var args = manageCommonArgs(this, [clipNameLabel]);\n\n var soundtrack = getSoundTrack(this.args[0]);\n var volumeProportion = args[1] !== undefined ? args[1] : soundtrack.volumeProportion;\n soundtrack.overlap = args[2] !== undefined ? args[2] : defaultOverlap;\n var loop = args[3] !== undefined ? args[3] : false;\n soundtrack.setVolumeProportion(volumeProportion);\n soundtrack.updateVolume();\n soundtrack.play(loop); \n }\n });\n\n\n /* playsounds\n \n Play multiple sounds at once (picking up where we left off)\n If you give it no sounds to play, it quietly ignores the command.\n\n Parameters:\n\n OPTIONAL: clipName\n OPTIONAL: decimal proportion of volume (0.0 being minimum/mute, and 1.0 being maximum/default)\n OPTIONAL: number of milliseconds to overlap/crossfade (0 ms by default)\n OPTIONAL: true if you'd like to loop, false if no\n \n /\n */\n macros.add("playsounds", {\n handler: function () {\n\n var clipNameString = this.args[0];\n if (this.args[0] === undefined || this.args[0] == "") return;\n clipNameString = this.args[0].toString();\n if (clipNameString == "[]") return;\n var clipNames = clipNameString.split(",");\n if (clipNames.length < 1) return;\n var args = manageCommonArgs(this);\n for (var index = 0; index < clipNames.length; index++) {\n var soundtrack = getSoundTrack(cleanClipName(clipNames[index]));\n var volumeProportion = args[1] !== undefined ? args[1] : soundtrack.volumeProportion;\n soundtrack.overlap = args[2] !== undefined ? args[2] : defaultOverlap;\n var loop = args[3] !== undefined ? args[3] : false;\n soundtrack.setVolumeProportion(volumeProportion);\n soundtrack.updateVolume();\n soundtrack.play(loop); \n }\n }\n });\n\n\n\n /* pausesound\n \n Pauses clip at its current location. \n Use playsound to resume it.\n\n Parameters:\n\n REQUIRED: clipName\n\n */ \n macros.add("pausesound", {\n handler: function() {\n var args = manageCommonArgs(this, [clipNameLabel]); \n getSoundTrack(this.args[0]).pause();\n }\n });\n\n\n /* <<pauseallsound>> \n \n Pauses all sounds at their current location. \n \n If you'd like the option to start multiple sounds,\n take a look at <<playsounds>> and <<fadeinsounds>>\n */ \n macros.add("pauseallsound", {\n handler: function () {\n for (var clipName in clips) {\n if (clips.hasOwnProperty(clipName)) {\n getSoundTrack(clipName).pause();\n }\n }\n }\n });\n\n /* stopsound\n \n Stop the given sound immediately\n If the sound is played again, it will play from the beginning\n \n Parameters:\n\n REQUIRED: clipName \n */ \n macros.add("stopsound", {\n handler: function() {\n var args = manageCommonArgs(this, [clipNameLabel]); \n getSoundTrack(this.args[0]).stopAndClear();\n }\n });\n\n\n /* <<stopallsound>>\n \n Stops all sounds immediately.\n If any stopped sound is played again, it will play from the beginning\n \n If you'd like the option to start multiple sounds,\n take a look at <<playsounds>> and <<fadeinsounds>>\n */ \n macros.add("stopallsound", {\n handler: function () {\n for (var clipName in clips) {\n if (clips.hasOwnProperty(clipName)) {\n if (clips[clipName] !== undefined) clips[clipName].stopAndClear();\n }\n }\n }\n });\n\n /* loopsound\n \n Starts playing the given clip on repeat.\n Note that browsers will not necessarily play looping audio seamlessly.\n For seamless audio, use a fade duration/overlap (third parameter) greater than 1 millisecond\n (Well, you probably want something more perceptibe than 1 millisecond!)\n \n Parameters:\n\n REQUIRED: clipName \n OPTIONAL: decimal proportion of volume (0.0 being minimum/mute, and 1.0 being maximum/default)\n OPTIONAL: number of milliseconds to overlap/crossfade the loop (0 ms by default)\n */ \n macros.add("loopsound", {\n handler: function () {\n \n var args = manageCommonArgs(this, [clipNameLabel]);\n var soundtrack = getSoundTrack(this.args[0]);\n var volumeProportion = args[1] !== undefined ? args[1] : soundtrack.volumeProportion;\n soundtrack.overlap = args[2] !== undefined ? args[2] : defaultOverlap;\n soundtrack.setVolumeProportion(volumeProportion);\n soundtrack.updateVolume();\n soundtrack.loop();\n }\n });\n\n\n /* unloopsound \n \n Let the given sound stop when it finishes its current loop\n (so the sound no longer repeats.)\n\n Parameters:\n\n REQUIRED: clipName \n\n */ \n macros.add("unloopsound", {\n handler: function () {\n var args = manageCommonArgs(this, [clipNameLabel]); \n getSoundTrack(this.args[0]).looping = false;\n }\n });\n\n\n /* fadeinsound\n \n Identical to loopsound, but fades in the sound over 2 seconds.\n\n Parameters:\n\n REQUIRED: clipName\n OPTIONAL: decimal proportion of volume (0.0 being minimum/mute, and 1.0 being maximum/default)\n OPTIONAL: number of milliseconds to overlap/crossfade the loop (defaults to clip's last set overlap)\n\n */\n macros.add("fadeinsound", {\n handler: function () {\n\n var args = manageCommonArgs(this, [clipNameLabel]);\n \n var soundtrack = getSoundTrack(this.args[0]);\n var volumeProportion = args[1] !== undefined ? args[1] : soundtrack.volumeProportion; \n soundtrack.overlap = args[2] !== undefined ? args[2] : soundtrack.overlap;\n soundtrack.volumeProportion=volumeProportion;\n soundtrack.fadeSound(true);\n }\n });\n\n /* fadeinsounds\n\n Fade in multiple sounds at once.\n \n Parameters:\n\n REQUIRED: clipNames as list \n OPTIONAL: decimal proportion of volume (0.0 being minimum/mute, and 1.0 being maximum/default)\n OPTIONAL: number of milliseconds to overlap/crossfade the loop (defaults to clip's last set overlap)\n \n */\n macros.add("fadeinsounds", {\n handler: function () {\n\n var clipNameString = this.args[0];\n if (this.args[0] === undefined || this.args[0] == "") return;\n clipNameString = this.args[0].toString();\n if (clipNameString == "[]") return;\n var clipNames = clipNameString.split(",");\n if (clipNames.length < 1) return;\n\n var args = manageCommonArgs(this);\n\n for (var index = 0; index < clipNames.length; index++) {\n var soundtrack = getSoundTrack(this.args[0]);\n var volumeProportion = args[1] !== undefined ? args[1] : soundtrack.volumeProportion; \n soundtrack.overlap = args[2] !== undefined ? args[2] : soundtrack.overlap;\n soundtrack.volumeProportion=volumeProportion;\n soundtrack.fadeSound(true); \n }\n }\n });\n\n /* fadeoutsound\n \n Identical to stopsound, but fades out the sound over the stored fade duration (overlap).\n \n Parameters:\n\n REQUIRED: clipName \n\n */\n macros.add("fadeoutsound", {\n handler: function () {\n var args = manageCommonArgs(this, [clipNameLabel]); \n fadeSound(this.args[0].toString(), false);\n }\n });\n\n\n /* fadeoutsounds\n \n Fade out multiple sounds at once.\n If you give it no sounds to play, it quietly ignores the command.\n\n Parameters:\n\n REQUIRED: clipNames as list \n \n */\n macros.add("fadeoutsounds", {\n handler: function () {\n\n var clipNameString = this.args[0];\n if (this.args[0] === undefined) return;\n clipNameString = this.args[0].toString();\n if (clipNameString == "[]") return;\n var clipNames = clipNameString.split(",");\n if (clipNames.length < 1) return;\n\n for (var index = 0; index < clipNames.length; index++) {\n fadeSound(cleanClipName(clipNames[index]), false);\n }\n }\n });\n\n\n /* <<quieter>>\n \n Reduces the story's globalVolume by 1/10th of the reader's system volume.\n Thus creates a 10-unit volume range for the story\n \n */\n macros.add("quieter", {\n handler: function () {\n adjustVolume(-1);\n }\n });\n\n /* <<louder>>\n \n Increases the story's globalVolume by 1/10th of the reader's system volume.\n Thus creates a 10-unit volume range for the story\n \n */\n macros.add("louder", {\n handler: function () {\n adjustVolume(1);\n }\n });\n\n\n /* jumpscare\n \n Play the clip at maximum story volume\n Don't affect any stored volume options\n PLEASE GIVE THE READER A STARTLE WARNING BEFORE USING THIS.\n \n */\n macros.add("jumpscare", {\n handler: function () {\n var args = manageCommonArgs(this, [clipNameLabel]);\n var soundtrack = getSoundTrack(this.args[0]);\n soundtrack.setVolumeProportion(1.0);\n soundtrack.updateVolume();\n soundtrack.play();\n }\n });\n\n /***********************************************************\n * END MACROS\n /***********************************************************/\n\n\n\n}());\n\n// You read the whole thing! THAT'S PRETTY RAD. Keep up the good work, and happy Twining.\n\n
<<timedcontinue 2s>><<playsound "audio/thump.mp3" 0.30>>\s
<<display "Typing">>\s
<<set $currentLoops.push($city_ambience_crickets)>>\s\n<<fadeinsound $city_ambience_crickets 0.25 2000>>\s\n<<display "Typing">>\s
<<display "Typing">>\s
<<display "Notification">>\s
<<display "Typing">>\s
<<display "Typing">>\s
<<updatevolume $city_ambience_plain 0.25>>\s\n<<timedcontinue 2s>>\s\n<<updatevolume $city_ambience_plain 0.10>>\s
<<display "Typing">>\s
<h2><center>Dead Week / 데드 위크 (죽음의 주)</center></h2><h4><center>Credits and How-Tos</center></h4>\n(All links open in new tabs.)\n\n<h3>Text</h3>\s\nText by Tory Hoke.\nMore work appears at <a href="http://www.toryhoke.com" target="_blank">toryhoke.com</a>. Follow her on Twitter <a href="http://www.twitter.com/toryhoke" target="_blank">@toryhoke</a>.\n\n<ul>\s\n<li>Korean Translation: serris2</li>\s\n<li>Language Editor: <a href="https://www.elance.com/s/edit/eunagil/" target="_blank">Euna G.</a></li>\s\n<li>Additional Translation: translang</li>\s\n</ul>\s\n\n\n<h3>Image</h3>\s\nArt by <a href="http://www.toryhoke.com/portfolio" target="_blank">Tory Hoke</a>.\n\nEditing and Animation by <a href="http://jeremyrwoodward.com/" target="_blank">Jeremy Woodward</a>.\n\nJPEG Glitch effect by <a href="http://snorpey.github.io/jpg-glitch/" target="_blank">Georg Fischer</a>\n\n\n<h3>Sound</h3>\s\n\nThis game uses the following sounds from freesound.org:\n\n<ul>\s\n<li><a href="https://www.freesound.org/people/amszala/" target="_blank">City_Street.aif</a> by amszala</li>\s\n<li><a href="https://www.freesound.org/people/thebigracket/" target="_blank">crickets.wav</a> by thebigracket</li>\s\n<li><a href="https://www.freesound.org/people/Aiwha/" target="_blank">Street at night</a> by Aiwha</li>\s\n<li><a href="https://www.freesound.org/people/DJ%20Chronos/" target="_blank">Horror drone 006.wav</a> by DJ Chronos</li>\s\n<li><a href="https://www.freesound.org/people/RICHERlandTV/" target="_blank">Heavy Impacts</a> by RICHERlandTV</li>\s\n<li><a href="https://www.freesound.org/people/mkoenig/" target="_blank">Horn Honk.wav</a> by mkoenig</li>\s\n<li><a href="https://www.freesound.org/people/ceberation/)" target="_blank">Car Horn.wav</a> by ceberation</li>\s\n</ul>\s\n\nThis game uses the following sounds from AudioJungle.com. Please do not reuse without a license.\n<ul><li><a href="http://audiojungle.net/item/dog-barking/813912" target="_blank">Dog Barking</a> by celadith</li>\n<li><a href="http://audiojungle.net/item/footsteps-in-heels-on-concrete/3267179" target="_blank">Footsteps in Heels on Concrete</a> by urbazon</li>\n<li><a href="http://audiojungle.net/item/soft-thump-blow/4270215" target="_blank">Soft Thump Blow</a> by urbazon</li>\n<li><a href="http://audiojungle.net/item/typing-keyboard/5557738" target="_blank">Typing Keyboard</a> by SuperSoundFactory</li>\n<li><a href="http://audiojungle.net/item/playing-with-the-lightswitch/2034931" target="_blank">Playing with the Lightswitch</a> by CosminSerban</li>\n<li><a href="http://audiojungle.net/item/closing-book/337113" target="_blank">Closing Book</a> by Vintervarg</li>\n<li><a href="http://audiojungle.net/item/low-vibrating-rumble/4431784" target="_blank">Low Vibrating Rumble</a> by gamesounds</li>\s\n</ul>\s\n\n<h3>Interactivity</h3>\s\nInteractivity by Tory Hoke on the following foundation:\n<ul><li>Twine can be downloaded at <a href="http://twinery.org/" target="_blank">Twinery.org</a></li>\n<li><a href="http://www.motoslave.net/sugarcube/">Sugarcube story format v 1.0.3</a> by Thomas Michael Edwards</li>\n<li>Sound macros by <a href="http://sub-q.com/plugins/sqtwinesound/" target="_blank">sub-Q</a> (while site is in beta, use password: ThinkVast).</li>\n<li>Timed replace macro and CSS by <a href="http://www.glorioustrainwrecks.com/blog/584">Leon Arnott</a>.</li>\n<li>Style Changer macro (changing background) learned from the work of <a href="http://www.lifeinneon.com/mygames/" target="_blank">Lydia Neon</a>.</li>\n<li>Styling "submit" button learned from <a href="http://twinery.org/forum/index.php/topic,707.msg959.html#msg959" target="_blank">this post by L</a> (CSS selector is ".passage button")</li>\n<li>CSS for a pretty "submit" button acquired via <a href="http://www.bestcssbuttongenerator.com/" target="_blank">Button X</a>.</li></ul>\s\n\nFeel free to import this HTML file into Twine for more details, and happy Twining.
/* Your story will use the CSS in this passage to style the page.\nGive this passage more tags, and it will only affect passages with those tags.\nExample selectors: */\n\n@import url(http://fonts.googleapis.com/css?family=Lato|Antic+Slab);\n\nbody {\n\t/* This affects the entire page */\n\tbackground-color: #333;\n\tcolor: #F5F5F5;\n\tmargin: 0;\n\tfont-family: 'Lato', sans-serif;\n}\n\na {\n\t/* This affects passage links */\n\n\tcolor: #FFFFFF;\n\t\n\t\n}\na:hover {\n\t/* This affects links while the cursor is over them */\n\t\n\tcolor: #C0C0C0;\n\n}\n\ntd {\n\tvertical-align: top;\n}\n\ntd.align-right {\n\ttext-align: right;\n}\n\ntd.align-center {\n\ttext-align: center;\n}\n\n#ui-bar {\n\twidth: 125px;\n\tposition: relative;\n\ttop: 0;\n\tleft: 0;\n\twidth: auto;\n\theight: auto;\n\tmargin: 0;\n\tpadding: 2.5% 3.5% 0;\n\tborder: none;\n\tborder-bottom: 1px solid #fff;\n\tfont-family: 'Lato', sans-serif;\n\n\n}\n#ui-body {\n\tmax-width: 100%;\n\tmax-height: 100%;\n}\n\n\t#ui-bar header, #story-caption, #ui-bar footer {\n\t\ttext-align: left;\n\t\twidth: 66%;\n\t}\n\t#menu {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tright: 0;\n\t\tmargin: 2.5% 3.5% 0 0;\n\t}\n\t#menu ul {\n\t\tmargin: 0;\n\t}\n\t#menu li {\n\t\tmargin-bottom: 0.5em;\n\t}\n\t#menu-story {\n\t\tmargin-bottom: 0.7em;\n\t\tline-height: 0.85;\n\t}\n\n\n\n#passages {\n margin-left: 0px;\n height:100%;\n min-height: 100%;\n padding-bottom: 0;\n margin-bottom: 0;\n border: 0;\n font-family: 'Antic Slab', serif;\n width: auto;\n margin: 1.5em 3.5% 3.5%;\n\n}\n\n\n.passage {\n\t/* This only affects passages */\n\t/* font */\n\tcolor: #F5F5F5;\n\tfont-size: medium;\n\n\t/* transition */\n\ttransition: 2.0s;\n\t-webkit-transition: 2.0s;\n\n\t\n}\n.passage a {\n\t/* This affects passage links */\n\n\tcolor: #AAA;\n\tfont-family: 'Lato', sans-serif;\n\tfont-size: large;\n\t\n\t\n}\n.passage a:hover {\n\t/* This affects links while the cursor is over them */\n\t\n\tcolor: #F5F5F5;\n\n}\n\n.centralImage img {\n\twidth:100%;\n\tmax-width:1280px;\n}\n\n\n@media (max-width:768px){\n\n.captionImage img {\n\twidth:100%;\n\tmax-width: 450px;\n\t}\n\n}\n\n@media (max-width:480px){\n\n.captionImage img {\n\twidth:100%;\n\tmax-width: 300px;\n\t}\n\n}\n\n@media (max-width:320px){\n\n.captionImage img {\n\twidth:100%;\n\tmax-width: 300px;\n\t}\n\n}\n\n\n\np.police {\n\tfont-family: 'Lucida Sans Typewriter', 'Lucida Console', monaco, 'Bitstream Vera Sans Mono', monospace;\n\tfont-size: 12px;\n\tfont-style: normal;\n\tfont-variant: normal;\n}\n\n.transition-in {\n\topacity: 0;\n\tposition: absolute;\n}\n.transition-out {\n\topacity: 0 !important;\n\tposition: absolute;\n}\n\n.revision-span-in {\n\topacity: 0;\n}\n.revision-span:not(.revision-span-out) {\n\ttransition: 2s; \n\t-webkit-transition: 2s;\n}\n.revision-span-out {\n\tposition:absolute;\n\topacity: 0;\n}\n\n\n.timedreplacement.replacement-in {\n\topacity: 0;\n}\n.timedreplacement {\n\ttransition: 0s;\n\t-webkit-transition: 0s;\n}\n.timedreplacement.replacement-out {\n\topacity: 0;\n}\n\n\n\n.disabled { display:none; }\n\n\n\n\n\n.startButton button {\n\t-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;\n\t-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;\n\tbox-shadow:inset 0px 1px 0px 0px #ffffff;\n\tbackground:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf));\n\tbackground:-moz-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-webkit-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-o-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-ms-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:linear-gradient(to bottom, #ededed 5%, #dfdfdf 100%);\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf',GradientType=0);\n\tbackground-color:#ededed;\n\t-moz-border-radius:11px;\n\t-webkit-border-radius:11px;\n\tborder-radius:11px;\n\tborder:1px solid #dcdcdc;\n\tdisplay:inline-block;\n\tcursor:pointer;\n\tcolor:#777777;\n\tfont-family: 'Lato', sans-serif;\n\tfont-size:22px;\n\tfont-weight:bold;\n\tpadding:10px 61px;\n\ttext-decoration:none;\n\ttext-shadow:0px 1px 0px #ffffff;\n}\n.startButton button:hover {\n\tbackground:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #dfdfdf), color-stop(1, #ededed));\n\tbackground:-moz-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-webkit-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-o-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-ms-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:linear-gradient(to bottom, #dfdfdf 5%, #ededed 100%);\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dfdfdf', endColorstr='#ededed',GradientType=0);\n\tbackground-color:#dfdfdf;\n}\n.startButton button:active {\n\tposition:relative;\n\ttop:1px;\n}\n\n\n\n\n\n\n.audioButton button {\n\t-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;\n\t-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;\n\tbox-shadow:inset 0px 1px 0px 0px #ffffff;\n\tbackground:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf));\n\tbackground:-moz-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-webkit-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-o-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:-ms-linear-gradient(top, #ededed 5%, #dfdfdf 100%);\n\tbackground:linear-gradient(to bottom, #ededed 5%, #dfdfdf 100%);\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf',GradientType=0);\n\tbackground-color:#ededed;\n\t-moz-border-radius:4px;\n\t-webkit-border-radius:4px;\n\tborder-radius:4px;\n\tborder:1px solid #dcdcdc;\n\tdisplay:inline-block;\n\tcursor:pointer;\n\tcolor:#777777;\n\tfont-family:Verdana;\n\tfont-size:10px;\n\tpadding:4px 3px;\n\ttext-decoration:none;\n\ttext-shadow:0px 1px 0px #ffffff;\n}\n.audioButton button:hover {\n\tbackground:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #dfdfdf), color-stop(1, #ededed));\n\tbackground:-moz-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-webkit-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-o-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:-ms-linear-gradient(top, #dfdfdf 5%, #ededed 100%);\n\tbackground:linear-gradient(to bottom, #dfdfdf 5%, #ededed 100%);\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dfdfdf', endColorstr='#ededed',GradientType=0);\n\tbackground-color:#dfdfdf;\n}\n.audioButton button:active {\n\tposition:relative;\n\ttop:1px;\n}\n\n
<<set $indent to either(" "," "," "," "," "," "," "," "," "," "," "," ")>>\n\n<<print $indent>>[[Run|End][$suttonLives="True"]]\s
<video width="100%" max-width="1280" autoplay>\s\n<source src="centralImages/frame_18.webm" type="video/webm">\s\n<source src="centralImages/frame_18.mp4" type="video/mp4">\s\n</video>\s
<<updatevolume $city_ambience_crickets 0.25>>\s
<<if $language eq "en">>\s\nGPS on Sutton's mobile phone indicates departure from house at 9:27 PM\s\n<<elseif $language eq "kor">>\s\n서튼 핸드폰의 GPS는 9:27 PM에 집에서 출발했음을 표시한다.\s\n<<endif>>\s
<<if $language eq "en">>\s\n9:37 PM CCTV captures Sutton's exit from the Sedona 7-11.\s\n<<elseif $language eq "kor">>\s\n9:37 PM 세도나 세븐 일레븐 편의점 CCTV가 서튼이 나가는 모습을 포착한다.\s\n<<endif>>\s
<<if $language eq "en">>\s\n7:45 PM - 1:00 AM: Josie's boyfriend Jason Cho placed at his residence, 4880 Grange St, by phone records and eyewitnesses.\s\n<<elseif $language eq "kor">>\s\n7:45 PM - 1:00 AM: 목격자들과 전화 기록에 의하면, 피해자의 남자친구인 제이슨 조는 4880 그랜지 스트리트에 있는 자신의 집에 머물렀다.\s\n<<endif>>\s
<<set $continueText=". . .">>\s
<video width="100%" max-width="1280" autoplay>\s\n<source src="centralImages/frame_25.webm" type="video/webm">\s\n<source src="centralImages/frame_25.mp4" type="video/mp4">\s\n</video>\s
<div class="audioButton" align="right"><<button "[]">><<stopallsound>><<set $sound = "no">><</button>> \s\n<<button "<)">><<quieter>><</button>> \s\n<<button "<)))">><<louder>><</button>> \s\n<<button "|>">><<fadeinsounds $currentLoops>><<set $sound = "yes">><</button>></div>\s
<<updatevolume $city_ambience_crickets 0.45>>\s
<<if $language eq "en">>\s\n7-11 RECEIPT\nPotato wedges - $1.99\n20 oz soda - $1.19\nSales tax - 7.5%\nDecember 8, 2013 9:36 PM\s\n<<elseif $language eq "kor">>\s\n7-11 RECEIPT\n감자튀김 - $1.99\n20 oz 음료수 - $1.19\n부가세 – 7.5%\n2013년 12월 8일\n9:36 PM\s\n<<endif>>\s
// Replace macros created by Glorious Trainwrecks\n// http://www.glorioustrainwrecks.com/blog/584\n\n\n\n(function() {\n version.extensions.replaceMacrosCombined = {\n major: 1,\n minor: 1,\n revision: 4\n };\n var nullobj = {\n handler: function() {}\n };\n\n function showVer(n, notrans) {\n if (!n) {\n return\n }\n n.innerHTML = "";\n new Wikifier(n, n.tweecode);\n n.setAttribute("data-enabled", "true");\n n.style.display = "inline";\n n.classList.remove("revision-span-out");\n if (!notrans) {\n n.classList.add("revision-span-in");\n if (n.timeout) {\n clearTimeout(n.timeout)\n }\n n.timeout = setTimeout(function() {\n n.classList.remove("revision-span-in");\n n = null\n }, 1)\n }\n }\n\n function hideVer(n, notrans) {\n if (!n) {\n return\n }\n n.setAttribute("data-enabled", "false");\n n.classList.remove("revision-span-in");\n if (n.timeout) {\n clearTimeout(n.timeout)\n }\n if (!notrans) {\n n.classList.add("revision-span-out");\n n.timeout = setTimeout(function() {\n if (n.getAttribute("data-enabled") == "false") {\n n.classList.remove("revision-span-out");\n n.style.display = "none";\n n.innerHTML = ""\n }\n n = null\n }, 1000)\n } else {\n n.style.display = "none";\n n.innerHTML = "";\n n = null\n }\n }\n\n function tagcontents(b, starttags, desttags, endtags, k) {\n var l = 0,\n c = "",\n tg, a, i;\n\n function tagfound(i, e) {\n for (var j = 0; j < e.length; j++) {\n if (a.indexOf("<<" + e[j], i) == i) {\n return e[j]\n }\n }\n }\n a = b.source.slice(k);\n for (i = 0; i < a.length; i++) {\n if (tg = tagfound(i, starttags)) {\n l++\n } else {\n if ((tg = tagfound(i, desttags)) && l == 0) {\n b.nextMatch = k + i + tg.length + 4;\n return [c, tg]\n } else {\n if (tg = tagfound(i, endtags)) {\n l--;\n if (l < 0) {\n return null\n }\n }\n }\n }\n c += a.charAt(i)\n }\n return null\n }\n var begintags = [];\n var endtags = [];\n\n function revisionSpanHandler(g, e, f, b) {\n var k = b.source.indexOf(">>", b.matchStart) + 2,\n vsns = [],\n vtype = e,\n flen = f.length,\n becomes, c, cn, m, h, vsn;\n\n function mkspan(vtype) {\n h = insertElement(m, "span", null, "revision-span " + vtype);\n h.setAttribute("data-enabled", false);\n h.style.display = "none";\n h.tweecode = "";\n return h\n }\n if (this.shorthand && flen) {\n while (f.length > 0) {\n vsns.push([f.shift(), (this.flavour == "insert" ? "gains" : "becomes")])\n }\n } else {\n if (this.flavour == "insert" || (this.flavour == "continue" && this.trigger == "time")) {\n vsns.push(["", "becomes"])\n }\n } if (this.flavour == "continue" && flen) {\n b.nextMatch = k + b.source.slice(k).length;\n vsns.push([b.source.slice(k), vtype])\n } else {\n becomes = ["becomes", "gains"];\n c = tagcontents(b, begintags, becomes.concat(endtags), endtags, k);\n if (c && endtags.indexOf(c[1]) == -1) {\n while (c) {\n vsns.push(c);\n c = tagcontents(b, begintags, becomes, endtags, b.nextMatch)\n }\n c = tagcontents(b, begintags, ["end" + e], endtags, b.nextMatch)\n }\n if (!c) {\n throwError(g, "can't find matching end" + e);\n return\n }\n vsns.push(c);\n if (this.flavour == "continue") {\n k = b.nextMatch;\n b.nextMatch = k + b.source.slice(k).length;\n vsns.push([b.source.slice(k), ""])\n }\n } if (this.flavour == "remove") {\n vsns.push(["", "becomes"])\n }\n cn = 0;\n m = insertElement(g, "span", null, e);\n m.setAttribute("data-flavour", this.flavour);\n h = mkspan("initial");\n vsn = vsns.shift();\n h.tweecode = vsn[0];\n showVer(h, true);\n while (vsns.length > 0) {\n if (vsn) {\n vtype = vsn[1]\n }\n vsn = vsns.shift();\n h = mkspan(vtype);\n h.tweecode = vsn[0]\n }\n if (typeof this.setup == "function") {\n this.setup(m, g, f)\n }\n }\n\n function quantity(m) {\n return (m.children.length - 1) + (m.getAttribute("data-flavour") == "remove")\n }\n\n function revisionSetup(m, g, f) {\n m.className += " " + f[0].replace(" ", "_")\n }\n\n function keySetup(m, g, f) {\n var key = f[0];\n m.setEventListener("keydown", function l(e) {\n var done = !revise("revise", m);\n if (done) {\n m.removeEventListener("keydown", l)\n }\n })\n }\n\n function timeSetup(m, g, f) {\n function cssTimeUnit(s) {\n if (typeof s == "string") {\n if (s.slice(-2).toLowerCase() == "ms") {\n return Number(s.slice(0, -2)) || 0\n } else {\n if (s.slice(-1).toLowerCase() == "s") {\n return Number(s.slice(0, -1)) * 1000 || 0\n }\n }\n }\n throwError(g, s + " isn't a CSS time unit");\n return 0\n }\n var tm = cssTimeUnit(f[0]);\n setTimeout(function timefn() {\n var done = !revise("revise", m);\n if (!done) {\n setTimeout(timefn, tm)\n }\n }, tm)\n }\n\n function hoverSetup(m) {\n var fn, noMouseEnter = (document.head.onmouseenter !== null),\n m1 = m.children[0],\n m2 = m.children[1];\n if (!m1 || !m2) {\n return\n }\n m1.onmouseenter = function(e) {\n if (this.getAttribute("data-enabled") != "false") {\n revise("revise", this.parentNode)\n }\n };\n m2.onmouseleave = function(e) {\n if (this.getAttribute("data-enabled") != "false") {\n revise("revert", this.parentNode)\n }\n };\n if (noMouseEnter) {\n fn = function(n) {\n return function(e) {\n if (!event.relatedTarget || (event.relatedTarget != this && !(this.compareDocumentPosition(event.relatedTarget) & Node.DOCUMENT_POSITION_CONTAINED_BY))) {\n this[n]()\n }\n }\n };\n m1.onmouseover = fn("onmouseenter");\n m2.onmouseout = fn("onmouseleave")\n }\n m = null\n }\n\n function mouseSetup(m) {\n var evt = (document.head.onmouseenter === null ? "onmouseenter" : "onmouseover");\n m[evt] = function() {\n var done = !revise("revise", this);\n if (done) {\n this[evt] = null\n }\n };\n m = null\n }\n\n function linkSetup(m, g, f) {\n var l = Wikifier.createInternalLink(),\n p = m.parentNode;\n l.className = "internalLink replaceLink";\n p.insertBefore(l, m);\n l.insertBefore(m, null);\n l.onclick = function() {\n var p, done = false;\n if (m && m.parentNode == this) {\n done = !revise("revise", m);\n scrollWindowTo(m)\n }\n if (done) {\n this.parentNode.insertBefore(m, this);\n this.parentNode.removeChild(this)\n }\n };\n l = null\n }\n\n function visitedSetup(m, g, f) {\n var i, done, shv = state.history[0].variables,\n os = "once seen",\n d = (m.firstChild && (this.flavour == "insert" ? m.firstChild.nextSibling : m.firstChild).tweecode);\n shv[os] = shv[os] || {};\n if (d && !shv[os].hasOwnProperty(d)) {\n shv[os][d] = 1\n } else {\n for (i = shv[os][d]; i > 0 && !done; i--) {\n done = !revise("revise", m, true)\n }\n if (shv[os].hasOwnProperty(d)) {\n shv[os][d] += 1\n }\n }\n }[{\n name: "insert",\n flavour: "insert",\n trigger: "link",\n setup: linkSetup\n }, {\n name: "timedinsert",\n flavour: "insert",\n trigger: "time",\n setup: timeSetup\n }, {\n name: "insertion",\n flavour: "insert",\n trigger: "revisemacro",\n setup: revisionSetup\n }, {\n name: "later",\n flavour: "insert",\n trigger: "visited",\n setup: visitedSetup\n }, {\n name: "keyinsert",\n flavour: "insert",\n trigger: "key",\n setup: keySetup\n }, {\n name: "replace",\n flavour: "replace",\n trigger: "link",\n setup: linkSetup\n }, {\n name: "timedreplace",\n flavour: "replace",\n trigger: "time",\n setup: timeSetup\n }, {\n name: "mousereplace",\n flavour: "replace",\n trigger: "mouse",\n setup: mouseSetup\n }, {\n name: "hoverreplace",\n flavour: "replace",\n trigger: "hover",\n setup: hoverSetup\n }, {\n name: "revision",\n flavour: "replace",\n trigger: "revisemacro",\n setup: revisionSetup\n }, {\n name: "keyreplace",\n flavour: "replace",\n trigger: "key",\n setup: keySetup\n }, {\n name: "timedremove",\n flavour: "remove",\n trigger: "time",\n setup: timeSetup\n }, {\n name: "mouseremove",\n flavour: "remove",\n trigger: "mouse",\n setup: mouseSetup\n }, {\n name: "hoverremove",\n flavour: "remove",\n trigger: "hover",\n setup: hoverSetup\n }, {\n name: "removal",\n flavour: "remove",\n trigger: "revisemacro",\n setup: revisionSetup\n }, {\n name: "once",\n flavour: "remove",\n trigger: "visited",\n setup: visitedSetup\n }, {\n name: "keyremove",\n flavour: "remove",\n trigger: "key",\n setup: keySetup\n }, {\n name: "continue",\n flavour: "continue",\n trigger: "link",\n setup: linkSetup\n }, {\n name: "timedcontinue",\n flavour: "continue",\n trigger: "time",\n setup: timeSetup\n }, {\n name: "mousecontinue",\n flavour: "continue",\n trigger: "mouse",\n setup: mouseSetup\n }, {\n name: "keycontinue",\n flavour: "continue",\n trigger: "key",\n setup: keySetup\n }, {\n name: "cycle",\n flavour: "cycle",\n trigger: "revisemacro",\n setup: revisionSetup\n }, {\n name: "mousecycle",\n flavour: "cycle",\n trigger: "mouse",\n setup: mouseSetup\n }, {\n name: "timedcycle",\n flavour: "cycle",\n trigger: "time",\n setup: timeSetup\n }, {\n name: "keycycle",\n flavour: "replace",\n trigger: "key",\n setup: keySetup\n }].forEach(function(e) {\n e.handler = revisionSpanHandler;\n e.shorthand = (["link", "mouse", "hover"].indexOf(e.trigger) > -1);\n macros[e.name] = e;\n macros["end" + e.name] = nullobj;\n begintags.push(e.name);\n endtags.push("end" + e.name)\n });\n\n function insideDepartingSpan(elem) {\n var r = elem.parentNode;\n while (!r.classList.contains("passage")) {\n if (r.classList.contains("revision-span-out")) {\n return true\n }\n r = r.parentNode\n }\n }\n\n function reviseAll(rt, rname) {\n var rall = document.querySelectorAll(".passage [data-flavour]." + rname),\n ret = false;\n for (var i = 0; i < rall.length; i++) {\n if (!insideDepartingSpan(rall[i])) {\n ret = revise(rt, rall[i]) || ret\n }\n }\n return ret\n }\n\n function revise(rt, r, notrans) {\n var ind2, curr, next, ind = -1,\n rev = (rt == "revert"),\n rnd = (rt.indexOf("random") > -1),\n fl = r.getAttribute("data-flavour"),\n rc = r.childNodes,\n cyc = (fl == "cycle"),\n rcl = rc.length - 1;\n\n function doToGainerSpans(n, fn) {\n for (var k = n - 1; k >= 0; k--) {\n if (rc[k + 1].classList.contains("gains")) {\n fn(rc[k], notrans)\n } else {\n break\n }\n }\n }\n for (var k = 0; k <= rcl; k++) {\n if (rc[k].getAttribute("data-enabled") == "true") {\n ind = k\n }\n }\n if (rev) {\n ind -= 1\n }\n curr = (ind >= 0 ? rc[ind] : (cyc ? rc[rcl] : null));\n ind2 = ind;\n if (rnd) {\n ind2 = (ind + (Math.floor(Math.random() * rcl))) % rcl\n }\n next = ((ind2 < rcl) ? rc[ind2 + 1] : (cyc ? rc[0] : null));\n var docurr = (rev ? showVer : hideVer);\n var donext = (rev ? hideVer : showVer);\n var currfn = function() {\n if (!(next && next.classList.contains("gains")) || rnd) {\n docurr(curr, notrans);\n doToGainerSpans(ind, docurr, notrans)\n }\n };\n var nextfn = function() {\n donext(next, notrans);\n if (rnd) {\n doToGainerSpans(ind2 + 1, donext, notrans)\n }\n };\n if (!rev) {\n currfn();\n nextfn()\n } else {\n nextfn();\n currfn()\n }\n return (cyc ? true : (rev ? (ind > 0) : (ind2 < rcl - 1)))\n }\n macros.revert = macros.revise = macros.randomise = macros.randomize = {\n handler: function(a, b, c) {\n var l, rev, rname;\n\n function disableLink(l) {\n l.style.display = "none"\n }\n\n function enableLink(l) {\n l.style.display = "inline"\n }\n\n function updateLink(l) {\n if (l.className.indexOf("random") > -1) {\n enableLink(l);\n return\n }\n var rall = document.querySelectorAll(".passage [data-flavour]." + rname),\n cannext, canprev, i, ind, r, fl;\n for (i = 0; i < rall.length; i++) {\n r = rall[i], fl = r.getAttribute("data-flavour");\n if (insideDepartingSpan(r)) {\n continue\n }\n if (fl == "cycle") {\n cannext = canprev = true\n } else {\n if (r.firstChild.getAttribute("data-enabled") == !1 + "") {\n canprev = true\n }\n if (r.lastChild.getAttribute("data-enabled") == !1 + "") {\n cannext = true\n }\n }\n }\n var can = (l.classList.contains("revert") ? canprev : cannext);\n (can ? enableLink : disableLink)(l)\n }\n\n function toggleText(w) {\n w.classList.toggle(rl + "Enabled");\n w.classList.toggle(rl + "Disabled");\n w.style.display = ((w.style.display == "none") ? "inline" : "none")\n }\n var rl = "reviseLink";\n if (c.length < 2) {\n throwError(a, b + " macro needs 2 parameters");\n return\n }\n rname = c.shift().replace(" ", "_");\n l = Wikifier.createInternalLink(a, null);\n l.className = "internalLink " + rl + " " + rl + "_" + rname + " " + b;\n var v = "";\n var end = false;\n var out = false;\n if (c.length > 1 && c[0][0] == "$") {\n v = c[0].slice(1);\n c.shift()\n }\n switch (c[c.length - 1]) {\n case "end":\n end = true;\n c.pop();\n break;\n case "out":\n out = true;\n c.pop();\n break\n }\n var h = state.history[0].variables;\n for (var i = 0; i < c.length; i++) {\n var on = (i == Math.max(c.indexOf(h[v]), 0));\n var d = insertElement(null, "span", null, rl + ((on) ? "En" : "Dis") + "abled");\n if (on) {\n h[v] = c[i];\n l.setAttribute("data-cycle", i)\n } else {\n d.style.display = "none"\n }\n insertText(d, c[i]);\n l.appendChild(d)\n }\n l.onclick = function() {\n reviseAll(b, rname);\n var t = this.childNodes,\n u = this.getAttribute("data-cycle") - 0,\n m = t.length,\n n, lall, i;\n if ((end || out) && u == m - (end ? 2 : 1)) {\n if (end) {\n n = this.removeChild(t[u + 1]);\n n.className = rl + "End";\n n.style.display = "inline";\n this.parentNode.replaceChild(n, this)\n } else {\n this.parentNode.removeChild(this);\n return\n }\n } else {\n toggleText(t[u]);\n u = (u + 1) % m;\n if (v) {\n h[v] = c[u]\n }\n toggleText(t[u]);\n this.setAttribute("data-cycle", u)\n }\n lall = document.getElementsByClassName(rl + "_" + rname);\n for (i = 0; i < lall.length; i++) {\n updateLink(lall[i])\n }\n };\n l = null\n }\n };\n macros.mouserevise = macros.hoverrevise = {\n handler: function(a, b, c, d) {\n var endtags = ["end" + b],\n evt = (window.onmouseenter === null ? "onmouseenter" : "onmouseover"),\n t = tagcontents(d, [b], endtags, endtags, d.source.indexOf(">>", d.matchStart) + 2);\n if (t) {\n var rname = c[0].replace(" ", "_"),\n h = insertElement(a, "span", null, "hoverrevise hoverrevise_" + rname),\n f = function() {\n var done = !reviseAll("revise", rname);\n if (b != "hoverrevise" && done) {\n this[evt] = null\n }\n };\n new Wikifier(h, t[0]);\n if (b == "hoverrevise") {\n h.onmouseover = f;\n h.onmouseout = function() {\n reviseAll("revert", rname)\n }\n } else {\n h[evt] = f\n }\n h = null\n }\n }\n };\n macros.instantrevise = {\n handler: function(a, b, c, d) {\n reviseAll("revise", c[0].replace(" ", "_"))\n }\n };\n macros.endmouserevise = nullobj;\n macros.endhoverrevise = nullobj\n}());
<<loopsound $barking 0.15>>\s\n<<set $currentLoops.push($barking) >>\s\n<<timedcontinue 2s>><<display "Typing">>\s
<<display "Notification">>
<<display "TrafficCricketsQuieter">>\s
<<display "Notification">>\s
<<display "TrafficCricketsLouder">>\s
<<playsound "audio/lightswitch.mp3" 0.40>>\s
by Tory Hoke\s
<<fadeoutsound $city_ambience_crickets 0.10 2000>>\s\n<<set $currentLoops.splice($currentLoops.indexOf($city_ambience_crickets),1)>>\s\n<<fadeinsound $city_ambience_plain 0.10 2000>>\s\n<<set $currentLoops.push($city_ambience_plain)>>\s
<<unloopsound $barking>>\s\n<<set $currentLoops.splice($currentLoops.indexOf($barking),1)>>\s