Compare commits
11 commits
77ddefc3d1
...
d3b047cab2
| Author | SHA1 | Date | |
|---|---|---|---|
| d3b047cab2 | |||
| 9ec21b5243 | |||
| b5c6bb6eb7 | |||
| c4d0b78234 | |||
| 3e23d4c39f | |||
| 9b1c5dcc18 | |||
| b4a1503235 | |||
| 65509975da | |||
| efcaee8b20 | |||
| 243f957037 | |||
| 1909dbf0bb |
3 changed files with 167 additions and 76 deletions
|
|
@ -32,6 +32,7 @@
|
||||||
<input
|
<input
|
||||||
id="toc-search"
|
id="toc-search"
|
||||||
type="search"
|
type="search"
|
||||||
|
autofocus
|
||||||
placeholder="Search the entries..."
|
placeholder="Search the entries..."
|
||||||
/>
|
/>
|
||||||
<div id="toc-letters" class="toc-letters"></div>
|
<div id="toc-letters" class="toc-letters"></div>
|
||||||
|
|
|
||||||
144
script.js
144
script.js
|
|
@ -53,39 +53,66 @@ Array.from(firstByLetter.entries())
|
||||||
});
|
});
|
||||||
|
|
||||||
const searchInput = document.getElementById("toc-search");
|
const searchInput = document.getElementById("toc-search");
|
||||||
|
let searchTimeout;
|
||||||
searchInput?.addEventListener("input", (event) => {
|
searchInput?.addEventListener("input", (event) => {
|
||||||
const query = event.target.value.trim().toLowerCase();
|
clearTimeout(searchTimeout);
|
||||||
Array.from(tocList?.querySelectorAll("li") ?? []).forEach((item) => {
|
searchTimeout = setTimeout(() => {
|
||||||
const text = item.textContent.toLowerCase();
|
const query = event.target.value.trim().toLowerCase();
|
||||||
item.style.display = text.includes(query) ? "" : "none";
|
Array.from(tocList?.querySelectorAll("li") ?? []).forEach((item) => {
|
||||||
});
|
const text = item.textContent.toLowerCase();
|
||||||
|
item.style.display = text.includes(query) ? "" : "none";
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
const specialCaseMap = {
|
// OCR/formatting errors from epub conversion
|
||||||
|
const typoFixes = {
|
||||||
|
"GAY MA G E": "GAY MAGE",
|
||||||
|
"MORE ON RIVERS RIVERS": "RIVERS",
|
||||||
|
"REEK OF WRONG NESS": "REEK OF WRONGNESS",
|
||||||
|
"WITCH LIGHT": "WITCHLIGHT",
|
||||||
|
};
|
||||||
|
|
||||||
|
// truncated possessives and hyphenated terms
|
||||||
|
const partialMatches = {
|
||||||
|
"A KING'S": "KINGS",
|
||||||
|
"KING'": "KINGS",
|
||||||
|
"MERCHANT'": "MERCHANTS",
|
||||||
|
"POWER-": "POWER",
|
||||||
|
"WIZARD'": "WIZARDS",
|
||||||
|
"WIZARD'S": "WIZARDS",
|
||||||
|
"WIZARD'S BREEDING PROGRAMME": "BREEDING PROGRAMMES",
|
||||||
|
"WIZARD'S STAFF": "STAFFS",
|
||||||
|
};
|
||||||
|
|
||||||
|
// British/American spelling and verb forms
|
||||||
|
const spellingVariants = {
|
||||||
|
AMBUSHED: "AMBUSHES",
|
||||||
|
BACKLASHES: "BACKLASH OF MAGIC",
|
||||||
|
CURSED: "CURSES",
|
||||||
|
"FELLOW TRAVELLER": "FELLOW TRAVELERS",
|
||||||
|
"FELLOW TRAVELLERS": "FELLOW TRAVELERS",
|
||||||
|
};
|
||||||
|
|
||||||
|
// different terms mapping to canonical entries
|
||||||
|
const synonyms = {
|
||||||
"A BARD": "BARDS",
|
"A BARD": "BARDS",
|
||||||
"A COURTIER": "COURTIERS",
|
"A COURTIER": "COURTIERS",
|
||||||
"A DEMON": "DEMONS",
|
"A DEMON": "DEMONS",
|
||||||
"A GODDESS OR GOD": "GODDESSES AND GODS",
|
"A GODDESS OR GOD": "GODDESSES AND GODS",
|
||||||
"A HERBWOMAN": "HERBWOMAN",
|
"A HERBWOMAN": "HERBWOMAN",
|
||||||
"A KING'S": "KINGS",
|
|
||||||
"A MAGIC USER": "MAGIC USERS",
|
"A MAGIC USER": "MAGIC USERS",
|
||||||
"A SEER": "SEER",
|
"A SEER": "SEER",
|
||||||
"A WIZARD": "WIZARDS",
|
"A WIZARD": "WIZARDS",
|
||||||
AMBUSHED: "AMBUSHES",
|
|
||||||
ASSASSIN: "ASSASSINS, GUILD OF",
|
ASSASSIN: "ASSASSINS, GUILD OF",
|
||||||
ASSASSINS: "ASSASSINS, GUILD OF",
|
ASSASSINS: "ASSASSINS, GUILD OF",
|
||||||
BACKLASHES: "BACKLASH OF MAGIC",
|
|
||||||
BALLAD: "BALLAD, How to Compose a",
|
BALLAD: "BALLAD, How to Compose a",
|
||||||
BALLADS: "BALLAD, How to Compose a",
|
BALLADS: "BALLAD, How to Compose a",
|
||||||
BLOCKED: "MOUNTAIN PASS, BLOCKED",
|
BLOCKED: "MOUNTAIN PASS, BLOCKED",
|
||||||
CHILD: "CHILDREN",
|
CHILD: "CHILDREN",
|
||||||
CURSED: "CURSES",
|
|
||||||
ETERNAL: "ETERNAL QUEST",
|
ETERNAL: "ETERNAL QUEST",
|
||||||
"EVIL SPELLS": "SPELLS",
|
"EVIL SPELLS": "SPELLS",
|
||||||
FEMALE: "SLAVES, FEMALE,",
|
FEMALE: "SLAVES, FEMALE,",
|
||||||
"FELLOW TRAVELLER": "FELLOW TRAVELERS",
|
|
||||||
"FELLOW TRAVELLERS": "FELLOW TRAVELERS",
|
|
||||||
"GAY MA G E": "GAY MAGE",
|
|
||||||
"GIFT OF SIGHT": "SIGHT",
|
"GIFT OF SIGHT": "SIGHT",
|
||||||
GOD: "GODDESSES AND GODS",
|
GOD: "GODDESSES AND GODS",
|
||||||
GODDESS: "GODDESSES AND GODS",
|
GODDESS: "GODDESSES AND GODS",
|
||||||
|
|
@ -102,91 +129,90 @@ const specialCaseMap = {
|
||||||
"HOW TO INTERACT WITH WIZARDS": "WIZARDS",
|
"HOW TO INTERACT WITH WIZARDS": "WIZARDS",
|
||||||
IMPORT: "IMPORT/EXPORT",
|
IMPORT: "IMPORT/EXPORT",
|
||||||
"JOURNEY CAKE": "WAYBREAD OR JOURNEY CAKE",
|
"JOURNEY CAKE": "WAYBREAD OR JOURNEY CAKE",
|
||||||
"KING'": "KINGS",
|
|
||||||
"LOST LAND": "LOST LANDS,",
|
"LOST LAND": "LOST LANDS,",
|
||||||
"LOST LANDS": "LOST LANDS,",
|
"LOST LANDS": "LOST LANDS,",
|
||||||
MAGELIGHT: "MAGELIGHT OR MAGEFIRE",
|
MAGELIGHT: "MAGELIGHT OR MAGEFIRE",
|
||||||
MALE: "SLAVES, MALE,",
|
MALE: "SLAVES, MALE,",
|
||||||
"MERCHANT'": "MERCHANTS",
|
|
||||||
MINION: "MINIONS OF THE DARK LORD",
|
MINION: "MINIONS OF THE DARK LORD",
|
||||||
"MINION OF THE DARK LORD": "MINIONS OF THE DARK LORD",
|
"MINION OF THE DARK LORD": "MINIONS OF THE DARK LORD",
|
||||||
MINIONS: "MINIONS OF THE DARK LORD",
|
MINIONS: "MINIONS OF THE DARK LORD",
|
||||||
"MORE ON RIVERS": "RIVERS",
|
|
||||||
"MORE ON RIVERS RIVERS": "RIVERS",
|
|
||||||
MOON: "MOON(S)",
|
MOON: "MOON(S)",
|
||||||
|
"MORE ON RIVERS": "RIVERS",
|
||||||
"MOUNTAIN PASS": "MOUNTAIN PASS, BLOCKED",
|
"MOUNTAIN PASS": "MOUNTAIN PASS, BLOCKED",
|
||||||
"NORTHERN BARBARIANS DWELL": "NORTHERN BARBARIANS",
|
"NORTHERN BARBARIANS DWELL": "NORTHERN BARBARIANS",
|
||||||
PANCELTIC: "PANCELTIC TOURS",
|
PANCELTIC: "PANCELTIC TOURS",
|
||||||
"PANCELTIC TOUR": "PANCELTIC TOURS",
|
"PANCELTIC TOUR": "PANCELTIC TOURS",
|
||||||
PENTAGRAM: "PENTAGRAM OR PENTACLE",
|
PENTAGRAM: "PENTAGRAM OR PENTACLE",
|
||||||
PENTAGRAMS: "PENTAGRAM OR PENTACLE",
|
PENTAGRAMS: "PENTAGRAM OR PENTACLE",
|
||||||
"POWER-": "POWER",
|
|
||||||
"PRACTICE RING": "PRACTICE RING OR COMBAT RING",
|
"PRACTICE RING": "PRACTICE RING OR COMBAT RING",
|
||||||
PRIESTESSES: "HIGH PRIESTESSES",
|
PRIESTESSES: "HIGH PRIESTESSES",
|
||||||
"SECRET VALLEY": "VALLEYS",
|
|
||||||
RIVERBOAT: "RIVERS",
|
RIVERBOAT: "RIVERS",
|
||||||
"REEK OF WRONG NESS": "REEK OF WRONGNESS",
|
"SECRET VALLEY": "VALLEYS",
|
||||||
SLAVE: "GALLEY SLAVE",
|
SLAVE: "GALLEY SLAVE",
|
||||||
SLAVES: "SLAVES, MALE,",
|
SLAVES: "SLAVES, MALE,",
|
||||||
"STANDING STONES": "STONE CIRCLES",
|
"STANDING STONES": "STONE CIRCLES",
|
||||||
THIEVES: "THIEVES’ GUILD",
|
THIEVES: "THIEVES' GUILD",
|
||||||
"TOWN COUNCIL": "COUNCIL",
|
|
||||||
"TOUR COMPANIONS": "COMPANIONS",
|
"TOUR COMPANIONS": "COMPANIONS",
|
||||||
|
"TOWN COUNCIL": "COUNCIL",
|
||||||
TROTS: "TROTS, THE",
|
TROTS: "TROTS, THE",
|
||||||
WAYBREAD: "WAYBREAD OR JOURNEY CAKE",
|
WAYBREAD: "WAYBREAD OR JOURNEY CAKE",
|
||||||
"WITCH LIGHT": "WITCHLIGHT",
|
};
|
||||||
"WIZARD'": "WIZARDS",
|
|
||||||
"WIZARD'S": "WIZARDS",
|
const specialCaseMap = {
|
||||||
"WIZARD'S BREEDING PROGRAMME": "BREEDING PROGRAMMES",
|
...typoFixes,
|
||||||
"WIZARD'S STAFF": "STAFFS",
|
...partialMatches,
|
||||||
|
...spellingVariants,
|
||||||
|
...synonyms,
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveTerm = (term) => {
|
const resolveTerm = (term) => {
|
||||||
const normalized = term.replace(/’/g, "'");
|
const normalized = term.replace(/'/g, "'");
|
||||||
const special = specialCaseMap[normalized];
|
const special = specialCaseMap[normalized];
|
||||||
if (special && entryMap.has(special)) {
|
if (special && entryMap.has(special)) {
|
||||||
return special;
|
return special;
|
||||||
}
|
}
|
||||||
if (entryMap.has(term)) {
|
if (entryMap.has(normalized)) {
|
||||||
return term;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lower = term.toLowerCase();
|
const lower = normalized.toLowerCase();
|
||||||
const candidates = [];
|
const candidates = [];
|
||||||
|
|
||||||
// Singularize
|
// Singularize
|
||||||
if (lower.endsWith("ies")) {
|
if (lower.endsWith("ies")) {
|
||||||
candidates.push(term.slice(0, -3) + "Y");
|
candidates.push(normalized.slice(0, -3) + "Y");
|
||||||
}
|
}
|
||||||
if (lower.endsWith("ves")) {
|
if (lower.endsWith("ves")) {
|
||||||
candidates.push(term.slice(0, -3) + "F");
|
candidates.push(normalized.slice(0, -3) + "F");
|
||||||
candidates.push(term.slice(0, -3) + "FE");
|
candidates.push(normalized.slice(0, -3) + "FE");
|
||||||
}
|
}
|
||||||
if (lower.endsWith("es")) {
|
if (lower.endsWith("es")) {
|
||||||
candidates.push(term.slice(0, -2));
|
candidates.push(normalized.slice(0, -2));
|
||||||
}
|
}
|
||||||
if (lower.endsWith("s")) {
|
if (lower.endsWith("s")) {
|
||||||
candidates.push(term.slice(0, -1));
|
candidates.push(normalized.slice(0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pluralize
|
// Pluralize
|
||||||
if (lower.endsWith("y") && !/[aeiou]y$/.test(lower)) {
|
if (lower.endsWith("y") && !/[aeiou]y$/.test(lower)) {
|
||||||
candidates.push(term.slice(0, -1) + "IES");
|
candidates.push(normalized.slice(0, -1) + "IES");
|
||||||
}
|
}
|
||||||
if (lower.endsWith("f")) {
|
if (lower.endsWith("f")) {
|
||||||
candidates.push(term.slice(0, -1) + "VES");
|
candidates.push(normalized.slice(0, -1) + "VES");
|
||||||
}
|
}
|
||||||
if (lower.endsWith("fe")) {
|
if (lower.endsWith("fe")) {
|
||||||
candidates.push(term.slice(0, -2) + "VES");
|
candidates.push(normalized.slice(0, -2) + "VES");
|
||||||
}
|
}
|
||||||
candidates.push(`${term}S`);
|
candidates.push(`${normalized}S`);
|
||||||
if (/(s|x|z|ch|sh)$/i.test(lower)) {
|
if (/(s|x|z|ch|sh)$/i.test(lower)) {
|
||||||
candidates.push(`${term}ES`);
|
candidates.push(`${normalized}ES`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidates.find((candidate) => entryMap.has(candidate)) || null;
|
return candidates.find((candidate) => entryMap.has(candidate)) || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CAPS_TERM_REGEX = /\b[A-Z][A-Z0-9''\-]*(?:\s+[A-Z][A-Z0-9''\-]*)*\b/g;
|
||||||
|
|
||||||
const linkifyTextNode = (node) => {
|
const linkifyTextNode = (node) => {
|
||||||
const text = node.nodeValue;
|
const text = node.nodeValue;
|
||||||
if (!text || !/[A-Z]{2}/.test(text)) {
|
if (!text || !/[A-Z]{2}/.test(text)) {
|
||||||
|
|
@ -194,9 +220,9 @@ const linkifyTextNode = (node) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const matches = [];
|
const matches = [];
|
||||||
const regex = /\b[A-Z][A-Z0-9'’\-]*(?:\s+[A-Z][A-Z0-9'’\-]*)*\b/g;
|
CAPS_TERM_REGEX.lastIndex = 0;
|
||||||
let match;
|
let match;
|
||||||
while ((match = regex.exec(text)) !== null) {
|
while ((match = CAPS_TERM_REGEX.exec(text)) !== null) {
|
||||||
const raw = match[0];
|
const raw = match[0];
|
||||||
const cleaned = cleanTerm(raw);
|
const cleaned = cleanTerm(raw);
|
||||||
const resolved = resolveTerm(cleaned);
|
const resolved = resolveTerm(cleaned);
|
||||||
|
|
@ -290,8 +316,38 @@ document.body.appendChild(tocToggle);
|
||||||
const toc = document.querySelector(".toc");
|
const toc = document.querySelector(".toc");
|
||||||
const layout = document.querySelector(".layout");
|
const layout = document.querySelector(".layout");
|
||||||
|
|
||||||
|
const isMobile = () => window.matchMedia("(max-width: 700px)").matches;
|
||||||
|
|
||||||
tocToggle.addEventListener("click", () => {
|
tocToggle.addEventListener("click", () => {
|
||||||
toc?.classList.toggle("collapsed");
|
toc?.classList.toggle("collapsed");
|
||||||
layout?.classList.toggle("toc-hidden");
|
layout?.classList.toggle("toc-hidden");
|
||||||
document.body.classList.toggle("toc-collapsed");
|
if (isMobile()) {
|
||||||
|
document.body.classList.toggle("toc-open");
|
||||||
|
} else {
|
||||||
|
document.body.classList.toggle("toc-collapsed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// auto-collapse on mobile (CSS defaults to collapsed, just ensure classes match)
|
||||||
|
if (isMobile()) {
|
||||||
|
toc?.classList.add("collapsed");
|
||||||
|
layout?.classList.add("toc-hidden");
|
||||||
|
document.body.classList.remove("toc-open");
|
||||||
|
}
|
||||||
|
|
||||||
|
// close drawer when clicking a toc link on mobile
|
||||||
|
tocList?.addEventListener("click", (e) => {
|
||||||
|
if (e.target.tagName === "A" && isMobile()) {
|
||||||
|
toc?.classList.add("collapsed");
|
||||||
|
layout?.classList.add("toc-hidden");
|
||||||
|
document.body.classList.remove("toc-open");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// scroll TOC item into view when navigating via hash
|
||||||
|
window.addEventListener("hashchange", () => {
|
||||||
|
const id = location.hash.slice(1);
|
||||||
|
if (id) {
|
||||||
|
tocList?.querySelector(`a[href="#${id}"]`)?.scrollIntoView({ block: "nearest" });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
98
style.css
98
style.css
|
|
@ -14,8 +14,13 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
max-width: 100%;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
background:
|
background:
|
||||||
radial-gradient(
|
radial-gradient(
|
||||||
|
|
@ -40,7 +45,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero {
|
.hero {
|
||||||
padding: 48px 6vw 32px;
|
padding: clamp(24px, 6vw, 48px) clamp(16px, 6vw, 6vw) clamp(16px, 4vw, 32px);
|
||||||
background:
|
background:
|
||||||
linear-gradient(120deg, rgba(182, 82, 47, 0.12), transparent 55%),
|
linear-gradient(120deg, rgba(182, 82, 47, 0.12), transparent 55%),
|
||||||
linear-gradient(220deg, rgba(122, 46, 26, 0.18), transparent 45%);
|
linear-gradient(220deg, rgba(122, 46, 26, 0.18), transparent 45%);
|
||||||
|
|
@ -51,7 +56,7 @@ body {
|
||||||
.hero h1 {
|
.hero h1 {
|
||||||
font-family:
|
font-family:
|
||||||
"Iowan Old Style", "Palatino Linotype", "Book Antiqua", Garamond, serif;
|
"Iowan Old Style", "Palatino Linotype", "Book Antiqua", Garamond, serif;
|
||||||
font-size: clamp(2.4rem, 4vw, 3.6rem);
|
font-size: clamp(1.5rem, 6vw, 3.6rem);
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
margin: 0 0 8px;
|
margin: 0 0 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -65,15 +70,15 @@ body {
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
|
grid-template-columns: minmax(200px, 280px) minmax(0, 1fr);
|
||||||
gap: 28px;
|
gap: clamp(16px, 4vw, 28px);
|
||||||
padding: 32px 6vw 64px;
|
padding: clamp(16px, 4vw, 32px) clamp(12px, 6vw, 6vw) clamp(32px, 8vw, 64px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc {
|
.toc {
|
||||||
background: var(--nav-bg);
|
background: var(--nav-bg);
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
padding: 24px;
|
padding: clamp(16px, 4vw, 24px);
|
||||||
box-shadow: 0 18px 40px var(--shadow);
|
box-shadow: 0 18px 40px var(--shadow);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 24px;
|
top: 24px;
|
||||||
|
|
@ -101,8 +106,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-letters {
|
.toc-letters {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: repeat(auto-fill, minmax(28px, 1fr));
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +115,7 @@ body {
|
||||||
.toc-letters a {
|
.toc-letters a {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
color: var(--accent-deep);
|
color: var(--accent-deep);
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|
@ -147,10 +153,13 @@ body {
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
background: rgba(255, 255, 255, 0.6);
|
background: rgba(255, 255, 255, 0.6);
|
||||||
border-radius: 24px;
|
border-radius: clamp(12px, 3vw, 24px);
|
||||||
padding: 32px 36px;
|
padding: clamp(16px, 4vw, 32px) clamp(16px, 5vw, 36px);
|
||||||
box-shadow: 0 20px 55px var(--shadow);
|
box-shadow: 0 20px 55px var(--shadow);
|
||||||
animation: fade-up 0.8s ease 0.2s both;
|
animation: fade-up 0.8s ease 0.2s both;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content h2,
|
.content h2,
|
||||||
|
|
@ -167,6 +176,7 @@ body {
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
animation: fade-up 0.6s ease both;
|
animation: fade-up 0.6s ease both;
|
||||||
animation-delay: var(--entry-delay, 0s);
|
animation-delay: var(--entry-delay, 0s);
|
||||||
|
scroll-margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-title:target {
|
.entry-title:target {
|
||||||
|
|
@ -257,41 +267,65 @@ body.toc-collapsed .toc-toggle::before {
|
||||||
grid-template-columns: 0 minmax(0, 1fr);
|
grid-template-columns: 0 minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 980px) {
|
@media (max-width: 700px) {
|
||||||
.layout {
|
.page,
|
||||||
grid-template-columns: 1fr;
|
.hero,
|
||||||
|
.content {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc {
|
.toc {
|
||||||
position: relative;
|
position: fixed;
|
||||||
max-height: none;
|
top: 0;
|
||||||
}
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
.toc.collapsed {
|
width: min(85vw, 320px);
|
||||||
|
max-height: 100vh;
|
||||||
|
border-radius: 0 18px 18px 0;
|
||||||
|
z-index: 200;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-top: -100%;
|
transform: translateX(-100%);
|
||||||
height: 0;
|
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||||
padding: 0;
|
animation: none;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout.toc-hidden {
|
body.toc-open .toc {
|
||||||
grid-template-columns: 1fr;
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-toggle {
|
.toc-toggle {
|
||||||
top: auto;
|
top: 50%;
|
||||||
bottom: 20px;
|
bottom: auto;
|
||||||
left: 20px;
|
transform: translateY(-50%);
|
||||||
transform: none;
|
z-index: 201;
|
||||||
border-radius: 8px;
|
transition: left 0.3s ease;
|
||||||
|
padding: 10px 6px;
|
||||||
|
font-size: 1rem;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.toc-open .toc-toggle {
|
||||||
|
left: min(85vw, 320px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-toggle::before {
|
.toc-toggle::before {
|
||||||
content: "▲";
|
content: "▶";
|
||||||
}
|
}
|
||||||
|
|
||||||
body.toc-collapsed .toc-toggle::before {
|
body.toc-open .toc-toggle::before {
|
||||||
content: "▼";
|
content: "◀";
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout,
|
||||||
|
.layout.toc-hidden {
|
||||||
|
display: block;
|
||||||
|
grid-template-columns: none;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
border-radius: clamp(8px, 2vw, 16px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue