diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..323b1b0 Binary files /dev/null and b/.DS_Store differ diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000..6716543 Binary files /dev/null and b/assets/.DS_Store differ diff --git a/assets/scripts/script.js b/assets/scripts/script.js index aa63c66..4436a66 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -1,175 +1,184 @@ -// COPY BUTTON: + +/* Event listener function for the COPY BUTTON */ document.addEventListener("DOMContentLoaded", function () { - document.querySelectorAll("pre.src").forEach(function (block) { - const button = document.createElement("button"); - button.innerText = "Copy"; - button.className = "copy-btn"; + document.querySelectorAll("pre.src").forEach(function (codeBlock) { + const button = document.createElement("button"); + button.innerText = "Copy"; + button.className = "copy-btn"; - // Append button inside
- block.appendChild(button);
+ // Append button inside
+ codeBlock.appendChild(button);
- button.addEventListener("click", function () {
- const text = block.innerText.replace(button.innerText, ""); // exclude button text
- navigator.clipboard.writeText(text.trim()).then(() => {
- button.innerText = "Copied!";
- setTimeout(() => (button.innerText = "Copy"), 1500);
- });
+ button.addEventListener("click", function () {
+ const text = codeBlock.innerText.replace(button.innerText, ""); // exclude button text
+ navigator.clipboard.writeText(text.trim()).then(() => {
+ button.innerText = "Copied!";
+ setTimeout(() => (button.innerText = "Copy"), 1500);
+ });
+ });
});
- });
});
+
+/* Event listener for footnotes and sidenotes*/
document.addEventListener("DOMContentLoaded", () => {
- document.querySelectorAll('a.footref[href^="#fn"]').forEach(ref => {
- const sup = ref.closest("sup") || ref;
- // idempotent: don't insert twice
- if (sup.nextElementSibling && sup.nextElementSibling.classList?.contains("footnote-sidenote")) return;
+ document.querySelectorAll('a.footref[href^="#fn"]').forEach(ref => {
+ const sup = ref.closest("sup") || ref;
+ // idempotent: don't insert twice
+ if (sup.nextElementSibling && sup.nextElementSibling.classList?.contains("footnote-sidenote")) return;
+
+ const targetId = ref.getAttribute("href").replace(/^#/, ""); // works for fn.2 or fn2
- const targetId = ref.getAttribute("href").replace(/^#/, ""); // works for fn.2 or fn2
+ const anchor = document.getElementById(targetId);
+ if (!anchor) return;
+
+ const footdef = anchor.closest(".footdef") || anchor.parentElement;
+ if (!footdef) return;
+
+ // 1) Prefer leaf paragraphs to avoid div+p duplication
+ let paras = footdef.querySelectorAll("p.footpara");
+ if (!paras.length) {
+ // fallback: any .footpara elements that don't contain another .footpara
+ paras = footdef.querySelectorAll(".footpara:not(:has(.footpara))");
+ }
- const anchor = document.getElementById(targetId);
- if (!anchor) return;
+ // 2) Build HTML, de-duplicating by text content
+ let parts = [];
+ if (paras.length) {
+ const seen = new Set();
+ parts = Array.from(paras).map(p => {
+ const txt = p.textContent.trim().replace(/\s+/g, " ");
+ if (seen.has(txt)) return "";
+ seen.add(txt);
+ return p.innerHTML.trim();
+ }).filter(Boolean);
+ }
- const footdef = anchor.closest(".footdef") || anchor.parentElement;
- if (!footdef) return;
+ // 3) Fallback: clean full block if no paras found
+ if (!parts.length) {
+ const clone = footdef.cloneNode(true);
+ clone.querySelectorAll("sup.footnum, a[role='doc-backlink']").forEach(n => n.remove());
+ parts = [clone.innerHTML.trim()];
+ }
- // 1) Prefer leaf paragraphs to avoid div+p duplication
- let paras = footdef.querySelectorAll("p.footpara");
- if (!paras.length) {
- // fallback: any .footpara elements that don't contain another .footpara
- paras = footdef.querySelectorAll(".footpara:not(:has(.footpara))");
- }
-
- // 2) Build HTML, de-duplicating by text content
- let parts = [];
- if (paras.length) {
- const seen = new Set();
- parts = Array.from(paras).map(p => {
- const txt = p.textContent.trim().replace(/\s+/g, " ");
- if (seen.has(txt)) return "";
- seen.add(txt);
- return p.innerHTML.trim();
- }).filter(Boolean);
- }
-
- // 3) Fallback: clean full block if no paras found
- if (!parts.length) {
- const clone = footdef.cloneNode(true);
- clone.querySelectorAll("sup.footnum, a[role='doc-backlink']").forEach(n => n.remove());
- parts = [clone.innerHTML.trim()];
- }
-
- // 4) Insert the sidenote
- const sn = document.createElement("span");
- sn.className = "sidenote footnote-sidenote";
- sn.setAttribute("data-fn", (ref.textContent || "").trim());
- sn.innerHTML = parts.join(" ");
-
- sup.insertAdjacentElement("afterend", sn);
- });
+ // 4) Insert the sidenote
+ const sn = document.createElement("span");
+ sn.className = "sidenote footnote-sidenote";
+ sn.setAttribute("data-fn", (ref.textContent || "").trim());
+ sn.innerHTML = parts.join(" ");
+
+ sup.insertAdjacentElement("afterend", sn);
+ });
});
- (function(){
+
+
+/* Function for setting the theme */
+(function(){
const root = document.documentElement;
const storageKey = "theme";
const saved = localStorage.getItem(storageKey);
if (saved === "dark" || saved === "light") {
- root.setAttribute("data-theme", saved);
+ root.setAttribute("data-theme", saved);
}
const btn = document.getElementById("theme-toggle");
if (!btn) return;
btn.addEventListener("click", () => {
- const current = root.getAttribute("data-theme");
- const next = current === "dark" ? "light" : "dark";
- // If no current (auto), assume we’re toggling to dark first
- const target = current ? next : "dark";
- root.setAttribute("data-theme", target);
- localStorage.setItem(storageKey, target);
+ const current = root.getAttribute("data-theme");
+ const next = current === "dark" ? "light" : "dark";
+ // If no current (auto), assume we’re toggling to dark first
+ const target = current ? next : "dark";
+ root.setAttribute("data-theme", target);
+ localStorage.setItem(storageKey, target);
});
- })();
+})();
+
+/* Event listener for scrolling and changing the active label on the TOC */
document.addEventListener("DOMContentLoaded", () => {
- const toc = document.querySelector("#text-table-of-contents");
- if (!toc) { console.warn("No #text-table-of-contents found"); return; }
+ const toc = document.querySelector("#text-table-of-contents");
+ if (!toc) { console.warn("No #text-table-of-contents found"); return; }
- const links = toc.querySelectorAll('a[href^="#"]');
- if (!links.length) { console.warn("No ToC links found"); return; }
+ const links = toc.querySelectorAll('a[href^="#"]'); // '^=' is a starts with operator.
+ // Intro matches
+ if (!links.length) { console.warn("No ToC links found"); return; }
- // Map: id -> link
- const linkById = new Map();
- links.forEach(a => {
- const id = decodeURIComponent(a.getAttribute("href").slice(1));
- const el = document.getElementById(id);
- if (el) linkById.set(id, a);
- });
- if (!linkById.size) { console.warn("No matching headings with IDs"); return; }
-
- // Headings to observe (h2–h4 usually)
- const headings = [...document.querySelectorAll("h2[id], h3[id], h4[id]")]
- .filter(h => linkById.has(h.id));
-
- // Helper to mark active
- const setActive = (id) => {
+ // Map: id -> link
+ const linkById = new Map();
links.forEach(a => {
- const active = a.getAttribute("href") === `#${id}`;
- a.classList.toggle("is-active", active);
- if (active) a.setAttribute("aria-current", "true");
- else a.removeAttribute("aria-current");
+ const id = decodeURIComponent(a.getAttribute("href").slice(1));
+ const el = document.getElementById(id);
+ if (el) linkById.set(id, a);
});
- };
+ if (!linkById.size) { console.warn("No matching headings with IDs"); return; }
- // Calculate sticky header offset in px
- const headerOffsetPx = 6.5 * parseFloat(getComputedStyle(document.documentElement).fontSize);
+ // Headings to observe (h2–h4 usually)
+ const headings = [...document.querySelectorAll("h2[id], h3[id], h4[id]")]
+ .filter(h => linkById.has(h.id));
- // Track visible headings (id -> distance from top)
- const visible = new Map();
+ // Helper to mark active
+ const setActive = (id) => {
+ links.forEach(a => {
+ const active = a.getAttribute("href") === `#${id}`;
+ a.classList.toggle("is-active", active);
+ if (active) a.setAttribute("aria-current", "true");
+ else a.removeAttribute("aria-current");
+ });
+ };
- const observer = new IntersectionObserver((entries) => {
- entries.forEach(entry => {
- const id = entry.target.id;
- if (entry.isIntersecting) {
- // How far from the top (after header offset)
- const dist = entry.target.getBoundingClientRect().top - headerOffsetPx;
- visible.set(id, dist);
- } else {
- visible.delete(id);
- }
+ // Calculate sticky header offset in px
+ const headerOffsetPx = 6.5 * parseFloat(getComputedStyle(document.documentElement).fontSize);
+
+ // Track visible headings (id -> distance from top)
+ const visible = new Map();
+
+ const observer = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ const id = entry.target.id;
+ if (entry.isIntersecting) {
+ // How far from the top (after header offset)
+ const dist = entry.target.getBoundingClientRect().top - headerOffsetPx;
+ visible.set(id, dist);
+ } else {
+ visible.delete(id);
+ }
+ });
+
+ if (visible.size) {
+ // Choose the heading closest to the top (>= -headerOffset)
+ const topMost = [...visible.entries()]
+ .sort((a,b) => Math.abs(a[1]) - Math.abs(b[1]))[0][0];
+ setActive(topMost);
+ // console.log("Active:", topMost, visible);
+ }
+ }, {
+ root: null, // track relative to viewport
+ rootMargin: `-${headerOffsetPx}px 0px -70% 0px`,
+ threshold: [0, 0.01, 0.1] // fire as soon as it enters
});
+
+ headings.forEach(h => observer.observe(h));
- if (visible.size) {
- // Choose the heading closest to the top (>= -headerOffset)
- const topMost = [...visible.entries()]
- .sort((a,b) => Math.abs(a[1]) - Math.abs(b[1]))[0][0];
- setActive(topMost);
- // console.log("Active:", topMost, visible);
- }
- }, {
- root: null, // track relative to viewport
- rootMargin: `-${headerOffsetPx}px 0px -70% 0px`,
- threshold: [0, 0.01, 0.1] // fire as soon as it enters
- });
-
- headings.forEach(h => observer.observe(h));
-
- // Initial highlight (in case you load mid‑page)
- let bestId = null, bestDist = Infinity;
- headings.forEach(h => {
- const top = h.getBoundingClientRect().top - headerOffsetPx;
- const dist = top < 0 ? Math.abs(top) : top + 1e6;
- if (dist < bestDist) { bestDist = dist; bestId = h.id; }
- });
- if (bestId) setActive(bestId);
-
- // Optional: smooth-scroll ToC clicks
- toc.addEventListener("click", (e) => {
- const a = e.target.closest('a[href^="#"]');
- if (!a) return;
- const id = decodeURIComponent(a.hash.slice(1));
- const el = document.getElementById(id);
- if (!el) return;
- e.preventDefault();
- el.scrollIntoView({ behavior: "smooth", block: "start" });
- el.setAttribute("tabindex", "-1");
- el.focus({ preventScroll: true });
- history.pushState(null, "", `#${id}`);
- });
+ // Initial highlight (in case load mid‑page)
+ let bestId = null, bestDist = Infinity;
+ headings.forEach(h => {
+ const top = h.getBoundingClientRect().top - headerOffsetPx;
+ const dist = top < 0 ? Math.abs(top) : top + 1e6;
+ if (dist < bestDist) { bestDist = dist; bestId = h.id; }
+ });
+ if (bestId) setActive(bestId);
+
+ // smooth-scroll ToC clicks
+ toc.addEventListener("click", (e) => {
+ const a = e.target.closest('a[href^="#"]');
+ if (!a) return;
+ const id = decodeURIComponent(a.hash.slice(1));
+ const el = document.getElementById(id);
+ if (!el) return;
+ e.preventDefault();
+ el.scrollIntoView({ behavior: "smooth", block: "start" });
+ el.setAttribute("tabindex", "-1");
+ el.focus({ preventScroll: true });
+ history.pushState(null, "", `#${id}`);
+ });
});
diff --git a/assets/styles/style.css b/assets/styles/style.css
index ed3ef82..0639f51 100644
--- a/assets/styles/style.css
+++ b/assets/styles/style.css
@@ -3,11 +3,17 @@
========================= */
:root{
/* Layout */
- --content: 880px;
+
--gutter: 2rem;
--margin: 420px;
- --body-pad: 1rem;
-
+ --body-pad: 1rem;
+ --content: clamp(
+ var(--content-min),
+ calc(100vi - 2*var(--body-pad) - 2*(var(--margin) + var(--gutter))),
+ var(--content-max)
+ );
+ --content-min: 60ch;
+ --content-max: 880px;
/* Fullwidth media tuning */
--bleed: 48px;
--fullwidth-cap: 860px;
@@ -91,7 +97,7 @@ nav{
max-width: 100%;
}
-@media (max-width: 1100px){
+@media (max-width: 1250px){
#preamble.status{
padding-right: var(--body-pad);
}
@@ -139,8 +145,9 @@ footer{
.marginnote{
float: right;
width: var(--margin);
- margin-right: calc(-1 * ( (95vw - var(--content)) / 2 ));
- padding-left: var(--gutter);
+ //margin-right: calc(-1 * ( (95vw - var(--content)) / 2 ));
+ margin-right: calc(-1 * ((100vi - var(--content)) / 2));
+ padding-right: var(--gutter);
overflow-wrap: break-word; /* preferred */
word-wrap: break-word; /* legacy support */
word-break: break-word; /* safety for stubborn cases */
@@ -207,7 +214,7 @@ body{ counter-reset: sidenote-counter; }
text-align: center; font-size: .95rem; color: #666; margin-top: .4rem;
}
-@media (max-width: 1100px){
+@media (max-width: 1250px){
#content.content{
padding-right: var(--body-pad);
}
@@ -506,7 +513,7 @@ li ol li::before {
.epigraph blockquote footer{ color: var(--muted); }
/* Mobile sidenote rule uses a light border; make it theme-aware */
-@media (max-width: 1100px){
+@media (max-width: 1250px){
.sidenote, .marginnote{
border-left: 3px solid color-mix(in oklab, var(--fg) 12%, transparent);
}
@@ -577,7 +584,7 @@ li ol li::before {
/* Mobile: these already stack under content via your media query; nothing special needed,
but we can soften the border a touch to match the mobile sidenote rule */
-@media (max-width: 1100px){
+@media (max-width: 1250px){
.sidenote .mn-img,
.marginnote .mn-img{
border-color: color-mix(in oklab, var(--fg) 12%, transparent);
@@ -600,8 +607,9 @@ li ol li::before {
/* push into the left gutter, mirroring .sidenote on the right */
float: left;
width: var(--margin);
- margin-left: calc(-1 * ( (95vw - var(--content)) / 2 ));
- padding-right: var(--gutter);
+ //margin-left: calc(-1 * ( (95vw - var(--content)) / 2 ));
+ margin-left: calc(-1 * ((100vi - var(--content)) / 2));
+ padding-left: var(--gutter);
box-sizing: border-box;
/* sticky behavior */
@@ -648,7 +656,7 @@ h2[id], h3[id], h4[id] { scroll-margin-top: 6.5rem; }
/* =========================
Mobile / narrow view
========================= */
-@media (max-width: 1100px){
+@media (max-width: 1250px){
#table-of-contents{
float: none;
position: static; /* no sticky on small screens */
diff --git a/sitemap.org b/sitemap.org
index 02f4887..7a4a7f0 100644
--- a/sitemap.org
+++ b/sitemap.org
@@ -14,8 +14,8 @@
- [[file:blogs/blogs-list.org][Blogs List]]
- tags
- [[file:tags/introduction.org][Tag: introduction]]
+ - [[file:tags/insights.org][Tag: insights]]
- [[file:tags/emacs.org][Tag: emacs]]
- - [[file:tags/education.org][Tag: education]]
- [[file:tags/website.org][Tag: website]]
- - [[file:tags/review.org][Tag: review]]
- - [[file:tags/insights.org][Tag: insights]]
\ No newline at end of file
+ - [[file:tags/education.org][Tag: education]]
+ - [[file:tags/review.org][Tag: review]]
\ No newline at end of file