removed old name

master
Leo Coogan 4 months ago
parent 5ce49f9e69
commit 8ddee836e1
Signed by: lcoogan
GPG Key ID: 54DBD17B0D75ABB0

BIN
ruixi/.DS_Store vendored

Binary file not shown.

@ -1,38 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ruixi</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="outerContainer">
<h3 class="written-in-ink"><a href="https://www.inklestudios.com/ink">WRITTEN IN INK</a></h3>
<div id="controls" class="buttons">
<a id="rewind" title="Restart story from beginning">restart</a>
<a id="save" title="Save progress">save</a>
<a id="reload" title="Reload from save point">load</a>
<a id="theme-switch" title="Switch theme">theme</a>
</div>
<div id="story" class="container">
<div class="header">
<h1>ruixi</h1>
<h2 class="byline"></h2>
</div>
</div>
</div>
<script src="ink.js"></script>
<script src="ruixi.js"></script>
<script src="main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -1,439 +0,0 @@
(function(storyContent) {
// Create ink story from the content using inkjs
var story = new inkjs.Story(storyContent);
var savePoint = "";
let savedTheme;
let globalTagTheme;
// Global tags - those at the top of the ink file
// We support:
// # theme: dark
// # author: Your Name
var globalTags = story.globalTags;
if( globalTags ) {
for(var i=0; i<story.globalTags.length; i++) {
var globalTag = story.globalTags[i];
var splitTag = splitPropertyTag(globalTag);
// THEME: dark
if( splitTag && splitTag.property == "theme" ) {
globalTagTheme = splitTag.val;
}
// author: Your Name
else if( splitTag && splitTag.property == "author" ) {
var byline = document.querySelector('.byline');
byline.innerHTML = "by "+splitTag.val;
}
}
}
var storyContainer = document.querySelector('#story');
var outerScrollContainer = document.querySelector('.outerContainer');
// page features setup
setupTheme(globalTagTheme);
var hasSave = loadSavePoint();
setupButtons(hasSave);
// Set initial save point
savePoint = story.state.toJson();
// Kick off the start of the story!
continueStory(true);
// Main story processing function. Each time this is called it generates
// all the next content up as far as the next set of choices.
function continueStory(firstTime) {
var paragraphIndex = 0;
var delay = 0.0;
// Don't over-scroll past new content
var previousBottomEdge = firstTime ? 0 : contentBottomEdgeY();
// Generate story text - loop through available content
while(story.canContinue) {
// Get ink to generate the next paragraph
var paragraphText = story.Continue();
var tags = story.currentTags;
// Any special tags included with this line
var customClasses = [];
for(var i=0; i<tags.length; i++) {
var tag = tags[i];
// Detect tags of the form "X: Y". Currently used for IMAGE and CLASS but could be
// customised to be used for other things too.
var splitTag = splitPropertyTag(tag);
splitTag.property = splitTag.property.toUpperCase();
// AUDIO: src
if( splitTag && splitTag.property == "AUDIO" ) {
if('audio' in this) {
this.audio.pause();
this.audio.removeAttribute('src');
this.audio.load();
}
this.audio = new Audio(splitTag.val);
this.audio.play();
}
// AUDIOLOOP: src
else if( splitTag && splitTag.property == "AUDIOLOOP" ) {
if('audioLoop' in this) {
this.audioLoop.pause();
this.audioLoop.removeAttribute('src');
this.audioLoop.load();
}
this.audioLoop = new Audio(splitTag.val);
this.audioLoop.play();
this.audioLoop.loop = true;
}
// IMAGE: src
if( splitTag && splitTag.property == "IMAGE" ) {
var imageElement = document.createElement('img');
imageElement.src = splitTag.val;
storyContainer.appendChild(imageElement);
imageElement.onload = () => {
console.log(`scrollingto ${previousBottomEdge}`)
scrollDown(previousBottomEdge)
}
showAfter(delay, imageElement);
delay += 200.0;
}
// LINK: url
else if( splitTag && splitTag.property == "LINK" ) {
window.location.href = splitTag.val;
}
// LINKOPEN: url
else if( splitTag && splitTag.property == "LINKOPEN" ) {
window.open(splitTag.val);
}
// BACKGROUND: src
else if( splitTag && splitTag.property == "BACKGROUND" ) {
outerScrollContainer.style.backgroundImage = 'url('+splitTag.val+')';
}
// CLASS: className
else if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
// CLEAR - removes all existing content.
// RESTART - clears everything and restarts the story from the beginning
else if( tag == "CLEAR" || tag == "RESTART" ) {
removeAll("p");
removeAll("img");
// Comment out this line if you want to leave the header visible when clearing
setVisible(".header", false);
if( tag == "RESTART" ) {
restart();
return;
}
}
}
// Check if paragraphText is empty
if (paragraphText.trim().length == 0) {
continue; // Skip empty paragraphs
}
// Create paragraph element (initially hidden)
var paragraphElement = document.createElement('p');
paragraphElement.innerHTML = paragraphText;
storyContainer.appendChild(paragraphElement);
// Add any custom classes derived from ink tags
for(var i=0; i<customClasses.length; i++)
paragraphElement.classList.add(customClasses[i]);
// Fade in paragraph after a short delay
showAfter(delay, paragraphElement);
delay += 200.0;
}
// Create HTML choices from ink choices
story.currentChoices.forEach(function(choice) {
// Create paragraph with anchor element
var choiceTags = choice.tags;
var customClasses = [];
var isClickable = true;
for(var i=0; i<choiceTags.length; i++) {
var choiceTag = choiceTags[i];
var splitTag = splitPropertyTag(choiceTag);
splitTag.property = splitTag.property.toUpperCase();
if(choiceTag.toUpperCase() == "UNCLICKABLE"){
isClickable = false
}
if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
}
var choiceParagraphElement = document.createElement('p');
choiceParagraphElement.classList.add("choice");
for(var i=0; i<customClasses.length; i++)
choiceParagraphElement.classList.add(customClasses[i]);
if(isClickable){
choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>`
}else{
choiceParagraphElement.innerHTML = `<span class='unclickable'>${choice.text}</span>`
}
storyContainer.appendChild(choiceParagraphElement);
// Fade choice in after a short delay
showAfter(delay, choiceParagraphElement);
delay += 200.0;
// Click on choice
if(isClickable){
var choiceAnchorEl = choiceParagraphElement.querySelectorAll("a")[0];
choiceAnchorEl.addEventListener("click", function(event) {
// Don't follow <a> link
event.preventDefault();
// Extend height to fit
// We do this manually so that removing elements and creating new ones doesn't
// cause the height (and therefore scroll) to jump backwards temporarily.
storyContainer.style.height = contentBottomEdgeY()+"px";
// Remove all existing choices
removeAll(".choice");
// Tell the story where to go next
story.ChooseChoiceIndex(choice.index);
// This is where the save button will save from
savePoint = story.state.toJson();
// Aaand loop
continueStory();
});
}
});
// Unset storyContainer's height, allowing it to resize itself
storyContainer.style.height = "";
if( !firstTime )
scrollDown(previousBottomEdge);
}
function restart() {
story.ResetState();
setVisible(".header", true);
// set save point to here
savePoint = story.state.toJson();
continueStory(true);
outerScrollContainer.scrollTo(0, 0);
}
// -----------------------------------
// Various Helper functions
// -----------------------------------
// Detects whether the user accepts animations
function isAnimationEnabled() {
return window.matchMedia('(prefers-reduced-motion: no-preference)').matches;
}
// Fades in an element after a specified delay
function showAfter(delay, el) {
if( isAnimationEnabled() ) {
el.classList.add("hide");
setTimeout(function() { el.classList.remove("hide") }, delay);
} else {
// If the user doesn't want animations, show immediately
el.classList.remove("hide");
}
}
// Scrolls the page down, but no further than the bottom edge of what you could
// see previously, so it doesn't go too far.
function scrollDown(previousBottomEdge) {
// If the user doesn't want animations, let them scroll manually
if ( !isAnimationEnabled() ) {
return;
}
// Line up top of screen with the bottom of where the previous content ended
var target = previousBottomEdge;
// Can't go further than the very bottom of the page
var limit = outerScrollContainer.scrollHeight - outerScrollContainer.clientHeight;
if( target > limit ) target = limit;
var start = outerScrollContainer.scrollTop;
var dist = target - start;
var duration = 300 + 300*dist/100;
var startTime = null;
function step(time) {
if( startTime == null ) startTime = time;
var t = (time-startTime) / duration;
var lerp = 3*t*t - 2*t*t*t; // ease in/out
outerScrollContainer.scrollTo(0, (1.0-lerp)*start + lerp*target);
if( t < 1 ) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
// The Y coordinate of the bottom end of all the story content, used
// for growing the container, and deciding how far to scroll.
function contentBottomEdgeY() {
var bottomElement = storyContainer.lastElementChild;
return bottomElement ? bottomElement.offsetTop + bottomElement.offsetHeight : 0;
}
// Remove all elements that match the given selector. Used for removing choices after
// you've picked one, as well as for the CLEAR and RESTART tags.
function removeAll(selector)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
el.parentNode.removeChild(el);
}
}
// Used for hiding and showing the header when you CLEAR or RESTART the story respectively.
function setVisible(selector, visible)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
if( !visible )
el.classList.add("invisible");
else
el.classList.remove("invisible");
}
}
// Helper for parsing out tags of the form:
// # PROPERTY: value
// e.g. IMAGE: source path
function splitPropertyTag(tag) {
var propertySplitIdx = tag.indexOf(":");
if( propertySplitIdx != null ) {
var property = tag.substr(0, propertySplitIdx).trim();
var val = tag.substr(propertySplitIdx+1).trim();
return {
property: property,
val: val
};
}
return null;
}
// Loads save state if exists in the browser memory
function loadSavePoint() {
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) {
story.state.LoadJson(savedState);
return true;
}
} catch (e) {
console.debug("Couldn't load save state");
}
return false;
}
// Detects which theme (light or dark) to use
function setupTheme(globalTagTheme) {
// load theme from browser memory
var savedTheme;
try {
savedTheme = window.localStorage.getItem('theme');
} catch (e) {
console.debug("Couldn't load saved theme");
}
// Check whether the OS/browser is configured for dark mode
var browserDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (savedTheme === "dark"
|| (savedTheme == undefined && globalTagTheme === "dark")
|| (savedTheme == undefined && globalTagTheme == undefined && browserDark))
document.body.classList.add("dark");
}
// Used to hook up the functionality for global functionality buttons
function setupButtons(hasSave) {
let rewindEl = document.getElementById("rewind");
if (rewindEl) rewindEl.addEventListener("click", function(event) {
removeAll("p");
removeAll("img");
setVisible(".header", false);
restart();
});
let saveEl = document.getElementById("save");
if (saveEl) saveEl.addEventListener("click", function(event) {
try {
window.localStorage.setItem('save-state', savePoint);
document.getElementById("reload").removeAttribute("disabled");
window.localStorage.setItem('theme', document.body.classList.contains("dark") ? "dark" : "");
} catch (e) {
console.warn("Couldn't save state");
}
});
let reloadEl = document.getElementById("reload");
if (!hasSave) {
reloadEl.setAttribute("disabled", "disabled");
}
reloadEl.addEventListener("click", function(event) {
if (reloadEl.getAttribute("disabled"))
return;
removeAll("p");
removeAll("img");
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) story.state.LoadJson(savedState);
} catch (e) {
console.debug("Couldn't load save state");
}
continueStory(true);
});
let themeSwitchEl = document.getElementById("theme-switch");
if (themeSwitchEl) themeSwitchEl.addEventListener("click", function(event) {
document.body.classList.add("switched");
document.body.classList.toggle("dark");
});
}
})(storyContent);

@ -1 +0,0 @@
var storyContent = {"inkVersion":21,"root":[["^Blood zigzags out in all eight directions. Acoustic aromas flood the air. Night begins to turn and rain finds its way down from the threadbare sky. In the middle of the room stands a thought, \"what had caused this tragedy?\" The body of a man was blundered to a puddy. The body of an aristocrat. The body of a lecher. He sure would taste like leather. Out the window, children run wild in sporadic grey motion.","\n","ev","str","^Continue","/str","/ev",{"*":"0.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_2"},{"->":"0.g-0"},{"#f":5}],"g-0":["done",{"#f":5}]}],"done",{"paragraph_2":[["^Out of all people, you had to be the one to discover the body. You want to scream, but you can't, and you know that if you do, there'll be repercussions. The terror feels like daylight beneath your skin in the neon of night.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_3"},{"#f":5}]}],{"#f":1}],"paragraph_3":[["^\"Who could have done this?\" the thought repeats its presence in the white velvet-coated study as the blood crusts slowly to a mediocre brown stain across the parquet floor.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_4"},{"#f":5}]}],{"#f":1}],"paragraph_4":[["^[SEPARATE FRAGMENT]","\n","^Dmitry ran into Katya's mother, Dolores, on the way to the prison. She was silk, saying, \"I thought I meant birth like the apparation of Summer approaching the South, but how wrong I was to give the gift of life to such a cruel woman.\" There she stands with her moon-shaven eyes against the delicately placed watermelons on the table of the street vendor selling fruit.","\n","^\"Are you going to buy anything? I'm about ready to pack up.\" the street vendor said interrupting the intense conversation we were having.","\n","^Dolores's son was originally sent to die in a some unimportant war while her daughter amounted the social ladder to become a laywer with cunning ambition. She was responsible for more executions than holidays in the Hebrew year.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_5"},{"#f":5}]}],{"#f":1}],"paragraph_5":["^[SEPARATE FRAGMENT]","\n","^You spot a black notebook left on the bench by the traintracks. This is nice, to have something to discover. People should leave their belongings in public more often.","\n","^[SEPARATE FRAGMENT]","\n","^Face-down you fall onto the bed into a straight-jacket sleep. Your eyes gently-pressing to the sheets reveal all sorts of hypnagogic decompressions, decompressing into memories that you're not sure you can trust.","\n","end",{"#f":1}],"#f":1}],"listDefs":{}};

Binary file not shown.

Binary file not shown.

@ -1,38 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ruixi</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="outerContainer">
<h3 class="written-in-ink"><a href="https://www.inklestudios.com/ink">WRITTEN IN INK</a></h3>
<div id="controls" class="buttons">
<a id="rewind" title="Restart story from beginning">restart</a>
<a id="save" title="Save progress">save</a>
<a id="reload" title="Reload from save point">load</a>
<a id="theme-switch" title="Switch theme">theme</a>
</div>
<div id="story" class="container">
<div class="header">
<h1>ruixi</h1>
<h2 class="byline"></h2>
</div>
</div>
</div>
<script src="ink.js"></script>
<script src="ruixi.js"></script>
<script src="main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -1,439 +0,0 @@
(function(storyContent) {
// Create ink story from the content using inkjs
var story = new inkjs.Story(storyContent);
var savePoint = "";
let savedTheme;
let globalTagTheme;
// Global tags - those at the top of the ink file
// We support:
// # theme: dark
// # author: Your Name
var globalTags = story.globalTags;
if( globalTags ) {
for(var i=0; i<story.globalTags.length; i++) {
var globalTag = story.globalTags[i];
var splitTag = splitPropertyTag(globalTag);
// THEME: dark
if( splitTag && splitTag.property == "theme" ) {
globalTagTheme = splitTag.val;
}
// author: Your Name
else if( splitTag && splitTag.property == "author" ) {
var byline = document.querySelector('.byline');
byline.innerHTML = "by "+splitTag.val;
}
}
}
var storyContainer = document.querySelector('#story');
var outerScrollContainer = document.querySelector('.outerContainer');
// page features setup
setupTheme(globalTagTheme);
var hasSave = loadSavePoint();
setupButtons(hasSave);
// Set initial save point
savePoint = story.state.toJson();
// Kick off the start of the story!
continueStory(true);
// Main story processing function. Each time this is called it generates
// all the next content up as far as the next set of choices.
function continueStory(firstTime) {
var paragraphIndex = 0;
var delay = 0.0;
// Don't over-scroll past new content
var previousBottomEdge = firstTime ? 0 : contentBottomEdgeY();
// Generate story text - loop through available content
while(story.canContinue) {
// Get ink to generate the next paragraph
var paragraphText = story.Continue();
var tags = story.currentTags;
// Any special tags included with this line
var customClasses = [];
for(var i=0; i<tags.length; i++) {
var tag = tags[i];
// Detect tags of the form "X: Y". Currently used for IMAGE and CLASS but could be
// customised to be used for other things too.
var splitTag = splitPropertyTag(tag);
splitTag.property = splitTag.property.toUpperCase();
// AUDIO: src
if( splitTag && splitTag.property == "AUDIO" ) {
if('audio' in this) {
this.audio.pause();
this.audio.removeAttribute('src');
this.audio.load();
}
this.audio = new Audio(splitTag.val);
this.audio.play();
}
// AUDIOLOOP: src
else if( splitTag && splitTag.property == "AUDIOLOOP" ) {
if('audioLoop' in this) {
this.audioLoop.pause();
this.audioLoop.removeAttribute('src');
this.audioLoop.load();
}
this.audioLoop = new Audio(splitTag.val);
this.audioLoop.play();
this.audioLoop.loop = true;
}
// IMAGE: src
if( splitTag && splitTag.property == "IMAGE" ) {
var imageElement = document.createElement('img');
imageElement.src = splitTag.val;
storyContainer.appendChild(imageElement);
imageElement.onload = () => {
console.log(`scrollingto ${previousBottomEdge}`)
scrollDown(previousBottomEdge)
}
showAfter(delay, imageElement);
delay += 200.0;
}
// LINK: url
else if( splitTag && splitTag.property == "LINK" ) {
window.location.href = splitTag.val;
}
// LINKOPEN: url
else if( splitTag && splitTag.property == "LINKOPEN" ) {
window.open(splitTag.val);
}
// BACKGROUND: src
else if( splitTag && splitTag.property == "BACKGROUND" ) {
outerScrollContainer.style.backgroundImage = 'url('+splitTag.val+')';
}
// CLASS: className
else if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
// CLEAR - removes all existing content.
// RESTART - clears everything and restarts the story from the beginning
else if( tag == "CLEAR" || tag == "RESTART" ) {
removeAll("p");
removeAll("img");
// Comment out this line if you want to leave the header visible when clearing
setVisible(".header", false);
if( tag == "RESTART" ) {
restart();
return;
}
}
}
// Check if paragraphText is empty
if (paragraphText.trim().length == 0) {
continue; // Skip empty paragraphs
}
// Create paragraph element (initially hidden)
var paragraphElement = document.createElement('p');
paragraphElement.innerHTML = paragraphText;
storyContainer.appendChild(paragraphElement);
// Add any custom classes derived from ink tags
for(var i=0; i<customClasses.length; i++)
paragraphElement.classList.add(customClasses[i]);
// Fade in paragraph after a short delay
showAfter(delay, paragraphElement);
delay += 200.0;
}
// Create HTML choices from ink choices
story.currentChoices.forEach(function(choice) {
// Create paragraph with anchor element
var choiceTags = choice.tags;
var customClasses = [];
var isClickable = true;
for(var i=0; i<choiceTags.length; i++) {
var choiceTag = choiceTags[i];
var splitTag = splitPropertyTag(choiceTag);
splitTag.property = splitTag.property.toUpperCase();
if(choiceTag.toUpperCase() == "UNCLICKABLE"){
isClickable = false
}
if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
}
var choiceParagraphElement = document.createElement('p');
choiceParagraphElement.classList.add("choice");
for(var i=0; i<customClasses.length; i++)
choiceParagraphElement.classList.add(customClasses[i]);
if(isClickable){
choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>`
}else{
choiceParagraphElement.innerHTML = `<span class='unclickable'>${choice.text}</span>`
}
storyContainer.appendChild(choiceParagraphElement);
// Fade choice in after a short delay
showAfter(delay, choiceParagraphElement);
delay += 200.0;
// Click on choice
if(isClickable){
var choiceAnchorEl = choiceParagraphElement.querySelectorAll("a")[0];
choiceAnchorEl.addEventListener("click", function(event) {
// Don't follow <a> link
event.preventDefault();
// Extend height to fit
// We do this manually so that removing elements and creating new ones doesn't
// cause the height (and therefore scroll) to jump backwards temporarily.
storyContainer.style.height = contentBottomEdgeY()+"px";
// Remove all existing choices
removeAll(".choice");
// Tell the story where to go next
story.ChooseChoiceIndex(choice.index);
// This is where the save button will save from
savePoint = story.state.toJson();
// Aaand loop
continueStory();
});
}
});
// Unset storyContainer's height, allowing it to resize itself
storyContainer.style.height = "";
if( !firstTime )
scrollDown(previousBottomEdge);
}
function restart() {
story.ResetState();
setVisible(".header", true);
// set save point to here
savePoint = story.state.toJson();
continueStory(true);
outerScrollContainer.scrollTo(0, 0);
}
// -----------------------------------
// Various Helper functions
// -----------------------------------
// Detects whether the user accepts animations
function isAnimationEnabled() {
return window.matchMedia('(prefers-reduced-motion: no-preference)').matches;
}
// Fades in an element after a specified delay
function showAfter(delay, el) {
if( isAnimationEnabled() ) {
el.classList.add("hide");
setTimeout(function() { el.classList.remove("hide") }, delay);
} else {
// If the user doesn't want animations, show immediately
el.classList.remove("hide");
}
}
// Scrolls the page down, but no further than the bottom edge of what you could
// see previously, so it doesn't go too far.
function scrollDown(previousBottomEdge) {
// If the user doesn't want animations, let them scroll manually
if ( !isAnimationEnabled() ) {
return;
}
// Line up top of screen with the bottom of where the previous content ended
var target = previousBottomEdge;
// Can't go further than the very bottom of the page
var limit = outerScrollContainer.scrollHeight - outerScrollContainer.clientHeight;
if( target > limit ) target = limit;
var start = outerScrollContainer.scrollTop;
var dist = target - start;
var duration = 300 + 300*dist/100;
var startTime = null;
function step(time) {
if( startTime == null ) startTime = time;
var t = (time-startTime) / duration;
var lerp = 3*t*t - 2*t*t*t; // ease in/out
outerScrollContainer.scrollTo(0, (1.0-lerp)*start + lerp*target);
if( t < 1 ) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
// The Y coordinate of the bottom end of all the story content, used
// for growing the container, and deciding how far to scroll.
function contentBottomEdgeY() {
var bottomElement = storyContainer.lastElementChild;
return bottomElement ? bottomElement.offsetTop + bottomElement.offsetHeight : 0;
}
// Remove all elements that match the given selector. Used for removing choices after
// you've picked one, as well as for the CLEAR and RESTART tags.
function removeAll(selector)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
el.parentNode.removeChild(el);
}
}
// Used for hiding and showing the header when you CLEAR or RESTART the story respectively.
function setVisible(selector, visible)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
if( !visible )
el.classList.add("invisible");
else
el.classList.remove("invisible");
}
}
// Helper for parsing out tags of the form:
// # PROPERTY: value
// e.g. IMAGE: source path
function splitPropertyTag(tag) {
var propertySplitIdx = tag.indexOf(":");
if( propertySplitIdx != null ) {
var property = tag.substr(0, propertySplitIdx).trim();
var val = tag.substr(propertySplitIdx+1).trim();
return {
property: property,
val: val
};
}
return null;
}
// Loads save state if exists in the browser memory
function loadSavePoint() {
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) {
story.state.LoadJson(savedState);
return true;
}
} catch (e) {
console.debug("Couldn't load save state");
}
return false;
}
// Detects which theme (light or dark) to use
function setupTheme(globalTagTheme) {
// load theme from browser memory
var savedTheme;
try {
savedTheme = window.localStorage.getItem('theme');
} catch (e) {
console.debug("Couldn't load saved theme");
}
// Check whether the OS/browser is configured for dark mode
var browserDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (savedTheme === "dark"
|| (savedTheme == undefined && globalTagTheme === "dark")
|| (savedTheme == undefined && globalTagTheme == undefined && browserDark))
document.body.classList.add("dark");
}
// Used to hook up the functionality for global functionality buttons
function setupButtons(hasSave) {
let rewindEl = document.getElementById("rewind");
if (rewindEl) rewindEl.addEventListener("click", function(event) {
removeAll("p");
removeAll("img");
setVisible(".header", false);
restart();
});
let saveEl = document.getElementById("save");
if (saveEl) saveEl.addEventListener("click", function(event) {
try {
window.localStorage.setItem('save-state', savePoint);
document.getElementById("reload").removeAttribute("disabled");
window.localStorage.setItem('theme', document.body.classList.contains("dark") ? "dark" : "");
} catch (e) {
console.warn("Couldn't save state");
}
});
let reloadEl = document.getElementById("reload");
if (!hasSave) {
reloadEl.setAttribute("disabled", "disabled");
}
reloadEl.addEventListener("click", function(event) {
if (reloadEl.getAttribute("disabled"))
return;
removeAll("p");
removeAll("img");
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) story.state.LoadJson(savedState);
} catch (e) {
console.debug("Couldn't load save state");
}
continueStory(true);
});
let themeSwitchEl = document.getElementById("theme-switch");
if (themeSwitchEl) themeSwitchEl.addEventListener("click", function(event) {
document.body.classList.add("switched");
document.body.classList.toggle("dark");
});
}
})(storyContent);

