code:
/***********************************************************************************************************************

	it-IT.js – Italiano

	Localization by: Karime Chehbouni.

	Copyright © 2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'gioco';
	l10nStrings.aborting = 'Interrompendo';
	l10nStrings.cancel   = 'Annulla';
	l10nStrings.close    = 'Chiudi';
	l10nStrings.ok       = 'OK';

	/* Errors. */
	l10nStrings.errorTitle              = 'Errore';
	l10nStrings.errorToggle             = 'Attiva visualizzazione errori';
	l10nStrings.errorNonexistentPassage = 'il passaggio "{passage}" non esiste'; // NOTE: `passage` is supplied locally
	l10nStrings.errorSaveMissingData    = 'al salvataggio mancano i dati richiesti. Il file caricato non è un salvataggio o il salvataggio è danneggiato';
	l10nStrings.errorSaveIdMismatch     = 'il salvataggio non proviene da {identity}';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Il tuo browser necessita di \\ ha disabilitato';
	l10nStrings._warningOutroDegraded = ', quindi quest\'{identity} è in esecuzione in una modalità degradata. Puoi continuare, tuttavia alcune parti potrebbero non funzionare correttamente';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} l\'API di archiviazione web{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} alcune delle capacità richieste da {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Mostra la barra debug';
	l10nStrings.debugBarNoWatches   = '\u2014 nessuna sorveglianza attiva \u2014';
	l10nStrings.debugBarAddWatch    = 'Aggiungi sorveglianza';
	l10nStrings.debugBarDeleteWatch = 'Elimina sorveglianza';
	l10nStrings.debugBarWatchAll    = 'Sorveglia tutti';
	l10nStrings.debugBarWatchNone   = 'Elimina tutti';
	l10nStrings.debugBarLabelAdd    = 'Aggiungi';
	l10nStrings.debugBarLabelWatch  = 'Sorveglia';
	l10nStrings.debugBarLabelTurn   = 'Turno'; // (noun) chance to act (in a game), moment, period
	l10nStrings.debugBarLabelViews  = 'Visualizzazioni';
	l10nStrings.debugBarViewsToggle = 'Mostra visualizzazioni debug';
	l10nStrings.debugBarWatchToggle = 'Mostra pannello di sorveglianza';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Mostra barra UI';
	l10nStrings.uiBarBackward = 'Vai indietro nella cronologia di {identity}';
	l10nStrings.uiBarForward  = 'Vai avanti nella cronologia di {identity}';
	l10nStrings.uiBarJumpto   = 'Salta a un punto specifico nella cronologia di {identity}';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Salta A';
	l10nStrings.jumptoTurn        = 'Turno'; // (noun) chance to act (in a game), moment, period
	l10nStrings.jumptoUnavailable = 'Nessun punto di salto attualmente disponibile\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Salvataggi';
	l10nStrings.savesDisallowed  = 'Salvare non è stato consentito in questo passaggio.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} le capacità necessarie per supportare salvataggi, quindi i salvataggi sono stati disabilitati per questa sessione.';
	l10nStrings.savesLabelAuto   = 'Salvataggio Automatico';
	l10nStrings.savesLabelDelete = 'Elimina';
	l10nStrings.savesLabelExport = 'Salva su Disco\u2026';
	l10nStrings.savesLabelImport = 'Carica dal Disco\u2026';
	l10nStrings.savesLabelLoad   = 'Carica';
	l10nStrings.savesLabelClear  = 'Elimina Tutto';
	l10nStrings.savesLabelSave   = 'Salva';
	l10nStrings.savesLabelSlot   = 'Slot';
	l10nStrings.savesUnavailable = 'Nessuno slot di salvataggio trovato\u2026';
	l10nStrings.savesUnknownDate = 'sconosciuto';

	/* Settings. */
	l10nStrings.settingsTitle = 'Impostazioni';
	l10nStrings.settingsOff   = 'Off';
	l10nStrings.settingsOn    = 'On';
	l10nStrings.settingsReset = 'Ripristina Predefiniti';

	/* Restart. */
	l10nStrings.restartTitle  = 'Ricomincia';
	l10nStrings.restartPrompt = 'Siete certi di voler ricominciare? Il progresso non salvato verrà perso.';

	/* Share. */
	l10nStrings.shareTitle = 'Condividi';

	/* Alert. */
	l10nStrings.alertTitle = 'Segnalazione';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Caricamento Automatico';
	l10nStrings.autoloadCancel = 'Vai all\'inizio';
	l10nStrings.autoloadOk     = 'Carica salvataggio automatico';
	l10nStrings.autoloadPrompt = 'È presente un salvataggio automatico. Caricarlo adesso o andare all\'inizio?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Indietro'; // (verb) rewind, revert
	l10nStrings.macroReturnText = 'Ritorna'; // (verb) go/send back
})();


code:
/***********************************************************************************************************************

	l10n-template.js – Localization Template

	Copyright © 2019–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

/*
	ATTENTION TRANSLATORS

	The capitalization and punctuation used within the default replacement strings is
	deliberate, especially within the error and warning strings.  You would do well
	to keep your translations similar when possible.

	Replacement patterns have the format `{NAME}` (e.g. {identity}), where NAME is the
	name of a property within either the `l10nStrings` object or, in a few cases, an
	object supplied locally where the string is used—these instances will be commented.

	By convention, properties starting with an underscore (e.g. _warningIntroLacking)
	are used as templates, only being included within other localized strings.  Feel
	free to add your own if that makes localization easier—e.g. for gender, plurals,
	and whatnot.  As an example, the default replacement strings make use of this to
	handle various warning intros and outros.

	In use, replacement patterns are replaced recursively, so replacement strings may
	contain patterns whose replacements contain other patterns.  Because replacement is
	recursive, care must be taken to ensure infinite loops are not created—the system
	will detect an infinite loop and throw an error.

	FOR MORE INFORMATION: http://www.motoslave.net/sugarcube/2/docs/#guide-localization

	ALSO NOTE: There are two versions of this file within the repository.

		* The current release version, which is on the `master` branch.
			https://raw.githubusercontent.com/tmedwards/sugarcube-2/master/locale/l10n-template.js

		* The development version, which is on the `develop` branch.
			https://raw.githubusercontent.com/tmedwards/sugarcube-2/develop/locale/l10n-template.js

	You will likely want to use the development version.
*/
(function () {
	/* General. */
	l10nStrings.identity = 'game';
	l10nStrings.aborting = 'Aborting';
	l10nStrings.cancel   = 'Cancel';
	l10nStrings.close    = 'Close';
	l10nStrings.ok       = 'OK';

	/* Errors. */
	l10nStrings.errorTitle              = 'Error';
	l10nStrings.errorToggle             = 'Toggle the error view';
	l10nStrings.errorNonexistentPassage = 'the passage "{passage}" does not exist'; // NOTE: `passage` is supplied locally
	l10nStrings.errorSaveDiskLoadFailed = 'failed to load save file from disk';
	l10nStrings.errorSaveMissingData    = 'save is missing required data. Either the loaded file is not a save or the save has become corrupted';
	l10nStrings.errorSaveIdMismatch     = 'save is from the wrong {identity}';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Your browser either lacks or has disabled';
	l10nStrings._warningOutroDegraded = ', so this {identity} is running in a degraded mode. You may be able to continue, however, some parts may not work properly.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} the Web Storage API{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} some of the capabilities required by this {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Toggle the debug bar';
	l10nStrings.debugBarNoWatches   = '\u2014 no watches set \u2014';
	l10nStrings.debugBarAddWatch    = 'Add watch';
	l10nStrings.debugBarDeleteWatch = 'Delete watch';
	l10nStrings.debugBarWatchAll    = 'Watch all';
	l10nStrings.debugBarWatchNone   = 'Delete all';
	l10nStrings.debugBarLabelAdd    = 'Add';
	l10nStrings.debugBarLabelWatch  = 'Watch';
	l10nStrings.debugBarLabelTurn   = 'Turn'; // (noun) chance to act (in a game), moment, period
	l10nStrings.debugBarLabelViews  = 'Views';
	l10nStrings.debugBarViewsToggle = 'Toggle the debug views';
	l10nStrings.debugBarWatchToggle = 'Toggle the watch panel';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Toggle the UI bar';
	l10nStrings.uiBarBackward = 'Go backward within the {identity} history';
	l10nStrings.uiBarForward  = 'Go forward within the {identity} history';
	l10nStrings.uiBarJumpto   = 'Jump to a specific point within the {identity} history';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Jump To';
	l10nStrings.jumptoTurn        = 'Turn'; // (noun) chance to act (in a game), moment, period
	l10nStrings.jumptoUnavailable = 'No jump points currently available\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Saves';
	l10nStrings.savesDisallowed  = 'Saving has been disallowed on this passage.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} the capabilities required to support saves, so saves have been disabled for this session.';
	l10nStrings.savesLabelAuto   = 'Autosave';
	l10nStrings.savesLabelDelete = 'Delete';
	l10nStrings.savesLabelExport = 'Save to Disk\u2026';
	l10nStrings.savesLabelImport = 'Load from Disk\u2026';
	l10nStrings.savesLabelLoad   = 'Load';
	l10nStrings.savesLabelClear  = 'Delete All';
	l10nStrings.savesLabelSave   = 'Save';
	l10nStrings.savesLabelSlot   = 'Slot';
	l10nStrings.savesUnavailable = 'No save slots found\u2026';
	l10nStrings.savesUnknownDate = 'unknown';

	/* Settings. */
	l10nStrings.settingsTitle = 'Settings';
	l10nStrings.settingsOff   = 'Off';
	l10nStrings.settingsOn    = 'On';
	l10nStrings.settingsReset = 'Reset to Defaults';

	/* Restart. */
	l10nStrings.restartTitle  = 'Restart';
	l10nStrings.restartPrompt = 'Are you sure that you want to restart? Unsaved progress will be lost.';

	/* Share. */
	l10nStrings.shareTitle = 'Share';

	/* Alert. */
	l10nStrings.alertTitle = 'Alert';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Autoload';
	l10nStrings.autoloadCancel = 'Go to start';
	l10nStrings.autoloadOk     = 'Load autosave';
	l10nStrings.autoloadPrompt = 'An autosave exists. Load it now or go to the start?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Back'; // (verb) rewind, revert
	l10nStrings.macroReturnText = 'Return'; // (verb) go/send back
})();


code:
/***********************************************************************************************************************

	nl.js – Dutch

	Localization by: Sjoerd Hekking.

	Copyright © 2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'Spel';
	l10nStrings.aborting = 'Afbreken';
	l10nStrings.cancel   = 'Annuleren';
	l10nStrings.close    = 'Sluiten';
	l10nStrings.ok       = 'Oke';

	/* Errors. */
	l10nStrings.errorTitle              = 'Fout';
	l10nStrings.errorToggle             = 'Schakel de foutweergave in';
	l10nStrings.errorNonexistentPassage = 'De passage "{passage}" bestaat niet'; // NOTE: `passage` is supplied locally
	l10nStrings.errorSaveDiskLoadFailed = 'gefaald om de opslag te laden vanuit de schijf';
	l10nStrings.errorSaveMissingData    = 'De opslag ontbreekt de vereiste gegevens. Ofwel het geladen bestand is geen save of de save is beschadigd geraakt';
	l10nStrings.errorSaveIdMismatch     = 'De opslag is van de foute {identity}';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Uw browser ontbreekt of heeft uitgeschakeld';
	l10nStrings._warningOutroDegraded = ', dus deze {identity} draait in een gedegradeerde modus. Mogelijk kunt u doorgaan, maar sommige onderdelen werken mogelijk niet goed.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} de webopslag-API{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} enkele van de mogelijkheden die vereist zijn voor deze {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Schakel de foutopsporingsbalk in';
	l10nStrings.debugBarNoWatches   = '\u2014 geen kijkers ingesteld \u2014';
	l10nStrings.debugBarAddWatch    = 'Voeg kijker toe';
	l10nStrings.debugBarDeleteWatch = 'Verwijder kijker';
	l10nStrings.debugBarWatchAll    = 'Bekijk alles';
	l10nStrings.debugBarWatchNone   = 'Verwijder alles';
	l10nStrings.debugBarLabelAdd    = 'Toevoegen';
	l10nStrings.debugBarLabelWatch  = 'Kijker';
	l10nStrings.debugBarLabelTurn   = 'Ronde'; // (noun) chance to act (in a game), moment, period
	l10nStrings.debugBarLabelViews  = 'Weergave';
	l10nStrings.debugBarViewsToggle = 'Schakel de foutopsporingsweergaven in';
	l10nStrings.debugBarWatchToggle = 'Schakel het kijkpaneel in';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Schakel de UI-balk in';
	l10nStrings.uiBarBackward = 'Ga terug in de {identity} geschiedenis';
	l10nStrings.uiBarForward  = 'Ga vooruit binnen de {identity} geschiedenis';
	l10nStrings.uiBarJumpto   = 'Spring naar een specifiek punt in de {identity} geschiedenis';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Spring naar';
	l10nStrings.jumptoTurn        = 'Ronde'; // (noun) chance to act (in a game), moment, period
	l10nStrings.jumptoUnavailable = 'Momenteel geen historiepunten beschikbaar\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Opslaan';
	l10nStrings.savesDisallowed  = 'Op deze passage is opslaan niet toegestaan.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} de mogelijkheden die nodig zijn om saves te ondersteunen, dus saves zijn uitgeschakeld voor deze sessie.';
	l10nStrings.savesLabelAuto   = 'Auto-opslag';
	l10nStrings.savesLabelDelete = 'Verwijder';
	l10nStrings.savesLabelExport = 'Sla op naar opslag\u2026';
	l10nStrings.savesLabelImport = 'Laad vanuit opslag\u2026';
	l10nStrings.savesLabelLoad   = 'Laad';
	l10nStrings.savesLabelClear  = 'Verwijder alles';
	l10nStrings.savesLabelSave   = 'Opslaan';
	l10nStrings.savesLabelSlot   = 'Slot';
	l10nStrings.savesUnavailable = 'Geen opslag sloten gevonden\u2026';
	l10nStrings.savesUnknownDate = 'onbekend';

	/* Settings. */
	l10nStrings.settingsTitle = 'Instellingen';
	l10nStrings.settingsOff   = 'Uit';
	l10nStrings.settingsOn    = 'Aan';
	l10nStrings.settingsReset = 'Herstel naar begin waarde';

	/* Restart. */
	l10nStrings.restartTitle  = 'Herstart';
	l10nStrings.restartPrompt = 'Weet u zeker dat u opnieuw wilt opstarten? Niet-opgeslagen voortgang gaat verloren.';

	/* Share. */
	l10nStrings.shareTitle = 'Delen';

	/* Alert. */
	l10nStrings.alertTitle = 'Waarschuwing';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Automatisch laden';
	l10nStrings.autoloadCancel = 'Ga naar start';
	l10nStrings.autoloadOk     = 'Laad automatische opslag';
	l10nStrings.autoloadPrompt = 'Er bestaat een autosave. Nu laden of naar start gaan?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Terugspoelen'; // (verb) rewind, revert
	l10nStrings.macroReturnText = 'Teruggaan'; // (verb) go/send back
})();


code:
/***********************************************************************************************************************

	pl.js – Polski

	Localization by: ciupac.

	Copyright © 2018 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

------------------------------------------------------------------------------------------------------------------------

	Notes from the original translator (ciupac)
	===========================================

	The following Polish localization represents an attempt to find a middle ground
	between a literal translation and idiomatic use of Polish IT language.

	I have included comments next to potentionally controversial choices, and also
	to mark where the current logical organization is incompatible with the language
	itself (`BUG:`) and where certain things had to be rephrased for lack of the
	equivalent term(s) (`NOTE:`) or due to grammatical/semantic ambiguity.

	I am not a professional translator, and therefore I relied mostly on my intuition,
	which may have been incorrect. Input from persons with more experience in this
	field is appreciated.

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	// BUG: Polish has cases, so one noun in the nominative won’t cut it.
	l10nStrings.identity = 'gra';
	// NOTE: No direct, single corresponding term that would be equivalent to "Aborting" in the use context (what I wrote here instead is "Operation interrupted").
	l10nStrings.aborting = 'Przerwano operację';
	l10nStrings.cancel   = 'Anuluj';
	l10nStrings.close    = 'Zamknij';
	l10nStrings.ok       = 'OK';

	/* Errors. */
	l10nStrings.errorTitle              = 'Błąd';
	// NOTE: No single-word term for verb "toggle" in Polish, must use the equivalent of "show/hide" everywhere.
	l10nStrings.errorToggle             = 'Pokaż/ukryj widok błędu';
	// NOTE: The quoting style of Polish opens with U+201E („) and closes with U+201D (”). Second level uses single-quote equivalents U+201A and U+2019.
	l10nStrings.errorNonexistentPassage = 'żądany ustęp „{passage}” nie istnieje';
	l10nStrings.errorSaveMissingData    = 'wczytany plik nie zawiera wymaganych danych. Plik może nie być plikiem zapisu gry lub może być uszkodzony';
	l10nStrings.errorSaveIdMismatch     = 'wczytany plik zapisu nie pochodzi z tej gry';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Twoja przeglądarka nie wspiera lub ma wyłączone';
	l10nStrings._warningOutroDegraded = ', dlatego {identity} pracuje w zubożonym trybie. Jest możliwe, że da się kontynuować grę, lecz niektóre elementy mogą nie działać.';
	// NOTE: Included English keyword for use in Google searches.
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} funkcje przechowywania danych (Web Storage API){_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} niektóre funkcje wymagane przez tą grę{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Pokaż/ukryj okienko debuggera';
	l10nStrings.debugBarNoWatches   = '\u2014 brak ustawionych podglądów zmiennych \u2014';
	l10nStrings.debugBarAddWatch    = 'Dodaj podgląd';
	l10nStrings.debugBarDeleteWatch = 'Usuń podgląd';
	l10nStrings.debugBarWatchAll    = 'Włącz podgląd wszystkiego';
	l10nStrings.debugBarWatchNone   = 'Usuń wszystkie podglądy';
	l10nStrings.debugBarLabelAdd    = 'Dodaj';
	l10nStrings.debugBarLabelWatch  = 'Podglądy';
	l10nStrings.debugBarLabelTurn   = 'Tura';
	l10nStrings.debugBarLabelViews  = 'Widoki';
	// NOTE: I have found "views" to be too vague, so I mention that they refer to macros.
	l10nStrings.debugBarViewsToggle = 'Pokaż/ukryj widoki debugowania makr';
	// NOTE: Same, wrt. "watches" referring to variables.
	l10nStrings.debugBarWatchToggle = 'Pokaż/ukryj panel podglądów zmiennych';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Pokaż/ukryj panel boczny';
	l10nStrings.uiBarBackward = 'Krok do tyłu w historii gry';
	l10nStrings.uiBarForward  = 'Krok do przodu w historii gry';
	l10nStrings.uiBarJumpto   = 'Skocz do konkretnego punktu gry';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Skocz do';
	l10nStrings.jumptoTurn        = 'Tura';
	l10nStrings.jumptoUnavailable = 'Obecnie brak punktów, do których można by przeskoczyć\u2026';

	/* Saves. */
	// NOTE: Assuming "Save" is used as a verb here.
	l10nStrings.savesTitle       = 'Zapisz';
	l10nStrings.savesDisallowed  = 'Zapisywanie zostało wyłączone w tym ustępie.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} funkcje niezbędne do zapisu danych, zatem zapis i odczyt danych nie jest możliwy w tej sesji.';
	l10nStrings.savesLabelAuto   = 'Zapis automatyczny';
	l10nStrings.savesLabelDelete = 'Usuń';
	// NOTE: Using equivalent expression "Save to file" as it is more commonly encountered in Polish.
	l10nStrings.savesLabelExport = 'Zapisz do pliku\u2026';
	// NOTE: Using equivalent "Read from file", see reasons above.
	l10nStrings.savesLabelImport = 'Wczytaj z pliku\u2026';
	l10nStrings.savesLabelLoad   = 'Wczytaj';
	l10nStrings.savesLabelClear  = 'Usuń wszystkie';
	// BUG: "Save" not clear if used as a noun or a verb; cannot be overloaded like this by some languages. Assuming verb.
	l10nStrings.savesLabelSave   = 'Zapisz';
	// NOTE: No direct equivalent to "Slot" noun that would be commonly-accepted in computing terminology; using generic term meaning "place", "space", "location" instead.
	l10nStrings.savesLabelSlot   = 'Miejsce';
	l10nStrings.savesUnavailable = 'Nie znaleziono miejsc do zapisu danych\u2026';
	// NOTE: Assuming we're referring to a date, which is feminine.
	l10nStrings.savesUnknownDate = 'nieznana';

	/* Settings. */
	l10nStrings.settingsTitle = 'Ustawienia';
	l10nStrings.settingsOff   = 'Wyłączone';
	l10nStrings.settingsOn    = 'Włączone';
	l10nStrings.settingsReset = 'Przywróć wartości domyślne';

	/* Restart. */
	l10nStrings.restartTitle  = 'Uruchom ponownie';
	// NOTE: Mirroring the usual habit of putting an exclamation mark after a data loss warning.
	l10nStrings.restartPrompt = 'Czy jesteś pewien, że chcesz zacząć grę od początku? Niezapisany postęp zostanie utracony!';

	/* Share. */
	l10nStrings.shareTitle = 'Udostępnij';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Załadowanie automatyczne';
	l10nStrings.autoloadCancel = 'Rozpocznij od początku';
	l10nStrings.autoloadOk     = 'Wczytaj plik automatycznego zapisu';
	l10nStrings.autoloadPrompt = 'Istnieje plik automatycznego zapisu. Załadować go teraz czy zacząć od początku?';

	/* Macros. */
	// NOTE: These two are contentious, since there is no clear-cut difference.
	l10nStrings.macroBackText   = 'Wstecz';
	l10nStrings.macroReturnText = 'Wróć';
})();


code:
/***********************************************************************************************************************

	pt-BR.js – Português (Brazil)

	Localization by: Janos Biro.

	Copyright © 2018 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'jogo';
	l10nStrings.aborting = 'Abortando';
	l10nStrings.cancel   = 'Cancelar';
	l10nStrings.close    = 'Fechar';
	l10nStrings.ok       = 'OK';

	/* Errors. */
	l10nStrings.errorTitle              = 'Erro';
	l10nStrings.errorToggle             = 'Alternar a visualização de erro';
	l10nStrings.errorNonexistentPassage = 'a passagem "{passage}" não existe';
	l10nStrings.errorSaveMissingData    = 'arquivo está incompleto. Ou não é um arquivo de jogo ou o arquivo está corrompido';
	l10nStrings.errorSaveIdMismatch     = 'arquivo do {identity} errado';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Seu navegador ou não tem ou desativou';
	l10nStrings._warningOutroDegraded = ', então esse {identity} está rodando no modo degradado. Você pode continuar, porém algumas partes podem não funcionar direito.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} o Web Storage API{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} algum componente requerido por este {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Alternar a barra de depuração';
	l10nStrings.debugBarNoWatches   = '\u2014 sem vigias \u2014';
	l10nStrings.debugBarAddWatch    = 'Adicionar vigia';
	l10nStrings.debugBarDeleteWatch = 'Apagar vigia';
	l10nStrings.debugBarWatchAll    = 'Vigiar tudo';
	l10nStrings.debugBarWatchNone   = 'Apagar tudo';
	l10nStrings.debugBarLabelAdd    = 'Adicionar';
	l10nStrings.debugBarLabelWatch  = 'Vigiar';
	l10nStrings.debugBarLabelTurn   = 'Virar';
	l10nStrings.debugBarLabelViews  = 'Visualizações';
	l10nStrings.debugBarViewsToggle = 'Alternar visualizações de depuração';
	l10nStrings.debugBarWatchToggle = 'Alternar o painel de vigia';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Alternar a barra de interface';
	l10nStrings.uiBarBackward = 'Voltar na história do {identity}';
	l10nStrings.uiBarForward  = 'Avançar na história do {identity}';
	l10nStrings.uiBarJumpto   = 'Pular para um ponto específico da história do {identity}';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Pular para';
	l10nStrings.jumptoTurn        = 'Vez';
	l10nStrings.jumptoUnavailable = 'Sem pontos de salto disponíveis\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Salvar';
	l10nStrings.savesDisallowed  = 'O salvamento foi desativado nessa passagem.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} o suporte necessário, então a opção de salvar está desativada nesta seção.';
	l10nStrings.savesLabelAuto   = 'Salvamento automático';
	l10nStrings.savesLabelDelete = 'Apagar';
	l10nStrings.savesLabelExport = 'Salvar para arquivo\u2026';
	l10nStrings.savesLabelImport = 'Carregar de arquivo\u2026';
	l10nStrings.savesLabelLoad   = 'Carregar';
	l10nStrings.savesLabelClear  = 'Apagar tudo';
	l10nStrings.savesLabelSave   = 'Salvar';
	l10nStrings.savesLabelSlot   = 'Espaço vazio';
	l10nStrings.savesUnavailable = 'Sem espaço vazio\u2026';
	l10nStrings.savesUnknownDate = 'data desconhecida';

	/* Settings. */
	l10nStrings.settingsTitle = 'Configurações';
	l10nStrings.settingsOff   = 'Desligado';
	l10nStrings.settingsOn    = 'Ligado';
	l10nStrings.settingsReset = 'Restaurar padrões';

	/* Restart. */
	l10nStrings.restartTitle  = 'Recomeçar';
	l10nStrings.restartPrompt = 'Tem certeza que quer recomeçar? O progresso não salvo será perdido.';

	/* Share. */
	l10nStrings.shareTitle = 'Compartilhar';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Salvamento automático';
	l10nStrings.autoloadCancel = 'Ir para o começo';
	l10nStrings.autoloadOk     = 'Carregar o salvamento automático';
	l10nStrings.autoloadPrompt = 'Um salvamento automático existe. Carregar agora ou ir para o começo?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Voltar';
	l10nStrings.macroReturnText = 'Retornar';
})();


code:
/***********************************************************************************************************************

	pt-PT.js – Português (Portugal)

	Localization by: Magma.

	Copyright © 2017–2018 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'jogo';
	l10nStrings.aborting = 'Abortar';
	l10nStrings.cancel   = 'Cancelar';
	l10nStrings.close    = 'Fechar';
	l10nStrings.ok       = 'OK';

	/* Errors. */
	l10nStrings.errorTitle              = 'Erro';
	l10nStrings.errorToggle             = 'Alternar a visualização de erro';
	l10nStrings.errorNonexistentPassage = 'a passagem "{passage}" não existe';
	l10nStrings.errorSaveMissingData    = 'o ficheiro não contem a informação necessária. Ou o ficheiro carregado não é correcto ou foi corrumpido';
	l10nStrings.errorSaveIdMismatch     = 'o ficheiro não pertence ao {identity}';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'O seu browser não tem esta opção ou a opção foi desabilitada';
	l10nStrings._warningOutroDegraded = ', portanto este {identity} não está a correr a 100%. Pode continuar, mas algumas partes não irão funcionar.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} o Web Storage API{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} algum componente requerido por este {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Alternar a barra de depuração';
	l10nStrings.debugBarNoWatches   = '\u2014 sem vigias \u2014';
	l10nStrings.debugBarAddWatch    = 'Adicionar vigia';
	l10nStrings.debugBarDeleteWatch = 'Apagar vigia';
	l10nStrings.debugBarWatchAll    = 'Vigiar tudo';
	l10nStrings.debugBarWatchNone   = 'Apagar tudo';
	l10nStrings.debugBarLabelAdd    = 'Adicionar';
	l10nStrings.debugBarLabelWatch  = 'Vigiar';
	l10nStrings.debugBarLabelTurn   = 'Virar';
	l10nStrings.debugBarLabelViews  = 'Visualizações';
	l10nStrings.debugBarViewsToggle = 'Alternar visualizações de depuração';
	l10nStrings.debugBarWatchToggle = 'Alternar o painel de vigia';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Alternar a barra de interface';
	l10nStrings.uiBarBackward = 'Voltar um passo atrás na história do {identity}';
	l10nStrings.uiBarForward  = 'Ir um passo a frente na história do {identity}';
	l10nStrings.uiBarJumpto   = 'Saltar para um ponto especifico na história do {identity}';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Saltar para';
	l10nStrings.jumptoTurn        = 'Vez';
	l10nStrings.jumptoUnavailable = 'Não existem pontos de salto disponíveis\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Jogos Guardados';
	l10nStrings.savesDisallowed  = 'Não se pode guardar o jogo nesta passagem. A opção foi desabilitada.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking} assim sendo como não é possivel guardar, a opção está desabilitada nesta sessão.';
	l10nStrings.savesLabelAuto   = 'Guardado Automaticamente';
	l10nStrings.savesLabelDelete = 'Apagar';
	l10nStrings.savesLabelExport = 'Salvar para o Disco\u2026';
	l10nStrings.savesLabelImport = 'Carregar do Disco\u2026';
	l10nStrings.savesLabelLoad   = 'Carregar';
	l10nStrings.savesLabelClear  = 'Apagar Tudo';
	l10nStrings.savesLabelSave   = 'Salvar';
	l10nStrings.savesLabelSlot   = 'Espaço Vazio';
	l10nStrings.savesUnavailable = 'Não existem Jogos Guardados\u2026';
	l10nStrings.savesUnknownDate = 'data desconhecida';

	/* Settings. */
	l10nStrings.settingsTitle = 'Opções';
	l10nStrings.settingsOff   = 'Desabilitar';
	l10nStrings.settingsOn    = 'Habilitar';
	l10nStrings.settingsReset = 'Reset para configurações iniciais';

	/* Restart. */
	l10nStrings.restartTitle  = 'Recomeçar';
	l10nStrings.restartPrompt = 'Tem a certeza que quer recomeçar? Qualquer progresso que não tenha sido guardado será perdido.';

	/* Share. */
	l10nStrings.shareTitle = 'Partilhar';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Guardado Automaticamente';
	l10nStrings.autoloadCancel = 'Voltar ao ínicio';
	l10nStrings.autoloadOk     = 'Carregar jogo guardado automaticamente';
	l10nStrings.autoloadPrompt = 'Um jogo guardado automaticamente está disponivel. Carregar agora ou voltar ao ínicio?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Para trás';
	l10nStrings.macroReturnText = 'Voltar';
})();


code:
/***********************************************************************************************************************

	ru.js – Ру́сский

	Localization by: Konstantin Kitmanov.

	Copyright © 2017–2020 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'игры';
	l10nStrings.aborting = 'Идет отмена';
	l10nStrings.cancel   = 'Отменить';
	l10nStrings.close    = 'Закрыть';
	l10nStrings.ok       = 'ОК';

	/* Errors. */
	l10nStrings.errorTitle              = 'Ошибка';
	l10nStrings.errorToggle             = 'Режим просмотра ошибок';
	l10nStrings.errorNonexistentPassage = 'Параграф "{passage}" не существует'; // NOTE: `passage` is supplied locally
	l10nStrings.errorSaveMissingData    = 'в сохранении нет необходимых данных. Сохранение было повреждено или загружен неверный файл';
	l10nStrings.errorSaveIdMismatch     = 'сохранение от другой {identity}';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Приносим извинения! В вашем браузере отсутствуют либо выключены необходимые функции';
	l10nStrings._warningOutroDegraded = ', так что включен ограниченный режим. Вы можете продолжать, но кое-что может работать некорректно.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} (Web Storage API){_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} (необходимые для {identity}){_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Панель отладки';
	l10nStrings.debugBarNoWatches   = '\u2014 отсутствуют отслеживания \u2014';
	l10nStrings.debugBarAddWatch    = 'Добавить отслеживание';
	l10nStrings.debugBarDeleteWatch = 'Удалить отслеживание';
	l10nStrings.debugBarWatchAll    = 'Отслеживать все';
	l10nStrings.debugBarWatchNone   = 'Удалить все';
	l10nStrings.debugBarLabelAdd    = 'Добавить';
	l10nStrings.debugBarLabelWatch  = 'Отслеживать';
	l10nStrings.debugBarLabelTurn   = 'Ход'; // (noun) chance to act (in a game), moment, period
	l10nStrings.debugBarLabelViews  = 'Макросы';
	l10nStrings.debugBarViewsToggle = 'Панель отладки макросов';
	l10nStrings.debugBarWatchToggle = 'Панель отслеживания';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'Открыть/закрыть панель навигации';
	l10nStrings.uiBarBackward = 'Назад по истории {identity}';
	l10nStrings.uiBarForward  = 'Вперед по истории {identity}';
	l10nStrings.uiBarJumpto   = 'Перейти в определенную точку истории {identity}';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Перейти на';
	l10nStrings.jumptoTurn        = 'Ход'; // (noun) chance to act (in a game), moment, period
	l10nStrings.jumptoUnavailable = 'В данный момент нет точек для перехода\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Сохранения';
	l10nStrings.savesDisallowed  = 'На этом параграфе сохранение запрещено.';
	l10nStrings.savesIncapable   = '{_warningIntroLacking}, так что сохранения невозможны в текущей сессии.';
	l10nStrings.savesLabelAuto   = 'Автосохранение';
	l10nStrings.savesLabelDelete = 'Удалить';
	l10nStrings.savesLabelExport = 'Сохранить на диск\u2026';
	l10nStrings.savesLabelImport = 'Загрузить с диска\u2026';
	l10nStrings.savesLabelLoad   = 'Загрузить';
	l10nStrings.savesLabelClear  = 'Удалить все';
	l10nStrings.savesLabelSave   = 'Сохранить';
	l10nStrings.savesLabelSlot   = 'Слот';
	l10nStrings.savesUnavailable = 'Слоты сохранения не обнаружены\u2026';
	l10nStrings.savesUnknownDate = 'неизвестно';

	/* Settings. */
	l10nStrings.settingsTitle = 'Настройки';
	l10nStrings.settingsOff   = 'Выкл.';
	l10nStrings.settingsOn    = 'Вкл.';
	l10nStrings.settingsReset = 'По умолчанию';

	/* Restart. */
	l10nStrings.restartTitle  = 'Начать сначала';
	l10nStrings.restartPrompt = 'Вы уверены, что хотите начать сначала? Несохраненный прогресс будет утерян.';

	/* Share. */
	l10nStrings.shareTitle = 'Поделиться';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Автосохранение';
	l10nStrings.autoloadCancel = 'Начать сначала';
	l10nStrings.autoloadOk     = 'Загрузить сохранение';
	l10nStrings.autoloadPrompt = 'Найдено автосохранение. Загрузить его или начать сначала?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Назад'; // (verb) rewind, revert
	l10nStrings.macroReturnText = 'Вернуться'; // (verb) go/send back
})();


