← back to Crazy News Channel Shadowman
p24: move all 22 cartoon-strip pages + the reference page onto the shared stylesheet
f3c1a2d265148cd2c5ba3bbb2477f6d3c9cc78a6 · 2026-09-25 09:16:16 -0700 · Steve
Each of the 22 cartoons/2026*.html pages (plus cartoons/reference/index.html)
carried its own <style> block — 10 distinct copy-pasted/drifting variants —
on top of already linking ../assets/style.css, plus a per-page "Dark mode"
theme-toggle button+script on 17 of them. Some variants set a serif font
(Georgia/'Times New Roman'/'Iowan Old Style'/Palatino) that didn't match the
site's sans-serif stack, so which page you clicked into changed both the
font and (via the toggle, or the mood-swap removed in the prior commit) the
colors.
Deleted every inline <style> block and moved its rules into assets/style.css
under body classes scoped per layout family (cartoon-page[-wide], -frame,
-diagram, -editorial, -reference) so none of it can leak onto index.html or
cartoons/index.html. Removed the per-page theme toggles (button + JS) along
with the mismatched serif fonts. Functionality (panels, reveal/twist
buttons, sliders, status messages, the one true 3-state auto/dark/light
toggle on budget-pie-fight) is unchanged — only the styling mechanism moved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Files touched
M assets/style.cssM cartoons/20260924-budget-pie-fight.htmlM cartoons/20260924-casserole-succession.htmlM cartoons/20260924-come-in-and-get-me-meter.htmlM cartoons/20260924-commission-turtles.htmlM cartoons/20260924-conrad-filibuster-ink.htmlM cartoons/20260924-conrad-filibuster-qwen25-7b.htmlM cartoons/20260924-filibuster-vs-cloture.htmlM cartoons/20260924-four-minutes-ahead.htmlM cartoons/20260924-gnome-who-wouldnt-hush.htmlM cartoons/20260924-gold-tier-treadmill.htmlM cartoons/20260924-hedge-non-aggression-pact.htmlM cartoons/20260924-jackalope-custody-battle.htmlM cartoons/20260924-lobbyist-revolving-door.htmlM cartoons/20260924-meter-that-wouldnt-yield.htmlM cartoons/20260924-pork-barrel-train.htmlM cartoons/20260924-quorum-call-hide-seek.htmlM cartoons/20260924-row-by-row-marshal.htmlM cartoons/20260924-row-by-row-only.htmlM cartoons/20260924-the-corner-with-its-own-weather.htmlM cartoons/20260924-the-zipper-that-ended-an-inning.htmlM cartoons/20260924-tollpoints-diamond-status.htmlM cartoons/20260924-tuber-bank-of-chugwater.htmlM cartoons/reference/index.html
Diff
commit f3c1a2d265148cd2c5ba3bbb2477f6d3c9cc78a6
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Sep 25 09:16:16 2026 -0700
p24: move all 22 cartoon-strip pages + the reference page onto the shared stylesheet
Each of the 22 cartoons/2026*.html pages (plus cartoons/reference/index.html)
carried its own <style> block — 10 distinct copy-pasted/drifting variants —
on top of already linking ../assets/style.css, plus a per-page "Dark mode"
theme-toggle button+script on 17 of them. Some variants set a serif font
(Georgia/'Times New Roman'/'Iowan Old Style'/Palatino) that didn't match the
site's sans-serif stack, so which page you clicked into changed both the
font and (via the toggle, or the mood-swap removed in the prior commit) the
colors.
Deleted every inline <style> block and moved its rules into assets/style.css
under body classes scoped per layout family (cartoon-page[-wide], -frame,
-diagram, -editorial, -reference) so none of it can leak onto index.html or
cartoons/index.html. Removed the per-page theme toggles (button + JS) along
with the mismatched serif fonts. Functionality (panels, reveal/twist
buttons, sliders, status messages, the one true 3-state auto/dark/light
toggle on budget-pie-fight) is unchanged — only the styling mechanism moved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---
assets/style.css | 312 +++++++++++++++++++++
cartoons/20260924-budget-pie-fight.html | 69 +----
cartoons/20260924-casserole-succession.html | 38 +--
cartoons/20260924-come-in-and-get-me-meter.html | 20 +-
cartoons/20260924-commission-turtles.html | 46 +--
cartoons/20260924-conrad-filibuster-ink.html | 175 +-----------
cartoons/20260924-conrad-filibuster-qwen25-7b.html | 48 +---
cartoons/20260924-filibuster-vs-cloture.html | 46 +--
cartoons/20260924-four-minutes-ahead.html | 38 +--
cartoons/20260924-gnome-who-wouldnt-hush.html | 38 +--
cartoons/20260924-gold-tier-treadmill.html | 24 +-
cartoons/20260924-hedge-non-aggression-pact.html | 38 +--
cartoons/20260924-jackalope-custody-battle.html | 38 +--
cartoons/20260924-lobbyist-revolving-door.html | 47 +---
cartoons/20260924-meter-that-wouldnt-yield.html | 38 +--
cartoons/20260924-pork-barrel-train.html | 48 +---
cartoons/20260924-quorum-call-hide-seek.html | 46 +--
cartoons/20260924-row-by-row-marshal.html | 20 +-
cartoons/20260924-row-by-row-only.html | 38 +--
.../20260924-the-corner-with-its-own-weather.html | 38 +--
.../20260924-the-zipper-that-ended-an-inning.html | 38 +--
cartoons/20260924-tollpoints-diamond-status.html | 38 +--
cartoons/20260924-tuber-bank-of-chugwater.html | 38 +--
cartoons/reference/index.html | 50 +---
24 files changed, 356 insertions(+), 1013 deletions(-)
diff --git a/assets/style.css b/assets/style.css
index ae60827..b878939 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -912,6 +912,318 @@ footer { max-width: 1200px; margin: 30px auto; padding: 0 20px 30px; color: var(
links per-context instead, so this was missing from Part 1). */
a { color: var(--accent2); }
+/* ----------------------------------------------------------------
+ PART 3b — Shared cartoon-strip-page layout (TK-12226)
+ Every rule below is scoped under a body class so it can NEVER leak
+ onto index.html/cartoons/index.html. Consolidated from 10 distinct
+ per-page <style> block variants that used to be copy-pasted into
+ each of the 22 cartoons/2026*.html files (+ cartoons/reference/
+ index.html) — none of them are reproduced verbatim here: every
+ `font-family:-apple-system,...` (redundant — body already sets the
+ one site font and `button{font-family:inherit}` from Part 1 covers
+ buttons), every 'Iowan Old Style'/Palatino/Georgia serif override,
+ and every per-page dark-mode toggle/--ink+--paper hardcoded color
+ pair was DROPPED so the whole site renders in one font and one
+ palette regardless of which cartoon page you're on or what you
+ click. ---------------------------------------------------------- */
+
+/* ---- body.cartoon-page: the majority "case file" layout (11 pages:
+ casserole-succession, four-minutes-ahead, gnome-who-wouldnt-hush,
+ hedge-non-aggression-pact, jackalope-custody-battle, meter-that-
+ wouldnt-yield, row-by-row-only, the-corner-with-its-own-weather,
+ the-zipper-that-ended-an-inning, tollpoints-diamond-status,
+ tuber-bank-of-chugwater) plus the shared base for the "wide" 3-panel
+ variant below (commission-turtles, filibuster-vs-cloture, quorum-
+ call-hide-seek, budget-pie-fight, lobbyist-revolving-door,
+ pork-barrel-train). ---- */
+body.cartoon-page header {
+ padding: 16px 20px 10px; border-bottom: 3px solid var(--rule);
+ display: flex; justify-content: space-between; align-items: flex-start;
+ flex-wrap: wrap; gap: 10px;
+}
+body.cartoon-page header a.back {
+ font-size: .8rem; color: var(--ink-dim); text-decoration: none;
+ border: 1px solid var(--ink-dim); border-radius: 6px; padding: 5px 10px;
+}
+/* Replaces the identical inline style="display:flex;flex-direction:column;
+ gap:8px;align-items:flex-end" wrapper that used to hold the back-link +
+ (now removed) per-page theme-toggle button on 17 of these pages. */
+body.cartoon-page .header-actions {
+ display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
+}
+body.cartoon-page .kicker {
+ font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
+}
+body.cartoon-page h1 { font-size: 1.7rem; margin-top: 2px; }
+body.cartoon-page .dek { font-style: italic; color: var(--ink-dim); max-width: 60ch; margin-top: 4px; }
+body.cartoon-page main { max-width: 640px; margin: 0 auto; padding: 18px 20px; }
+body.cartoon-page figure {
+ margin: 0; background: var(--panel); border: 3px solid var(--rule);
+ border-radius: 8px; overflow: hidden; display: flex; flex-direction: column;
+ position: relative;
+}
+body.cartoon-page .phead {
+ display: flex; justify-content: space-between; font-size: .65rem;
+ letter-spacing: .05em; text-transform: uppercase; color: var(--ink-dim);
+ padding: 6px 10px; border-bottom: 1px solid var(--ink-dim);
+}
+body.cartoon-page .art { width: 100%; aspect-ratio: 3/2; display: block; cursor: pointer; background: transparent; }
+body.cartoon-page .art:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
+body.cartoon-page .car { cursor: pointer; }
+body.cartoon-page .car:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
+body.cartoon-page figcaption { font-size: .92rem; color: var(--ink); padding: 12px; border-top: 1px solid var(--ink-dim); }
+body.cartoon-page .dock { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 16px 0; }
+body.cartoon-page button.twist {
+ font-size: .9rem; font-weight: 700; border-radius: 6px; padding: 9px 16px;
+ cursor: pointer; border: 2px solid var(--seal); background: var(--seal); color: #241c14;
+}
+body.cartoon-page button.primary {
+ font-size: .9rem; font-weight: 700; border-radius: 6px; padding: 9px 16px;
+ cursor: pointer; border: 2px solid var(--rule); background: var(--ink); color: var(--panel);
+}
+body.cartoon-page button:disabled { opacity: .45; cursor: not-allowed; }
+body.cartoon-page .counter {
+ font-size: .8rem; font-weight: 700; color: var(--ink); border: 2px dashed var(--seal);
+ border-radius: 6px; padding: 6px 12px; white-space: nowrap;
+}
+body.cartoon-page #status {
+ font-size: .82rem; padding: 8px 12px; border-radius: 6px; border: 1px solid var(--ink-dim);
+ color: var(--ink-dim); min-height: 1.2em;
+}
+body.cartoon-page #status.ok { border-color: var(--accent2); color: var(--accent2); }
+body.cartoon-page #status.err { border-color: var(--accent); color: var(--accent); }
+body.cartoon-page #status.info { border-color: var(--focus); color: var(--focus); }
+body.cartoon-page .slider-row {
+ display: flex; flex-direction: column; gap: 4px; width: 100%;
+ background: var(--panel); border: 2px solid var(--rule); border-radius: 8px; padding: 10px 14px;
+}
+body.cartoon-page .slider-row .row1 { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; flex-wrap: wrap; }
+body.cartoon-page .slider-row label { font-size: .82rem; font-weight: 700; }
+body.cartoon-page .slider-row .val { font-size: .82rem; color: var(--ink-dim); }
+body.cartoon-page .slider-row input[type=range] { width: 100%; accent-color: var(--accent); }
+body.cartoon-page footer { max-width: 640px; margin: 20px auto 0; padding: 0 20px; font-size: .72rem; color: var(--ink-dim); }
+body.cartoon-page .hint { font-size: .72rem; color: var(--ink-dim); margin-top: 6px; }
+body.cartoon-page .seal-anim { transition: transform .3s ease; }
+body.cartoon-page .door-anim { transition: transform .45s ease; }
+@media (prefers-reduced-motion: reduce) {
+ body.cartoon-page .seal-anim, body.cartoon-page .door-anim { transition: none; }
+}
+
+/* ---- body.cartoon-page-wide: the 3-panel strip variant, layered on
+ top of body.cartoon-page (commission-turtles, filibuster-vs-cloture,
+ quorum-call-hide-seek, budget-pie-fight, lobbyist-revolving-door,
+ pork-barrel-train). ---- */
+body.cartoon-page-wide main { max-width: 900px; }
+body.cartoon-page-wide footer { max-width: 900px; }
+body.cartoon-page-wide .strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
+@media (max-width: 720px) { body.cartoon-page-wide .strip { grid-template-columns: 1fr; } }
+body.cartoon-page-wide .art { aspect-ratio: 1/1; }
+body.cartoon-page-wide figcaption { font-size: .8rem; color: var(--ink-dim); padding: 8px 10px; }
+body.cartoon-page-wide .cover {
+ width: 100%; height: 100%;
+ background: repeating-linear-gradient(45deg, var(--panel), var(--panel) 10px, color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px, color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);
+ border: none; display: flex; align-items: center; justify-content: center;
+ font-size: .85rem; color: var(--ink-dim); cursor: pointer; aspect-ratio: 1/1;
+}
+body.cartoon-page-wide .cover:hover { color: var(--ink); }
+
+/* ---- body.cartoon-page-frame: the minimalist "newsprint clipping in a
+ parchment frame" layout (come-in-and-get-me-meter, row-by-row-marshal,
+ gold-tier-treadmill). Each of these 3 pages used to hardcode its OWN
+ --ink/--paper pair (near-duplicates of --text/--panel) and a serif
+ font-family; both are dropped in favor of the single shared palette
+ and font so these pages read identically to the rest of the site. ---- */
+body.cartoon-page-frame {
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
+ padding: 24px 16px;
+}
+body.cartoon-page-frame figure { margin: 0; width: 100%; max-width: 900px; background: none; border: none; }
+body.cartoon-page-frame .frame { background: var(--panel); border: 6px solid var(--text); border-radius: 4px; box-shadow: 0 12px 40px #0009; }
+body.cartoon-page-frame svg { display: block; width: 100%; height: auto; }
+body.cartoon-page-frame figcaption { margin-top: 14px; text-align: center; }
+body.cartoon-page-frame .cap { font-size: clamp(18px, 3vw, 26px); font-weight: 700; color: var(--text); }
+body.cartoon-page-frame .cap .q { color: var(--accent2); font-style: italic; }
+body.cartoon-page-frame .sub { margin-top: 6px; font-size: 13px; color: var(--text-dim); }
+body.cartoon-page-frame .back { margin-top: 18px; font-size: 13px; }
+
+/* ---- body.cartoon-queue-page: daily-cartoons/review.html, generated by
+ daily-cartoons/build_review.py (a LOCAL-only admin review queue, never
+ deployed). TK-12226: the generator used to emit its own <style> block
+ with a hardcoded --bg/--ink/--mint/--card/--dim palette, a Georgia font,
+ and a `prefers-color-scheme: dark` swap; now it links only this
+ stylesheet and gets this one shared layout instead. ---- */
+body.cartoon-queue-page { padding: 16px; }
+body.cartoon-queue-page header {
+ max-width: 1400px; margin: 0 auto 14px; display: flex; flex-wrap: wrap;
+ gap: 12px; align-items: center; justify-content: space-between;
+}
+body.cartoon-queue-page header > div { min-width: 0; }
+body.cartoon-queue-page code { word-break: break-all; }
+body.cartoon-queue-page h1 { margin: 0; font-size: 1.5rem; }
+body.cartoon-queue-page .note { color: var(--text-dim); font-size: .9rem; margin: 4px 0 0; }
+body.cartoon-queue-page .ctrl { display: flex; gap: 12px; align-items: center; font-size: .9rem; }
+body.cartoon-queue-page select, body.cartoon-queue-page input { font: inherit; }
+body.cartoon-queue-page #grid {
+ max-width: 1400px; margin: 0 auto; display: grid; gap: 16px;
+ grid-template-columns: repeat(auto-fill, minmax(min(var(--min, 340px), 100%), 1fr));
+}
+body.cartoon-queue-page .card { background: var(--panel); border: 3px solid var(--ink); overflow: hidden; }
+body.cartoon-queue-page .card video, body.cartoon-queue-page .card img {
+ display: block; width: 100%; aspect-ratio: 4/3; object-fit: cover; background: #000;
+}
+body.cartoon-queue-page .body { padding: 10px 12px; }
+body.cartoon-queue-page h2 { margin: 0 0 4px; font-size: 1.15rem; }
+body.cartoon-queue-page .cap { margin: 0 0 8px; font-style: italic; color: var(--text-dim); }
+body.cartoon-queue-page .chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
+body.cartoon-queue-page .chip { font: 12px/1.6 -apple-system, sans-serif; border: 1px solid var(--accent); padding: 0 8px; border-radius: 10px; }
+body.cartoon-queue-page .st-error, body.cartoon-queue-page .st-incomplete-cap { border-color: #c0392b; color: #c0392b; }
+body.cartoon-queue-page .st-approved { background: var(--accent); color: #fff; }
+body.cartoon-queue-page details { font-size: .8rem; color: var(--text-dim); }
+body.cartoon-queue-page .cmd {
+ display: block; margin-top: 8px; font-size: 11px; background: var(--ink); color: var(--bg);
+ padding: 6px; cursor: pointer; word-break: break-all;
+}
+
+/* ---- body.cartoon-page-simple: the minimal single-image layout emitted
+ by daily-cartoons/approve.py for every newly-approved cartoon page (TK-
+ 12226 — the generator used to emit its own <style> block with a
+ hardcoded --cream/--ink/--mint palette + Georgia font; now it links only
+ this stylesheet and gets this one shared layout instead). ---- */
+body.cartoon-page-simple { max-width: 1000px; margin: 0 auto; padding: 24px 16px; }
+body.cartoon-page-simple video, body.cartoon-page-simple img { display: block; width: 100%; border: 4px solid var(--ink); }
+body.cartoon-page-simple h1 { margin: 14px 0 4px; }
+body.cartoon-page-simple .cap { font-style: italic; }
+
+/* ---- body.cartoon-page-diagram: the single-figure centered SVG-diagram
+ layout (conrad-filibuster-qwen25-7b — the only strip with no <header>/
+ <figure> chrome at all, just a centered SVG illustration). ---- */
+body.cartoon-page-diagram {
+ display: flex; flex-direction: column; justify-content: center; align-items: center;
+ min-height: 100vh; gap: 1rem; padding: 1rem;
+}
+body.cartoon-page-diagram .back {
+ align-self: flex-start; font-size: .8rem; color: var(--text-dim); text-decoration: none;
+ border: 1px solid var(--panel-border); border-radius: 6px; padding: 5px 10px;
+}
+body.cartoon-page-diagram .back:hover { color: var(--text); }
+body.cartoon-page-diagram .cartoon { width: 100%; max-width: 1440px; min-width: 390px; text-align: center; }
+/* .title font-size 2em kept; the inline style="font-size:1.1em" that used
+ to sit on the one .accent <p> inside the SVG foreignObject is folded in
+ here since that's the only place .accent is used on this page. */
+body.cartoon-page-diagram .title { font-size: 2em; margin-bottom: 1em; color: var(--text); }
+body.cartoon-page-diagram .accent { color: var(--accent); font-size: 1.1em; }
+body.cartoon-page-diagram .lectern,
+body.cartoon-page-diagram .delegate,
+body.cartoon-page-diagram .phonebook,
+body.cartoon-page-diagram .clock { fill: var(--text); }
+body.cartoon-page-diagram .clock-dial,
+body.cartoon-page-diagram .clock-hand,
+body.cartoon-page-diagram .chamber-members { stroke: var(--text); }
+
+/* ---- body.cartoon-page-editorial: the "front page masthead" layout
+ (conrad-filibuster-ink — the site's one featured/linked-from-index
+ cartoon). Its former Georgia/'Times New Roman' font-family and its
+ own light/dark theme-toggle button + --frame-shadow swap are both
+ dropped: one font, one palette, no toggle. --cream/--mint/--mint-dim
+ are this page's fixed parchment-frame accent colors (independent of
+ the single site palette, same idea as --ink/--paper on the "frame"
+ variant above) — kept local since nothing else on the site uses them. ---- */
+body.cartoon-page-editorial {
+ display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
+ padding: clamp(16px, 4vw, 48px) clamp(12px, 3vw, 32px) clamp(28px, 5vw, 56px);
+ --cream: #cdf5e0; --mint: #0f9d78; --mint-dim: #0c7d5f;
+ --frame-shadow: 0 18px 45px rgba(0, 0, 0, .28);
+}
+body.cartoon-page-editorial .masthead { width: 100%; max-width: 1040px; text-align: center; margin-bottom: clamp(10px, 2vw, 22px); }
+body.cartoon-page-editorial .masthead .kicker {
+ font-style: italic; letter-spacing: .14em; text-transform: uppercase;
+ font-size: clamp(10px, 1.4vw, 13px); color: var(--mint); margin: 0 0 6px;
+}
+body.cartoon-page-editorial .masthead h1 {
+ font-weight: 900; letter-spacing: .01em; font-size: clamp(26px, 5vw, 52px);
+ margin: 0; line-height: 1.02; color: var(--text);
+}
+body.cartoon-page-editorial .masthead .deck {
+ font-style: italic; font-weight: 400; font-size: clamp(12px, 1.8vw, 16px);
+ color: var(--text); opacity: .72; margin: 8px 0 0;
+}
+body.cartoon-page-editorial .frame-wrap {
+ width: 100%; max-width: 1040px; min-width: min(100%, 390px);
+ background: var(--cream); border-radius: 6px; box-shadow: var(--frame-shadow);
+ padding: clamp(10px, 1.6vw, 18px);
+}
+body.cartoon-page-editorial .cartoon-img { display: block; width: 100%; height: auto; border: 6px solid #0b0b0c; outline: 1.5px solid #0b0b0c; outline-offset: 5px; }
+body.cartoon-page-editorial .panel-caption {
+ margin: clamp(14px, 2vw, 20px) 0 4px; text-align: center; font-style: italic;
+ font-size: clamp(14px, 2.1vw, 20px); color: #0b0b0c; line-height: 1.35;
+}
+body.cartoon-page-editorial .panel-title {
+ margin: 6px 0 2px; text-align: center; font-weight: 700; letter-spacing: .14em;
+ font-size: clamp(15px, 2.4vw, 24px); color: var(--mint); border-top: 2px solid var(--mint); padding-top: 8px;
+}
+body.cartoon-page-editorial .cartoon-svg { display: block; width: 100%; height: auto; }
+body.cartoon-page-editorial .caption-row {
+ width: 100%; max-width: 1040px; display: flex; justify-content: space-between;
+ align-items: baseline; flex-wrap: wrap; gap: 8px; margin-top: clamp(10px, 2vw, 18px); padding: 0 4px;
+}
+body.cartoon-page-editorial .caption-row .cred { font-size: clamp(11px, 1.5vw, 13px); font-style: italic; opacity: .65; color: var(--text); }
+body.cartoon-page-editorial .caption-row .stamp {
+ font-size: clamp(10px, 1.4vw, 12px); letter-spacing: .08em; text-transform: uppercase;
+ color: var(--mint); font-weight: 700;
+}
+@media (max-width: 520px) {
+ body.cartoon-page-editorial .masthead h1 { letter-spacing: 0; }
+ body.cartoon-page-editorial .caption-row { justify-content: center; text-align: center; }
+}
+
+/* ---- body.cartoon-page-reference: cartoons/reference/index.html (the
+ "how these cartoons are built" design-reference doc — not a strip).
+ Its .chrome header bar is renamed to .ref-chrome so it can never
+ collide with the site's own sticky nav .chrome from Part 1. Its former
+ Iowan Old Style/Palatino/Georgia body font is dropped for the one
+ shared sans-serif stack. ---- */
+body.cartoon-page-reference { --maxw: 1000px; }
+body.cartoon-page-reference .ref-chrome {
+ display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
+ background: var(--chrome); border-bottom: 3px solid var(--accent); padding: 12px 20px;
+}
+body.cartoon-page-reference .logo-badge {
+ background: var(--accent); color: #220808; font-weight: 800; letter-spacing: .05em;
+ padding: 3px 8px; border-radius: 3px;
+}
+body.cartoon-page-reference .ref-chrome h1 { font-size: clamp(18px, 3vw, 26px); margin: 0; flex: 1; }
+body.cartoon-page-reference .ref-chrome a.home { color: var(--text-dim); text-decoration: none; font-size: 13px; }
+body.cartoon-page-reference .ref-chrome a.home:hover { color: var(--accent2); }
+body.cartoon-page-reference main { max-width: var(--maxw); margin: 0 auto; padding: 22px 20px 60px; }
+body.cartoon-page-reference .lede {
+ font-size: clamp(17px, 2.4vw, 21px); border-left: 4px solid var(--accent);
+ padding-left: 14px; margin: 4px 0 24px; color: var(--text);
+}
+body.cartoon-page-reference .creed { font-style: italic; color: var(--accent2); }
+body.cartoon-page-reference section { background: var(--panel); border: 1px solid var(--panel-border); border-radius: 6px; padding: 18px 20px; margin-bottom: 20px; }
+body.cartoon-page-reference section > h2 { margin: 0 0 12px; font-size: 20px; border-bottom: 1px solid var(--panel-border); padding-bottom: 6px; }
+body.cartoon-page-reference dl.style-grid { margin: 0; display: grid; grid-template-columns: 150px 1fr; gap: 8px 16px; }
+body.cartoon-page-reference dl.style-grid dt { color: var(--accent2); font-weight: 700; }
+body.cartoon-page-reference dl.style-grid dd { margin: 0; color: var(--text); }
+body.cartoon-page-reference ul.devices, body.cartoon-page-reference ol.brief { padding-left: 0; margin: 0; list-style: none; }
+body.cartoon-page-reference ul.devices li { padding: 8px 0; border-bottom: 1px dashed var(--panel-border); }
+body.cartoon-page-reference ul.devices li:last-child { border-bottom: none; }
+body.cartoon-page-reference .dev-name { font-weight: 800; color: var(--accent); }
+body.cartoon-page-reference .dev-seed { display: block; font-size: 12.5px; color: var(--text-dim); margin-top: 2px; }
+body.cartoon-page-reference ol.brief { list-style: decimal; padding-left: 22px; }
+body.cartoon-page-reference ol.brief li { margin: 6px 0; }
+body.cartoon-page-reference table.works { width: 100%; border-collapse: collapse; font-size: 14px; }
+body.cartoon-page-reference table.works caption { text-align: left; color: var(--text-dim); font-size: 12.5px; margin-bottom: 8px; }
+body.cartoon-page-reference table.works th, body.cartoon-page-reference table.works td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--panel-border); vertical-align: top; }
+body.cartoon-page-reference table.works th { color: var(--accent2); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
+body.cartoon-page-reference table.works td.year { white-space: nowrap; color: var(--text-dim); }
+body.cartoon-page-reference .rights { font-size: 12.5px; color: var(--text-dim); font-style: italic; margin-top: 12px; border-top: 1px solid var(--panel-border); padding-top: 10px; }
+body.cartoon-page-reference footer { text-align: center; color: var(--text-dim); font-size: 12.5px; padding: 24px 20px; }
+@media (max-width: 620px) {
+ body.cartoon-page-reference dl.style-grid { grid-template-columns: 1fr; gap: 2px 0; }
+ body.cartoon-page-reference dl.style-grid dt { margin-top: 8px; }
+}
+
/* ============================================================
PART 4 — TAGS (TK-12165)
Shared tag-chip/filter-bar/cloud styling for the front page
diff --git a/cartoons/20260924-budget-pie-fight.html b/cartoons/20260924-budget-pie-fight.html
index e75ffa1..8c05164 100644
--- a/cartoons/20260924-budget-pie-fight.html
+++ b/cartoons/20260924-budget-pie-fight.html
@@ -6,53 +6,16 @@
<title>Who Gets the Last Slice — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: an invented town budget is a pie that diners keep re-slicing smaller at a banquet table. Drag the slider to re-carve it and watch the caption rewrite live." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column;position:relative}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px;min-height:2.6em}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em;width:100%}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-.slider-row{display:flex;flex-direction:column;gap:4px;width:100%;background:var(--panel);border:2px solid var(--rule);border-radius:8px;padding:10px 14px;font-family:-apple-system,sans-serif}
-.slider-row .row1{display:flex;justify-content:space-between;align-items:baseline;gap:8px;flex-wrap:wrap}
-.slider-row label{font-size:.82rem;font-weight:700}
-.slider-row .val{font-size:.82rem;color:var(--ink-dim)}
-.slider-row input[type=range]{width:100%;accent-color:var(--accent)}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.seal-anim{transition:transform .3s ease}
-@media (prefers-reduced-motion: reduce){ .seal-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>Who Gets the Last Slice</h1>
<p class="dek">An invented town's budget arrives at the banquet table as one pie. By dessert, five invented departments are still holding forks and the pie has not gotten any bigger.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -360,34 +323,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
say('info', describeLive(idx, val, state.twists));
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') {
- document.documentElement.setAttribute('data-theme','dark');
- themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true');
- } else if (theme === 'light') {
- document.documentElement.setAttribute('data-theme','light');
- themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false');
- } else {
- // auto — remove any override so the prefers-color-scheme media query decides
- document.documentElement.removeAttribute('data-theme');
- const osDark = matchMedia('(prefers-color-scheme: dark)').matches;
- themeBtn.textContent = osDark ? 'Dark mode: on' : 'Dark mode: off';
- themeBtn.setAttribute('aria-pressed', osDark ? 'true' : 'false');
- }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => {
- const osDark = matchMedia('(prefers-color-scheme: dark)').matches;
- const currentlyDark = theme === 'dark' || (theme === 'auto' && osDark);
- theme = currentlyDark ? 'light' : 'dark';
- safeSet('p24cartoon.theme', theme);
- applyTheme();
- });
-
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
const tag = (e.target.tagName || '').toLowerCase();
diff --git a/cartoons/20260924-casserole-succession.html b/cartoons/20260924-casserole-succession.html
index a6576c8..91f4c9a 100644
--- a/cartoons/20260924-casserole-succession.html
+++ b/cartoons/20260924-casserole-succession.html
@@ -6,40 +6,16 @@
<title>The Casserole Succession — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Savannah imposes term limits on its ceremonial Bean Queen, the sash won't come off, and a courthouse finally settles it." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Savannah, GA</div>
<h1>The Casserole Succession</h1>
<p class="dek">Savannah's council is debating whether to impose term limits on the city's ceremonial "Bean Queen" title, a bean-casserole honor that has never had one.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -180,16 +156,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-come-in-and-get-me-meter.html b/cartoons/20260924-come-in-and-get-me-meter.html
index a925e46..5a4b068 100644
--- a/cartoons/20260924-come-in-and-get-me-meter.html
+++ b/cartoons/20260924-come-in-and-get-me-meter.html
@@ -6,26 +6,8 @@
<title>Come In and Get Me — P24 Cartoon Desk</title>
<meta name="description" content="Original P24 editorial cartoon in the manner of Paul Conrad: the one-day honorary mayor — a parking meter — refuses to vacate the office." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
- /* --ink/--paper are this strip's fixed newsprint-clipping ink+parchment
- colors (the illustration always reads as dark ink on cream paper,
- regardless of site mood) — everything else (page background/accent/
- focus) now comes from the shared stylesheet's body[data-mood] palette. */
- :root { --ink:#12100f; --paper:#efe7d2; }
- body { margin:0; min-height:100vh;
- font-family:'Iowan Old Style','Palatino Linotype',Georgia,serif;
- display:flex; flex-direction:column; align-items:center; justify-content:center; padding:24px 16px; }
- figure { margin:0; width:100%; max-width:900px; }
- .frame { background:var(--paper); border:6px solid var(--ink); border-radius:4px; box-shadow:0 12px 40px #0009; }
- svg { display:block; width:100%; height:auto; }
- figcaption { margin-top:14px; text-align:center; }
- .cap { font-size:clamp(18px,3vw,26px); font-weight:700; color:var(--text); }
- .cap .q { color:var(--accent2); font-style:italic; }
- .sub { margin-top:6px; font-size:13px; color:#ffd7d7aa; font-family:system-ui,sans-serif; }
- .back { margin-top:18px; font-size:13px; font-family:system-ui,sans-serif; }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page-frame">
<figure>
<div class="frame">
<svg viewBox="0 0 900 620" role="img" aria-label="A parking meter, wearing a mayoral sash and an expired-flag crown, barricaded behind an overturned desk in the mayor's office, snarling 'Come in and get me!' at officials peering around the door.">
diff --git a/cartoons/20260924-commission-turtles.html b/cartoons/20260924-commission-turtles.html
index 5adb13a..1e37471 100644
--- a/cartoons/20260924-commission-turtles.html
+++ b/cartoons/20260924-commission-turtles.html
@@ -6,48 +6,16 @@
<title>Commissions All the Way Down — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: a blue-ribbon commission recommends forming a commission to study its own recommendation, nesting smaller and smaller." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.seal-anim{transition:transform .3s ease}
-@media (prefers-reduced-motion: reduce){ .seal-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>Commissions All the Way Down</h1>
<p class="dek">An invented blue-ribbon commission recommends forming a commission to study its own recommendation. It keeps going.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -245,16 +213,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
document.getElementById('art'+i).addEventListener('keydown', (e) => { if ((e.key==='Enter'||e.key===' ') && i===state.revealed) { e.preventDefault(); next(); } });
}
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
diff --git a/cartoons/20260924-conrad-filibuster-ink.html b/cartoons/20260924-conrad-filibuster-ink.html
index 1d0ae57..88029df 100644
--- a/cartoons/20260924-conrad-filibuster-ink.html
+++ b/cartoons/20260924-conrad-filibuster-ink.html
@@ -5,146 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The Filibuster Marathon</title>
<link rel="stylesheet" href="../assets/style.css" />
-<style>
- /* --cream/--ink/--mint are this strip's fixed newsprint-clipping frame
- colors (the AI-generated illustration sits in a parchment frame that
- doesn't change with site mood); the page's own background/text now
- come straight from the shared stylesheet's body[data-mood] palette
- (via --bg/--text) instead of a locally hardcoded copy of it, and its
- dark-mode toggle (data-theme on <html>, unchanged below) is handled by
- the shared stylesheet's own html[data-theme="dark"] body rule. */
- :root{
- --cream:#cdf5e0;
- --ink:#0b0b0c;
- --mint:#0f9d78;
- --mint-dim:#0c7d5f;
- --frame-shadow: 0 18px 45px rgba(0,0,0,.28);
- }
- @media (prefers-color-scheme: dark){
- :root:not([data-theme="light"]){
- --frame-shadow: 0 22px 60px rgba(0,0,0,.6);
- }
- }
- :root[data-theme="dark"]{
- --frame-shadow: 0 22px 60px rgba(0,0,0,.6);
- }
-
- body{
- font-family:"Georgia","Times New Roman",Cambria,serif;
- display:flex;
- flex-direction:column;
- align-items:center;
- justify-content:flex-start;
- padding:clamp(16px,4vw,48px) clamp(12px,3vw,32px) clamp(28px,5vw,56px);
- }
-
- .masthead{
- width:100%;
- max-width:1040px;
- text-align:center;
- margin-bottom:clamp(10px,2vw,22px);
- }
- .masthead .kicker{
- font-family:Georgia,serif;
- font-style:italic;
- letter-spacing:.14em;
- text-transform:uppercase;
- font-size:clamp(10px,1.4vw,13px);
- color:var(--mint);
- margin:0 0 6px;
- }
- .masthead h1{
- font-family:"Times New Roman",Georgia,serif;
- font-weight:900;
- letter-spacing:.01em;
- font-size:clamp(26px,5vw,52px);
- margin:0;
- line-height:1.02;
- color:var(--text);
- }
- .masthead .deck{
- font-style:italic;
- font-weight:400;
- font-size:clamp(12px,1.8vw,16px);
- color:var(--text);
- opacity:.72;
- margin:8px 0 0;
- }
-
- .frame-wrap{
- width:100%;
- max-width:1040px;
- min-width:min(100%,390px);
- background:var(--cream);
- border-radius:6px;
- box-shadow:var(--frame-shadow);
- padding:clamp(10px,1.6vw,18px);
- }
-
-
- .cartoon-img{display:block;width:100%;height:auto;border:6px solid #0b0b0c;outline:1.5px solid #0b0b0c;outline-offset:5px;}
- .panel-caption{margin:clamp(14px,2vw,20px) 0 4px;text-align:center;font-family:Georgia,"Times New Roman",serif;font-style:italic;
- font-size:clamp(14px,2.1vw,20px);color:#0b0b0c;line-height:1.35;}
- .panel-title{margin:6px 0 2px;text-align:center;font-family:"Times New Roman",Georgia,serif;font-weight:700;letter-spacing:.14em;
- font-size:clamp(15px,2.4vw,24px);color:var(--mint);border-top:2px solid var(--mint);padding-top:8px;}
- .cartoon-svg{
- display:block;
- width:100%;
- height:auto;
- }
-
- .caption-row{
- width:100%;
- max-width:1040px;
- display:flex;
- justify-content:space-between;
- align-items:baseline;
- flex-wrap:wrap;
- gap:8px;
- margin-top:clamp(10px,2vw,18px);
- padding:0 4px;
- font-family:Georgia,serif;
- }
- .caption-row .cred{
- font-size:clamp(11px,1.5vw,13px);
- font-style:italic;
- opacity:.65;
- color:var(--text);
- }
- .caption-row .stamp{
- font-size:clamp(10px,1.4vw,12px);
- letter-spacing:.08em;
- text-transform:uppercase;
- color:var(--mint);
- font-weight:700;
- }
-
- .theme-toggle{
- position:fixed;
- top:14px;
- right:14px;
- font-family:Georgia,serif;
- font-size:11px;
- letter-spacing:.06em;
- text-transform:uppercase;
- background:transparent;
- border:1.5px solid var(--mint);
- color:var(--mint);
- border-radius:20px;
- padding:6px 12px;
- cursor:pointer;
- }
- .theme-toggle:hover{background:var(--mint);color:var(--cream);}
-
- @media (max-width:520px){
- .masthead h1{letter-spacing:0;}
- .caption-row{justify-content:center;text-align:center;}
- }
-</style>
</head>
-<body data-mood="politics">
-
-<button class="theme-toggle" id="themeToggle" type="button" aria-label="Toggle light / dark chrome">Dark mode</button>
+<body data-mood="politics" class="cartoon-page-editorial">
<header class="masthead">
<p class="kicker">Editorial Cartoon</p>
@@ -163,40 +25,5 @@
<span class="stamp">Vol. I • No. 1</span>
</div>
-<script>
-(function(){
- var KEY = 'filibuster-marathon-theme';
- var btn = document.getElementById('themeToggle');
- var root = document.documentElement;
-
- function apply(mode){
- if(mode === 'dark'){
- root.setAttribute('data-theme','dark');
- btn.textContent = 'Light mode';
- } else if(mode === 'light'){
- root.setAttribute('data-theme','light');
- btn.textContent = 'Dark mode';
- } else {
- root.removeAttribute('data-theme');
- var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
- btn.textContent = prefersDark ? 'Light mode' : 'Dark mode';
- }
- }
-
- var saved = null;
- try { saved = localStorage.getItem(KEY); } catch(e) {}
- apply(saved);
-
- btn.addEventListener('click', function(){
- var current = root.getAttribute('data-theme');
- var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
- var effectiveDark = current === 'dark' || (!current && prefersDark);
- var next = effectiveDark ? 'light' : 'dark';
- apply(next);
- try { localStorage.setItem(KEY, next); } catch(e) {}
- });
-})();
-</script>
-
</body>
</html>
diff --git a/cartoons/20260924-conrad-filibuster-qwen25-7b.html b/cartoons/20260924-conrad-filibuster-qwen25-7b.html
index 7130643..bd0d8f9 100644
--- a/cartoons/20260924-conrad-filibuster-qwen25-7b.html
+++ b/cartoons/20260924-conrad-filibuster-qwen25-7b.html
@@ -6,50 +6,8 @@
<title>The Filibuster Marathon — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: a filibustering delegate stands flat and unmoved as the chamber clock winds on. Model Arena pick (qwen25-7b)." />
<link rel="stylesheet" href="../assets/style.css" />
- <style>
- body {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- min-height: 100vh;
- gap: 1rem;
- padding: 1rem;
- }
- .back {
- align-self: flex-start;
- font-family: -apple-system, sans-serif;
- font-size: .8rem;
- color: var(--text-dim);
- text-decoration: none;
- border: 1px solid var(--panel-border);
- border-radius: 6px;
- padding: 5px 10px;
- }
- .back:hover { color: var(--text); }
- .cartoon {
- width: 100%;
- max-width: 1440px;
- min-width: 390px;
- text-align: center;
- }
- .title {
- font-size: 2em;
- margin-bottom: 1em;
- color: var(--text);
- }
- .lectern, .delegate, .phonebook, .clock {
- fill: var(--text);
- }
- .clock-dial, .clock-hand, .chamber-members {
- stroke: var(--text);
- }
- .accent {
- color: var(--accent);
- }
- </style>
-</head>
-<body data-mood="politics">
+ </head>
+<body data-mood="politics" class="cartoon-page-diagram">
<a class="back" href="index.html">← Cartoon Desk</a>
<div class="cartoon">
<div class="title">The Filibuster Marathon</div>
@@ -65,7 +23,7 @@
<!-- Lectern -->
<rect x="360" y="320" width="60" height="100" rx="10" class="lectern"/>
<foreignObject x="400" y="320" width="50" height="90">
- <p class="accent" style="font-size: 1.1em;">The Filibuster Marathon</p>
+ <p class="accent">The Filibuster Marathon</p>
</foreignObject>
<!-- Phonebook -->
<rect x="380" y="60" width="200" height="200" fill="#fff"/>
diff --git a/cartoons/20260924-filibuster-vs-cloture.html b/cartoons/20260924-filibuster-vs-cloture.html
index 68f1cbd..479ca3e 100644
--- a/cartoons/20260924-filibuster-vs-cloture.html
+++ b/cartoons/20260924-filibuster-vs-cloture.html
@@ -6,48 +6,16 @@
<title>Cloture o'Clock — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: the Forum of Delegates' ceremonial floor clock is wound tight by one side and wound right back by the other, ticking forward and backward until it just gives up." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.seal-anim{transition:transform .3s ease}
-@media (prefers-reduced-motion: reduce){ .seal-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>Cloture o'Clock</h1>
<p class="dek">The Forum of Delegates' ceremonial floor clock is wound tight by one side and wound right back by the other, ticking forward and backward until it simply gives up.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -343,16 +311,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
document.getElementById('art'+i).addEventListener('keydown', (e) => { if ((e.key==='Enter'||e.key===' ') && i===state.revealed) { e.preventDefault(); next(); } });
}
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
diff --git a/cartoons/20260924-four-minutes-ahead.html b/cartoons/20260924-four-minutes-ahead.html
index be7bfc3..dbfeda2 100644
--- a/cartoons/20260924-four-minutes-ahead.html
+++ b/cartoons/20260924-four-minutes-ahead.html
@@ -6,40 +6,16 @@
<title>Four Minutes Ahead of Everyone — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Bozeman sets its town clock four minutes fast, declares its own time zone, and petitions to secede from Mountain Time entirely." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Bozeman, MT</div>
<h1>Four Minutes Ahead of Everyone</h1>
<p class="dek">Bozeman's city council is debating whether to permanently reset the town clock four minutes ahead of standard time in hopes of nudging residents toward punctuality.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -177,16 +153,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-gnome-who-wouldnt-hush.html b/cartoons/20260924-gnome-who-wouldnt-hush.html
index e110f9f..00da44f 100644
--- a/cartoons/20260924-gnome-who-wouldnt-hush.html
+++ b/cartoons/20260924-gnome-who-wouldnt-hush.html
@@ -6,40 +6,16 @@
<title>The Gnome Who Wouldn't Hush — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Duluth taxes loud lawn gnomes, registers them, ankle-monitors repeat offenders, and finally convenes a Gnome Parole Board." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Duluth, MN</div>
<h1>The Gnome Who Wouldn't Hush</h1>
<p class="dek">Duluth officials are weighing a new annual fee on unusually loud lawn ornaments after residents complained about a rise in singing gnomes and motion-triggered flamingos.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -186,16 +162,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-gold-tier-treadmill.html b/cartoons/20260924-gold-tier-treadmill.html
index 37dbf6b..929bb80 100644
--- a/cartoons/20260924-gold-tier-treadmill.html
+++ b/cartoons/20260924-gold-tier-treadmill.html
@@ -6,28 +6,8 @@
<title>Gold Commuter — P24 Cartoon Desk</title>
<meta name="description" content="Original P24 editorial cartoon in the manner of Paul Conrad: motorists circle a toll bridge all night on a treadmill of asphalt, chasing 'Gold Commuter' status." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
- /* --ink/--paper are this strip's fixed newsprint-clipping ink+parchment
- colors (the illustration always reads as dark ink on cream paper,
- regardless of site mood) — everything else (page background/accent/
- focus) now comes from the shared stylesheet's body[data-mood] palette
- (this cartoon's manifest.js section is "politics", matching its
- political-cartoon siblings, not the green it used to hardcode). */
- :root { --ink:#0b1a0e; --paper:#eafff0; }
- body { margin:0; min-height:100vh;
- font-family:'Iowan Old Style','Palatino Linotype',Georgia,serif;
- display:flex; flex-direction:column; align-items:center; justify-content:center; padding:24px 16px; }
- figure { margin:0; width:100%; max-width:900px; }
- .frame { background:var(--paper); border:6px solid var(--ink); border-radius:4px; box-shadow:0 12px 40px #0009; }
- svg { display:block; width:100%; height:auto; }
- figcaption { margin-top:14px; text-align:center; }
- .cap { font-size:clamp(18px,3vw,26px); font-weight:700; color:var(--text); }
- .cap .q { color:var(--accent2); font-style:italic; }
- .sub { margin-top:6px; font-size:13px; color:#c9f5d6aa; font-family:system-ui,sans-serif; }
- .back { margin-top:18px; font-size:13px; font-family:system-ui,sans-serif; }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page-frame">
<figure>
<div class="frame">
<svg viewBox="0 0 900 620" role="img" aria-label="A toll booth sits at the hub of a giant hamster-wheel of bridge asphalt turning in the night; exhausted cars trudge around and around it chasing a dangling gold 'GOLD TIER' carrot, headlights tracing an endless loop under a crescent moon.">
@@ -46,7 +26,7 @@
<!-- hub = toll booth -->
<rect x="405" y="315" width="90" height="90" rx="6" fill="#0b1a0e"/>
<rect x="418" y="300" width="64" height="22" fill="#0b1a0e"/>
- <rect x="424" y="332" width="52" height="34" fill="var(--paper)"/>
+ <rect x="424" y="332" width="52" height="34" fill="var(--panel)"/>
<text x="450" y="356" text-anchor="middle" font-size="13" font-family="system-ui,sans-serif" font-weight="900" fill="#0b1a0e">BOOTH 3</text>
<!-- boom gate -->
<line x1="495" y1="360" x2="600" y2="330" stroke-width="6"/>
diff --git a/cartoons/20260924-hedge-non-aggression-pact.html b/cartoons/20260924-hedge-non-aggression-pact.html
index dfd9ba3..962afbb 100644
--- a/cartoons/20260924-hedge-non-aggression-pact.html
+++ b/cartoons/20260924-hedge-non-aggression-pact.html
@@ -6,40 +6,16 @@
<title>The Hedge Non-Aggression Pact — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Washington regulates statue-shaped hedges, fines a homeowner, gets accused of hedge espionage, and signs a topiary treaty with Idaho." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Spokane, WA</div>
<h1>The Hedge Non-Aggression Pact</h1>
<p class="dek">Washington lawmakers are proposing a height limit on hedges trimmed to resemble statues after complaints that some now overshadow actual public monuments.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -176,16 +152,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-jackalope-custody-battle.html b/cartoons/20260924-jackalope-custody-battle.html
index a2c84b6..132c8be 100644
--- a/cartoons/20260924-jackalope-custody-battle.html
+++ b/cartoons/20260924-jackalope-custody-battle.html
@@ -6,40 +6,16 @@
<title>The Jackalope Custody Battle — P24 Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: two Iowa towns feud over which one truly owns the jackalope legend, ending in a statue that commutes between them by flatbed." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="entertainment">
+<body data-mood="entertainment" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Cartoon Desk · Invented Satire · Story City, IA</div>
<h1>The Jackalope Custody Battle</h1>
<p class="dek">Story City unveils a 14-foot jackalope statue; neighboring Radcliffe claims the legend, and a governor's accord ends with the statue on a biweekly trailer tour.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -175,16 +151,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-lobbyist-revolving-door.html b/cartoons/20260924-lobbyist-revolving-door.html
index 5b3d57f..26b5a2e 100644
--- a/cartoons/20260924-lobbyist-revolving-door.html
+++ b/cartoons/20260924-lobbyist-revolving-door.html
@@ -6,49 +6,16 @@
<title>The Revolving Door — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: the same invented official exits an invented capitol's revolving door as a regulator and spins back in seconds later as a lobbyist, carrying a slightly bigger briefcase every time." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-.counter{font-family:-apple-system,sans-serif;font-size:.8rem;font-weight:700;color:var(--ink);border:2px dashed var(--seal);border-radius:6px;padding:6px 12px;white-space:nowrap}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.door-anim{transition:transform .45s ease}
-@media (prefers-reduced-motion: reduce){ .door-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>The Revolving Door</h1>
<p class="dek">An invented capitol's revolving door turns once. A regulator walks out. It turns again. A lobbyist walks in. Same coat, same face, slightly bigger briefcase.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -272,16 +239,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
});
}
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
diff --git a/cartoons/20260924-meter-that-wouldnt-yield.html b/cartoons/20260924-meter-that-wouldnt-yield.html
index e64b415..9016819 100644
--- a/cartoons/20260924-meter-that-wouldnt-yield.html
+++ b/cartoons/20260924-meter-that-wouldnt-yield.html
@@ -6,40 +6,16 @@
<title>The Meter That Wouldn't Yield — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Erie's most reliable parking meter is honored, seated, re-elected, and sworn in as honorary mayor — and then won't leave the office." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Erie, PA</div>
<h1>The Meter That Wouldn't Yield</h1>
<p class="dek">Erie's city council will vote Thursday on renaming a stretch of Elm Street after a parking meter that officials credit with decades of uneventful, reliable quarter collection.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -183,16 +159,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-pork-barrel-train.html b/cartoons/20260924-pork-barrel-train.html
index f809ff4..633a4cb 100644
--- a/cartoons/20260924-pork-barrel-train.html
+++ b/cartoons/20260924-pork-barrel-train.html
@@ -6,50 +6,16 @@
<title>The Pork Barrel Express — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: a fictional infrastructure bill turns into a runaway train as wildly unrelated riders couple on car by car. Click a car for its invented cost." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-.car{cursor:pointer}
-.car:focus-visible{outline:3px solid var(--focus); outline-offset:2px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.seal-anim{transition:transform .3s ease}
-@media (prefers-reduced-motion: reduce){ .seal-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>The Pork Barrel Express</h1>
<p class="dek">An invented infrastructure bill leaves committee as a single train car and picks up wildly unrelated riders at every stop. Click a car to see what it actually costs.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -374,16 +340,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
document.getElementById('art'+i).addEventListener('keydown', (e) => { if ((e.key==='Enter'||e.key===' ') && i===state.revealed) { e.preventDefault(); next(); } });
}
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
diff --git a/cartoons/20260924-quorum-call-hide-seek.html b/cartoons/20260924-quorum-call-hide-seek.html
index 8f197fb..1c5324f 100644
--- a/cartoons/20260924-quorum-call-hide-seek.html
+++ b/cartoons/20260924-quorum-call-hide-seek.html
@@ -6,48 +6,16 @@
<title>The Quorum Call — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire strip: an invented legislative chamber plays hide-and-seek to dodge a quorum call, with a new hiding spot each plot twist." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:900px;margin:0 auto;padding:18px 20px}
-.strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
-@media (max-width:720px){ .strip{grid-template-columns:1fr} }
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:1/1;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);padding:8px 10px}
-.cover{width:100%;height:100%;background:repeating-linear-gradient(45deg,var(--panel),var(--panel) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 10px,color-mix(in srgb, var(--panel) 85%, var(--ink)) 20px);border:none;display:flex;align-items:center;justify-content:center;font-family:-apple-system,sans-serif;font-size:.85rem;color:var(--ink-dim);cursor:pointer;aspect-ratio:1/1}
-.cover:hover{color:var(--ink)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.primary,button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--rule)}
-button.primary{background:var(--ink);color:var(--panel)}
-button.twist{background:var(--seal);color:#241c14;border-color:var(--seal)}
-button:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-.seal-anim{transition:transform .3s ease}
-@media (prefers-reduced-motion: reduce){ .seal-anim{transition:none} }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page cartoon-page-wide">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire</div>
<h1>The Quorum Call</h1>
<p class="dek">An invented legislative chamber plays hide-and-seek to dodge a quorum call. Nobody has technically left the building.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -283,16 +251,6 @@ footer{max-width:900px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
document.getElementById('art'+i).addEventListener('keydown', (e) => { if ((e.key==='Enter'||e.key===' ') && i===state.revealed) { e.preventDefault(); next(); } });
}
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
document.addEventListener('keydown', (e) => {
if (e.metaKey || e.ctrlKey || e.altKey) return;
diff --git a/cartoons/20260924-row-by-row-marshal.html b/cartoons/20260924-row-by-row-marshal.html
index 6231673..510be07 100644
--- a/cartoons/20260924-row-by-row-marshal.html
+++ b/cartoons/20260924-row-by-row-marshal.html
@@ -6,26 +6,8 @@
<title>Row by Row, Citizen — P24 Cartoon Desk</title>
<meta name="description" content="Original P24 editorial cartoon in the manner of Paul Conrad: a state Corn Marshal confiscates a cob and outlaws the cob holder as a 'cheating device.'" />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
- /* --ink/--paper are this strip's fixed newsprint-clipping ink+parchment
- colors (the illustration always reads as dark ink on cream paper,
- regardless of site mood) — everything else (page background/accent/
- focus) now comes from the shared stylesheet's body[data-mood] palette. */
- :root { --ink:#12100f; --paper:#efe7d2; }
- body { margin:0; min-height:100vh;
- font-family:'Iowan Old Style','Palatino Linotype',Georgia,serif;
- display:flex; flex-direction:column; align-items:center; justify-content:center; padding:24px 16px; }
- figure { margin:0; width:100%; max-width:900px; }
- .frame { background:var(--paper); border:6px solid var(--ink); border-radius:4px; box-shadow:0 12px 40px #0009; }
- svg { display:block; width:100%; height:auto; }
- figcaption { margin-top:14px; text-align:center; }
- .cap { font-size:clamp(18px,3vw,26px); font-weight:700; color:var(--text); }
- .cap .q { color:var(--accent2); font-style:italic; }
- .sub { margin-top:6px; font-size:13px; color:#ffd7d7aa; font-family:system-ui,sans-serif; }
- .back { margin-top:18px; font-size:13px; font-family:system-ui,sans-serif; }
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page-frame">
<figure>
<div class="frame">
<svg viewBox="0 0 900 620" role="img" aria-label="A towering, jackbooted Corn Marshal in a badge and peaked cap looms over a small trembling diner, confiscating a corn cob with tongs while a cob holder lies stamped 'CHEATING DEVICE' at his boot.">
diff --git a/cartoons/20260924-row-by-row-only.html b/cartoons/20260924-row-by-row-only.html
index 9c5c535..938811c 100644
--- a/cartoons/20260924-row-by-row-only.html
+++ b/cartoons/20260924-row-by-row-only.html
@@ -6,40 +6,16 @@
<title>Row by Row Only — P24 Political Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Kansas legislates the one true way to eat corn on the cob, deputizes Corn Marshals, and bans the cheating devices known as cob holders." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="politics">
+<body data-mood="politics" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Political Cartoon Desk · Invented Satire · Topeka, KS</div>
<h1>Row by Row Only</h1>
<p class="dek">Kansas lawmakers are considering legislation that would establish a single official method for eating corn on the cob at state-funded events, citing years of inconsistent technique.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -189,16 +165,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-the-corner-with-its-own-weather.html b/cartoons/20260924-the-corner-with-its-own-weather.html
index e27d213..a533760 100644
--- a/cartoons/20260924-the-corner-with-its-own-weather.html
+++ b/cartoons/20260924-the-corner-with-its-own-weather.html
@@ -6,40 +6,16 @@
<title>The Corner With Its Own Weather — P24 Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: a persistent crosswind at one small-town intersection escalates from a windsock to a paid Wind Spotter to an annual Hat-Chasing Festival." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="weather">
+<body data-mood="weather" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Cartoon Desk · Invented Satire · Cut Bank, MT</div>
<h1>The Corner With Its Own Weather</h1>
<p class="dek">A stubborn crosswind at one Montana intersection earns a windsock, a paid Wind Spotter, a proposed windbreak, and finally its own festival.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -179,16 +155,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-the-zipper-that-ended-an-inning.html b/cartoons/20260924-the-zipper-that-ended-an-inning.html
index 6379069..4853761 100644
--- a/cartoons/20260924-the-zipper-that-ended-an-inning.html
+++ b/cartoons/20260924-the-zipper-that-ended-an-inning.html
@@ -6,40 +6,16 @@
<title>The Zipper That Ended an Inning — P24 Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: a minor league mascot's costume zipper failure escalates into a league-wide mascot-safety bureaucracy." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="sports">
+<body data-mood="sports" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Cartoon Desk · Invented Satire · Chillicothe, OH</div>
<h1>The Zipper That Ended an Inning</h1>
<p class="dek">A minor-league mascot's zipper fails mid-dance, and the fallout escalates through a reinforced costume, an 11-point checklist, and a league-wide Mascot Integrity Officer.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -184,16 +160,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-tollpoints-diamond-status.html b/cartoons/20260924-tollpoints-diamond-status.html
index 3b3ab35..5a3bcfc 100644
--- a/cartoons/20260924-tollpoints-diamond-status.html
+++ b/cartoons/20260924-tollpoints-diamond-status.html
@@ -6,40 +6,16 @@
<title>The Booth That Became an Airline — P24 Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: Ashtabula's toll bridge loyalty program escalates from gift-card points to a Gold Lounge to its own currency and chartered airline." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="business">
+<body data-mood="business" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Cartoon Desk · Invented Satire · Ashtabula, OH</div>
<h1>The Booth That Became an Airline</h1>
<p class="dek">Ashtabula's toll bridge rewards E-ZPass loyalty with points, gift cards, a Gold Lounge, and eventually its own currency and chartered flight.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -175,16 +151,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/20260924-tuber-bank-of-chugwater.html b/cartoons/20260924-tuber-bank-of-chugwater.html
index f71b973..0642478 100644
--- a/cartoons/20260924-tuber-bank-of-chugwater.html
+++ b/cartoons/20260924-tuber-bank-of-chugwater.html
@@ -6,40 +6,16 @@
<title>The Tuber Bank of Chugwater — P24 Cartoon Desk</title>
<meta name="description" content="An original invented-satire cartoon: a Wyoming lab's potato-battery pilot escalates from soil sensors to a custom potato cultivar to a wired 'tuber bank' backing the county grid." />
<link rel="stylesheet" href="../assets/style.css" />
-<style>
-header{padding:16px 20px 10px;border-bottom:3px solid var(--rule);display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px}
-header a.back{font-family:-apple-system,sans-serif;font-size:.8rem;color:var(--ink-dim);text-decoration:none;border:1px solid var(--ink-dim);border-radius:6px;padding:5px 10px}
-.kicker{font-family:-apple-system,sans-serif;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
-h1{font-size:1.7rem;margin-top:2px}
-.dek{font-style:italic;color:var(--ink-dim);max-width:60ch;margin-top:4px}
-main{max-width:640px;margin:0 auto;padding:18px 20px}
-figure{margin:0;background:var(--panel);border:3px solid var(--rule);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
-.phead{display:flex;justify-content:space-between;font-family:-apple-system,sans-serif;font-size:.65rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-dim);padding:6px 10px;border-bottom:1px solid var(--ink-dim)}
-.art{width:100%;aspect-ratio:3/2;display:block;cursor:pointer;background:transparent}
-.art:focus-visible{outline:3px solid var(--focus); outline-offset:-3px}
-figcaption{font-family:-apple-system,sans-serif;font-size:.92rem;color:var(--ink);padding:12px;border-top:1px solid var(--ink-dim)}
-.dock{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:16px 0;font-family:-apple-system,sans-serif}
-button.twist{font-family:-apple-system,sans-serif;font-size:.9rem;font-weight:700;border-radius:6px;padding:9px 16px;cursor:pointer;border:2px solid var(--seal);background:var(--seal);color:#241c14}
-button.twist:disabled{opacity:.45;cursor:not-allowed}
-button.theme{margin-left:auto;background:transparent;border:1px solid var(--ink-dim);color:var(--ink-dim);border-radius:6px;padding:6px 10px;font-family:-apple-system,sans-serif;font-size:.8rem;cursor:pointer}
-#status{font-family:-apple-system,sans-serif;font-size:.82rem;padding:8px 12px;border-radius:6px;border:1px solid var(--ink-dim);color:var(--ink-dim);min-height:1.2em}
-#status.ok{border-color:var(--accent2);color:var(--accent2)}
-#status.err{border-color:var(--accent);color:var(--accent)}
-#status.info{border-color:var(--focus);color:var(--focus)}
-footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim)}
-.hint{font-family:-apple-system,sans-serif;font-size:.72rem;color:var(--ink-dim);margin-top:6px}
-</style>
</head>
-<body data-mood="scitech">
+<body data-mood="scitech" class="cartoon-page">
<header>
<div>
<div class="kicker">P24 Cartoon Desk · Invented Satire · Chugwater, WY</div>
<h1>The Tuber Bank of Chugwater</h1>
<p class="dek">A Wyoming lab's potato-powered soil sensors outlast lithium cells, get their own custom-bred spud, and end up wired into the county's emergency power grid.</p>
</div>
- <div style="display:flex;flex-direction:column;gap:8px;align-items:flex-end">
+ <div class="header-actions">
<a class="back" href="index.html">← Cartoon Desk</a>
- <button class="theme" id="themeBtn" type="button" aria-pressed="false">Dark mode: off</button>
</div>
</header>
<main>
@@ -175,16 +151,6 @@ footer{max-width:640px;margin:20px auto 0;padding:0 20px;font-family:-apple-syst
if (k === 'n' || e.key === 'ArrowRight') { e.preventDefault(); advance(); }
});
- const themeBtn = document.getElementById('themeBtn');
- function safeGet(k,d){ try { return localStorage.getItem(k) ?? d; } catch { return d; } }
- function safeSet(k,v){ try { localStorage.setItem(k,v); } catch {} }
- let theme = safeGet('p24cartoon.theme', 'auto');
- function applyTheme(){
- if (theme === 'dark') { document.documentElement.setAttribute('data-theme','dark'); themeBtn.textContent='Dark mode: on'; themeBtn.setAttribute('aria-pressed','true'); }
- else { document.documentElement.setAttribute('data-theme','light'); themeBtn.textContent='Dark mode: off'; themeBtn.setAttribute('aria-pressed','false'); }
- }
- applyTheme();
- themeBtn.addEventListener('click', () => { theme = theme === 'dark' ? 'light' : 'dark'; safeSet('p24cartoon.theme', theme); applyTheme(); });
paint();
say('info', 'Case file open. Press N, click the art, or hit Plot Twist to advance the story.');
diff --git a/cartoons/reference/index.html b/cartoons/reference/index.html
index 24b0028..5802dd3 100644
--- a/cartoons/reference/index.html
+++ b/cartoons/reference/index.html
@@ -6,55 +6,9 @@
<title>Masters: Paul Conrad — P24 Political Cartoon Desk</title>
<meta name="description" content="The style reference the P24 Political Cartoon Desk draws on: Paul Conrad (1924–2010), three-time Pulitzer editorial cartoonist. His devices, creed, and works — metadata and link-out only." />
<link rel="stylesheet" href="../../assets/style.css" />
-<style>
- /* General reference page, not tied to one category — uses the shared
- stylesheet's default "all" mood (../../assets/style.css) instead of a
- locally hardcoded palette, so its background matches every other P24
- page under the "all" mood. --maxw is page-specific layout, kept local. */
- :root { --maxw: 1000px; }
- body { font-family: 'Iowan Old Style', 'Palatino Linotype', Georgia, serif; }
- .chrome {
- display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
- background: var(--chrome); border-bottom: 3px solid var(--accent);
- padding: 12px 20px;
- }
- .logo-badge {
- background: var(--accent); color: #220808; font-weight: 800; letter-spacing: .05em;
- padding: 3px 8px; border-radius: 3px; font-family: system-ui, sans-serif;
- }
- .chrome h1 { font-size: clamp(18px, 3vw, 26px); margin: 0; flex: 1; }
- .chrome a.home { color: var(--text-dim); text-decoration: none; font-size: 13px; font-family: system-ui, sans-serif; }
- .chrome a.home:hover { color: var(--accent2); }
- main { max-width: var(--maxw); margin: 0 auto; padding: 22px 20px 60px; }
- .lede {
- font-size: clamp(17px, 2.4vw, 21px); border-left: 4px solid var(--accent);
- padding-left: 14px; margin: 4px 0 24px; color: var(--text);
- }
- .creed { font-style: italic; color: var(--accent2); }
- section { background: var(--panel); border: 1px solid var(--panel-border); border-radius: 6px; padding: 18px 20px; margin-bottom: 20px; }
- section > h2 { margin: 0 0 12px; font-size: 20px; border-bottom: 1px solid var(--panel-border); padding-bottom: 6px; }
- dl.style-grid { margin: 0; display: grid; grid-template-columns: 150px 1fr; gap: 8px 16px; }
- dl.style-grid dt { color: var(--accent2); font-weight: 700; }
- dl.style-grid dd { margin: 0; color: var(--text); }
- ul.devices, ol.brief { padding-left: 0; margin: 0; list-style: none; }
- ul.devices li { padding: 8px 0; border-bottom: 1px dashed var(--panel-border); }
- ul.devices li:last-child { border-bottom: none; }
- .dev-name { font-weight: 800; color: var(--accent); }
- .dev-seed { display: block; font-size: 12.5px; color: var(--text-dim); margin-top: 2px; }
- ol.brief { list-style: decimal; padding-left: 22px; }
- ol.brief li { margin: 6px 0; }
- table.works { width: 100%; border-collapse: collapse; font-size: 14px; }
- table.works caption { text-align: left; color: var(--text-dim); font-size: 12.5px; margin-bottom: 8px; font-family: system-ui, sans-serif; }
- table.works th, table.works td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--panel-border); vertical-align: top; }
- table.works th { color: var(--accent2); font-family: system-ui, sans-serif; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
- table.works td.year { white-space: nowrap; color: var(--text-dim); }
- .rights { font-size: 12.5px; color: var(--text-dim); font-style: italic; margin-top: 12px; border-top: 1px solid var(--panel-border); padding-top: 10px; }
- footer { text-align: center; color: var(--text-dim); font-size: 12.5px; padding: 24px 20px; font-family: system-ui, sans-serif; }
- @media (max-width: 620px) { dl.style-grid { grid-template-columns: 1fr; gap: 2px 0; } dl.style-grid dt { margin-top: 8px; } }
-</style>
</head>
-<body data-mood="all">
-<header class="chrome">
+<body data-mood="all" class="cartoon-page-reference">
+<header class="ref-chrome">
<span class="logo-badge" aria-hidden="true">P24</span>
<h1>Masters: Paul Conrad</h1>
<a class="home" href="../index.html">← Cartoon Desk</a>
← 455c6ee p24: move index.html's 9 inline style="..." attrs into style
·
back to Crazy News Channel Shadowman
·
p24: fix cartoon-page generators to emit zero inline styles 3619366 →