@ -1 +0,0 @@
var storyContent = {"inkVersion":21,"root":[["^Blood zigzags out in all eight directions. Acoustic aromas flood the air. Night begins to turn and rain finds its way down from the threadbare sky. In the middle of the room stands a thought, \"what had caused this tragedy?\" The body of a man was blundered to a puddy. The body of an aristocrat. The body of a lecher. He sure would taste like leather. Out the window, children run wild in sporadic grey motion.","\n","ev","str","^Continue","/str","/ev",{"*":"0.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_2"},{"->":"0.g-0"},{"#f":5}],"g-0":["done",{"#f":5}]}],"done",{"paragraph_2":[["^Out of all people, you had to be the one to discover the body. You want to scream, but you can't, and you know that if you do, there'll be repercussions. The terror feels like daylight beneath your skin in the neon of night.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_3"},{"#f":5}]}],{"#f":1}],"paragraph_3":[["^\"Who could have done this?\" the thought repeats its presence in the white velvet-coated study as the blood crusts slowly to a mediocre brown stain across the parquet floor.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_4"},{"#f":5}]}],{"#f":1}],"paragraph_4":[["^[SEPARATE FRAGMENT]","\n","^Dmitry ran into Katya's mother, Dolores, on the way to the prison. She was silk, saying, \"I thought I meant birth like the apparation of Summer approaching the South, but how wrong I was to give the gift of life to such a cruel woman.\" There she stands with her moon-shaven eyes against the delicately placed watermelons on the table of the street vendor selling fruit.","\n","^\"Are you going to buy anything? I'm about ready to pack up.\" the street vendor said interrupting the intense conversation we were having.","\n","^Dolores's son was originally sent to die in a some unimportant war while her daughter amounted the social ladder to become a laywer with cunning ambition. She was responsible for more executions than holidays in the Hebrew year.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_5"},{"#f":5}]}],{"#f":1}],"paragraph_5":["^[SEPARATE FRAGMENT]","\n","^You spot a black notebook left on the bench by the traintracks. This is nice, to have something to discover. People should leave their belongings in public more often.","\n","^[SEPARATE FRAGMENT]","\n","^Face-down you fall onto the bed into a straight-jacket sleep. Your eyes gently-pressing to the sheets reveal all sorts of hypnagogic decompressions, decompressing into memories that you're not sure you can trust.","\n","end",{"#f":1}],"#f":1}],"listDefs":{}};