code:
/***********************************************************************************************************************

	tr.js – Türkçe

	Localization by: Guena Varia.

	Copyright © 2017–2019 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

	For more information about the guidelines used to create this localization, see:
		http://www.motoslave.net/sugarcube/2/docs/#guide-localization

***********************************************************************************************************************/
/* global l10nStrings */
/* eslint-disable strict */

(function () {
	/* General. */
	l10nStrings.identity = 'oyun';
	l10nStrings.aborting = 'Durduruluyor';
	l10nStrings.cancel   = 'İptal';
	l10nStrings.close    = 'Kapat';
	l10nStrings.ok       = 'Tamam';

	/* Errors. */
	l10nStrings.errorTitle              = 'Hata';
	l10nStrings.errorToggle             = 'Hata görünümüne geç';
	l10nStrings.errorNonexistentPassage = 'bölüm "{passage}" mevcut değil';
	l10nStrings.errorSaveMissingData    = 'gerekli kayıt verisi eksik. Yüklenen dosya bir kayıt dosyası değil veya bozuldu';
	l10nStrings.errorSaveIdMismatch     = 'kayıt yanlış {identity}den';

	/* Warnings. */
	l10nStrings._warningIntroLacking  = 'Tarayıcınız eksik veya devre dışı';
	l10nStrings._warningOutroDegraded = ', yani bu {identity} bozulmuş bir modda çalışıyor. Devam etmek mümkün olabilir, ancak, bazı kısımlar düzgün çalışmayabilir.';
	l10nStrings.warningNoWebStorage   = '{_warningIntroLacking} Web Depolama API\'si{_warningOutroDegraded}';
	l10nStrings.warningDegraded       = '{_warningIntroLacking} bunun için lazım olan gereklilklerin bazıları {identity}{_warningOutroDegraded}';

	/* Debug bar. */
	l10nStrings.debugBarToggle      = 'Hata ayıklama çubuğunu aç/kapat';
	l10nStrings.debugBarNoWatches   = '\u2014 gözlem ayarlanmamış \u2014';
	l10nStrings.debugBarAddWatch    = 'Gözlem ekle';
	l10nStrings.debugBarDeleteWatch = 'Gözlemi sil';
	l10nStrings.debugBarWatchAll    = 'Tüm Gözlemler';
	l10nStrings.debugBarWatchNone   = 'Hepsini Sil';
	l10nStrings.debugBarLabelAdd    = 'Ekle';
	l10nStrings.debugBarLabelWatch  = 'Gözlem';
	l10nStrings.debugBarLabelTurn   = 'Dönüm';
	l10nStrings.debugBarLabelViews  = 'Görünümler';
	l10nStrings.debugBarViewsToggle = 'Hata ayıklama görünümünü değiştir';
	l10nStrings.debugBarWatchToggle = 'Gözlem panelini değiştir';

	/* UI bar. */
	l10nStrings.uiBarToggle   = 'UI barı değiştir';
	l10nStrings.uiBarBackward = '{identity} Geçmişinde geriye git';
	l10nStrings.uiBarForward  = '{identity} Geçmişinde ileriye git';
	l10nStrings.uiBarJumpto   = '{identity} Geçmişinde belirli bir noktaya git';

	/* Jump To. */
	l10nStrings.jumptoTitle       = 'Atla';
	l10nStrings.jumptoTurn        = 'Dönüm';
	l10nStrings.jumptoUnavailable = 'Şu anda mevcut atlama noktası yok\u2026';

	/* Saves. */
	l10nStrings.savesTitle       = 'Kayıtlar';
	l10nStrings.savesDisallowed  = 'Bu bölümde kayıt yapılmasına izin verilmedi.';
	l10nStrings.savesIncapable   = 'kayıtları desteklemek için lazım olan gereklilikler {_warningIntroLacking}, bu nedenle bu oturum için kayıtlat devre dışı bırakıldı.';
	l10nStrings.savesLabelAuto   = 'Oto Kayıt';
	l10nStrings.savesLabelDelete = 'Sil';
	l10nStrings.savesLabelExport = 'Diske kaydet\u2026';
	l10nStrings.savesLabelImport = 'Diskten yükle\u2026';
	l10nStrings.savesLabelLoad   = 'Yükle';
	l10nStrings.savesLabelClear  = 'Hepsini Sil';
	l10nStrings.savesLabelSave   = 'Kaydet';
	l10nStrings.savesLabelSlot   = 'Yuva';
	l10nStrings.savesUnavailable = 'Kayıt yuvası bulunamadı\u2026';
	l10nStrings.savesUnknownDate = 'bilinmeyen';

	/* Settings. */
	l10nStrings.settingsTitle = 'Ayarlar';
	l10nStrings.settingsOff   = 'Kapat';
	l10nStrings.settingsOn    = 'Aç';
	l10nStrings.settingsReset = 'Varsayılana Sıfırla';

	/* Restart. */
	l10nStrings.restartTitle  = 'Yeniden Başlat';
	l10nStrings.restartPrompt = 'Yeniden başlatmak istediğine emin misin ? Kaydedilmemiş ilerleme kaybedilecek.';

	/* Share. */
	l10nStrings.shareTitle = 'Paylaş';

	/* Autoload. */
	l10nStrings.autoloadTitle  = 'Oto Yükleme';
	l10nStrings.autoloadCancel = 'Başla';
	l10nStrings.autoloadOk     = 'Oto kayıdı yükle';
	l10nStrings.autoloadPrompt = 'Bir oto kayıt var. Şimdi yükle yada başlangıca git ?';

	/* Macros. */
	l10nStrings.macroBackText   = 'Geri';
	l10nStrings.macroReturnText = 'Geri Dön';
})();


SugarCube

type: opencollective

acorn: bin/acorn

type: github

autoprefixer: bin/autoprefixer

cssesc: bin/cssesc

type: patreon

which: bin/which

jsesc: bin/jsesc

semver: bin/semver

type: consulting

regjsparser: bin/parser

specificity: bin/specificity

terser: bin/terser

node-which: bin/node-which


author: Thomas Michael Edwards <thomasmedwards@gmail.com>

description: Dependency install configuration for SugarCube's Node.js-hosted build script, build.js.

type: git


code:
/***********************************************************************************************************************

	scripts/build-utils.js (v1.1.1, 2021-12-21)
		Build utility functions for SugarCube.

	Copyright © 2020–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/
/* eslint-env node, es2021 */
'use strict';

const _fs     = require('fs');
const _path   = require('path');
const _indent = ' -> ';

function log(message, indent) {
	console.log('%s%s', indent ? indent : _indent, message);
}

function die(message, error) {
	if (error) {
		console.error('error: %s\n[@: %d/%d] Trace:\n', message, error.line, error.col, error.stack);
	}
	else {
		console.error('error: %s', message);
	}

	process.exit(1);
}

function fileExists(pathname) {
	return _fs.existsSync(pathname);
}

function makePath(pathname) {
	const pathBits = _path.normalize(pathname).split(_path.sep);

	for (let i = 0; i < pathBits.length; ++i) {
		const dirPath = i === 0 ? pathBits[i] : pathBits.slice(0, i + 1).join(_path.sep);

		if (!fileExists(dirPath)) {
			_fs.mkdirSync(dirPath);
		}
	}
}

function copyFile(srcFilename, destFilename) {
	const srcPath  = _path.normalize(srcFilename);
	const destPath = _path.normalize(destFilename);
	let buf;

	try {
		buf = _fs.readFileSync(srcPath);
	}
	catch (ex) {
		die(`cannot open file "${srcPath}" for reading (reason: ${ex.message})`);
	}

	try {
		_fs.writeFileSync(destPath, buf);
	}
	catch (ex) {
		die(`cannot open file "${destPath}" for writing (reason: ${ex.message})`);
	}

	return true;
}

function readFileContents(filename) {
	const filepath = _path.normalize(filename);

	try {
		// the replace() is necessary because Node.js only offers binary mode file
		// access, regardless of platform, so we convert DOS-style line terminators
		// to UNIX-style, just in case someone adds/edits a file and gets DOS-style
		// line termination all over it
		return _fs.readFileSync(filepath, { encoding : 'utf8' }).replace(/\r\n/g, '\n');
	}
	catch (ex) {
		die(`cannot open file "${filepath}" for reading (reason: ${ex.message})`);
	}
}

function writeFileContents(filename, data) {
	const filepath = _path.normalize(filename);

	try {
		_fs.writeFileSync(filepath, data, { encoding : 'utf8' });
	}
	catch (ex) {
		die(`cannot open file "${filepath}" for writing (reason: ${ex.message})`);
	}
}

function concatFiles(filenames, callback) {
	const output = filenames.map(filename => {
		const contents = readFileContents(filename);
		return typeof callback === 'function' ? callback(contents, filename) : contents;
	});
	return output.join('\n');
}

exports.log               = log;
exports.die               = die;
exports.fileExists        = fileExists;
exports.makePath          = makePath;
exports.copyFile          = copyFile;
exports.readFileContents  = readFileContents;
exports.writeFileContents = writeFileContents;
exports.concatFiles       = concatFiles;


code:
/***********************************************************************************************************************

	config.js

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/
/* global Save, Util */

