264 lines
11 KiB
Plaintext
264 lines
11 KiB
Plaintext
@model CatherineLynwood.Models.TitlePageViewModel
|
|
|
|
@{
|
|
ViewData["Title"] = "The Alpha Flame: Reckoning";
|
|
}
|
|
|
|
<div class="reckoning-page-shell">
|
|
<!-- Detective desk / case file section -->
|
|
<section class="reckoning-desk-section">
|
|
<div class="reckoning-desk-surface">
|
|
|
|
<div class="reckoning-desk-props">
|
|
<div class="reckoning-desk-photos">
|
|
<div class="reckoning-desk-photo reckoning-desk-photo-1">
|
|
<responsive-image src="flyover-at-night.png" class="img-fluid" alt="The Rubery flyover at night time" display-width-percentage="50"></responsive-image>
|
|
</div>
|
|
<div class="reckoning-desk-photo reckoning-desk-photo-2">
|
|
<responsive-image src="sophie-jones-nightclub.png" class="img-fluid" alt="Sophie Jones" display-width-percentage="50"></responsive-image>
|
|
</div>
|
|
<div class="reckoning-desk-photo reckoning-desk-photo-3">
|
|
<responsive-image src="the-alpha-flame-reckoning-cover.png" class="img-fluid" alt="Maggie Grant" display-width-percentage="50"></responsive-image>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="reckoning-desk-postit">
|
|
<span>Fashion show<br />Scandals,<br />tonight!</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="reckoning-casefile-page">
|
|
<div class="casefile-stage">
|
|
|
|
<div class="casefile" id="caseFile">
|
|
|
|
<div class="casefile-rear">
|
|
<img src="/images/webp/folder-rear.webp" alt="Case file interior" class="casefile-rear-img" />
|
|
<div class="casefile-flap-shadow"></div>
|
|
|
|
<div class="casefile-inner">
|
|
<div class="casefile-paper-stack">
|
|
<div class="casefile-paper-stack-layer casefile-paper-stack-layer-1"></div>
|
|
<div class="casefile-paper-stack-layer casefile-paper-stack-layer-2"></div>
|
|
|
|
<div class="casefile-content">
|
|
<div class="casefile-panel active" data-tab="summary">
|
|
<partial name="_ReckoningSummary" model="Model"></partial>
|
|
</div>
|
|
|
|
<div class="casefile-panel" data-tab="subjects">
|
|
<partial name="_ReckoningSubjects" model="Model"></partial>
|
|
</div>
|
|
|
|
<div class="casefile-panel" data-tab="evidence">
|
|
<partial name="_ReckoningEvidence" model="Model"></partial>
|
|
</div>
|
|
|
|
<div class="casefile-panel" data-tab="notes">
|
|
<partial name="_ReckoningReview" model="Model"></partial>
|
|
</div>
|
|
|
|
<div class="casefile-panel" data-tab="buy">
|
|
<partial name="_ReckoningBuy" model="Model"></partial>
|
|
</div>
|
|
|
|
<div class="casefile-panel restricted-panel" data-tab="restricted">
|
|
<partial name="_ReckoningRestricted" model="Model"></partial>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="casefile-tabs">
|
|
<button type="button" class="casefile-tab active" data-tab="summary">Summary</button>
|
|
<button type="button" class="casefile-tab" data-tab="subjects">Subjects</button>
|
|
<button type="button" class="casefile-tab" data-tab="evidence">Evidence</button>
|
|
<button type="button" class="casefile-tab" data-tab="notes">Review</button>
|
|
<button type="button" class="casefile-tab" data-tab="buy">Purchase</button>
|
|
<button type="button" class="casefile-tab restricted" data-tab="restricted">Restricted</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="casefile-front" id="caseFileFront" role="button" tabindex="0" aria-label="Open case file">
|
|
<div class="casefile-front-face casefile-front-face-front">
|
|
<img src="/images/webp/folder-front.webp" alt="Case file cover" class="casefile-front-img" />
|
|
|
|
<div class="casefile-front-overlay">
|
|
<div class="casefile-stamp">
|
|
RESTRICTED
|
|
</div>
|
|
|
|
<div class="casefile-cover-text">
|
|
<div class="casefile-cover-kicker">WEST MIDLANDS POLICE</div>
|
|
<h1>ALPHA FLAME: RECKONING</h1>
|
|
<p>Case Ref: AFR-1983-06</p>
|
|
<p>Status: Active Investigation</p>
|
|
</div>
|
|
|
|
<div class="casefile-open-hint">Click to open file</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="casefile-front-face casefile-front-face-back">
|
|
<img src="/images/webp/folder-front-inside.webp" alt="" class="casefile-front-img casefile-front-img-back" />
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
@section BackgroundVideo {
|
|
<div></div>
|
|
}
|
|
|
|
@section CSS {
|
|
<link href="~/css/reckoning.css" rel="stylesheet" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Permanent+Marker&family=Shadows+Into+Light&display=swap" rel="stylesheet">
|
|
}
|
|
|
|
@section Scripts {
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
const trigger = document.querySelector(".casefile-audio-trigger");
|
|
const audio = document.getElementById("evidenceTapeAudio");
|
|
|
|
if (!trigger || !audio) return;
|
|
|
|
trigger.addEventListener("click", function () {
|
|
if (audio.paused) {
|
|
audio.play().then(function () {
|
|
trigger.classList.add("is-playing");
|
|
}).catch(function () {
|
|
});
|
|
} else {
|
|
audio.pause();
|
|
trigger.classList.remove("is-playing");
|
|
}
|
|
});
|
|
|
|
audio.addEventListener("pause", function () {
|
|
if (!audio.ended) {
|
|
trigger.classList.remove("is-playing");
|
|
}
|
|
});
|
|
|
|
audio.addEventListener("ended", function () {
|
|
trigger.classList.remove("is-playing");
|
|
audio.currentTime = 0;
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
const caseFile = document.getElementById("caseFile");
|
|
const frontCover = document.getElementById("caseFileFront");
|
|
const tabs = caseFile.querySelectorAll(".casefile-tab");
|
|
const panels = caseFile.querySelectorAll(".casefile-panel");
|
|
const images = caseFile.querySelectorAll("img");
|
|
|
|
let loadedCount = 0;
|
|
let assetsReady = false;
|
|
let openTimer = null;
|
|
let isOpening = false;
|
|
let hasEnteredView = false;
|
|
|
|
function openCaseFile() {
|
|
if (!assetsReady || isOpening || caseFile.classList.contains("open")) {
|
|
return;
|
|
}
|
|
|
|
isOpening = true;
|
|
caseFile.classList.add("revealed");
|
|
caseFile.classList.add("open");
|
|
|
|
if (openTimer) {
|
|
clearTimeout(openTimer);
|
|
openTimer = null;
|
|
}
|
|
}
|
|
|
|
function startAutoOpenTimer() {
|
|
if (!assetsReady || hasEnteredView === false || openTimer || caseFile.classList.contains("open")) {
|
|
return;
|
|
}
|
|
|
|
openTimer = setTimeout(() => {
|
|
openCaseFile();
|
|
}, 3000);
|
|
}
|
|
|
|
function onAssetLoaded() {
|
|
loadedCount++;
|
|
|
|
if (loadedCount === images.length) {
|
|
assetsReady = true;
|
|
caseFile.classList.add("assets-ready");
|
|
|
|
setTimeout(() => {
|
|
caseFile.classList.add("ready");
|
|
}, 250);
|
|
|
|
startAutoOpenTimer();
|
|
}
|
|
}
|
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting && !hasEnteredView) {
|
|
hasEnteredView = true;
|
|
startAutoOpenTimer();
|
|
observer.disconnect();
|
|
}
|
|
});
|
|
}, {
|
|
threshold: 0.35
|
|
});
|
|
|
|
observer.observe(caseFile);
|
|
|
|
images.forEach(img => {
|
|
if (img.complete) {
|
|
onAssetLoaded();
|
|
} else {
|
|
img.addEventListener("load", onAssetLoaded, { once: true });
|
|
img.addEventListener("error", onAssetLoaded, { once: true });
|
|
}
|
|
});
|
|
|
|
frontCover.addEventListener("click", function () {
|
|
openCaseFile();
|
|
});
|
|
|
|
frontCover.addEventListener("keydown", function (e) {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault();
|
|
openCaseFile();
|
|
}
|
|
});
|
|
|
|
tabs.forEach(tab => {
|
|
tab.addEventListener("click", function () {
|
|
const tabName = this.dataset.tab;
|
|
|
|
tabs.forEach(t => t.classList.remove("active"));
|
|
panels.forEach(p => p.classList.remove("active"));
|
|
|
|
this.classList.add("active");
|
|
|
|
const targetPanel = caseFile.querySelector(`.casefile-panel[data-tab="${tabName}"]`);
|
|
if (targetPanel) {
|
|
targetPanel.classList.add("active");
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
} |