|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | +<meta charset="UTF-8"> |
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | +<title>Master Slide Navigator</title> |
| 7 | +<style> |
| 8 | +*,*::before,*::after{box-sizing:border-box;margin:0;padding:0} |
| 9 | +:root{ |
| 10 | + --bg:#070a14; |
| 11 | + --bg2:#10182b; |
| 12 | + --fg:#eef2ff; |
| 13 | + --fg2:#c2cce8; |
| 14 | + --fg3:#92a0c7; |
| 15 | + --line:rgba(172,190,240,.28); |
| 16 | + --accent:#59d3ff; |
| 17 | + --accent2:#8bff92; |
| 18 | +} |
| 19 | +html,body{height:100%} |
| 20 | +body{ |
| 21 | + font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif; |
| 22 | + color:var(--fg); |
| 23 | + background: |
| 24 | + radial-gradient(1200px 700px at -10% -20%,rgba(89,211,255,.18),transparent 60%), |
| 25 | + radial-gradient(900px 500px at 110% 120%,rgba(139,255,146,.14),transparent 60%), |
| 26 | + linear-gradient(145deg,var(--bg),#0c1324 60%,#09101e); |
| 27 | + min-height:100%; |
| 28 | + padding:28px; |
| 29 | +} |
| 30 | +.wrap{max-width:1300px;margin:0 auto;display:grid;gap:20px} |
| 31 | +.hero{background:rgba(16,24,43,.65);border:1px solid var(--line);border-radius:18px;padding:24px} |
| 32 | +.kicker{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--fg3)} |
| 33 | +h1{font-size:clamp(1.9rem,4vw,3.2rem);line-height:1.12;margin-top:10px} |
| 34 | +p{margin-top:10px;color:var(--fg2);line-height:1.5} |
| 35 | +.actions{margin-top:18px;display:flex;flex-wrap:wrap;gap:10px} |
| 36 | +.btn{ |
| 37 | + display:inline-flex;align-items:center;justify-content:center; |
| 38 | + padding:10px 14px;border-radius:10px; |
| 39 | + border:1px solid var(--line); |
| 40 | + color:var(--fg);text-decoration:none;background:rgba(7,10,20,.6); |
| 41 | + font-weight:600;font-size:14px |
| 42 | +} |
| 43 | +.btn.primary{border-color:rgba(89,211,255,.6);box-shadow:0 0 0 1px rgba(89,211,255,.28) inset} |
| 44 | +.btn.good{border-color:rgba(139,255,146,.55);box-shadow:0 0 0 1px rgba(139,255,146,.25) inset} |
| 45 | +.btn[aria-disabled="true"]{opacity:.35;pointer-events:none} |
| 46 | +.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px} |
| 47 | +.card{ |
| 48 | + display:block; |
| 49 | + background:rgba(16,24,43,.62); |
| 50 | + border:1px solid var(--line); |
| 51 | + border-radius:14px; |
| 52 | + padding:14px; |
| 53 | + color:inherit; |
| 54 | + text-decoration:none; |
| 55 | +} |
| 56 | +.card:hover{border-color:rgba(89,211,255,.5);transform:translateY(-1px)} |
| 57 | +.idx{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--fg3)} |
| 58 | +.name{font-weight:700;font-size:16px;margin-top:6px;line-height:1.25} |
| 59 | +.meta{font-size:12px;color:var(--fg2);margin-top:8px} |
| 60 | +.footer{font-size:12px;color:var(--fg3)} |
| 61 | +@media(max-width:980px){.grid{grid-template-columns:repeat(2,minmax(0,1fr));}} |
| 62 | +@media(max-width:640px){body{padding:16px}.hero{padding:18px}.grid{grid-template-columns:1fr}} |
| 63 | +</style> |
| 64 | +</head> |
| 65 | +<body> |
| 66 | +<div class="wrap"> |
| 67 | + <section class="hero"> |
| 68 | + <div class="kicker">Presentation Control</div> |
| 69 | + <h1>Master Slide Navigator</h1> |
| 70 | + <p>Use this page to jump between deck files, or continue in sequence to the next stage. In any deck, pressing next on the final slide automatically opens the next deck.</p> |
| 71 | + <div class="actions"> |
| 72 | + <a id="back-btn" class="btn" href="#">Back</a> |
| 73 | + <a class="btn primary" href="slides/00_overview_slides.html#1">Start Full Sequence</a> |
| 74 | + <a id="continue-btn" class="btn good" href="slides/00_overview_slides.html#1">Continue to Next Deck</a> |
| 75 | + <a id="resume-btn" class="btn" href="slides/00_overview_slides.html#1">Resume Current Deck</a> |
| 76 | + </div> |
| 77 | + </section> |
| 78 | + |
| 79 | + <section class="grid" id="deck-grid"></section> |
| 80 | + |
| 81 | + <div class="footer">Tip: from any deck, press <code>M</code> to return to this master slide.</div> |
| 82 | +</div> |
| 83 | + |
| 84 | +<script> |
| 85 | +(function(){ |
| 86 | + const decks = [ |
| 87 | + { file: "slides/00_overview_slides.html", title: "00 Overview" }, |
| 88 | + { file: "slides/01_entry_point_slides.html", title: "01 Entry Point" }, |
| 89 | + { file: "slides/02_friendly_file_slides.html", title: "02 Friendly File" }, |
| 90 | + { file: "slides/03_static_engine_cascade_slides.html", title: "03 Static Engine Cascade" }, |
| 91 | + { file: "slides/04_aaggregator_collection_slides.html", title: "04 AAGGREGATOR Collection" }, |
| 92 | + { file: "slides/05_pe_emulation_slides.html", title: "05 PE Emulation" }, |
| 93 | + { file: "slides/06_unpacked_content_slides.html", title: "06 Unpacked Content" }, |
| 94 | + { file: "slides/07_container_extraction_slides.html", title: "07 Container Extraction" }, |
| 95 | + { file: "slides/08_script_deobfuscation_slides.html", title: "08 Script Deobfuscation" }, |
| 96 | + { file: "slides/09_brute_matching_slides.html", title: "09 BRUTE Matching" }, |
| 97 | + { file: "slides/10_lua_scripts_slides.html", title: "10 Lua Scripts" }, |
| 98 | + { file: "slides/11_aaggregator_evaluation_slides.html", title: "11 AAGGREGATOR Evaluation" }, |
| 99 | + { file: "slides/12_maps_cloud_lookup_slides.html", title: "12 MAPS Cloud Lookup" }, |
| 100 | + { file: "slides/13_verdict_resolution_slides.html", title: "13 Verdict Resolution" } |
| 101 | + ]; |
| 102 | + |
| 103 | + const grid = document.getElementById("deck-grid"); |
| 104 | + decks.forEach(function(deck, i){ |
| 105 | + const card = document.createElement("a"); |
| 106 | + card.className = "card"; |
| 107 | + card.href = deck.file + "#1"; |
| 108 | + card.innerHTML = |
| 109 | + '<div class="idx">Deck ' + String(i + 1).padStart(2, "0") + ' of ' + String(decks.length).padStart(2, "0") + '</div>' + |
| 110 | + '<div class="name">' + deck.title + '</div>' + |
| 111 | + '<div class="meta">Open deck at slide 1</div>'; |
| 112 | + grid.appendChild(card); |
| 113 | + }); |
| 114 | + |
| 115 | + const params = new URLSearchParams(location.search); |
| 116 | + const fromRaw = Number(params.get("from")); |
| 117 | + const fromIndex = Number.isInteger(fromRaw) ? fromRaw : -1; |
| 118 | + |
| 119 | + const backBtn = document.getElementById("back-btn"); |
| 120 | + const continueBtn = document.getElementById("continue-btn"); |
| 121 | + const resumeBtn = document.getElementById("resume-btn"); |
| 122 | + |
| 123 | + backBtn.addEventListener("click", function(e){ |
| 124 | + e.preventDefault(); |
| 125 | + if (window.history.length > 1) { |
| 126 | + window.history.back(); |
| 127 | + return; |
| 128 | + } |
| 129 | + if (fromIndex >= 0 && fromIndex < decks.length) { |
| 130 | + location.href = decks[fromIndex].file + "#1"; |
| 131 | + return; |
| 132 | + } |
| 133 | + location.href = decks[0].file + "#1"; |
| 134 | + }); |
| 135 | + |
| 136 | + if (fromIndex >= 0 && fromIndex < decks.length) { |
| 137 | + resumeBtn.href = decks[fromIndex].file + "#1"; |
| 138 | + resumeBtn.textContent = "Resume " + decks[fromIndex].title; |
| 139 | + |
| 140 | + if (fromIndex + 1 < decks.length) { |
| 141 | + continueBtn.href = decks[fromIndex + 1].file + "#1"; |
| 142 | + continueBtn.textContent = "Continue: " + decks[fromIndex + 1].title; |
| 143 | + } else { |
| 144 | + continueBtn.textContent = "At Final Deck"; |
| 145 | + continueBtn.setAttribute("aria-disabled", "true"); |
| 146 | + } |
| 147 | + } else { |
| 148 | + resumeBtn.textContent = "Resume Current Deck"; |
| 149 | + resumeBtn.setAttribute("aria-disabled", "true"); |
| 150 | + continueBtn.href = decks[0].file + "#1"; |
| 151 | + continueBtn.textContent = "Continue to Next Deck"; |
| 152 | + } |
| 153 | +})(); |
| 154 | +</script> |
| 155 | +</body> |
| 156 | +</html> |
0 commit comments