var Config = (() => { // eslint-disable-line no-unused-vars, no-var
	'use strict';

	// General settings.
	let _debug                 = false;
	let _addVisitedLinkClass   = false;
	let _cleanupWikifierOutput = false;
	let _loadDelay             = 0;

	// Audio settings.
	let _audioPauseOnFadeToZero = true;
	let _audioPreloadMetadata   = true;

	// State history settings.
	let _historyControls  = true;
	let _historyMaxStates = 40;
	let _sessionMaxStates = 40;
	let _expiredMaxStates = 100;

	// Macros settings.
	let _macrosIfAssignmentError   = true;
	let _macrosMaxLoopIterations   = 1000;
	let _macrosTypeSkipKey         = '\x20'; // Space
	let _macrosTypeVisitedPassages = true;

	// Navigation settings.
	let _navigationOverride;
	let _navigationRememberYPos;
	let _navigationGoToHell;

	// Passages settings.
	let _passagesDescriptions;
	let _passagesDisplayTitles = false;
	let _passagesNobr          = false;
	let _passagesStart; // set by `Story.load()`
	let _passagesOnProcess;
	let _passagesTransitionOut;

	// Saves settings.
	let _savesAutoload;
	let _savesAutosave;
	let _savesId              = 'untitled-story';
	let _savesIsAllowed;
	let _savesSlots           = 8;
	let _savesTryDiskOnMobile = true;
	let _savesVersion;
	let _savesUseLZString     = -1; // try autodetect

	// UI settings.
	let _uiStowBarInitially    = 800;
	let _uiUpdateStoryElements = true;

	/*******************************************************************************
		Error Constants.
	*******************************************************************************/

	const _errHistoryModeDeprecated     = 'Config.history.mode has been deprecated and is no longer used by SugarCube, please remove it from your code';
	const _errHistoryTrackingDeprecated = 'Config.history.tracking has been deprecated, use Config.history.maxStates instead';
	const _errSavesOnLoadDeprecated     = 'Config.saves.onLoad has been deprecated, use the Save.onLoad API instead';
	const _errSavesOnSaveDeprecated     = 'Config.saves.onSave has been deprecated, use the Save.onSave API instead';

	/*******************************************************************************
		Object Exports.
	*******************************************************************************/

	return Object.freeze({
		/*
			General settings.
		*/
		get debug() { return _debug; },
		set debug(value) { _debug = Boolean(value); },

		get addVisitedLinkClass() { return _addVisitedLinkClass; },
		set addVisitedLinkClass(value) { _addVisitedLinkClass = Boolean(value); },

		get cleanupWikifierOutput() { return _cleanupWikifierOutput; },
		set cleanupWikifierOutput(value) { _cleanupWikifierOutput = Boolean(value); },

		get loadDelay() { return _loadDelay; },
		set loadDelay(value) {
			if (!Number.isSafeInteger(value) || value < 0) {
				throw new RangeError('Config.loadDelay must be a non-negative integer');
			}

			_loadDelay = value;
		},

		/*
			Audio settings.
		*/
		audio : Object.freeze({
			get pauseOnFadeToZero() { return _audioPauseOnFadeToZero; },
			set pauseOnFadeToZero(value) { _audioPauseOnFadeToZero = Boolean(value); },

			get preloadMetadata() { return _audioPreloadMetadata; },
			set preloadMetadata(value) { _audioPreloadMetadata = Boolean(value); }
		}),

		/*
			State history settings.
		*/
		history : Object.freeze({
			// TODO: (v3) This should be under UI settings → `Config.ui.historyControls`.
			get controls() { return _historyControls; },
			set controls(value) {
				const controls = Boolean(value);

				if (_historyMaxStates === 1 && controls) {
					throw new Error('Config.history.controls must be false when Config.history.maxStates is 1');
				}

				_historyControls = controls;
			},

			get maxStates() { return _historyMaxStates; },
			set maxStates(value) {
				if (!Number.isSafeInteger(value) || value < 1) {
					throw new RangeError('Config.history.maxStates must be a positive integer');
				}

				_historyMaxStates = value;

				// Force `Config.history.controls` to `false`, when limited to `1` moment.
				if (_historyControls && value === 1) {
					_historyControls = false;
				}
			},

			get maxSessionStates() { return _sessionMaxStates; },
			set maxSessionStates(value) {
				if (!Number.isSafeInteger(value) || value < 0) {
					throw new RangeError('Config.history.maxSessionStates must be a non-negative integer');
				}

				_sessionMaxStates = value;
			},

			get maxExpired() { return _expiredMaxStates; },
			set maxExpired(value) {
				_expiredMaxStates = value;
			},

			// legacy
			// Die if deprecated state history settings are accessed.
			get mode()  { throw new Error(_errHistoryModeDeprecated); },
			set mode(_) { throw new Error(_errHistoryModeDeprecated); },
			get tracking()  { throw new Error(_errHistoryTrackingDeprecated); },
			set tracking(_) { throw new Error(_errHistoryTrackingDeprecated); }
			// /legacy
		}),

		/*
			Macros settings.
		*/
		macros : Object.freeze({
			get ifAssignmentError() { return _macrosIfAssignmentError; },
			set ifAssignmentError(value) { _macrosIfAssignmentError = Boolean(value); },

			get maxLoopIterations() { return _macrosMaxLoopIterations; },
			set maxLoopIterations(value) {
				if (!Number.isSafeInteger(value) || value < 1) {
					throw new RangeError('Config.macros.maxLoopIterations must be a positive integer');
				}

				_macrosMaxLoopIterations = value;
			},

			get typeSkipKey() { return _macrosTypeSkipKey; },
			set typeSkipKey(value) { _macrosTypeSkipKey = String(value); },

			get typeVisitedPassages() { return _macrosTypeVisitedPassages; },
			set typeVisitedPassages(value) { _macrosTypeVisitedPassages = Boolean(value); }
		}),

		/*
			Navigation settings.
		*/
		navigation : Object.freeze({
			get override() { return _navigationOverride; },
			set override(value) {
				if (!(value == null || value instanceof Function)) { // lazy equality for null
					throw new TypeError(`Config.navigation.override must be a function or null/undefined (received: ${Util.getType(value)})`);
				}

				_navigationOverride = value;
			},
			get gotohell() { return _navigationGoToHell; },
			set gotohell(value) { _navigationGoToHell = value; },
			get rememberYPos() { return _navigationRememberYPos; },
			set rememberYPos(value) { _navigationRememberYPos = value; }
		}),

		/*
			Passages settings.
		*/
		passages : Object.freeze({
			get descriptions() { return _passagesDescriptions; },
			set descriptions(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					if (valueType !== 'boolean' && valueType !== 'Object' && valueType !== 'function') {
						throw new TypeError(`Config.passages.descriptions must be a boolean, object, function, or null/undefined (received: ${valueType})`);
					}
				}

				_passagesDescriptions = value;
			},

			// TODO: (v3) This should be under Navigation settings → `Config.navigation.updateTitle`.
			get displayTitles() { return _passagesDisplayTitles; },
			set displayTitles(value) { _passagesDisplayTitles = Boolean(value); },

			get nobr() { return _passagesNobr; },
			set nobr(value) { _passagesNobr = Boolean(value); },

			get onProcess() { return _passagesOnProcess; },
			set onProcess(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					if (valueType !== 'function') {
						throw new TypeError(`Config.passages.onProcess must be a function or null/undefined (received: ${valueType})`);
					}
				}

				_passagesOnProcess = value;
			},

			// TODO: (v3) This should be under Navigation settings → `Config.navigation.(start|startingPassage)`.
			get start() { return _passagesStart; },
			set start(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					if (valueType !== 'string') {
						throw new TypeError(`Config.passages.start must be a string or null/undefined (received: ${valueType})`);
					}
				}

				_passagesStart = value;
			},

			// TODO: (v3) This should be under Navigation settings → `Config.navigation.transitionOut`.
			get transitionOut() { return _passagesTransitionOut; },
			set transitionOut(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					if (
						   valueType !== 'string'
						&& (valueType !== 'number' || !Number.isSafeInteger(value) || value < 0)
					) {
						throw new TypeError(`Config.passages.transitionOut must be a string, non-negative integer, or null/undefined (received: ${valueType})`);
					}
				}

				_passagesTransitionOut = value;
			}
		}),

		/*
			Saves settings.
		*/
		saves : Object.freeze({
			get autoload() { return _savesAutoload; },
			set autoload(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					if (valueType !== 'boolean' && valueType !== 'string' && valueType !== 'function') {
						throw new TypeError(`Config.saves.autoload must be a boolean, string, function, or null/undefined (received: ${valueType})`);
					}
				}

				_savesAutoload = value;
			},

			get autosave() { return _savesAutosave; },
			set autosave(value) {
				if (value != null) { // lazy equality for null
					const valueType = Util.getType(value);

					// legacy
					// Convert a string value to an Array of string.
					if (valueType === 'string') {
						_savesAutosave = [value];
						return;
					}
					// /legacy

					if (
						   valueType !== 'boolean'
						&& (valueType !== 'Array' || !value.every(item => typeof item === 'string'))
						&& valueType !== 'function'
					) {
						throw new TypeError(`Config.saves.autosave must be a boolean, Array<string>, function, or null/undefined (received: ${valueType}${valueType === 'Array' ? '<any>' : ''})`);
					}
				}

				_savesAutosave = value;
			},

			get id() { return _savesId; },
			set id(value) {
				if (typeof value !== 'string' || value === '') {
					throw new TypeError(`Config.saves.id must be a non-empty string (received: ${Util.getType(value)})`);
				}

				_savesId = value;
			},

			get isAllowed() { return _savesIsAllowed; },
			set isAllowed(value) {
				if (!(value == null || value instanceof Function)) { // lazy equality for null
					throw new TypeError(`Config.saves.isAllowed must be a function or null/undefined (received: ${Util.getType(value)})`);
				}

				_savesIsAllowed = value;
			},

			get slots() { return _savesSlots; },
			set slots(value) {
				if (!Number.isSafeInteger(value) || value < 0) {
					throw new TypeError(`Config.saves.slots must be a non-negative integer (received: ${Util.getType(value)})`);
				}

				_savesSlots = value;
			},

			get tryDiskOnMobile() { return _savesTryDiskOnMobile; },
			set tryDiskOnMobile(value) { _savesTryDiskOnMobile = Boolean(value); },

			get version() { return _savesVersion; },
			set version(value) { _savesVersion = value; },

			get useLZString() { return _savesUseLZString; },
			set useLZString(value) { return _savesUseLZString = value; },

			// legacy
			// Die if deprecated saves onLoad handler getter is accessed.
			get onLoad() { throw new Error(_errSavesOnLoadDeprecated); },
			// Warn if deprecated saves onLoad handler setter is assigned to, then
			// pass the handler to the `Save.onLoad` API for compatibilities sake.
			set onLoad(value) {
				console.warn(_errSavesOnLoadDeprecated);
				Save.onLoad.add(value);
			},

			// Die if deprecated saves onSave handler getter is accessed.
			get onSave() { throw new Error(_errSavesOnSaveDeprecated); },
			// Warn if deprecated saves onSave handler setter is assigned to, then
			// pass the handler to the `Save.onSave` API for compatibilities sake.
			set onSave(value) {
				console.warn(_errSavesOnSaveDeprecated);
				Save.onSave.add(value);
			}
			// /legacy
		}),

		/*
			UI settings.
		*/
		ui : Object.freeze({
			get stowBarInitially() { return _uiStowBarInitially; },
			set stowBarInitially(value) {
				const valueType = Util.getType(value);

				if (
					   valueType !== 'boolean'
					&& (valueType !== 'number' || !Number.isSafeInteger(value) || value < 0)
				) {
					throw new TypeError(`Config.ui.stowBarInitially must be a boolean or non-negative integer (received: ${valueType})`);
				}

				_uiStowBarInitially = value;
			},

			get updateStoryElements() { return _uiUpdateStoryElements; },
			set updateStoryElements(value) { _uiUpdateStoryElements = Boolean(value); }
		})
	});
})();


code:
/***********************************************************************************************************************

	css/_mixins.css

	Copyright © 2020–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

@define-mixin tme-fa-icons-properties {
	font-family: tme-fa-icons !important; /* stylelint-disable-line font-family-no-missing-generic-family-keyword */
	font-style: normal;
	font-weight: 900;
	font-variant: normal;
	line-height: 1;
	speak: never;
	text-rendering: auto;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}


code:
/***********************************************************************************************************************

	css/core-macro.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Default appearance styles.
*/
@keyframes cursor-blink {
	0% { opacity: 1; }
	50% { opacity: 0; }
	100% { opacity: 1; }
}

.macro-linkappend-insert,
.macro-linkprepend-insert,
.macro-linkreplace-insert,
.macro-append-insert,
.macro-prepend-insert,
.macro-replace-insert,
.macro-repeat-insert,
.macro-timed-insert {
	transition: opacity 400ms ease-in;
}
.macro-linkappend-in,
.macro-linkprepend-in,
.macro-linkreplace-in,
.macro-append-in,
.macro-prepend-in,
.macro-replace-in,
.macro-repeat-in,
.macro-timed-in {
	opacity: 0;
}

.macro-type-cursor:after {
	animation: cursor-blink 1s infinite;
	content: "\2590"; /* "\2588" */
	opacity: 1;
}


code:
/***********************************************************************************************************************

	css/core-passage.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Default appearance styles.
*/
.passage {
	line-height: 1.75;
	text-align: left;
	transition: opacity 400ms ease-in;
}
.passage-in {
	opacity: 0;
}
.passage ul, .passage ol {
	margin-left: 0.5em;
	padding-left: 1.5em;
}
.passage table {
	margin: 1em 0;
	border-collapse: collapse;
	font-size: 100%;
}
.passage tr, .passage th, .passage td, .passage caption {
	padding: 3px;
}

/*
	Accessibility styles.
*/
@media (prefers-reduced-motion: reduce) {
	.passage {
		transition: opacity 0s;
	}
}


code:
/***********************************************************************************************************************

	css/core.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Default structural styles.
*/
html {
	/*
		We define the base font size and line height here as they affect the layout
		of the base page elements (i.e. `#ui-bar`, `#ui-dialog`, and `#story`).
	*/
	font: 16px/1 Helmet, Freesans, sans-serif;
}

/* Story data styling. */
#store-area, tw-storydata {
	display: none !important;
	z-index: 0;
}

/* Special no transition styling. */
.no-transition {
	transition: none !important;
}

/*
	Fullscreen appearance styles.
*/
*:fullscreen { /* Cause Blink/WebKit to behave like Gecko. */
	height: 100%;
	width: 100%;
}
body::-ms-backdrop { /* Prevent IE 11 from hiding the `body` element's background. */
	background: none;
}

/*
	Default appearance styles.
*/
*:focus {
	outline: thin dotted;
}
*:disabled {
	cursor: not-allowed !important;
}
body {
	color: #eee;
	background-color: #111;
	overflow: auto;
}
a {
	cursor: pointer;
	color: #68d;
	text-decoration: none;
	transition-duration: 200ms;
}
a:hover {
	color: #8af;
	text-decoration: underline;
}
a.link-broken {
	color: #c22;
}
a.link-broken:hover {
	color: #e44;
}
a[disabled], span.link-disabled {
	color: #aaa;
	cursor: not-allowed !important;
	/*
		NOTE: Do not use `pointer-events` here as it disables
		the display of a cursor in some browsers.

		pointer-events: none;
	*/
	text-decoration: none;
}
area {
	cursor: pointer;
}
button {
	cursor: pointer;
	color: #eee;
	background-color: #35a;
	border: 1px solid #57c;
	line-height: normal;
	padding: 0.4em;
	transition-duration: 200ms;
	user-select: none;
}
button:hover {
	background-color: #57c;
	border-color: #79e;
}
button:disabled {
	background-color: #444;
	border: 1px solid #666;
}
input, select, textarea {
	color: #eee;
	background-color: transparent;
	border: 1px solid #444;
	padding: 0.4em;
}
select {
	padding: 0.34em 0.4em;
}
input[type="text"] {
	min-width: 18em;
}
textarea {
	min-width: 30em;
	resize: vertical;
}
input[type="checkbox"], input[type="file"], input[type="radio"], select {
	cursor: pointer;
}
/* BEGIN: input[type="range"] */
input[type="range"] {
	-webkit-appearance: none;
	min-height: 1.2em;
}
input[type="range"]:focus {
	outline: none;
}
input[type="range"]::-webkit-slider-runnable-track {
	background: #222;
	border: 1px solid #444;
	border-radius: 0;
	cursor: pointer;
	height: 10px;
	width: 100%;
}
input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	background: #35a;
	border: 1px solid #57c;
	border-radius: 0;
	cursor: pointer;
	height: 18px;
	/*
		NOTE: Ideally, `margin-top` should be `0` for Edge/Spartan (ca. v17), but
		real WebKit/Blink-based browsers need it.  Since there's more of them and
		Edge is co-opting the prefix anyway, we cater to them.  Edge will simply
		have to look ever so slightly off.
	*/
	margin-top: -5px;
	width: 33px;
}
input[type="range"]:focus::-webkit-slider-runnable-track {
	background: #222;
}
input[type="range"]::-moz-range-track {
	background: #222;
	border: 1px solid #444;
	border-radius: 0;
	cursor: pointer;
	height: 10px;
	width: 100%;
}
input[type="range"]::-moz-range-thumb {
	background: #35a;
	border: 1px solid #57c;
	border-radius: 0;
	cursor: pointer;
	height: 18px;
	width: 33px;
}
input[type="range"]::-ms-track {
	background: transparent;
	border-color: transparent;
	color: transparent;
	cursor: pointer;
	height: 10px;
	width: calc(100% - 1px);
}
input[type="range"]::-ms-fill-lower {
	background: #222;
	border: 1px solid #444;
	border-radius: 0;
}
input[type="range"]::-ms-fill-upper {
	background: #222;
	border: 1px solid #444;
	border-radius: 0;
}
input[type="range"]::-ms-thumb {
	background: #35a;
	border: 1px solid #57c;
	border-radius: 0;
	cursor: pointer;
	height: 16px;
	width: 33px;
}
/* END: input[type="range"] */
input:not(:disabled):focus, select:not(:disabled):focus, textarea:not(:disabled):focus,
input:not(:disabled):hover, select:not(:disabled):hover, textarea:not(:disabled):hover {
	background-color: #333;
	border-color: #eee;
}
hr {
	display: block;
	height: 1px;
	border: none;
	border-top: 1px solid #eee;
	margin: 1em 0;
	padding: 0;
}
audio, canvas, progress, video {
	max-width: 100%;
	vertical-align: middle;
}

.error-view {
	background-color: #511;
	border-left: 0.5em solid #c22;
	display: inline-block;
	margin: 0.1em;
	max-width: 100%;
	padding: 0 0.25em;
	position: relative;
}
.error-view > .error-toggle {
	background-color: transparent;
	border: none;
	line-height: inherit;
	left: 0;
	padding: 0;
	position: absolute;
	top: 0;
	width: 1.75em;
}
.error-view > .error {
	display: inline-block;
	margin-left: 0.25em;
}
.error-view > .error-toggle + .error {
	margin-left: 1.5em;
}
.error-view > .error-source[hidden] {
	display: none;
}
.error-view > .error-source:not([hidden]) {
	background-color: rgba(0, 0, 0, 0.2);
	display: block;
	margin: 0 0 0.25em;
	overflow-x: auto;
	padding: 0.25em;
}

.highlight, .marked {
	color: yellow;
	font-weight: bold;
	font-style: italic;
}
.nobr {
	white-space: nowrap;
}

[data-icon]:before,
[data-icon-before]:before,
[data-icon-after]:after,
.error-view > .error-toggle:before,
.error-view > .error:before,
a.link-external:after {
	@mixin tme-fa-icons-properties;
}
[data-icon]:before {
	content: attr(data-icon);
}
[data-icon-before]:before {
	content: attr(data-icon-before) "\00a0\00a0";
}
[data-icon-after]:after {
	content: "\00a0\00a0" attr(data-icon-after);
}
.error-view > .error-toggle:before {
	content: "\e81a";
}
.error-view > .error-toggle.enabled:before {
	content: "\e818";
}
.error-view > .error:before {
	content: "\e80d\00a0\00a0";
}
a.link-external:after {
	content: "\00a0\e80e";
}


code:
#saves-export-reminder {
	padding: 0.5em 1em 0;
	font-size: 0.96em;
}

#saves-list-container {
	display: flex;
	flex-direction: column;
}

#saves-list-container .savesListRow {
	display: flex;
	flex-flow: row nowrap;
	align-items: center;
	border-top: 1px solid #444;
	padding: 4px;
}

@media (min-width: 40rem) {
	#saves-list-container .savesListRow {
		max-height: 2.4em;
	}
}

#saves-list-container .savesListRow .saveGroup {
	display: flex;
	flex-flow: row wrap;
	align-items: center;
	flex-grow: 1;
	flex-shrink: 1;
	/* Set min-width to allow parent correctly to resize this element's children */
	min-width: 0;
}

#saves-list-container .savesListRow .saveGroup > div {
	display: flex;
	justify-content: center;
	margin: 0 10px;
	flex-grow: 0;
	flex-shrink: 0;
}

#saves-list-container .savesListRow .saveGroup .saveId {
	min-width: 2em;
	margin-left: 4px;
	margin-right: -6px;
}

#saves-list-container .savesListRow .saveGroup .saveButton {
	display: flex;
	justify-content: center;
	min-width: 110px;
	margin: 0 10px;
}

#saves-list-container .savesListRow .saveGroup .saveName {
	width: 5em;
}

#saves-list-container .savesListRow .saveGroup .saveButton input {
	margin: 3px 0;
}

#saves-list-container .savesListRow .saveGroup > .saveDetails {
	display: flex;
	flex: 1 1 0;
	flex-direction: column;
	align-items: stretch;
	justify-content: stretch;
	min-width: 100px;
}

#saves-list-container .savesListRow .saveGroup > .saveDetails span {
	max-height: 80px;
	white-space: nowrap;
	overflow-x: clip;
}

.jumpToSaveTransition {
	background-color: #444;
	transition-duration: 1s;
}

/*
 * footer for the save list
 */
#savesListFooter {
	justify-content: space-between;
	padding: 0 !important;
	line-height: normal;
}

#savesListFooter div {
	display: flex;
	justify-content: stretch;
}

.datestamp {
	font-size: 0.8em;
}

.listMargin {
	display: inline-block;
	margin: 1px 0;
}

.right {
	float: right;
}

.saveMenuButton {
	background-color: #35a !important;
}

.saveMenuButton:hover {
	background-color: #35a !important;
}

.saveMenuConfirm {
	margin-top: 20px;
	margin-left: 150px;
}

.green {
	color: #38b20a
}

.gold {
	color: gold;
}

.red {
	color: #ec3535;
}

.saveBorder {
	max-width: 700px;
	margin: 10px 2px;
	padding: 5px 2px 30px;
	border: 1px solid var(--200);
}

/* dol-specific */
#saveList ul.buttons {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--750);
}

#saveList ul.buttons li {
	padding: 0.4em;
	display: inline-block;
	margin: 0;
}

#saveList ul.buttons li:last-child {
	float: right;
}