@ -1,38 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ruixi</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="outerContainer">
<h3 class="written-in-ink"><a href="https://www.inklestudios.com/ink">WRITTEN IN INK</a></h3>
<div id="controls" class="buttons">
<a id="rewind" title="Restart story from beginning">restart</a>
<a id="save" title="Save progress">save</a>
<a id="reload" title="Reload from save point">load</a>
<a id="theme-switch" title="Switch theme">theme</a>
</div>
<div id="story" class="container">
<div class="header">
<h1>ruixi</h1>
<h2 class="byline"></h2>
</div>
</div>
</div>
<script src="ink.js"></script>
<script src="ruixi.js"></script>
<script src="main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -1,439 +0,0 @@
(function(storyContent) {
// Create ink story from the content using inkjs
var story = new inkjs.Story(storyContent);
var savePoint = "";
let savedTheme;
let globalTagTheme;
// Global tags - those at the top of the ink file
// We support:
// # theme: dark
// # author: Your Name
var globalTags = story.globalTags;
if( globalTags ) {
for(var i=0; i<story.globalTags.length; i++) {
var globalTag = story.globalTags[i];
var splitTag = splitPropertyTag(globalTag);
// THEME: dark
if( splitTag && splitTag.property == "theme" ) {
globalTagTheme = splitTag.val;
}
// author: Your Name
else if( splitTag && splitTag.property == "author" ) {
var byline = document.querySelector('.byline');
byline.innerHTML = "by "+splitTag.val;
}
}
}
var storyContainer = document.querySelector('#story');
var outerScrollContainer = document.querySelector('.outerContainer');
// page features setup
setupTheme(globalTagTheme);
var hasSave = loadSavePoint();
setupButtons(hasSave);
// Set initial save point
savePoint = story.state.toJson();
// Kick off the start of the story!
continueStory(true);
// Main story processing function. Each time this is called it generates
// all the next content up as far as the next set of choices.
function continueStory(firstTime) {
var paragraphIndex = 0;
var delay = 0.0;
// Don't over-scroll past new content
var previousBottomEdge = firstTime ? 0 : contentBottomEdgeY();
// Generate story text - loop through available content
while(story.canContinue) {
// Get ink to generate the next paragraph
var paragraphText = story.Continue();
var tags = story.currentTags;
// Any special tags included with this line
var customClasses = [];
for(var i=0; i<tags.length; i++) {
var tag = tags[i];
// Detect tags of the form "X: Y". Currently used for IMAGE and CLASS but could be
// customised to be used for other things too.
var splitTag = splitPropertyTag(tag);
splitTag.property = splitTag.property.toUpperCase();
// AUDIO: src
if( splitTag && splitTag.property == "AUDIO" ) {
if('audio' in this) {
this.audio.pause();
this.audio.removeAttribute('src');
this.audio.load();
}
this.audio = new Audio(splitTag.val);
this.audio.play();
}
// AUDIOLOOP: src
else if( splitTag && splitTag.property == "AUDIOLOOP" ) {
if('audioLoop' in this) {
this.audioLoop.pause();
this.audioLoop.removeAttribute('src');
this.audioLoop.load();
}
this.audioLoop = new Audio(splitTag.val);
this.audioLoop.play();
this.audioLoop.loop = true;
}
// IMAGE: src
if( splitTag && splitTag.property == "IMAGE" ) {
var imageElement = document.createElement('img');
imageElement.src = splitTag.val;
storyContainer.appendChild(imageElement);
imageElement.onload = () => {
console.log(`scrollingto ${previousBottomEdge}`)
scrollDown(previousBottomEdge)
}
showAfter(delay, imageElement);
delay += 200.0;
}
// LINK: url
else if( splitTag && splitTag.property == "LINK" ) {
window.location.href = splitTag.val;
}
// LINKOPEN: url
else if( splitTag && splitTag.property == "LINKOPEN" ) {
window.open(splitTag.val);
}
// BACKGROUND: src
else if( splitTag && splitTag.property == "BACKGROUND" ) {
outerScrollContainer.style.backgroundImage = 'url('+splitTag.val+')';
}
// CLASS: className
else if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
// CLEAR - removes all existing content.
// RESTART - clears everything and restarts the story from the beginning
else if( tag == "CLEAR" || tag == "RESTART" ) {
removeAll("p");
removeAll("img");
// Comment out this line if you want to leave the header visible when clearing
setVisible(".header", false);
if( tag == "RESTART" ) {
restart();
return;
}
}
}
// Check if paragraphText is empty
if (paragraphText.trim().length == 0) {
continue; // Skip empty paragraphs
}
// Create paragraph element (initially hidden)
var paragraphElement = document.createElement('p');
paragraphElement.innerHTML = paragraphText;
storyContainer.appendChild(paragraphElement);
// Add any custom classes derived from ink tags
for(var i=0; i<customClasses.length; i++)
paragraphElement.classList.add(customClasses[i]);
// Fade in paragraph after a short delay
showAfter(delay, paragraphElement);
delay += 200.0;
}
// Create HTML choices from ink choices
story.currentChoices.forEach(function(choice) {
// Create paragraph with anchor element
var choiceTags = choice.tags;
var customClasses = [];
var isClickable = true;
for(var i=0; i<choiceTags.length; i++) {
var choiceTag = choiceTags[i];
var splitTag = splitPropertyTag(choiceTag);
splitTag.property = splitTag.property.toUpperCase();
if(choiceTag.toUpperCase() == "UNCLICKABLE"){
isClickable = false
}
if( splitTag && splitTag.property == "CLASS" ) {
customClasses.push(splitTag.val);
}
}
var choiceParagraphElement = document.createElement('p');
choiceParagraphElement.classList.add("choice");
for(var i=0; i<customClasses.length; i++)
choiceParagraphElement.classList.add(customClasses[i]);
if(isClickable){
choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>`
}else{
choiceParagraphElement.innerHTML = `<span class='unclickable'>${choice.text}</span>`
}
storyContainer.appendChild(choiceParagraphElement);
// Fade choice in after a short delay
showAfter(delay, choiceParagraphElement);
delay += 200.0;
// Click on choice
if(isClickable){
var choiceAnchorEl = choiceParagraphElement.querySelectorAll("a")[0];
choiceAnchorEl.addEventListener("click", function(event) {
// Don't follow <a> link
event.preventDefault();
// Extend height to fit
// We do this manually so that removing elements and creating new ones doesn't
// cause the height (and therefore scroll) to jump backwards temporarily.
storyContainer.style.height = contentBottomEdgeY()+"px";
// Remove all existing choices
removeAll(".choice");
// Tell the story where to go next
story.ChooseChoiceIndex(choice.index);
// This is where the save button will save from
savePoint = story.state.toJson();
// Aaand loop
continueStory();
});
}
});
// Unset storyContainer's height, allowing it to resize itself
storyContainer.style.height = "";
if( !firstTime )
scrollDown(previousBottomEdge);
}
function restart() {
story.ResetState();
setVisible(".header", true);
// set save point to here
savePoint = story.state.toJson();
continueStory(true);
outerScrollContainer.scrollTo(0, 0);
}
// -----------------------------------
// Various Helper functions
// -----------------------------------
// Detects whether the user accepts animations
function isAnimationEnabled() {
return window.matchMedia('(prefers-reduced-motion: no-preference)').matches;
}
// Fades in an element after a specified delay
function showAfter(delay, el) {
if( isAnimationEnabled() ) {
el.classList.add("hide");
setTimeout(function() { el.classList.remove("hide") }, delay);
} else {
// If the user doesn't want animations, show immediately
el.classList.remove("hide");
}
}
// Scrolls the page down, but no further than the bottom edge of what you could
// see previously, so it doesn't go too far.
function scrollDown(previousBottomEdge) {
// If the user doesn't want animations, let them scroll manually
if ( !isAnimationEnabled() ) {
return;
}
// Line up top of screen with the bottom of where the previous content ended
var target = previousBottomEdge;
// Can't go further than the very bottom of the page
var limit = outerScrollContainer.scrollHeight - outerScrollContainer.clientHeight;
if( target > limit ) target = limit;
var start = outerScrollContainer.scrollTop;
var dist = target - start;
var duration = 300 + 300*dist/100;
var startTime = null;
function step(time) {
if( startTime == null ) startTime = time;
var t = (time-startTime) / duration;
var lerp = 3*t*t - 2*t*t*t; // ease in/out
outerScrollContainer.scrollTo(0, (1.0-lerp)*start + lerp*target);
if( t < 1 ) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
// The Y coordinate of the bottom end of all the story content, used
// for growing the container, and deciding how far to scroll.
function contentBottomEdgeY() {
var bottomElement = storyContainer.lastElementChild;
return bottomElement ? bottomElement.offsetTop + bottomElement.offsetHeight : 0;
}
// Remove all elements that match the given selector. Used for removing choices after
// you've picked one, as well as for the CLEAR and RESTART tags.
function removeAll(selector)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
el.parentNode.removeChild(el);
}
}
// Used for hiding and showing the header when you CLEAR or RESTART the story respectively.
function setVisible(selector, visible)
{
var allElements = storyContainer.querySelectorAll(selector);
for(var i=0; i<allElements.length; i++) {
var el = allElements[i];
if( !visible )
el.classList.add("invisible");
else
el.classList.remove("invisible");
}
}
// Helper for parsing out tags of the form:
// # PROPERTY: value
// e.g. IMAGE: source path
function splitPropertyTag(tag) {
var propertySplitIdx = tag.indexOf(":");
if( propertySplitIdx != null ) {
var property = tag.substr(0, propertySplitIdx).trim();
var val = tag.substr(propertySplitIdx+1).trim();
return {
property: property,
val: val
};
}
return null;
}
// Loads save state if exists in the browser memory
function loadSavePoint() {
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) {
story.state.LoadJson(savedState);
return true;
}
} catch (e) {
console.debug("Couldn't load save state");
}
return false;
}
// Detects which theme (light or dark) to use
function setupTheme(globalTagTheme) {
// load theme from browser memory
var savedTheme;
try {
savedTheme = window.localStorage.getItem('theme');
} catch (e) {
console.debug("Couldn't load saved theme");
}
// Check whether the OS/browser is configured for dark mode
var browserDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (savedTheme === "dark"
|| (savedTheme == undefined && globalTagTheme === "dark")
|| (savedTheme == undefined && globalTagTheme == undefined && browserDark))
document.body.classList.add("dark");
}
// Used to hook up the functionality for global functionality buttons
function setupButtons(hasSave) {
let rewindEl = document.getElementById("rewind");
if (rewindEl) rewindEl.addEventListener("click", function(event) {
removeAll("p");
removeAll("img");
setVisible(".header", false);
restart();
});
let saveEl = document.getElementById("save");
if (saveEl) saveEl.addEventListener("click", function(event) {
try {
window.localStorage.setItem('save-state', savePoint);
document.getElementById("reload").removeAttribute("disabled");
window.localStorage.setItem('theme', document.body.classList.contains("dark") ? "dark" : "");
} catch (e) {
console.warn("Couldn't save state");
}
});
let reloadEl = document.getElementById("reload");
if (!hasSave) {
reloadEl.setAttribute("disabled", "disabled");
}
reloadEl.addEventListener("click", function(event) {
if (reloadEl.getAttribute("disabled"))
return;
removeAll("p");
removeAll("img");
try {
let savedState = window.localStorage.getItem('save-state');
if (savedState) story.state.LoadJson(savedState);
} catch (e) {
console.debug("Couldn't load save state");
}
continueStory(true);
});
let themeSwitchEl = document.getElementById("theme-switch");
if (themeSwitchEl) themeSwitchEl.addEventListener("click", function(event) {
document.body.classList.add("switched");
document.body.classList.toggle("dark");
});
}
})(storyContent);

@ -1 +0,0 @@
var storyContent = {"inkVersion":21,"root":[["^Blood zigzags out in all eight directions. Acoustic aromas flood the air. Night begins to turn and rain finds its way down from the threadbare sky. In the middle of the room stands a thought, \"what had caused this tragedy?\" The body of a man was blundered to a puddy. The body of an aristocrat. The body of a lecher. He sure would taste like leather. Out the window, children run wild in sporadic grey motion.","\n","ev","str","^Continue","/str","/ev",{"*":"0.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_2"},{"->":"0.g-0"},{"#f":5}],"g-0":["done",{"#f":5}]}],"done",{"paragraph_2":[["^Out of all people, you had to be the one to discover the body. You want to scream, but you can't, and you know that if you do, there'll be repercussions. The terror feels like daylight beneath your skin in the neon of night.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_3"},{"#f":5}]}],{"#f":1}],"paragraph_3":[["^\"Who could have done this?\" the thought repeats its presence in the white velvet-coated study as the blood crusts slowly to a mediocre brown stain across the parquet floor.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_4"},{"#f":5}]}],{"#f":1}],"paragraph_4":[["^Dmitry ran into Katya's mother, Dolores, on the way to the prison. She was silk, saying, \"I thought I meant birth like the apparation of Summer approaching the South, but how wrong I was to give the gift of life to such a cruel woman.\" There she stands with her moon-shaven eyes against the delicately placed watermelons on the table of the street vendor selling fruit.","\n","^\"Are you going to buy anything? I'm about ready to pack up.\" the street vendor said interrupting the intense conversation we were having.","\n","^Dolores's son was originally sent to die in a some unimportant war while her daughter amounted the social ladder to become a laywer with cunning ambition. She was responsible for more executions than holidays in the Hebrew year.","\n","ev","str","^Continue","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n",{"->":"paragraph_5"},{"#f":5}]}],{"#f":1}],"paragraph_5":["^You spot a black notebook left on the bench by the traintracks. This is nice, to have something to discover. People should leave their belongings in public more often.","\n","^Face-down you fall onto the bed into a straight-jacket sleep. Your eyes gently-pressing to the sheets reveal all sorts of hypnagogic decompressions, decompressing into memories that you're not sure you can trust.","\n","end",{"#f":1}],"#f":1}],"listDefs":{}};

@ -1,306 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,700|Quattrocento:700');
body {
font-family: 'Open Sans', sans-serif;
font-weight: lighter;
background: white;
overflow: hidden;
}
@media screen and (prefers-reduced-motion: no-preference) {
body.switched {
transition: color 0.6s, background-color 0.6s;
}
}
h1,
h2 {
text-align: center;
font-family: "Quattrocento", Georgia, 'Times New Roman', Times, serif;
margin: 0;
padding: 0;
}
h1 {
font-size: 30pt;
margin-bottom: 10px;
}
h2 {
font-size: 14pt;
font-style: italic;
font-family: sans-serif;
font-weight: lighter;
color: #BBB;
}
.header {
padding-top: 3em;
padding-bottom: 3em;
}
/*
Built-in class:
# author: Name
*/
.byline {
font-style: italic;
}
.written-in-ink {
z-index: 3;
font-size: 9pt;
font-family: sans-serif;
text-align: center;
font-weight: 700;
position: fixed;
display: block;
width: 100%;
background: white;
margin: 0;
padding-top: 6px;
padding-bottom: 6px;
height: 14px;
top: 0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.written-in-ink {
transition: color 0.6s, background 0.6s;
}
}
/*
Enables <iframe> support work on itch.io when using mobile iOS
*/
.outerContainer {
position: absolute;
display: block;
margin: 0;
padding: 0;
-webkit-overflow-scrolling: touch;
overflow: scroll;
overflow-x: hidden;
height: 100%;
width: 100%;
top: 0;
left: 0;
margin-top: 24px;
background-size: cover;
background-repeat: no-repeat;
}
@media screen and (max-width: 980px) {
.outerContainer {
margin-top: 44px;
background-size: cover;
background-repeat: no-repeat;
}
}
.container {
display: block;
max-width: 600px;
margin: 0 auto;
padding: 20px;
padding-top: 4em;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.switched .container {
transition: background-color 0.6s;
}
}
p {
font-size: 13pt;
color: #888;
line-height: 1.7em;
font-weight: lighter;
}
a {
font-weight: 700;
color: #b97c2c;
font-family: sans-serif;
text-decoration: none;
}
.unclickable {
font-weight: 700;
color: #4f3411;
font-family: sans-serif;
text-decoration: none;
cursor: not-allowed;
}
a:hover {
color: black;
}
@media screen and (prefers-reduced-motion: no-preference) {
a {
transition: color 0.6s;
}
a:hover {
transition: color 0.1s;
}
}
strong {
color: black;
font-weight: bold;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
.container .hide {
opacity: 0.0;
}
.container .invisible {
display: none;
}
.container>* {
opacity: 1.0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.container>* {
transition: opacity 1.0s;
}
}
/*
Class applied to all choices
(Will always appear inside <p> element by default.)
*/
.choice {
text-align: center;
line-height: 1.7em;
}
/*
Class applied to first choice
*/
:not(.choice)+.choice {
padding-top: 1em;
}
/*
Class applied to choice links
*/
.choice a, .choice span {
font-size: 15pt;
}
/*
Built-in class:
The End # CLASS: end
*/
.end {
text-align: center;
font-weight: bold;
color: black;
padding-top: 20px;
padding-bottom: 20px;
}
#controls {
z-index: 4;
font-size: 9pt;
text-align: center;
padding-bottom: 6px;
position: fixed;
right: 14px;
top: 4px;
user-select: none;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
#controls {
transition: color 0.6s, background 0.6s;
}
}
#controls [disabled] {
color: #ccc;
}
#controls>*:not(:last-child):after {
content: " | ";
}
@media screen and (max-width: 980px) {
#controls {
z-index: 2;
padding-top: 24px;
top: 0;
left: 0;
right: 0;
}
}
/*
Dark Theme (Added in Inky 0.10.0)
# theme: dark
*/
body.dark {
background: black;
color: white;
}
.dark h2 {
color: #666;
}
.dark .container {
background: black;
}
.dark .written-in-ink {
background: black;
}
.dark a {
color: #cc8f1a;
}
.dark .unclickable{
color: #c4af87;
cursor:not-allowed;
}
.dark a:hover {
color: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.dark a {
transition: color 0.6s;
}
}
.dark strong {
color: white;
}
.dark #controls [disabled] {
color: #444;
}
.dark .end {
color: white;
}
.dark #controls {
background: black;
}

@ -1,306 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,700|Quattrocento:700');
body {
font-family: 'Open Sans', sans-serif;
font-weight: lighter;
background: white;
overflow: hidden;
}
@media screen and (prefers-reduced-motion: no-preference) {
body.switched {
transition: color 0.6s, background-color 0.6s;
}
}
h1,
h2 {
text-align: center;
font-family: "Quattrocento", Georgia, 'Times New Roman', Times, serif;
margin: 0;
padding: 0;
}
h1 {
font-size: 30pt;
margin-bottom: 10px;
}
h2 {
font-size: 14pt;
font-style: italic;
font-family: sans-serif;
font-weight: lighter;
color: #BBB;
}
.header {
padding-top: 3em;
padding-bottom: 3em;
}
/*
Built-in class:
# author: Name
*/
.byline {
font-style: italic;
}
.written-in-ink {
z-index: 3;
font-size: 9pt;
font-family: sans-serif;
text-align: center;
font-weight: 700;
position: fixed;
display: block;
width: 100%;
background: white;
margin: 0;
padding-top: 6px;
padding-bottom: 6px;
height: 14px;
top: 0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.written-in-ink {
transition: color 0.6s, background 0.6s;
}
}
/*
Enables <iframe> support work on itch.io when using mobile iOS
*/
.outerContainer {
position: absolute;
display: block;
margin: 0;
padding: 0;
-webkit-overflow-scrolling: touch;
overflow: scroll;
overflow-x: hidden;
height: 100%;
width: 100%;
top: 0;
left: 0;
margin-top: 24px;
background-size: cover;
background-repeat: no-repeat;
}
@media screen and (max-width: 980px) {
.outerContainer {
margin-top: 44px;
background-size: cover;
background-repeat: no-repeat;
}
}
.container {
display: block;
max-width: 600px;
margin: 0 auto;
padding: 20px;
padding-top: 4em;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.switched .container {
transition: background-color 0.6s;
}
}
p {
font-size: 13pt;
color: #888;
line-height: 1.7em;
font-weight: lighter;
}
a {
font-weight: 700;
color: #b97c2c;
font-family: sans-serif;
text-decoration: none;
}
.unclickable {
font-weight: 700;
color: #4f3411;
font-family: sans-serif;
text-decoration: none;
cursor: not-allowed;
}
a:hover {
color: black;
}
@media screen and (prefers-reduced-motion: no-preference) {
a {
transition: color 0.6s;
}
a:hover {
transition: color 0.1s;
}
}
strong {
color: black;
font-weight: bold;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
.container .hide {
opacity: 0.0;
}
.container .invisible {
display: none;
}
.container>* {
opacity: 1.0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.container>* {
transition: opacity 1.0s;
}
}
/*
Class applied to all choices
(Will always appear inside <p> element by default.)
*/
.choice {
text-align: center;
line-height: 1.7em;
}
/*
Class applied to first choice
*/
:not(.choice)+.choice {
padding-top: 1em;
}
/*
Class applied to choice links
*/
.choice a, .choice span {
font-size: 15pt;
}
/*
Built-in class:
The End # CLASS: end
*/
.end {
text-align: center;
font-weight: bold;
color: black;
padding-top: 20px;
padding-bottom: 20px;
}
#controls {
z-index: 4;
font-size: 9pt;
text-align: center;
padding-bottom: 6px;
position: fixed;
right: 14px;
top: 4px;
user-select: none;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
#controls {
transition: color 0.6s, background 0.6s;
}
}
#controls [disabled] {
color: #ccc;
}
#controls>*:not(:last-child):after {
content: " | ";
}
@media screen and (max-width: 980px) {
#controls {
z-index: 2;
padding-top: 24px;
top: 0;
left: 0;
right: 0;
}
}
/*
Dark Theme (Added in Inky 0.10.0)
# theme: dark
*/
body.dark {
background: black;
color: white;
}
.dark h2 {
color: #666;
}
.dark .container {
background: black;
}
.dark .written-in-ink {
background: black;
}
.dark a {
color: #cc8f1a;
}
.dark .unclickable{
color: #c4af87;
cursor:not-allowed;
}
.dark a:hover {
color: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.dark a {
transition: color 0.6s;
}
}
.dark strong {
color: white;
}
.dark #controls [disabled] {
color: #444;
}
.dark .end {
color: white;
}
.dark #controls {
background: black;
}

@ -1,306 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,700|Quattrocento:700');
body {
font-family: 'Open Sans', sans-serif;
font-weight: lighter;
background: white;
overflow: hidden;
}
@media screen and (prefers-reduced-motion: no-preference) {
body.switched {
transition: color 0.6s, background-color 0.6s;
}
}
h1,
h2 {
text-align: center;
font-family: "Quattrocento", Georgia, 'Times New Roman', Times, serif;
margin: 0;
padding: 0;
}
h1 {
font-size: 30pt;
margin-bottom: 10px;
}
h2 {
font-size: 14pt;
font-style: italic;
font-family: sans-serif;
font-weight: lighter;
color: #BBB;
}
.header {
padding-top: 3em;
padding-bottom: 3em;
}
/*
Built-in class:
# author: Name
*/
.byline {
font-style: italic;
}
.written-in-ink {
z-index: 3;
font-size: 9pt;
font-family: sans-serif;
text-align: center;
font-weight: 700;
position: fixed;
display: block;
width: 100%;
background: white;
margin: 0;
padding-top: 6px;
padding-bottom: 6px;
height: 14px;
top: 0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.written-in-ink {
transition: color 0.6s, background 0.6s;
}
}
/*
Enables <iframe> support work on itch.io when using mobile iOS
*/
.outerContainer {
position: absolute;
display: block;
margin: 0;
padding: 0;
-webkit-overflow-scrolling: touch;
overflow: scroll;
overflow-x: hidden;
height: 100%;
width: 100%;
top: 0;
left: 0;
margin-top: 24px;
background-size: cover;
background-repeat: no-repeat;
}
@media screen and (max-width: 980px) {
.outerContainer {
margin-top: 44px;
background-size: cover;
background-repeat: no-repeat;
}
}
.container {
display: block;
max-width: 600px;
margin: 0 auto;
padding: 20px;
padding-top: 4em;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.switched .container {
transition: background-color 0.6s;
}
}
p {
font-size: 13pt;
color: #888;
line-height: 1.7em;
font-weight: lighter;
}
a {
font-weight: 700;
color: #b97c2c;
font-family: sans-serif;
text-decoration: none;
}
.unclickable {
font-weight: 700;
color: #4f3411;
font-family: sans-serif;
text-decoration: none;
cursor: not-allowed;
}
a:hover {
color: black;
}
@media screen and (prefers-reduced-motion: no-preference) {
a {
transition: color 0.6s;
}
a:hover {
transition: color 0.1s;
}
}
strong {
color: black;
font-weight: bold;
}
img {
display: block;
margin: 0 auto;
max-width: 100%;
}
.container .hide {
opacity: 0.0;
}
.container .invisible {
display: none;
}
.container>* {
opacity: 1.0;
}
@media screen and (prefers-reduced-motion: no-preference) {
.container>* {
transition: opacity 1.0s;
}
}
/*
Class applied to all choices
(Will always appear inside <p> element by default.)
*/
.choice {
text-align: center;
line-height: 1.7em;
}
/*
Class applied to first choice
*/
:not(.choice)+.choice {
padding-top: 1em;
}
/*
Class applied to choice links
*/
.choice a, .choice span {
font-size: 15pt;
}
/*
Built-in class:
The End # CLASS: end
*/
.end {
text-align: center;
font-weight: bold;
color: black;
padding-top: 20px;
padding-bottom: 20px;
}
#controls {
z-index: 4;
font-size: 9pt;
text-align: center;
padding-bottom: 6px;
position: fixed;
right: 14px;
top: 4px;
user-select: none;
background: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
#controls {
transition: color 0.6s, background 0.6s;
}
}
#controls [disabled] {
color: #ccc;
}
#controls>*:not(:last-child):after {
content: " | ";
}
@media screen and (max-width: 980px) {
#controls {
z-index: 2;
padding-top: 24px;
top: 0;
left: 0;
right: 0;
}
}
/*
Dark Theme (Added in Inky 0.10.0)
# theme: dark
*/
body.dark {
background: black;
color: white;
}
.dark h2 {
color: #666;
}
.dark .container {
background: black;
}
.dark .written-in-ink {
background: black;
}
.dark a {
color: #cc8f1a;
}
.dark .unclickable{
color: #c4af87;
cursor:not-allowed;
}
.dark a:hover {
color: white;
}
@media screen and (prefers-reduced-motion: no-preference) {
.dark a {
transition: color 0.6s;
}
}
.dark strong {
color: white;
}
.dark #controls [disabled] {
color: #444;
}
.dark .end {
color: white;
}
.dark #controls {
background: black;
}
Loading…
Cancel
Save