From 3f2a3f2de11accb4527275bcda12466ff598efff Mon Sep 17 00:00:00 2001 From: Chris Wage Date: Thu, 16 Apr 2026 15:17:43 -0500 Subject: [PATCH 1/2] Make Now section a carousel of recent items Replace the single-rendered Now block with a carousel so multiple recent items (articles, projects, etc.) can share the featured slot. Progressive enhancement: without JS, all items stack as before; with JS, one item is visible at a time, navigated via < > arrows and clickable dots. - Entries display in reverse YAML order so new items append at the bottom and show first - Controls sit above the slide so they stay anchored when the active item's height changes - Optional date field rendered alongside type - Framed container (subtle border + off-white bg) marks the section as featured Co-Authored-By: Claude Opus 4.6 (1M context) --- _data/now.yml | 8 +++- assets/css/style.css | 79 ++++++++++++++++++++++++++++++++++++++- assets/js/now-carousel.js | 62 ++++++++++++++++++++++++++++++ index.md | 18 +++++++-- 4 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 assets/js/now-carousel.js diff --git a/_data/now.yml b/_data/now.yml index 9ba7c78..eba2641 100644 --- a/_data/now.yml +++ b/_data/now.yml @@ -1,5 +1,11 @@ - title: "Platesolving for Fun and No Profit" url: https://quietlife.net/2026/04/08/platesolving-for-fun-and-no-profit/ - type: blog + type: article + date: 2026-04-08 image: https://quietlife.net/images/artemis-solved-annotation.jpg blurb: "Using Claude Code to identify stars and planets in an Artemis II eclipse photo taken from space." +- title: "Weekend project: whoarewe" + url: https://quietlife.net/2026/04/14/weekend-project-whoarewe/ + type: project + date: 2026-04-14 + blurb: "An Android app that uses rotating 6-digit cryptographic codes to let two people verify each other's identity — a defense against voice deepfakes and social engineering, with no servers or internet required." diff --git a/assets/css/style.css b/assets/css/style.css index 30a38ea..fbb7919 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -99,16 +99,91 @@ img { .now-image { max-width: 100%; height: auto; - margin-bottom: 0.5rem; + margin-top: 0.5rem; border-radius: 2px; } -.now-type { +.now-meta { font-size: 0.8rem; color: #666; text-transform: lowercase; } +/* Now carousel (JS-enhanced) */ +.now-carousel { + border: 1px solid #e5e5e5; + background: #fafafa; + border-radius: 4px; + padding: 1rem 1.25rem; +} + +.now-carousel .now-item:last-child { + margin-bottom: 0; +} + +.now-carousel .now-controls { + display: none; +} + +.now-carousel.js-enabled .now-item { + display: none; + margin-bottom: 0.75rem; +} + +.now-carousel.js-enabled .now-item.is-active { + display: block; +} + +.now-carousel.js-enabled .now-controls { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +.now-nav { + background: none; + border: 1px solid #ddd; + color: #555; + font-size: 1.1rem; + line-height: 1; + padding: 0.25rem 0.6rem; + cursor: pointer; + border-radius: 2px; + font-family: inherit; +} + +.now-nav:hover { + color: #222; + border-color: #888; +} + +.now-dots { + display: flex; + align-items: center; + gap: 0.4rem; +} + +.now-dot { + width: 0.5rem; + height: 0.5rem; + padding: 0; + border: 1px solid #bbb; + background: transparent; + border-radius: 50%; + cursor: pointer; +} + +.now-dot.is-active { + background: #555; + border-color: #555; +} + +.now-dot:hover { + border-color: #555; +} + /* Contact icons */ .contact-icons { display: flex; diff --git a/assets/js/now-carousel.js b/assets/js/now-carousel.js new file mode 100644 index 0000000..71efa85 --- /dev/null +++ b/assets/js/now-carousel.js @@ -0,0 +1,62 @@ +(function () { + 'use strict'; + + function initCarousel(root) { + var slides = root.querySelectorAll('[data-now-slide]'); + var dots = root.querySelectorAll('[data-now-dot]'); + var prev = root.querySelector('[data-now-prev]'); + var next = root.querySelector('[data-now-next]'); + + if (slides.length < 2) { + return; + } + + root.classList.add('js-enabled'); + + var index = 0; + + function show(i) { + index = (i + slides.length) % slides.length; + for (var s = 0; s < slides.length; s++) { + var active = s === index; + slides[s].classList.toggle('is-active', active); + } + for (var d = 0; d < dots.length; d++) { + var dotActive = d === index; + dots[d].classList.toggle('is-active', dotActive); + if (dotActive) { + dots[d].setAttribute('aria-current', 'true'); + } else { + dots[d].removeAttribute('aria-current'); + } + } + } + + if (prev) { + prev.addEventListener('click', function () { show(index - 1); }); + } + if (next) { + next.addEventListener('click', function () { show(index + 1); }); + } + for (var d = 0; d < dots.length; d++) { + (function (i) { + dots[i].addEventListener('click', function () { show(i); }); + })(d); + } + + show(0); + } + + function init() { + var carousels = document.querySelectorAll('[data-now-carousel]'); + for (var i = 0; i < carousels.length; i++) { + initCarousel(carousels[i]); + } + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); diff --git a/index.md b/index.md index 937d952..9ced1d7 100644 --- a/index.md +++ b/index.md @@ -13,12 +13,24 @@ I'm Chris Wage. You can call me `cwage`, most people do. Professionally, I'm a s A current sample of whatever bullshit I'm on: -{% for item in site.data.now %} -
+ +

Elsewhere

From ecc83fdb4444cb67ff0dfb59858321c714dd85f0 Mon Sep 17 00:00:00 2001 From: Chris Wage Date: Thu, 16 Apr 2026 15:21:33 -0500 Subject: [PATCH 2/2] Only load carousel JS when there's more than one Now entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Copilot review feedback: the script was fetched unconditionally but early-returned for 0–1 entries. Gate it behind the same size>1 check that guards the controls. Co-Authored-By: Claude Opus 4.6 (1M context) --- index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.md b/index.md index 9ced1d7..28d9380 100644 --- a/index.md +++ b/index.md @@ -30,7 +30,9 @@ A current sample of whatever bullshit I'm on: {% endfor %}
+{% if site.data.now.size > 1 %} +{% endif %}

Elsewhere