#saveList button[id="saves-export"]:before,
#saveList button[id="saves-toClipboard"]:before,
#saveList button[id="saves-import"]:before,
#saveList button[id="saves-clear"]:before {
	@mixin tme-fa-icons-properties;
}
#saveList button[id="saves-export"]:before {
	content: "\e829\00a0";
}
#saveList button[id="saves-toClipboard"]:before {
	content: "\e82b\00a0";
}
#saveList button[id="saves-import"]:before {
	content: "\e82a\00a0";
}
#saveList button[id="saves-clear"]:before {
	content: "\e827\00a0";
}

.saves-loading .saves {
	text-align: center;
	margin-top: 1em;
}


code:
/***********************************************************************************************************************

	css/init-screen.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

@keyframes init-loading-spin {
	0%   { transform: rotate(0deg); }
	100% { transform: rotate(360deg); }
}
#init-screen {
	display: none;
	z-index: 500000;
	position: fixed;
	top: 0px;
	left: 0px;
	height: 100%;
	width: 100%;
	font: 28px/1 Helmet, Freesans, sans-serif;
	font-weight: bold;
	color: #eee;
	background-color: #111;
	text-align: center;
}
#init-screen > div {
	display: none;
	position: relative;
	margin: 0 auto;
	max-width: 1136px;
	top: 25%;
}
html[data-init="no-js"] #init-screen, html[data-init="lacking"] #init-screen, html[data-init="loading"] #init-screen {
	display: block;
}
html[data-init="no-js"] #init-no-js, html[data-init="lacking"] #init-lacking {
	display: block;
	padding: 0 1em;
}
html[data-init="no-js"] #init-no-js {
	color: red;
}
html[data-init="loading"] #init-loading {
	display: block;
	border: 24px solid transparent;
	border-radius: 50%;
	border-top-color: #7f7f7f;
	border-bottom-color: #7f7f7f;
	width: 100px;
	height: 100px;
	animation: init-loading-spin 2s linear infinite;
}
html[data-init="loading"] #init-loading > div {
	text-indent: 9999em;
	overflow: hidden;
	white-space: nowrap;
}
html[data-init="loading"] #ui-bar, html[data-init="loading"] #passages {
	display: none;
}


code:
/***********************************************************************************************************************

	css/ui-bar.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Patches to the core styles.
*/
#story {
	margin-left: 20em;
	transition: margin-left 200ms ease-in;
}
#ui-bar.stowed ~ #story {
	margin-left: 4.5em;
}
@media screen and (max-width: 1136px) {
	#story {
		margin-left: 19em;
	}
	#ui-bar.stowed ~ #story {
		margin-left: 3.5em;
	}
}
/*
	At very narrow viewport widths, set `#story{margin-left}` equal to the value
	of `#ui-bar.stowed~#story{margin-left}`, so that `#ui-bar` will side over top
	of `#story` when unstowed, rather than shoving it over.
*/
@media screen and (max-width: 768px) {
	#story {
		margin-left: 3.5em;
	}
}

/*
	Default structural styles.
*/
#ui-bar {
	position: fixed;
	z-index: 50;
	top: 0;
	left: 0;
	width: 17.5em;
	height: 100%;
	margin: 0;
	padding: 0;
	transition: left 200ms ease-in;
}
#ui-bar.stowed {
	left: -15.5em;
}
#ui-bar-tray {
	position: absolute;
	top: 0.2em;
	left: 0;
	right: 0;
}
#ui-bar-body {
	height: 90%; /* fallback for browsers without support for calc() */
	height: calc(100% - 2.5em);
	margin: 2.5em 0;
	padding: 0 1.5em;
}
#ui-bar.stowed #ui-bar-history,
#ui-bar.stowed #ui-bar-body {
	visibility: hidden;
	transition: visibility 200ms step-end;
}

/*
	Accessibility styles.
*/
@media (prefers-reduced-motion: reduce) {
	#story {
		transition: margin-left 0s;
	}
	#ui-bar {
		transition: left 0s;
	}
}

/*
	Default appearance styles.
*/
#ui-bar {
	background-color: #222;
	border-right: 1px solid #444;
	text-align: center;
}
#ui-bar a {
	text-decoration: none;
}
#ui-bar hr {
	border-color: #444;
}
#ui-bar-toggle,
#ui-bar-history [id|="history"] {
	font-size: 1.2em;
	line-height: inherit;
	color: #eee;
	background-color: transparent;
	border: 1px solid #444;
}
#ui-bar-toggle {
	display: block;
	position: absolute;
	top: 0;
	right: 0;
	border-right: none;
	padding: 0.3em 0.45em 0.25em;
}
#ui-bar.stowed #ui-bar-toggle {
	padding: 0.3em 0.35em 0.25em 0.55em;
}
#ui-bar-toggle:hover {
	background-color: #444;
	border-color: #eee;
}
#ui-bar-history {
	margin: 0 auto;
}
#ui-bar-history [id|="history"] {
	padding: 0.2em 0.45em 0.35em;
}
#ui-bar-history #history-jumpto {
	padding: 0.2em 0.665em 0.35em;
}
#ui-bar-history [id|="history"]:not(:first-child) {
	margin-left: 1.2em;
}
#ui-bar-history [id|="history"]:hover {
	background-color: #444;
	border-color: #eee;
}
#ui-bar-history [id|="history"]:disabled {
	color: #444;
	background-color: transparent;
	border-color: #444;
}
#ui-bar-body {
	line-height: 1.5;
	overflow: auto;
}
#ui-bar-body > :not(:first-child) {
	margin-top: 2em;
}
#story-title {
	margin: 0;
	font-size: 162.5%;
}
#story-author {
	margin-top: 2em;
	font-weight: bold;
}
#menu ul {
	margin: 1em 0 0;
	padding: 0;
	list-style: none;
	border: 1px solid #444;
}
#menu ul:empty {
	display: none;
}
#menu li {
	margin: 0;
}
#menu li:not(:first-child) {
	border-top: 1px solid #444;
}
#menu li a {
	display: block;
	padding: 0.25em 0.75em;
	border: 1px solid transparent;
	color: #eee;
	text-transform: uppercase;
}
#menu li a:hover {
	background-color: #444;
	border-color: #eee;
}

/* Stop text selection on certain UI elements. */
#ui-bar-history [id|="history"],
#ui-bar-toggle,
#menu a {
	user-select: none;
}

/*
	Default font icon styles.
*/
#ui-bar-toggle:before,
#ui-bar-history [id|="history"],
#menu-core li[id|="menu-item"] a:before {
	@mixin tme-fa-icons-properties;
}
#ui-bar-toggle:before {
	content: "\e81d";
}
#ui-bar.stowed #ui-bar-toggle:before {
	content: "\e81e";
}
#menu-item-saves a:before {
	content: "\e82b\00a0";
}
#menu-item-settings a:before {
	content: "\e82d\00a0";
}
#menu-item-restart a:before {
	content: "\e82c\00a0";
}
#menu-item-share a:before {
	content: "\e82f\00a0";
}


code:
/***********************************************************************************************************************

	css/ui-debug.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Default debug bar styles.
*/
#debug-bar {
	background-color: #222;
	border-left: 1px solid #444;
	border-top: 1px solid #444;
	bottom: 0;
	margin: 0;
	max-height: 75%;
	/* max-width: 28em;
	min-width: 22em; */
	padding: 0.5em;
	position: fixed;
	right: 0;
	z-index: 99900;
}
#debug-bar > div:not([id]) + div {
	margin-top: 0.5em;
}
#debug-bar > div > label {
	margin-right: 0.5em;
}
#debug-bar > div > input[type="text"] {
	min-width: 0;
	width: 8em;
}
#debug-bar > div > select {
	width: 15em;
}

#debug-bar-toggle {
	color: #eee;
	background-color: #222;
	border: 1px solid #444;
	height: 101%; /* fallback for browsers without support for calc() */
	height: calc(100% + 1px);
	left: -2em; /* fallback for browsers without support for calc() */
	left: calc(-2em - 1px);
	position: absolute;
	top: -1px;
	width: 2em;
}
#debug-bar-toggle:hover {
	background-color: #333;
	border-color: #eee;
}

#debug-bar-hint {
	bottom: 0.175em;
	font-size: 4.5em;
	opacity: 0.33;
	pointer-events: none;
	position: fixed;
	right: 0.6em;
	user-select: none;
	white-space: nowrap;
}

#debug-bar-watch {
	background-color: #222;
	border-left: 1px solid #444;
	border-top: 1px solid #444;
	bottom: 102%; /* fallback for browsers without support for calc() */
	bottom: calc(100% + 1px);
	font-size: 0.9em;
	left: -1px;
	max-height: 650%; /* fallback for browsers without support for vh units */
	max-height: 65vh;
	position: absolute;
	overflow-x: hidden;
	overflow-y: scroll;
	right: 0;
	z-index: 99800;
}
#debug-bar-watch[hidden] {
	display: none;
}
#debug-bar-watch div {
	color: #999;
	font-style: italic;
	margin: 1em auto;
	text-align: center;
}
#debug-bar-watch table {
	width: 100%;
}
#debug-bar-watch tr:nth-child(2n) {
	background-color: rgba(127, 127, 127, 0.15);
}
#debug-bar-watch td {
	padding: 0.2em 0;
}
#debug-bar-watch td:first-child + td {
	padding: 0.2em 0.3em 0.2em 0.1em;
}
#debug-bar-watch .watch-delete {
	background-color: transparent;
	border: none;
	color: #c00;
}
#debug-bar-watch-all,
#debug-bar-watch-none {
	margin-left: 0.5em;
}
#debug-bar-watch-toggle,
#debug-bar-views-toggle {
	color: #eee;
	background-color: transparent;
	border: 1px solid #444;
	margin-right: 1em;
	padding: 0.4em;
}
#debug-bar-watch-toggle:hover,
#debug-bar-views-toggle:hover {
	background-color: #333;
	border-color: #eee;
}
#debug-bar-watch:not([hidden]) ~ div #debug-bar-watch-toggle,
html[data-debug-view] #debug-bar-views-toggle {
	background-color: #282;
	border-color: #4a4;
}
#debug-bar-watch:not([hidden]) ~ div #debug-bar-watch-toggle:hover,
html[data-debug-view] #debug-bar-views-toggle:hover {
	background-color: #4a4;
	border-color: #6c6;
}

#debug-bar-toggle:before,
#debug-bar-hint:after,
#debug-bar-watch .watch-delete:before,
#debug-bar-watch-add:before,
#debug-bar-watch-all:before,
#debug-bar-watch-none:before,
#debug-bar-watch-toggle:after,
#debug-bar-views-toggle:after {
	@mixin tme-fa-icons-properties;
}
#debug-bar-toggle:before {
	content: "\e838";
}
#debug-bar-hint:after {
	content: "\e838\202f\e822";
}
#debug-bar-watch .watch-delete:before {
	content: "\e804";
}
#debug-bar-watch-add:before {
	content: "\e805";
}
#debug-bar-watch-all:before {
	content: "\e83a";
}
#debug-bar-watch-none:before {
	content: "\e827";
}
#debug-bar-watch-toggle:after,
#debug-bar-views-toggle:after {
	content: "\00a0\00a0\e830";
}
#debug-bar-watch:not([hidden]) ~ div #debug-bar-watch-toggle:after,
html[data-debug-view] #debug-bar-views-toggle:after {
	content: "\00a0\00a0\e831";
}

/*
	Default debug view styles.
*/
html[data-debug-view] .debug {
	padding: 0.25em;
	background-color: #234; /* #541, #151 */
}
html[data-debug-view] .debug[title] {
	cursor: help;
}
html[data-debug-view] .debug.block {
	display: inline-block;
	vertical-align: middle;
}
html[data-debug-view] .debug.invalid {
	text-decoration: line-through;
}
html[data-debug-view] .debug.hidden,
html[data-debug-view] .debug.hidden .debug {
	background-color: #555;
}
html:not([data-debug-view]) .debug.hidden {
	display: none;
}

html[data-debug-view] .debug[data-name][data-type]:before,
html[data-debug-view] .debug[data-name][data-type].nonvoid:after {
	background-color: rgba(0,0,0,0.25);
	font-family: monospace, monospace;
	white-space: pre;
}
html[data-debug-view] .debug[data-name][data-type]:before {
	content: attr(data-name);
}
html[data-debug-view] .debug[data-name][data-type|="macro"]:before {
	content: "<<" attr(data-name) ">>";
}
html[data-debug-view] .debug[data-name][data-type|="macro"].nonvoid:after {
	content: "<</" attr(data-name) ">>";
}
html[data-debug-view] .debug[data-name][data-type|="html"]:before {
	content: "<" attr(data-name) ">";
}
html[data-debug-view] .debug[data-name][data-type|="html"].nonvoid:after {
	content: "</" attr(data-name) ">";
}
html[data-debug-view] .debug[data-name][data-type]:not(:empty):before {
	margin-right: 0.25em;
}
html[data-debug-view] .debug[data-name][data-type].nonvoid:not(:empty):after {
	margin-left: 0.25em;
}
html[data-debug-view] .debug[data-name][data-type|="special"],
html[data-debug-view] .debug[data-name][data-type|="special"]:before {
	display: block;
}


code:
/***********************************************************************************************************************

	css/ui-dialog.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Patches to the core styles.
*/
html[data-dialog] body {
	overflow: hidden;
}

/*
	Default structural styles.
*/
#ui-overlay.open {
	visibility: visible;
	transition: opacity 200ms ease-in;
}
#ui-overlay:not(.open) {
	transition: visibility 200ms step-end, opacity 200ms ease-in;
}
#ui-overlay {
	visibility: hidden;
	opacity: 0;
	z-index: 100000;
	position: fixed;
	/*
	top: -50vh;
	left: -50vw;
	height: 200vh;
	width: 200vw;
	*/
	top: -50%;
	left: -50%;
	height: 200%;
	width: 200%;
}
#ui-dialog.open {
	display: block;
	transition: opacity 200ms ease-in;
}
/*
	We do not animate `#ui-dialog:not(.open)` for various reasons.  Chief among
	them, however, is so that the dialog isn't in the middle of its animation
	when other page updates happen.

	e.g. The restoration of `overflow` on `body` would cause the still animating
	     dialog to jump around a little if a scrollbar were to pop in.

	     Any dialog action which performs a task which has its own animations
	     (e.g. passage display) or causes the page to reload in addition to
	     closing the dialog could cause display shenanigans.
*/
#ui-dialog {
	display: none;
	opacity: 0;
	z-index: 100100;
	position: fixed;
	top: 50px;
	margin: 0;
	padding: 0;
}
#ui-dialog > * {
	box-sizing: border-box;
}
#ui-dialog-titlebar {
	position: relative;
}
#ui-dialog-close {
	display: block;
	position: absolute;
	right: 0;
	top: 0;
	white-space: nowrap;
}
#ui-dialog-body {
	overflow: auto;
	min-width: 280px;
	height: 92%; /* fallback for browsers without support for calc() */
	height: calc(100% - 2.1em); /* parent - title(2.1em) */
}

/*
	Accessibility styles.
*/
@media (prefers-reduced-motion: reduce) {
	#ui-overlay.open {
		transition: opacity 0s;
	}
	#ui-overlay:not(.open) {
		transition: opacity 0s;
	}
	#ui-dialog.open {
		transition: opacity 0s;
	}
}

/*
	Default appearance styles.
*/
#ui-overlay {
	background-color: #000;
}
#ui-overlay.open {
	opacity: 0.8;
}
#ui-dialog {
	max-width: 66em;
}
#ui-dialog.open {
	opacity: 1;
}
#ui-dialog-titlebar {
	background-color: #444;
	min-height: 24px;
}
#ui-dialog-title {
	margin: 0;
	padding: 0.2em 3.5em 0.2em 0.5em;
	font-size: 1.5em;
	text-align: center;
	text-transform: uppercase;
}
#ui-dialog-close {
	cursor: pointer;
	font-size: 120%;
	margin: 0;
	padding: 0;
	width: 3.6em;
	height: 92%;
	background-color: transparent;
	border: 1px solid transparent;
	transition-duration: 200ms;
}
#ui-dialog-close:hover {
	background-color: #b44;
	border-color: #d66;
}
#ui-dialog-body {
	background-color: #111;
	border: 1px solid #444;
	text-align: left;
	line-height: 1.5;
	padding: 1em;
}
#ui-dialog-body > *:first-child {
	margin-top: 0;
}
#ui-dialog-body hr {
	background-color: #444;
}

/* Default dialog button bar styling. */
#ui-dialog-body ul.buttons {
	margin: 0;
	padding: 0;
	list-style: none;
}
#ui-dialog-body ul.buttons li {
	display: inline-block;
	margin: 0;
	padding: 0.4em 0.4em 0 0;
}
#ui-dialog-body ul.buttons > li + li > button {
	margin-left: 1em;
}

/* Stop text selection on certain UI elements. */
#ui-dialog-close {
	user-select: none;
}

/*
	Default font icon styles.
*/
#ui-dialog-close {
	@mixin tme-fa-icons-properties;
}


code:
/***********************************************************************************************************************

	css/ui.css

	Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
	Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.

***********************************************************************************************************************/

/*
	Default structural styles.
*/
/* Settings dialog styling. */
#ui-dialog-body.settings [id|="setting-body"] > div:first-child {
	display: table;
	width: 100%;
}
#ui-dialog-body.settings [id|="setting-label"] {
	display: table-cell;
	padding: 0.4em 2em 0.4em 0;
}
#ui-dialog-body.settings [id|="setting-label"] + div {
	display: table-cell;
	min-width: 8em;
	text-align: right;
	vertical-align: middle;
	white-space: nowrap;
}

/*
	Built-in dialog appearance styles.
*/
/* List-based dialog styling (primarily for the Jumpto & Share dialogs). */
#ui-dialog-body.list {
	padding: 0;
}
#ui-dialog-body.list ul {
	margin: 0;
	padding: 0;
	list-style: none;
	border: 1px solid transparent;
}
#ui-dialog-body.list li {
	margin: 0;
}
#ui-dialog-body.list li:not(:first-child) {
	border-top: 1px solid #444;
}
#ui-dialog-body.list li a {
	display: block;
	padding: 0.25em 0.75em;
	border: 1px solid transparent;
	color: #eee;
	text-decoration: none;
}
#ui-dialog-body.list li a:hover {
	background-color: #333;
	border-color: #eee;
}

/* Saves dialog styling. */
#ui-dialog-body.saves {
	padding: 0 0 1px; /* Webkit/Blink need 1px bottom padding or they'll trigger the scroll bar */
}
#ui-dialog-body.saves > *:not(:first-child) {
	border-top: 1px solid #444;
}
#ui-dialog-body.saves table {
	border-spacing: 0;
	width: 100%;
}
#ui-dialog-body.saves tr:not(:first-child) {
	border-top: 1px solid #444;
}
#ui-dialog-body.saves td {
	padding: 0.33em 0.33em;
}
#ui-dialog-body.saves td:first-child {
	min-width: 1.5em;
	text-align: center;
}
#ui-dialog-body.saves td:nth-child(3) {
	line-height: 1.2;
}
#ui-dialog-body.saves td:last-child {
	text-align: right;
}
#ui-dialog-body.saves .empty {
	color: #999;
	speak: none;
	text-align: center;
	user-select: none;
}
#ui-dialog-body.saves .datestamp {
	font-size: 75%;
	margin-left: 1em;
}
#ui-dialog-body.saves ul.buttons li {
	padding: 0.4em;
}
#ui-dialog-body.saves ul.buttons > li + li > button {
	margin-left: 0.2em;
}
#ui-dialog-body.saves ul.buttons li:last-child {
	/*
		Using `position:absolute;right:0;` here can produce poor results,
		so we use `float:right` instead.
	*/
	float: right;
}

/* Settings dialog styling. */
#ui-dialog-body.settings div[id|="header-body"] {
	margin: 1em 0;
}
#ui-dialog-body.settings div[id|="header-body"]:first-child {
	margin-top: 0;
}
#ui-dialog-body.settings div[id|="header-body"]:not(:first-child) {
	border-top: 1px solid #444;
	padding-top: 1em;
}
#ui-dialog-body.settings div[id|="header-body"] > * {
	margin: 0;
}
#ui-dialog-body.settings h2[id|="header-heading"] {
	font-size: 1.375em;
}
#ui-dialog-body.settings p[id|="header-desc"],
#ui-dialog-body.settings p[id|="setting-desc"] {
	font-size: 87.5%;
	margin: 0 0 0 0.5em;
}
#ui-dialog-body.settings div[id|="setting-body"] + div[id|="setting-body"] {
	margin: 1em 0;
}
#ui-dialog-body.settings [id|="setting-control"] {
	white-space: nowrap;
}
#ui-dialog-body.settings button[id|="setting-control"] {
	color: #eee;
	background-color: transparent;
	border: 1px solid #444;
	padding: 0.4em;
}
#ui-dialog-body.settings button[id|="setting-control"]:hover {
	background-color: #333;
	border-color: #eee;
}
#ui-dialog-body.settings button[id|="setting-control"].enabled {
	background-color: #282;
	border-color: #4a4;
}
#ui-dialog-body.settings button[id|="setting-control"].enabled:hover {
	background-color: #4a4;
	border-color: #6c6;
}
#ui-dialog-body.settings input[type="range"][id|="setting-control"] {
	max-width: 35vw;
}

/* Stop text selection on certain UI elements. */
#ui-dialog-body.list a,
#ui-dialog-body.settings span[id|="setting-input"] {
	user-select: none;
}

/*
	Default font icon styles.
*/
#ui-dialog-body.saves button[id="saves-export"]:before,
#ui-dialog-body.saves button[id="saves-toClipboard"]:before,
#ui-dialog-body.saves button[id="saves-import"]:before,
#ui-dialog-body.saves button[id="saves-clear"]:before,
#ui-dialog-body.settings button[id|="setting-control"]:after,
#ui-dialog-body.settings button[id|="setting-control"].enabled:after {
	@mixin tme-fa-icons-properties;
}
#ui-dialog-body.saves button[id="saves-export"]:before {
	content: "\e829\00a0";
}
#ui-dialog-body.saves button[id="saves-toClipboard"]:before {
	content: "\e82b\00a0";
}
#ui-dialog-body.saves button[id="saves-import"]:before {
	content: "\e82a\00a0";
}
#ui-dialog-body.saves button[id="saves-clear"]:before {
	content: "\e827\00a0";
}
#ui-dialog-body.settings button[id|="setting-control"]:after {
	content: "\00a0\00a0\e830";
}
#ui-dialog-body.settings button[id|="setting-control"].enabled:after {
	content: "\00a0\00a0\e831";
}