/*
Theme Name: Brzeziński Portfolio
Theme URI: https://bartoszbrzezinski.com
Author: Bartosz Brzeziński
Description: A corkboard-style masonry portfolio for journalism and photography. Supports three custom post types: Portfolio Photo, Portfolio Article, and Portfolio Note.
Version: 5.5
License: GNU General Public License v2 or later
Text Domain: brzezinski-portfolio
*/

/* ── Reset ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overflow-x: clip; }

/* ── Cross-document view transitions ──────────────────────────
   Opts the site into browser-native page transitions. When the user
   navigates between same-origin pages (e.g. /#notebook ↔ /reading),
   the browser snapshots the outgoing document and crossfades into
   the incoming one. No JS, no SPA framework, no portfolio.js
   re-entrancy work needed. Browsers without support fall back to
   instant navigation gracefully.

   Baseline support: Chrome 126+, Safari 18.2+, Firefox 144+
   (Interop 2026). Older browsers see normal navigation.

   We deliberately don't tag #nb-workspace-head with
   view-transition-name yet — a previous attempt to do that caused
   layout issues (max-width / padding not applying) inside the SPA
   path. With pure cross-document navigation, that issue may not
   recur, but the simpler root-level crossfade is the safer first
   step. Can revisit if/when we want the head to morph in place
   instead of crossfading. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
  animation-timing-function: ease-in-out;
}

/* ── Variables ────────────────────────────────────────────── */
:root {
  --bg:           #f2f0ea;
  --surface:      #fefcf8;
  --ink:          #1c1c1a;
  --ink-mid:      #5a5954;
  --ink-soft:     #9a9890;
  --rule:         rgba(28, 28, 26, 0.1);
  --shadow-sm:    0 2px 4px rgba(28,28,26,0.08), 0 6px 18px rgba(28,28,26,0.1), 0 14px 40px rgba(28,28,26,0.07);
  --shadow-md:    0 4px 8px rgba(28,28,26,0.1), 0 12px 32px rgba(28,28,26,0.12), 0 24px 56px rgba(28,28,26,0.08);
  --shadow-hover: 0 6px 16px rgba(28,28,26,0.14), 0 18px 40px rgba(28,28,26,0.16), 0 32px 72px rgba(28,28,26,0.1);
  --pin:          #c0392b;
  --tape:         rgba(210, 200, 175, 0.5);
  --sticky-yellow: #fdf5c8;
  --sticky-coral:  #fde8e4;
  --sticky-sage:   #e4f2e8;
  --sticky-blue:   #e2eff8;
}

/* ── Body ─────────────────────────────────────────────────── */
body {
  font-family: 'Libre Baskerville', Georgia, serif;
  background-color: var(--bg);
  position: relative;
  /* Ambient lamp glow — the SOFT subtle warmth that lives in body's
     background stack. This is the "the room is warm" baseline. The
     more focused, perceptibly-visible LAMP HOTSPOT lives on
     html::before below, with its own --lamp-hot-* variables. Don't
     conflate the two: this one is ambient warmth across the desk;
     that one is the bulb you can almost see. */
  --lamp-center: rgba(255, 218, 155, 0.18);
  --lamp-mid:    rgba(255, 218, 155, 0.10);
  --lamp-outer:  rgba(255, 218, 155, 0.03);
  /* Background image stack (top → bottom rendering order):
       1. Horizontal gridlines — 0deg repeating-linear-gradient
       2. Vertical gridlines — 90deg repeating-linear-gradient
       3. Paper-fiber noise — SVG feTurbulence at low opacity, gives
          the cream its sense of being a worked paper surface rather
          than flat fill. Same noise pattern as the /reading manila
          folder (baseFrequency 0.75, brown tint), but at 12% opacity
          since it covers the entire viewport not just one card.
       4. Ambient lamp pool — warm amber radial centered low on the
          viewport (50% 75%). Subtle, page-wide; this is not the
          perceptible lamp hotspot (that's on html::before).
       5. Cream radial — base atmosphere, white center fading to dim
          warm cream at edges. The radial's center at 50% 15% sits up
          in the hero zone; that's intentional (the time-of-day wash
          layers over it).
     All layers use background-attachment: fixed so they stay locked
     to the viewport during scroll (no parallax against each other). */
  background-image:
    repeating-linear-gradient(
      0deg,
      transparent,
      transparent 23px,
      rgba(100, 90, 75, 0.048) 23px,
      rgba(100, 90, 75, 0.048) 24px
    ),
    repeating-linear-gradient(
      90deg,
      transparent,
      transparent 23px,
      rgba(100, 90, 75, 0.032) 23px,
      rgba(100, 90, 75, 0.032) 24px
    ),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.18 0 0 0 0 0.12 0 0 0 0 0.04 0 0 0 0.12 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"),
    radial-gradient(
      ellipse 65% 55% at 50% 75%,
      var(--lamp-center) 0%,
      var(--lamp-mid) 35%,
      var(--lamp-outer) 65%,
      rgba(255, 218, 155, 0) 100%
    ),
    radial-gradient(ellipse at 50% 15%, #ffffff 0%, #f5f2ea 30%, #e8e4d8 70%, #dedad0 100%);
  background-size: auto, auto, 240px 240px, auto, auto;
  background-attachment: fixed;
  min-height: 100vh;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

/* Time-of-day lamp intensity. The hero sky darkens through the day;
   the desk lamp gets correspondingly more important. Morning &
   afternoon: defaults defined on body above (subtle warmth).
   Golden hour: lamp starts to register as the sky cools.
   Evening: lamp clearly visible, sky is muted brown.
   Night: lamp is the dominant light, sky is near-black. */
body.nb-time-golden_hour {
  /* Subtle warm wash — sun is doing most of the work, the ambient
     lamp just adds gentle warmth. */
  --lamp-center: rgba(255, 215, 150, 0.30);
  --lamp-mid:    rgba(255, 215, 150, 0.16);
  --lamp-outer:  rgba(255, 215, 150, 0.06);
}
body.nb-time-evening {
  /* Stronger warm wash — fills the room with the ambient warmth that
     comes from the lamp being on. The hotspot itself is provided by
     html::before; this is the *bleed* — the warmth that spreads from
     the lamp into the rest of the page. Position stays at 50% 75%
     (centered low) so it's an ambient room temperature rather than a
     directional source — the directional reading comes from the
     hotspot + vignette combination above. */
  --lamp-center: rgba(255, 200, 130, 0.55);
  --lamp-mid:    rgba(255, 200, 130, 0.32);
  --lamp-outer:  rgba(255, 200, 130, 0.12);
}
body.nb-time-night {
  /* Deepest warm wash. At night the lamp is the only meaningful light
     in the room, so the ambient bleed should be at its strongest —
     the parts of the desk near the lamp catch real warmth, the parts
     farther away fade through the vignette into shadow. */
  --lamp-center: rgba(255, 195, 125, 0.78);
  --lamp-mid:    rgba(255, 195, 125, 0.45);
  --lamp-outer:  rgba(255, 195, 125, 0.18);
}

/* ── Desk lamp + lit-room vignette ──────────────────────────────
   This is a SEPARATE lighting layer from the ambient body lamp
   above. Where the body's --lamp-* radial is a soft page-wide
   warm wash (ambient room temperature), this layer adds:

   1. A focused LAMP HOTSPOT (html::before) — a perceptibly bright
      spot at the upper-right of the document, near where the sun
      sits in the hero illustration. Fast falloff so you can almost
      see "the bulb." Position absolute on html, not fixed, so the
      lamp belongs to the top of the document — scroll down past
      the hero and you leave it behind (the way a real desk lamp
      stays put while you read a page below it).

   2. A LIT-ROOM VIGNETTE (html::after) — at evening + night, the
      whole viewport's corners and edges darken so the lit area
      reads AS lit by contrast. Without this the lamp is just "a
      warm glow somewhere"; with it, the page reads as "a lit
      spot in a dark room."

   Both effects are keyed to time-of-day classes on the html
   element (mirroring the existing body classes). Daytime: off.
   Golden hour: lamp registers gently. Evening: clearly visible
   directional warmth. Night: lamp is the room's primary light.

   Z-index: lamp at 1 (above body bg, below cards). Vignette at 2
   (above lamp, below cards). Cards live at z-index 5 — they sit
   opaquely on top of both effects, blocking the lamp where they
   overlap. */

html {
  --lamp-hot-color:   rgba(255, 200, 130, 0);
  --lamp-hot-radius:  0;
  --vignette-edge:    rgba(0, 0, 0, 0);
  --vignette-corner:  rgba(0, 0, 0, 0);
}
html.nb-time-golden_hour {
  --lamp-hot-color:   rgba(255, 195, 125, 0.22);
  --lamp-hot-radius:  240px;
  /* No vignette at golden hour — sky is still doing the work */
}
html.nb-time-evening {
  --lamp-hot-color:   rgba(255, 180, 105, 0.55);
  --lamp-hot-radius:  280px;
  --vignette-edge:    rgba(15, 10, 6, 0.18);
  --vignette-corner:  rgba(15, 10, 6, 0.45);
}
html.nb-time-night {
  --lamp-hot-color:   rgba(255, 175, 95, 0.85);
  --lamp-hot-radius:  320px;
  --vignette-edge:    rgba(0, 0, 0, 0.3);
  --vignette-corner:  rgba(0, 0, 0, 0.7);
}

html::before {
  content: '';
  position: absolute;
  /* Cover the top portion of the document — the lamp's "neighborhood".
     Full width so the element never overflows; the radial gradient
     inside it creates the focused lamp appearance via its own
     mathematical falloff. */
  top: 0;
  left: 0;
  right: 0;
  /* Tall enough to cover the hero region + some bleed below */
  height: 700px;
  pointer-events: none;
  z-index: 1;
  /* The radial is sized in absolute pixels (matched to the
     --lamp-hot-radius variable) and positioned at ~80% from left,
     near the top of this container. The gradient's own stops create
     the focused falloff — bright hot core, fast taper to transparent.
     Using calc() with the radius variable keeps the gradient's size
     consistent with the original design. */
  background: radial-gradient(
    circle var(--lamp-hot-radius) at 80% 50px,
    var(--lamp-hot-color) 0%,
    color-mix(in srgb, var(--lamp-hot-color) 35%, transparent) 35%,
    transparent 70%
  );
  transition: background 1.5s ease;
}

html::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  /* Aggressive stops: transparent only in central 30%, ramping to
     edge darkness by 70%, corner darkness at 100%. farthest-corner
     sizing ensures the gradient reaches all corners equally. */
  background: radial-gradient(
    ellipse farthest-corner at 50% 50%,
    transparent 30%,
    var(--vignette-edge) 70%,
    var(--vignette-corner) 100%
  );
  transition: background 1.5s ease;
}

/* Edge vignette — subtle darkening at viewport edges for depth */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(
    ellipse at 50% 40%,
    transparent 55%,
    rgba(28,24,14,0.06) 75%,
    rgba(28,24,14,0.12) 95%,
    transparent 100%
  );
}

/* ── Time-of-day atmospheric wash ────────────────────────────
   Page-level top-region wash that takes on the day's light. Lives
   on body::before as a fixed overlay anchored to the top of the
   viewport, fading DOWN to nothing as it approaches the masonry.
   This is the "atmosphere, not artifact" treatment of the hero:
   instead of a banner element CARRYING the time-of-day color, the
   page itself takes on that color across its top region. The hero
   becomes simply the place where the greeting sits within this
   light. No rectangle, no border, no card — just the day's color
   meeting the desk.
   The gradient direction (to bottom) means the wash dissolves into
   the cream desk as you scroll into the cards. Height covers the
   hero region plus a bit of fade-out below it. */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* Tall enough to cover the hero area (~250px) with a long fade
     dissolve below. The actual visible wash height varies by
     time-of-day (each gradient defines its own stops below). */
  height: 480px;
  pointer-events: none;
  /* Above the body background but below the edge vignette + everything
     else. z-index 0 puts it in the same stacking band as the desk
     gridlines without obscuring them; the gradient's own opacity
     stops control how transparent the lower portion is. */
  z-index: 0;
  /* Default: no wash. Time-of-day classes on body override below.
     Transition handles graceful color shifts when the time changes
     mid-session (rare, but a manual refresh at a boundary triggers
     it). */
  background: linear-gradient(to bottom, transparent 0%, transparent 100%);
  transition: background 1.5s ease;
}

/* Hide the wash on mobile — at narrow viewports the visual payoff
   is smaller and the wash competes with the already-tight layout. */
@media (max-width: 720px) {
  body::before { height: 320px; }
}

/* Time-of-day wash gradients. Each fades from the day's sky tone at
   the top of the viewport down through atmospheric stops to the cream
   desk color at the bottom.

   Earlier iteration used translucent overlays (rgba with low alpha)
   that bled the cream desk through everywhere, producing a muddy
   gray-brown haze for evening/night rather than actual sky color.
   Now: opaque or near-opaque sky tones at the top, transitioning
   through intermediate stops, then blending into cream (#f5f2ea —
   the desk color) at the bottom. Result: the hero greeting text
   reads against a proper sky background. */
body.nb-time-morning::before {
  /* Dawn — warm cream-gold at top, fading through softer cream to
     desk. Aiming for the visible warmth of diffused morning light
     through overcast cloud — definitely warm/cream, not neutral
     ivory (too pale) and not peach (too orange/pink). */
  background: linear-gradient(to bottom,
    rgba(248, 232, 195, 0.95) 0%,
    rgba(245, 228, 192, 0.82) 22%,
    rgba(243, 226, 192, 0.58) 45%,
    rgba(243, 226, 192, 0.28) 70%,
    rgba(245, 242, 234, 0) 100%
  ) !important;
}
body.nb-time-afternoon::before {
  /* Midday — pale cream-blue at top, fading to desk. The day's
     ambient sky is mostly visible at the top with the hills under. */
  background: linear-gradient(to bottom,
    rgba(220, 222, 215, 0.85) 0%,
    rgba(228, 223, 208, 0.62) 25%,
    rgba(232, 224, 205, 0.32) 55%,
    rgba(245, 242, 234, 0) 100%
  ) !important;
}
body.nb-time-golden_hour::before {
  /* Golden hour — warm amber-cream high, easing through softer
     ochre to desk. Less saturated than the previous orange wash;
     reads as "late-afternoon light" rather than "orange filter." */
  background: linear-gradient(to bottom,
    rgba(248, 215, 175, 0.78) 0%,
    rgba(245, 210, 170, 0.62) 18%,
    rgba(238, 205, 168, 0.38) 40%,
    rgba(235, 210, 175, 0.18) 65%,
    rgba(245, 242, 234, 0) 100%
  ) !important;
}
body.nb-time-evening::before {
  /* Evening / dusk — warm dark brown at top, transitioning through
     muted brown to desk. Warm family (browns and ochres), not cool
     family (blues and purples). Matches the workspace's overall
     palette of warm paper-and-pencil tones. */
  background: linear-gradient(to bottom,
    rgba(58, 48, 40, 0.97) 0%,
    rgba(65, 52, 42, 0.90) 15%,
    rgba(78, 62, 50, 0.75) 32%,
    rgba(95, 75, 58, 0.50) 55%,
    rgba(122, 101, 82, 0.22) 78%,
    rgba(245, 242, 234, 0) 100%
  ) !important;
}
body.nb-time-night::before {
  /* Night — deep near-black with the faintest warm tint at top,
     holding through the upper half before fading into dark warm
     brown, then desk. The zenith reads as black; only the campfire
     and stars are points of light. */
  background: linear-gradient(to bottom,
    rgba(20, 17, 14, 0.99) 0%,
    rgba(24, 20, 16, 0.99) 25%,
    rgba(34, 28, 22, 0.95) 45%,
    rgba(54, 44, 34, 0.75) 62%,
    rgba(85, 68, 50, 0.34) 82%,
    rgba(245, 242, 234, 0) 100%
  ) !important;
}

@media (max-width: 768px) {
  body::after { display: none; }
}
.site-header {
  text-align: center;
  padding: 4rem 2rem 2rem;
  max-height: 30rem; /* generous ceiling for the collapse transition */
  overflow: hidden;
  transition: max-height 0.45s cubic-bezier(.4, 0, .2, 1),
              padding     0.45s cubic-bezier(.4, 0, .2, 1),
              opacity     0.3s  ease;
}

/* Suppress transitions on initial paint (added by pre-paint inline
   script in header.php, removed by JS after first frame). Without this,
   the page would animate from "expanded" to "collapsed" every reload
   if the persisted state is collapsed — visible flash + repeated
   collapse animation when navigating between tabs. */
.no-transition .site-header,
.no-transition .filter-bar,
.no-transition .header-toggle,
.no-transition .header-toggle svg {
  transition: none !important;
}

/* Collapsed state — applied via JS or by the pre-paint inline script.
   We accept both .header-toggle-available on <html> (pre-paint) and
   on <body> (JS-managed) so the rule fires regardless of which sets
   it. Same for .header-collapsed.

   The nav (.filter-bar) collapses in sync with .site-header so the
   workspace views (notebook + standalone tabs) get a clean hero +
   masonry layout with no top chrome. Board views (All/Highlights/
   Articles/Photos) are unaffected because .header-toggle-available
   isn't set there. */
.header-toggle-available.header-collapsed .site-header,
html.header-toggle-available.header-collapsed .site-header,
body.header-toggle-available.header-collapsed .site-header,
.header-toggle-available.header-collapsed .filter-bar,
html.header-toggle-available.header-collapsed .filter-bar,
body.header-toggle-available.header-collapsed .filter-bar {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
  pointer-events: none;
}

/* The toggle tab itself — hidden by default, shown only when the
   toggle is available (set on either <html> by pre-paint or <body>
   by JS). */
.header-toggle {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  width: 44px;
  height: 18px;
  padding: 2px 0 4px;
  background: #faf8f4;
  border: 1px solid var(--rule);
  border-top: none;
  border-radius: 0 0 4px 4px;
  color: rgba(150, 65, 35, 0.55);
  cursor: pointer;
  display: none; /* default — overridden when .header-toggle-available */
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
  transition: color 0.15s, background 0.15s;
}
html.header-toggle-available .header-toggle,
body.header-toggle-available .header-toggle {
  display: flex;
}
.header-toggle:hover {
  color: rgba(150, 65, 35, 0.9);
  background: #fdfbf5;
}
.header-toggle svg {
  transition: transform 0.35s cubic-bezier(.4, 0, .2, 1);
  transform-origin: center;
}
html.header-toggle-available.header-collapsed .header-toggle svg,
body.header-toggle-available.header-collapsed .header-toggle svg {
  /* Keyframe overshoots past 180° then settles back, giving the
     chevron a small physical bounce on collapse. The
     animation-fill-mode is forwards so the final 180° rotation
     persists. The cubic-bezier curve combined with the keyframe
     produces a subtle but noticeable "click" feel. */
  animation: chevron-collapse 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
  /* Fallback for browsers that don't support the animation: still
     show the rotated state. */
  transform: rotate(180deg);
}

/* On expand (i.e. when .header-collapsed is removed), play a
   reverse-direction overshoot. Triggered by the absence of the
   collapsed class, which means we need an animation on the
   non-collapsed selector that fires only after a previous
   collapse. We achieve this with the .header-was-collapsed
   class set briefly by JS during the expand transition. */
html.header-toggle-available .header-toggle.header-was-collapsed svg,
body.header-toggle-available .header-toggle.header-was-collapsed svg {
  animation: chevron-expand 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes chevron-collapse {
  0%   { transform: rotate(0deg); }
  60%  { transform: rotate(195deg); }
  100% { transform: rotate(180deg); }
}

@keyframes chevron-expand {
  0%   { transform: rotate(180deg); }
  60%  { transform: rotate(-15deg); }
  100% { transform: rotate(0deg); }
}

@media (prefers-reduced-motion: reduce) {
  html.header-toggle-available.header-collapsed .header-toggle svg,
  body.header-toggle-available.header-collapsed .header-toggle svg,
  html.header-toggle-available .header-toggle.header-was-collapsed svg,
  body.header-toggle-available .header-toggle.header-was-collapsed svg {
    animation: none;
  }
}

.header-card {
  display: inline-block;
  position: relative;
  padding: 2rem 3.5rem 1.8rem;
  background: #faf8f4;
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-sm);
  transform: rotate(-0.25deg);
}

.header-card::before {
  content: '';
  position: absolute;
  top: -7px;
  left: 50%;
  transform: translateX(-50%) rotate(-0.5deg);
  width: 64px;
  height: 14px;
  background: var(--tape);
  border-radius: 1px;
}

.header-card .site-title {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.9rem, 5vw, 3rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  line-height: 1.1;
  text-decoration: none;
  display: block;
}

.header-card .site-title a {
  color: inherit;
  text-decoration: none;
}

.header-card .site-description {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  color: var(--ink-soft);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--rule);
}

/* ── Filter nav ───────────────────────────────────────────── */
.filter-bar {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem 1rem 1rem;
  flex-wrap: wrap;
  /* max-height + overflow + transition mirror .site-header so the nav
     collapses smoothly alongside it when .header-collapsed is set.
     Generous ceiling keeps the expanded state unconstrained on wrap. */
  max-height: 12rem;
  overflow: hidden;
  transition: max-height 0.45s cubic-bezier(.4, 0, .2, 1),
              padding     0.45s cubic-bezier(.4, 0, .2, 1),
              opacity     0.3s  ease;
}

.filter-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.4rem 1.1rem;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-mid);
  cursor: pointer;
  border-radius: 2px;
  transition: all 0.18s ease;
  text-decoration: none;
  display: inline-block;
}

.filter-btn:hover {
  border-color: var(--ink-mid);
  color: var(--ink);
}

.filter-btn.active {
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}

/* ── Masonry board ────────────────────────────────────────── */
.board {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.5rem;
  padding: 1.5rem 2.5rem 5rem;
  max-width: 1380px;
  margin: 0 auto;
  transition: opacity 0.18s ease;
  position: relative;
  /* Explicit z-index keeps the entire masonry above the scuffSvg
     silhouette layer (z-index 3) regardless of stacking contexts
     created by .item transforms. Without this, .item z-index 5
     only competes within its own stacking context (created by its
     transform), not against body-level siblings, so silhouettes
     could paint over cards. With z-index 5 on .board, the whole
     masonry sits cleanly above the silhouette field. */
  z-index: 5;
}

/* Inner workspace pages: any direct child of body that holds the
   main content needs to sit above the silhouette layer (z-index 3
   added by the inner-page IIFE in portfolio.js). Without this,
   silhouettes paint over the reading/pieces/transcripts/quotes
   content. */
body.reading-page > main,
body.pieces-page > main,
body.transcripts-page > main,
body.quotes-page > main,
body.reading-page .rd-wrap,
body.pieces-page .pieces-wrap,
body.transcripts-page .transcripts-wrap,
body.quotes-page .quotes-wrap {
  position: relative;
  z-index: 5;
}

.board.board-transitioning {
  opacity: 0;
  pointer-events: none;
}

.board-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

@media (max-width: 639px) {
  .board { padding: 1rem 1rem 4rem; }
}

/* ── Item base ────────────────────────────────────────────── */
.item {
  display: block;
  position: relative;
  /* Explicit z-index keeps cards above the scuffSvg silhouette layer
     (z-index 3). Without this, .item is position:relative with
     z-index:auto, and stacking order falls back to document order —
     which paints the scuffSvg (later in body) on top of cards.
     With z-index 5, cards sit cleanly above the silhouettes but
     below tooltips/overlays (z-index 50+). */
  z-index: 5;
}

/* Pin — small red dot at the top-center of a card.
   Previously this applied to EVERY .item, which meant pins were
   ambient decoration rather than a meaningful signal: every card
   on the desk had the same "pinned to corkboard" marker, so the
   marker stopped communicating anything.

   Now pins are reserved for cards that are actually pinned. Two
   different states qualify:
     - .item-pinned: post.meta.is_highlight (highlights/featured)
     - .item-pinned-top: post.meta.is_pinned_top (user-pinned via
       the .pin-trigger button)
   Either signal puts a red dot on the card. Widgets and unpinned
   content cards have no pin. */
.item.item-pinned::before,
.item.item-pinned-top::before {
  content: '';
  position: absolute;
  top: -7px;
  left: 50%;
  transform: translateX(-50%);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--pin);
  box-shadow: 0 2px 4px rgba(0,0,0,0.35);
  z-index: 10;
}

/* ── Card entry (transition-based) ────────────────────────
   Cards land via a transition from .pending → .visible. Per-item
   delay comes from --enter-delay (set by JS in staggerCardEntry).
   Using transitions instead of keyframe animations means: (a) the
   entry only fires when the property actually changes (pending →
   visible), (b) it doesn't restart when unrelated classes toggle
   (flutter, hover), and (c) IntersectionObserver-revealed items
   below the fold get the same animation when they become visible.

   --final-tilt resolves to the full --r on desktop and is reduced
   on mobile (see breakpoint override below). Both .pending and
   .visible reference --final-tilt so mobile cards animate to the
   correct angle. */
.item {
  --final-tilt: var(--r, -0.8deg);
}

.item.pending {
  opacity: 0;
  transform: translateY(22px) rotate(var(--final-tilt));
}

.item.visible {
  opacity: 1;
  transform: translateY(0) rotate(var(--final-tilt));
  transition:
    opacity 0.55s ease var(--enter-delay, 0ms),
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1) var(--enter-delay, 0ms);
}

/* One-shot flutter — applied periodically by JS to a single random
   card at a time (see maybeFlutterRandomCard). Single card moving
   against a still board reads as ambient life; multiple cards moving
   reads as noise. The animation drifts the card slightly off its rest
   tilt and returns, like a draft of air briefly disturbed it.

   Uses keyframe animation because the multi-stop flutter motion
   (drift one way, then partway back the other, then return) can't
   be expressed as a single transition. While the flutter is playing
   it overrides the .visible transform; when the class is removed,
   the .visible rule's transform takes over again. Since the flutter
   ends exactly at the rest transform, there's no visual jump. */
.item.visible.item-fluttering {
  animation: card-flutter 1.4s ease-in-out;
}

@keyframes card-flutter {
  0% {
    transform: translateY(0) rotate(var(--final-tilt));
  }
  35% {
    transform: translateY(-2px) rotate(calc(var(--final-tilt) + 0.7deg));
  }
  70% {
    transform: translateY(0) rotate(calc(var(--final-tilt) - 0.3deg));
  }
  100% {
    transform: translateY(0) rotate(var(--final-tilt));
  }
}

/* Hover always wins — if the user reaches for a fluttering card,
   the flutter shouldn't fight the hover lift. */
.item.visible.item-fluttering:hover {
  animation: none !important;
}

.item:hover {
  transform: translateY(-3px) rotate(0deg) scale(1.015) !important;
  z-index: 5;
  transition: transform 0.18s ease !important;
  animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {
  .item.visible {
    transition: none;
  }
}

.item.hidden { display: none; }

/* ── Photo items ──────────────────────────────────────────── */
.item-photo { cursor: pointer; }

.photo-print {
  background: var(--surface);
  padding: 7px 7px 0;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
}



.item-photo:hover .photo-print {
  box-shadow: var(--shadow-hover);
}

.photo-print img {
  width: 100%;
  height: auto;
  display: block;
}

.photo-landscape .photo-print img {
  max-height: 200px;
  object-fit: cover;
}

.photo-portrait .photo-print img {
  min-height: 280px;
  object-fit: cover;
}

.photo-caption {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  color: var(--ink-soft);
  text-align: center;
  letter-spacing: 0.07em;
  padding: 7px 2px 10px;
  display: block;
  margin-top: 0;
}
/* ── Album items — casual pile stack ─────────────────────── */
.item-album { cursor: pointer; }

/* Albums use clip, not pin or tape */
.item-album::before { display: none; }
.item-album::after  { display: none; }

.album-tab-wrap {
  position: relative;
  padding-top: 12px;
}

.album-tab {
  position: absolute;
  top: 0;
  right: 16px;
  width: 78px;
  height: 18px;
  background: #e8d9b8;
  box-shadow: 0 1px 2px rgba(28,22,8,0.06);
  transform: rotate(2deg);
  z-index: 1;
  pointer-events: none;
}

.album-print {
  background: var(--surface);
  padding: 7px 7px 26px;
  transition: box-shadow 0.22s ease;
  position: relative;
  z-index: 2;
  box-shadow:
    0 2px 6px rgba(28,28,26,0.1),
    0 6px 18px rgba(28,28,26,0.09),
    10px 3px 0 -1px #fff,
    10px 3px 0 0 rgba(28,28,26,0.1),
    -7px 8px 0 -1px #fefcf8,
    -7px 8px 0 0 rgba(28,28,26,0.07),
    4px 11px 0 -1px #f8f6f0,
    4px 11px 0 0 rgba(28,28,26,0.05);
}

.item-album:hover .album-print {
  box-shadow:
    0 8px 24px rgba(28,28,26,0.18),
    0 20px 48px rgba(28,28,26,0.14),
    10px 3px 0 -1px #fff,
    10px 3px 0 0 rgba(28,28,26,0.1),
    -7px 8px 0 -1px #fefcf8,
    -7px 8px 0 0 rgba(28,28,26,0.07),
    4px 11px 0 -1px #f8f6f0,
    4px 11px 0 0 rgba(28,28,26,0.05);
}

.album-print img {
  width: 100%;
  height: auto;
  display: block;
}

.album-tag {
  position: absolute;
  top: 10px;
  left: -4px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: rgba(160,60,60,0.88);
  color: rgba(255,255,255,0.92);
  padding: 0.22rem 0.6rem 0.22rem 0.7rem;
  transform: rotate(-1deg);
  z-index: 5;
  pointer-events: none;
}

.album-tag::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: rgba(120,30,30,0.6);
}

/* ── Lightbox navigation ──────────────────────────────────── */
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(245,244,240,0.15);
  border-radius: 2px;
  color: rgba(245,244,240,0.8);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 1.1rem;
  cursor: pointer;
  padding: 0.5rem 0.7rem;
  line-height: 1;
  transition: background 0.15s, color 0.15s;
  user-select: none;
  z-index: 10;
}

.lightbox-nav:hover { background: rgba(0,0,0,0.6); color: rgba(245,244,240,1); }
.lightbox-nav.prev { left: 0.6rem; }
.lightbox-nav.next { right: 0.6rem; }
.lightbox-nav[disabled] { opacity: 0.15; cursor: default; }

.lightbox-counter {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: rgba(245,244,240,0.4);
  text-align: center;
  margin-top: 0.6rem;
  letter-spacing: 0.12em;
}

.lightbox-hint {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  color: rgba(245,244,240,0.2);
  text-align: center;
  margin-top: 0.3rem;
  letter-spacing: 0.1em;
}

/* ── Article clipping items ───────────────────────────────── */
.item-clipping a,
.article-pkg-link {
  text-decoration: none;
  color: inherit;
  display: block;
}

.clipping {
  background: #faf8f4;
  padding: 1.3rem 1.5rem 1.5rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  position: relative;
  overflow: hidden;
}



.clipping > *,
.clipping a { position: relative; z-index: 1; }

.item-clipping:hover .clipping {
  box-shadow: var(--shadow-hover);
}

/* ── Featured clipping ───────────────────────────────────── */
.clipping.featured h2 {
  font-size: clamp(1.2rem, 3vw, 1.6rem);
  line-height: 1.18;
}

.clipping.featured .clipping-deck {
  font-size: 0.88rem;
}

/* ── Date divider ─────────────────────────────────────────── */
.date-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0 0.25rem;
  pointer-events: none;
}

.date-divider span {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
  flex-shrink: 0;
}

.date-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(28,28,26,0.1);
}

/* ── Year divider — more prominent than month ────────────── */
.year-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 0 0.25rem;
  pointer-events: none;
}

.year-divider span {
  font-family: 'Playfair Display', serif;
  font-size: 1rem;
  font-weight: 700;
  color: rgba(28,28,26,0.22);
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.year-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(28,28,26,0.12);
}

.clipping-masthead {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 0.45rem;
  margin-bottom: 0.6rem;
  border-bottom: 1px solid rgba(28,28,26,0.12);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}

/* Date recedes — the publication is what matters */
.clipping-masthead span:last-child {
  font-size: 0.46rem;
  opacity: 0.6;
  flex-shrink: 0;
}

.clipping h2 {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.05rem, 2.4vw, 1.35rem);
  font-weight: 700;
  line-height: 1.25;
  color: var(--ink);
  margin-bottom: 0.55rem;
}

.clipping-deck {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.8rem;
  line-height: 1.65;
  color: var(--ink-mid);
  margin-bottom: 0.75rem;
}

.clipping-byline {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.55);
  margin: 0.2rem 0 0.6rem;
  display: block;
}

.read-link {
  display: inline-block;
  margin-top: 0.8rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1.5px solid rgba(28,28,26,0.18);
  padding-bottom: 1px;
  transition: color 0.15s, border-color 0.15s;
  cursor: pointer;
}

.read-link:hover {
  color: rgba(150,65,35,0.85);
  border-color: rgba(150,65,35,0.4);
  opacity: 1;
}

/* Pull quote link — feels handwritten, distinct from article clipping */
.item-quote .read-link {
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(150,65,35,0.65);
  border-bottom: none;
  border-bottom: 1px dashed rgba(150,65,35,0.35);
  padding-bottom: 0;
  margin-top: 0.6rem;
}

.item-quote .read-link:hover {
  color: rgba(150,65,35,0.9);
  border-bottom-color: rgba(150,65,35,0.65);
  opacity: 1;
}

/* ── Sticky note items ────────────────────────────────────── */
.sticky {
  padding: 1.3rem 1.4rem 1.7rem;
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
  transition: box-shadow 0.22s ease;
}

/* Ruled lines — same approach as mind item */
.sticky > * { position: relative; z-index: 1; }

.sticky-yellow { background: var(--sticky-yellow); background-image: repeating-linear-gradient(transparent, transparent 22px, rgba(28,28,26,0.05) 22px, rgba(28,28,26,0.05) 23px); }
.sticky-coral  { background: var(--sticky-coral);  background-image: radial-gradient(circle, rgba(28,28,26,0.18) 1px, transparent 1px); background-size: 16px 16px; }
.sticky-sage   { background: var(--sticky-sage);   background-image: repeating-linear-gradient(rgba(28,28,26,0.04) 0 1px, transparent 1px 100%), repeating-linear-gradient(90deg, rgba(28,28,26,0.04) 0 1px, transparent 1px 100%); background-size: 18px 18px; }
.sticky-blue   { background: var(--sticky-blue); }

/* Top fold line — tinted per color */
.sticky::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: rgba(28,28,26,0.06);
}

/* Folded corner */
.sticky::after {
  content: '';
  position: absolute;
  bottom: 0;
  right: 0;
  width: 16px;
  height: 16px;
  background: linear-gradient(225deg, var(--bg) 50%, transparent 50%);
  opacity: 0.7;
}

.item-sticky:hover .sticky {
  box-shadow: var(--shadow-hover);
}

.sticky-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.38);
  margin-bottom: 0.65rem;
}

.sticky-source {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  color: rgba(28,28,26,0.38);
  margin-top: 0.85rem;
  font-style: italic;
}

.sticky blockquote {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: 1.02rem;
  line-height: 1.6;
  color: rgba(28,28,26,0.75);
}

/* ── Tape strips ──────────────────────────────────────────── */
.tape-left::after,
.tape-right::after {
  content: '';
  position: absolute;
  width: 70px;
  height: 18px;
  background: rgba(210, 200, 175, 0.72);
  border-radius: 1px;
  z-index: 10;
}

.tape-left::after  { top: -7px; left: 16%;  transform: rotate(-6deg); }
.tape-right::after { top: -7px; right: 16%; transform: rotate(5deg); }

/* ── Lightbox ─────────────────────────────────────────────── */
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(20,20,18,0.93);
  z-index: 9000;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  backdrop-filter: blur(4px);
}

.lightbox.open { display: flex; }

.lightbox-inner {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
}

.lightbox-inner img {
  max-width: 100%;
  max-height: 85vh;
  object-fit: contain;
  display: block;
  box-shadow: 0 0 60px rgba(0,0,0,0.5);
}

.lightbox-caption {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  color: rgba(245,244,240,0.5);
  text-align: center;
  margin-top: 1rem;
  letter-spacing: 0.1em;
}

.lightbox-close {
  position: absolute;
  top: -2.2rem;
  right: 0;
  background: none;
  border: none;
  color: rgba(245,244,240,0.55);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  cursor: pointer;
  text-transform: uppercase;
  transition: color 0.15s;
}

.lightbox-close:hover { color: rgba(245,244,240,0.95); }

/* ── Scroll sentinel ──────────────────────────────────────── */
.load-sentinel {
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.spinner {
  width: 18px;
  height: 18px;
  border: 1.5px solid rgba(28,28,26,0.12);
  border-top-color: rgba(28,28,26,0.45);
  border-radius: 50%;
  animation: spin 0.75s linear infinite;
  opacity: 0;
  transition: opacity 0.3s;
}

.spinner.active { opacity: 1; }

@keyframes spin { to { transform: rotate(360deg); } }

/* Brief outline pulse to confirm a deep-link arrival (e.g. from /pieces
   "published as" link). Draws attention without being garish. */
@keyframes article-deeplink-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(150,65,35,0); }
  20%  { box-shadow: 0 0 0 6px rgba(150,65,35,0.35); }
  100% { box-shadow: 0 0 0 0 rgba(150,65,35,0); }
}
.article-deeplink-pulse {
  animation: article-deeplink-pulse 1.6s ease-out;
}

/* ── Footer ───────────────────────────────────────────────── */
.site-footer {
  text-align: center;
  padding: 2rem 1rem 3rem;
}

/* Footer landscape echo — the same ground SVG used in the hero,
   rendered smaller and dimmer above the footer copyright. The
   composition (hills + clustered trees + tent) comes free with the
   illustration since it's the same SVG; we just style its container
   to be a quiet echo rather than a foreground element.
   Element is injected by JS only on the notebook view (see
   renderNotebookHero), so no scoping needed in CSS itself.
   The fade-out mask at the top makes the silhouette emerge from
   the page rather than starting with a hard edge. */
.nb-foot-echo {
  position: relative;
  width: 100%;
  height: 70px;
  margin-top: 2rem;
  opacity: 0.22;
  pointer-events: none;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0.35) 35%,
    rgba(0,0,0,1) 100%);
          mask-image: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0.35) 35%,
    rgba(0,0,0,1) 100%);
}

/* Desk-edge rule above the foot echo — a horizontal line suggesting
   the front edge of the desk where the work surface ends and the
   room beyond begins (which the distant-hills echo represents).
   Pulled up out of the echo's mask-faded top zone (where it was
   getting eaten by the fade) and rendered as its own visible
   element. Mask fades the ends so the line doesn't read as a hard
   UI rule; just enough of a horizon-cue that the eye registers
   "this is where the desk stops." */
.nb-foot-echo::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: -3rem;
  height: 1.5px;
  background: rgba(80, 50, 25, 0.7);
  -webkit-mask-image: linear-gradient(to right,
    transparent 0%,
    rgba(0,0,0,1) 12%,
    rgba(0,0,0,1) 88%,
    transparent 100%);
          mask-image: linear-gradient(to right,
    transparent 0%,
    rgba(0,0,0,1) 12%,
    rgba(0,0,0,1) 88%,
    transparent 100%);
  pointer-events: none;
}

/* A second faint stroke 3px below the main edge — the underside of
   the desk's front lip catching shadow. Gives the edge a sense of
   physical depth rather than reading as a single pen-stroke rule. */
.nb-foot-echo::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: calc(-3rem + 4px);
  height: 1px;
  background: rgba(50, 30, 10, 0.18);
  -webkit-mask-image: linear-gradient(to right,
    transparent 0%,
    rgba(0,0,0,1) 18%,
    rgba(0,0,0,1) 82%,
    transparent 100%);
          mask-image: linear-gradient(to right,
    transparent 0%,
    rgba(0,0,0,1) 18%,
    rgba(0,0,0,1) 82%,
    transparent 100%);
  pointer-events: none;
}
/* The ground SVG inside the echo — anchor to the bottom so the hill
   silhouettes sit at the floor of the echo container (like a far
   horizon line). */
.nb-foot-echo .nb-hero-ground {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Evening/night variants get the same dim treatment but slightly
   warmer because the night ground SVG already has darker fills.
   Keeps overall visual weight similar across time-of-day. */
.nb-foot-echo-evening,
.nb-foot-echo-night {
  opacity: 0.28;
}

/* Mobile: hide the echo. The footer is already compact on small
   screens and the echo adds vertical space that doesn't earn its
   keep at that scale. */
@media (max-width: 720px) {
  .nb-foot-echo { display: none; }
}

.footer-inner {
  display: inline-block;
  padding: 0.7rem 2rem;
  border-top: 1px solid var(--rule);
}

.footer-inner p {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.footer-inner a {
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1.5px solid rgba(28,28,26,0.18);
  transition: color 0.15s, border-color 0.15s;
}

.footer-inner a:hover {
  color: var(--ink);
  border-color: var(--ink-mid);
}

/* ────────────────────────────────────────────────────────────────────
   Floating music notes (Spotify widget, while playing)
   ────────────────────────────────────────────────────────────────────
   When the song item has the .song-playing class, notes drift up out
   of its left side, into corkboard space. Each note has a different
   shape, drift path, duration, and starting delay so they cascade
   organically rather than appearing in lockstep.

   Notes are paused by default — animations only run when the parent
   has .song-playing. Browsers automatically pause CSS animations on
   hidden tabs, so no JS bookkeeping needed.

   Positioning: the notes container sits absolutely off the LEFT side
   of the song item, with overflow visible. Notes start near the
   bottom (where the music is "coming from" — near the wave/
   controls row) and drift up-and-leftward into the empty corkboard
   space adjacent to the widget. */

.song-notes {
  position: absolute;
  top: 0;
  left: -90px;
  width: 90px;
  height: 100%;
  pointer-events: none;
  overflow: visible;
  z-index: 2;
}

/* When the song widget is in the rightmost column, notes drift RIGHT
   so they escape into the corkboard margin instead of flying across
   adjacent cards. JS adds .song-notes-right based on actual column
   position; left-drift is the default when the class is absent.

   Note: right offset is 78px not 90px (matching the left offset's
   absolute value). Empirically the right-side notes read as further
   from the widget than the left-side ones at equal offsets — likely
   a combination of the right-drift keyframes pulling notes outward
   harder and the absence of corkboard-margin texture on the right of
   the widget changing perceived spatial relationship. -78px brings
   the right-side cluster visually in line with the left. */
.item-song.song-notes-right .song-notes {
  left: auto;
  right: -78px;
}

.song-note {
  position: absolute;
  bottom: 30%;
  left: 50%;
  width: 16px;
  height: 22px;
  /* Belt-and-braces ceiling for iPad Safari, which has been observed to
     render SVGs without intrinsic width/height attributes at viewport
     scale when the surrounding layout context is non-standard. The SVG
     elements now also carry width/height attributes in markup; this
     max-* clamp catches any edge case where the attributes are also
     ignored. The notes' CSS sizes are already small, so a 30px ceiling
     never crops the intended rendering. */
  max-width: 30px;
  max-height: 30px;
  color: rgba(180, 130, 70, 0.7);
  /* No animation by default. Animations are only assigned inside the
     .song-playing scope below. We can't use animation-play-state:
     paused as a gate, because negative animation-delays render the
     element at the point in the keyframe they'd start at — which for
     our setup means notes appear visible when paused. Skipping the
     animation property entirely keeps notes at the base opacity 0. */
  opacity: 0;
}

.item-song.song-playing .song-note-1,
.mob-spotify-widget.song-playing .song-note-1 {
  animation: song-note-float-1 5s ease-out infinite;
  animation-delay: 0s;
  width: 14px; height: 20px;
}
.item-song.song-playing .song-note-2,
.mob-spotify-widget.song-playing .song-note-2 {
  animation: song-note-float-2 6s ease-out infinite;
  animation-delay: -1.2s;
  width: 20px; height: 22px;
}
.item-song.song-playing .song-note-3,
.mob-spotify-widget.song-playing .song-note-3 {
  animation: song-note-float-3 4.5s ease-out infinite;
  animation-delay: -2.5s;
  width: 12px; height: 16px;
}
.item-song.song-playing .song-note-4,
.mob-spotify-widget.song-playing .song-note-4 {
  animation: song-note-float-4 5.5s ease-out infinite;
  animation-delay: -3.6s;
  width: 14px; height: 20px;
}
.item-song.song-playing .song-note-5,
.mob-spotify-widget.song-playing .song-note-5 {
  animation: song-note-float-5 6.5s ease-out infinite;
  animation-delay: -0.6s;
  width: 11px; height: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .song-note { animation: none !important; opacity: 0 !important; }
}

/* Right-side drift overrides. Each note gets a mirrored keyframe
   (same vertical travel, X-translates flipped sign). Durations and
   delays inherit from the base rules — only the keyframe name swaps. */
.item-song.song-notes-right.song-playing .song-note-1 {
  animation-name: song-note-float-1-right;
}
.item-song.song-notes-right.song-playing .song-note-2 {
  animation-name: song-note-float-2-right;
}
.item-song.song-notes-right.song-playing .song-note-3 {
  animation-name: song-note-float-3-right;
}
.item-song.song-notes-right.song-playing .song-note-4 {
  animation-name: song-note-float-4-right;
}
.item-song.song-notes-right.song-playing .song-note-5 {
  animation-name: song-note-float-5-right;
}

@keyframes song-note-float-1 {
  0%   { opacity: 0;   transform: translate(0, 0)      rotate(-8deg); }
  15%  { opacity: 0.85; }
  85%  { opacity: 0.55; }
  100% { opacity: 0;   transform: translate(8px, -90px) rotate(12deg); }
}
@keyframes song-note-float-2 {
  0%   { opacity: 0;   transform: translate(0, 0)       rotate(-12deg); }
  20%  { opacity: 0.8; }
  80%  { opacity: 0.5; }
  100% { opacity: 0;   transform: translate(-22px, -100px) rotate(-25deg); }
}
@keyframes song-note-float-3 {
  0%   { opacity: 0;   transform: translate(0, 0)       rotate(-5deg); }
  18%  { opacity: 0.85; }
  82%  { opacity: 0.5; }
  100% { opacity: 0;   transform: translate(-6px, -85px)  rotate(8deg); }
}
@keyframes song-note-float-4 {
  0%   { opacity: 0;   transform: translate(0, 0)       rotate(-10deg); }
  25%  { opacity: 0.75; transform: translate(10px, -25px) rotate(-2deg); }
  65%  { opacity: 0.6;  transform: translate(-8px, -65px) rotate(-15deg); }
  100% { opacity: 0;   transform: translate(-18px, -95px) rotate(-20deg); }
}
@keyframes song-note-float-5 {
  0%   { opacity: 0;   transform: translate(0, 0)       rotate(-15deg); }
  20%  { opacity: 0.6; }
  80%  { opacity: 0.35; }
  100% { opacity: 0;   transform: translate(-14px, -80px) rotate(5deg); }
}

/* Right-drift variants — used when the song widget sits in the right
   column (All tab). Mirror images of the left-drift keyframes:
   translate-X values negated, rotation values negated so the note
   wobble feels naturally mirrored. Vertical travel and opacity
   curves are identical to the left versions. */
@keyframes song-note-float-1-right {
  0%   { opacity: 0;   transform: translate(0, 0)       rotate(8deg); }
  15%  { opacity: 0.85; }
  85%  { opacity: 0.55; }
  100% { opacity: 0;   transform: translate(-8px, -90px) rotate(-12deg); }
}
@keyframes song-note-float-2-right {
  0%   { opacity: 0;   transform: translate(0, 0)        rotate(12deg); }
  20%  { opacity: 0.8; }
  80%  { opacity: 0.5; }
  100% { opacity: 0;   transform: translate(22px, -100px) rotate(25deg); }
}
@keyframes song-note-float-3-right {
  0%   { opacity: 0;   transform: translate(0, 0)        rotate(5deg); }
  18%  { opacity: 0.85; }
  82%  { opacity: 0.5; }
  100% { opacity: 0;   transform: translate(6px, -85px)  rotate(-8deg); }
}
@keyframes song-note-float-4-right {
  0%   { opacity: 0;   transform: translate(0, 0)        rotate(10deg); }
  25%  { opacity: 0.75; transform: translate(-10px, -25px) rotate(2deg); }
  65%  { opacity: 0.6;  transform: translate(8px, -65px)   rotate(15deg); }
  100% { opacity: 0;   transform: translate(18px, -95px)  rotate(20deg); }
}
@keyframes song-note-float-5-right {
  0%   { opacity: 0;   transform: translate(0, 0)        rotate(15deg); }
  20%  { opacity: 0.6; }
  80%  { opacity: 0.35; }
  100% { opacity: 0;   transform: translate(14px, -80px) rotate(-5deg); }
}

/* ── Song / Spotify ──────────────────────────────────────── */
.item-song {
  cursor: default;
  position: relative;
  z-index: 3;
}

.song-card {
  display: flex;
  align-items: stretch;
  background: #2a1e0d;
  box-shadow:
    0 2px 4px rgba(0,0,0,0.3),
    0 8px 24px rgba(0,0,0,0.45),
    0 20px 48px rgba(0,0,0,0.25),
    inset 0 1px 0 rgba(200,165,100,0.08),
    inset 0 0 0 1px rgba(200,165,100,0.06);
  transition: box-shadow 0.22s;
  overflow: hidden;
  position: relative;
  z-index: 1;
  min-height: 110px;
}

.item-song:hover .song-card {
  box-shadow:
    0 4px 8px rgba(0,0,0,0.35),
    0 12px 32px rgba(0,0,0,0.5),
    0 24px 56px rgba(0,0,0,0.28),
    inset 0 1px 0 rgba(200,165,100,0.1),
    inset 0 0 0 1px rgba(200,165,100,0.09);
  transform: translateY(-1px);
}

/* Faint ruled lines */
.song-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(to bottom, transparent, transparent 18px, rgba(200,165,100,0.032) 18px, rgba(200,165,100,0.032) 19px);
  pointer-events: none;
  z-index: 0;
}

/* Left art panel — full height, no fixed size */
.song-cover-panel {
  /* Fixed square — art displays without cropping */
  flex-shrink: 0;
  width: 100px;
  height: 100px;
  position: relative;
  overflow: hidden;
  z-index: 2;
  align-self: center;
  margin: 0.6rem 0 0.6rem 0.6rem;
  box-shadow: 0 2px 12px rgba(0,0,0,0.5);
}

.song-cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.song-cover-empty {
  width: 100%;
  height: 100%;
  background: rgba(200,165,100,0.04);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Glow — blurred art bleeds behind panel */
.song-cover-glow {
  position: absolute;
  inset: -12px;
  background-size: cover;
  background-position: center;
  filter: blur(18px) saturate(1.6);
  opacity: 0.28;
  z-index: -1;
}



/* Info column */
.song-info {
  flex: 1;
  min-width: 0;
  padding: 0.55rem 0.75rem 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  position: relative;
  z-index: 1;
}

.song-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.08rem;
}

.song-type-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.43rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(200,165,100,0.38);
}

.song-ext {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.43rem;
  letter-spacing: 0.06em;
  color: rgba(200,165,100,0.25);
  text-decoration: none;
  text-transform: uppercase;
  transition: color 0.15s;
}
.song-ext:hover { color: rgba(200,165,100,0.55); }

.song-title {
  font-family: 'Playfair Display', serif;
  font-size: 0.9rem;
  font-weight: 700;
  color: rgba(238,224,196,0.9);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.song-artist {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.04em;
  color: rgba(200,165,100,0.42);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 0.9rem;
}

/* Progress bar */
.song-progress-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0.2rem 0 0.1rem;
}

.song-progress-bar {
  height: 2px;
  background: rgba(200,165,100,0.1);
  border-radius: 1px;
  overflow: hidden;
}

.song-progress-fill {
  height: 100%;
  background: rgba(200,165,100,0.45);
  border-radius: 1px;
  transition: width 0.9s linear;
}

.song-progress-times {
  display: flex;
  justify-content: space-between;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  color: rgba(200,165,100,0.28);
  letter-spacing: 0.04em;
}

/* Controls */
.song-controls {
  display: flex;
  align-items: center;
  gap: 0.32rem;
  margin-top: auto;
  padding-top: 0.25rem;
}

.song-btn {
  -webkit-appearance: none;
  appearance: none;
  background: rgba(200,165,100,0.08);
  border: 1px solid rgba(200,165,100,0.12);
  border-radius: 3px;
  color: rgba(218,198,158,0.72);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, color 0.12s;
  padding: 0;
  font-size: 0;
  outline: none;
  flex-shrink: 0;
}

.song-btn-prev, .song-btn-next { width: 24px; height: 24px; }

.song-btn-transfer {
  width: 22px;
  height: 22px;
  margin-left: auto;
  color: rgba(200,165,100,0.35);
  background: transparent;
  border-color: transparent;
}
.song-btn-transfer:hover { color: rgba(200,165,100,0.7); background: rgba(200,165,100,0.08); border-color: rgba(200,165,100,0.12); }

/* Like (heart) button — saves the current track to user's Liked Songs.
   The button contains exactly one SVG at any time — JS swaps between
   outline (not liked) and filled (liked). This avoids the Mobile Safari
   quirk where display:none on SVG elements doesn't reliably hide them.
   .song-btn-like-active flips colors only; the icon swap is in JS. */
.song-btn-like {
  width: 22px;
  height: 22px;
  color: rgba(200,165,100,0.35);
  background: transparent;
  border-color: transparent;
}
.song-btn-like:hover { color: rgba(200,165,100,0.7); background: rgba(200,165,100,0.08); border-color: rgba(200,165,100,0.12); }
.song-btn-like.song-btn-like-active {
  color: rgba(200,80,50,0.92); /* warm coral — like + Spotify accent */
}
.song-btn-like.song-btn-like-active:hover {
  color: rgba(200,80,50,1);
  background: rgba(200,80,50,0.1);
  border-color: rgba(200,80,50,0.18);
}
.song-btn-like.song-btn-like-loading {
  animation: song-like-pulse 0.9s ease-in-out infinite;
}
@keyframes song-like-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

.song-btn-play {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: rgba(150,65,35,0.82);
  border-color: rgba(185,90,50,0.2);
  color: rgba(245,232,210,0.92);
  box-shadow: 0 1px 4px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,200,150,0.12);
}

.song-btn:hover { background: rgba(200,165,100,0.16); color: rgba(238,224,196,0.95); }
.song-btn-play:hover { background: rgba(165,72,38,1); }

/* Wave bars */
.song-wave {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 2px;
  height: 20px;
  padding: 0 0.15rem;
}

.song-wave span {
  display: block;
  width: 2.5px;
  height: 3px;
  background: rgba(200,165,100,0.16);
  border-radius: 1.5px;
  transform-origin: center;
}

.song-wave-playing span {
  background: rgba(200,165,100,0.42);
  animation: song-wave-anim 0.85s ease-in-out infinite alternate;
}

.song-wave-playing span:nth-child(odd)  { animation-duration: 0.68s; }
.song-wave-playing span:nth-child(even) { animation-duration: 0.92s; }
.song-wave-playing span:nth-child(3n)   { animation-duration: 0.78s; animation-delay: 0.09s; }
.song-wave-playing span:nth-child(4n)   { animation-duration: 0.62s; animation-delay: 0.05s; }

@keyframes song-wave-anim {
  from { height: 2px; }
  to   { height: 16px; }
}

/* ── Film — YouTube trailer embed ─────────────────────────── */
.item-film { cursor: default; }

.film-embed {
  background: var(--ink);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
  position: relative;
}

.item-film:hover .film-embed { box-shadow: var(--shadow-hover); }

.film-embed iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
}

/* ── Media tag — shared by song and film ─────────────────── */
.media-tag {
  position: absolute;
  top: 10px;
  left: -4px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: rgba(160,60,60,0.88);
  color: rgba(255,255,255,0.92);
  padding: 0.22rem 0.6rem 0.22rem 0.7rem;
  transform: rotate(-1deg);
  z-index: 5;
  pointer-events: none;
}

.media-tag::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: rgba(120,30,30,0.6);
}

.film-embed-meta {
  padding: 0.7rem 0.9rem 0.8rem;
  background: var(--ink);
  border-top: 1px solid rgba(245,244,240,0.07);
}

.film-embed-meta .film-meta {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.54rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(245,244,240,0.4);
  margin-bottom: 0.25rem;
  display: flex;
  gap: 0.6rem;
}

.film-embed-meta h3 {
  font-family: 'Playfair Display', serif;
  font-size: 0.95rem;
  font-weight: 700;
  color: rgba(245,244,240,0.88);
  line-height: 1.2;
}

/* ── Book — library checkout card ──────────────────────────── */
.item-book { cursor: default; }

.book-card {
  background: #f5eed8;
  border: 1px solid rgba(180,155,100,0.25);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  padding: 1rem 1.2rem 1.1rem;
  position: relative;
  overflow: hidden;
}

.book-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 23px,
    rgba(180,155,100,0.18) 23px,
    rgba(180,155,100,0.18) 24px
  );
  pointer-events: none;
}

.item-book:hover .book-card { box-shadow: var(--shadow-hover); }

.book-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(120,80,40,0.45);
  margin-bottom: 0.65rem;
  position: relative;
}

.book-card h3 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.88rem;
  font-weight: 500;
  color: #2a1f0e;
  line-height: 1.4;
  margin-bottom: 0.25rem;
  position: relative;
}

.book-author {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: rgba(42,31,14,0.55);
  letter-spacing: 0.04em;
  position: relative;
}

.book-stamp {
  display: inline-block;
  margin-top: 0.9rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(160,60,60,0.55);
  border: 1.5px solid rgba(160,60,60,0.35);
  border-radius: 3px;
  padding: 0.18rem 0.55rem;
  transform: rotate(-1.5deg);
  position: relative;
}

.book-stamp-returned {
  display: none;
}

/* Background stamp — single stamp, swaps state */
.book-bg-stamp {
  position: absolute;
  bottom: 1rem;
  right: 1rem;
  font-family: 'Special Elite', cursive;
  font-size: 0.92rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(140,60,50,0.18);
  border: 2px solid rgba(140,60,50,0.14);
  border-radius: 2px;
  padding: 0.22rem 0.5rem;
  transform: rotate(7deg);
  pointer-events: none;
  user-select: none;
  line-height: 1.15;
  text-align: center;
}

.book-bg-stamp-returned {
  color: rgba(55,95,55,0.18);
  border-color: rgba(55,95,55,0.14);
  transform: rotate(-5deg);
}

/* Circular finished stamp */
.book-stamp-circular {
  position: absolute;
  bottom: 0.6rem;
  right: 0.6rem;
  width: 88px;
  height: 88px;
  transform: rotate(-8deg);
  pointer-events: none;
  user-select: none;
}

.book-link {
  display: block;
  margin-top: 0.7rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(120,80,40,0.5);
  text-decoration: none;
  border-bottom: 1px solid rgba(120,80,40,0.2);
  padding-bottom: 1px;
  width: fit-content;
  position: relative;
  transition: color 0.15s, border-color 0.15s;
}

.book-link:hover {
  color: rgba(120,80,40,0.85);
  border-color: rgba(120,80,40,0.5);
}

.book-rating {
  font-family: 'Caveat', cursive;
  font-size: 1.1rem;
  color: rgba(160,60,60,0.65);
  margin-top: 0.5rem;
  position: relative;
  letter-spacing: 0.05em;
  display: block;
}

.book-rating {
  font-family: 'Caveat', cursive;
  font-size: 1.1rem;
  color: rgba(160,60,60,0.65);
  margin-top: 0.5rem;
  position: relative;
  letter-spacing: 0.05em;
  display: block;
}

/* ── Reporting trip ticket stub ───────────────────────────── */
.item-trip { cursor: default; }

.ticket {
  background: #e8f2fa;
  border: 1px solid rgba(100,140,180,0.25);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  position: relative;
  overflow: hidden;
}

.item-trip:hover .ticket { box-shadow: var(--shadow-hover); }

/* Blue top band */
.ticket-band {
  height: 6px;
  background: #5b8db8;
  opacity: 0.7;
}

.ticket-body {
  padding: 0.85rem 1.1rem 0.95rem 1.1rem;
  position: relative;
}

/* Perforated left edge */
.ticket-body::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 5px;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0px,
    transparent 6px,
    rgba(100,140,180,0.35) 6px,
    rgba(100,140,180,0.35) 8px
  );
}

/* Torn stub right edge */
.ticket-body::after {
  content: '';
  position: absolute;
  right: 28px; top: 0; bottom: 0;
  border-left: 1px dashed rgba(100,140,180,0.35);
}

.ticket-type {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(40,70,110,0.4);
  margin-bottom: 0.35rem;
}

.ticket-destination {
  font-family: 'Playfair Display', serif;
  font-size: 1.45rem;
  font-weight: 700;
  color: #1a2d42;
  line-height: 1;
  letter-spacing: -0.01em;
  margin-bottom: 0.4rem;
}

.ticket-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 0.45rem;
}

.ticket-dates {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: rgba(40,70,110,0.55);
  letter-spacing: 0.06em;
}

.ticket-number {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(40,70,110,0.22);
  letter-spacing: 0.08em;
}

.ticket-note {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.72rem;
  line-height: 1.5;
  color: rgba(40,70,110,0.55);
  font-style: italic;
  margin-bottom: 0.5rem;
}

.ticket-stamp {
  display: inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(60,100,150,0.45);
  border: 1.5px solid rgba(60,100,150,0.28);
  border-radius: 2px;
  padding: 0.18rem 0.55rem;
  transform: rotate(-1.5deg);
}

.ticket-map {
  width: 100%;
  height: 110px;
  display: block;
  object-fit: cover;
  filter: saturate(0.5) brightness(1.05);
  border-top: 1px solid rgba(100,140,180,0.18);
}

.ticket-map-placeholder {
  width: 100%;
  height: 110px;
  background: rgba(100,140,180,0.1);
  border-top: 1px solid rgba(100,140,180,0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(40,70,110,0.3);
}

/* ── On my mind ───────────────────────────────────────────── */
.item-mind { cursor: pointer; }

.item-mind .mind-card { cursor: pointer; }

.item-mind .mind-card {
  background: #f8f4e8;
  border: 1px solid rgba(28,22,8,0.12);
  border-top: none;
  border-bottom: none;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease, border-left-color 0.22s ease;
  position: relative;
  overflow: hidden;
  padding: 0.75rem 1.2rem 0.9rem 1.2rem;
}

/* Spiral binding suggestion at top */
.mind-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 8px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px,
    transparent 10px,
    rgba(28,28,26,0.08) 10px,
    rgba(28,28,26,0.08) 14px
  );
  border-bottom: 1px solid rgba(28,28,26,0.08);
  z-index: 2;
}



.item-mind:hover .mind-card { box-shadow: var(--shadow-hover); }

/* Linked field notes — those with a piece_id meta — get a forest-green
   left edge in the same color family as the .mind-piece-badge. The
   visual signal is quiet but consistent: scanning the column, your eye
   can immediately separate standalone field notes from notes that are
   already feeding a piece in motion. The 4px width matches the
   scrap-note's left edge so the two card families feel sibling, with
   the color encoding the meaning (brown = scrap, green = linked). */
.item-mind .mind-card.is-piece-linked {
  border-left: 4px solid rgba(74,107,58,0.55);
  padding-left: calc(1.2rem - 3px);
}
.item-mind:hover .mind-card.is-piece-linked {
  border-left-color: rgba(74,107,58,0.85);
}

/* Header strip with red rule below */
.mind-header {
  padding: 0.8rem 0 0.35rem;
  border-bottom: 1px solid rgba(180,60,60,0.18);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
}

/* Wrap label + date together so the flex parent treats them as one
   subgroup, with the piece badge as the other. Without this wrapper,
   three siblings in a justify-content:space-between flex distribute
   themselves across the row — and in a narrow card, the date butts
   up against the FIELD NOTES label without any visible separation. */
.mind-header-meta {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  min-width: 0;
}

/* Ruled lines — Geyer notebook tone */
.mind-card::after {
  content: '';
  position: absolute;
  top: 8px; left: 0; right: 0; bottom: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 21px,
    rgba(100,80,50,0.12) 21px,
    rgba(100,80,50,0.12) 22px
  );
  pointer-events: none;
  z-index: 1;
}

.mind-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.28);
}

.mind-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  color: rgba(28,28,26,0.25);
  letter-spacing: 0.08em;
}

.mind-body {
  padding: 0.9rem 1.4rem 1rem;
  position: relative;
  z-index: 1;
}

.mind-content {
  font-family: 'Special Elite', cursive;
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(28,22,8,0.82);
  overflow: hidden;
}

.mind-content.collapsed {
  max-height: 90px;
  -webkit-mask-image: linear-gradient(to bottom, black 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, black 55%, transparent 100%);
}

.mind-content p,
.mind-content li {
  margin-bottom: 0.5rem;
}

.mind-content p:last-child { margin-bottom: 0; }

.mind-content strong { font-weight: 700; color: rgba(28,28,26,0.9); }
.mind-content em    { font-style: italic; }

.mind-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.28);
  border: none;
  background: none;
  cursor: pointer;
  padding: 0.3rem 0 0;
  display: block;
  position: relative;
  z-index: 1;
}

.mind-torn {
  display: block;
  width: 100%;
  height: 10px;
}

/* ── Saved link — printed page, circled in red ────────────── */
.item-link a {
  text-decoration: none;
  color: inherit;
  display: block;
}

.link-card {
  background: #fdfaf4;
  border: 1px solid rgba(28,28,26,0.1);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
}

.item-link:hover .link-card { box-shadow: var(--shadow-hover); }

.link-print-bar {
  background: rgba(28,28,26,0.04);
  border-bottom: 1px solid rgba(28,28,26,0.08);
  padding: 0.28rem 0.7rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}

.link-domain {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  color: rgba(28,28,26,0.28);
  letter-spacing: 0.04em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.link-print-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  color: rgba(28,28,26,0.2);
  flex-shrink: 0;
}

.link-body {
  padding: 0.7rem 0.9rem 0.8rem;
  position: relative;
}

.link-circle-wrap {
  position: relative;
  margin-bottom: 0.45rem;
}

.link-card h3 {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.8rem;
  font-weight: 400;
  color: rgba(28,28,26,0.82);
  line-height: 1.45;
  position: relative;
  z-index: 1;
}

.link-circle-svg {
  position: absolute;
  inset: -8px -10px;
  width: calc(100% + 20px);
  height: calc(100% + 16px);
  pointer-events: none;
  overflow: visible;
  z-index: 0;
}

.link-note {
  font-family: 'Caveat', cursive;
  font-size: 0.88rem;
  color: rgba(150,65,35,0.7);
  line-height: 1.35;
  transform: rotate(-0.4deg);
  display: block;
  margin-bottom: 0.4rem;
}

.link-ghost-lines {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 0.5rem;
}

.link-ghost-line {
  height: 5px;
  background: rgba(28,28,26,0.07);
  border-radius: 1px;
}

/* ── Highlights: manila folder card ─────────────────────── */
.item-folder { cursor: pointer; }
.item-folder::before { display: none; }

/* Outer wrapper — clip-path on all layers for the folder shape */
.folder-outer {
  position: relative;
}

/* Pages peeking behind */
.folder-back2 {
  position: absolute;
  top: 6px; left: -6px; right: -6px; bottom: -6px;
  background: #ede5d0;
  border: 1px solid rgba(28,28,26,0.07);
  clip-path: polygon(0 16px, 50% 16px, 60% 0, 100% 0, 100% 100%, 0 100%);
  z-index: 0;
}

.folder-back1 {
  position: absolute;
  top: 3px; left: -3px; right: -3px; bottom: -3px;
  background: #f5f0e0;
  border: 1px solid rgba(28,28,26,0.09);
  clip-path: polygon(0 16px, 50% 16px, 60% 0, 100% 0, 100% 100%, 0 100%);
  z-index: 1;
}

.folder-card {
  background: #f8f4ea;
  border: 1px solid rgba(28,28,26,0.12);
  clip-path: polygon(0 16px, 50% 16px, 60% 0, 100% 0, 100% 100%, 0 100%);
  padding: 26px 1.1rem 1rem;
  position: relative;
  z-index: 2;
  box-shadow: 0 2px 6px rgba(28,28,26,0.1), 0 6px 20px rgba(28,28,26,0.09);
  transition: box-shadow 0.22s ease;
}

.item-folder:hover .folder-card {
  box-shadow: 0 8px 24px rgba(28,28,26,0.18), 0 20px 48px rgba(28,28,26,0.14);
}

/* Open state — dashed top edge of the clipped shape */
.item-folder.folder-open .folder-card {
  background: #f5eed8;
}

/* Soft left rule */
.folder-card::before {
  content: '';
  position: absolute;
  left: 0; top: 16px; bottom: 0;
  width: 3px;
  background: rgba(28,28,26,0.14);
}

/* Tape strip — replaces pin */
.folder-tape {
  position: absolute;
  top: -6px; left: 18%;
  width: 64px; height: 14px;
  background: rgba(210,200,175,0.65);
  border-radius: 1px;
  transform: rotate(-0.5deg);
  z-index: 10;
}

.folder-tag {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.3);
  margin-bottom: 0.45rem;
  position: relative; z-index: 1;
}

.folder-title {
  font-family: 'Playfair Display', serif;
  font-size: 1rem;
  font-weight: 700;
  color: #1c1c1a;
  line-height: 1.25;
  margin-bottom: 0.38rem;
  position: relative; z-index: 1;
}

.folder-blurb {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.7rem;
  font-style: italic;
  line-height: 1.55;
  color: rgba(28,28,26,0.48);
  margin-bottom: 0.6rem;
  position: relative; z-index: 1;
}

.folder-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative; z-index: 1;
}

.folder-count {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.28);
}

.folder-toggle-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.38);
  border: none;
  background: none;
  cursor: pointer;
  border-bottom: 1px solid rgba(28,28,26,0.18);
  padding: 0;
  transition: color 0.15s;
}

.item-folder:hover .folder-toggle-btn { color: rgba(28,28,26,0.7); }

/* ── Expanded package board ───────────────────────────────── */
.package-expand-board {
  display: none;
  width: 100%;
  background: rgba(254,252,248,0.5);
  border: 1px solid rgba(28,28,26,0.08);
  padding: 1.5rem;
  margin-top: -0.5rem;
}

.package-expand-board.open {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
}

.package-expand-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

@media (max-width: 639px) {
  .package-expand-board.open { flex-direction: column; padding: 1rem; }
}


/* ── Highlights strip ─────────────────────────────────────── */
/* ── Featured section ────────────────────────────────────── */

/* Wrapper — subtle warm tint, inset from the board edges */
.featured-header {
  width: 100%;
  position: relative;
  background: rgba(210,195,165,0.18);
  border-top: 1px solid rgba(28,28,26,0.07);
  border-bottom: 1px solid rgba(28,28,26,0.07);
  margin-bottom: 2rem;
  padding: 0 2.5rem 0;
}

/* Label row */
.featured-header-bar {
  display: flex;
  align-items: center;
  padding: 0.75rem 0 0.6rem;
}

.featured-header-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* No toggle — always visible */
.featured-toggle { display: none; }

/* Carousel */
.pinned-row {
  width: 100%;
  position: relative;
  overflow: visible;
}

/* Clipping viewport — horizontal scroll hidden, vertical overflow visible */
.pinned-carousel-viewport {
  overflow: clip;
  padding-top: 1.4rem;
  padding-bottom: 5rem; /* contains shadows within clip boundary */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  position: relative;
  /* Fade cards at left/right edges */
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0%,
    black 3%,
    black 97%,
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    transparent 0%,
    black 3%,
    black 97%,
    transparent 100%
  );
}

/* Prevent iOS font inflation on carousel items */
.pinned-row-inner .item,
.pinned-row-inner .item * {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Items sized purely by CSS — JS only sets transform for sliding */
.pinned-row-inner .item {
  /* Width set by JS based on viewport — flex-shrink:0 prevents squishing */
  flex-shrink: 0;
}

.pinned-row-inner {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  transition: transform 0.52s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}

@media (max-width: 639px) {
  .pinned-row-inner {
    transition: transform 0.42s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  }
}

/* No scale on hover inside carousel */
.pinned-row-inner .item:hover {
  transform: translateY(-2px) rotate(0deg) !important;
}

/* Arrow buttons */
.carousel-btn {
  position: absolute;
  top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px;
  background: var(--surface);
  border: 1px solid rgba(28,28,26,0.12);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  transition: box-shadow 0.18s, opacity 0.18s;
  opacity: 0.6;
  padding: 0;
}
.carousel-btn:hover { box-shadow: var(--shadow-md); opacity: 1; }
.carousel-btn.disabled { opacity: 0.18; cursor: default; pointer-events: none; }
.carousel-btn svg { width: 11px; height: 11px; stroke: var(--ink); fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.carousel-btn-prev { left: -14px; }
.carousel-btn-next { right: -14px; }

/* Red corner flag */
.pin-flag {
  position: absolute;
  top: 0; right: 0;
  width: 0; height: 0;
  border-style: solid;
  border-width: 0 28px 28px 0;
  border-color: transparent var(--pin) transparent transparent;
  z-index: 6;
  pointer-events: none;
}

/* Slightly deeper shadow on originals in main board */
.item-pinned .clipping,
.item-pinned .photo-print,
.item-pinned .sticky,
.item-pinned .book-card,
.item-pinned .link-card,
.item-pinned .album-print,
.item-pinned .film-embed,
.item-pinned .song-sleeve,
.item-pinned .ticket {
  box-shadow: var(--shadow-md);
}

/* ── Press badge / bio ────────────────────────────────────── */
.item-bio { cursor: default; }
.item-bio::before { display: none; }

.badge-card {
  width: 100%;
  z-index: 2;
}

.badge-inner {
  background: #f5f0e4;
  border: 1px solid rgba(28,28,26,0.1);
  overflow: hidden;
  position: relative;
  box-shadow:
    0 4px 14px rgba(28,28,26,0.12),
    0 10px 30px rgba(28,28,26,0.08),
    inset 0 0 0 1px rgba(255,255,255,0.55);
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.22s ease;
}

/* Lamination sheen */
.badge-inner::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    -52deg,
    transparent 0px, transparent 20px,
    rgba(255,255,255,0.06) 20px, rgba(255,255,255,0.06) 22px,
    transparent 22px, transparent 42px,
    rgba(255,255,255,0.03) 42px, rgba(255,255,255,0.03) 44px
  );
  pointer-events: none;
  z-index: 10;
}

.item-bio:hover .badge-inner {
  box-shadow:
    0 8px 24px rgba(28,28,26,0.18),
    0 20px 48px rgba(28,28,26,0.12),
    inset 0 0 0 1px rgba(255,255,255,0.55);
}

/* Lanyard hole */
.badge-hole {
  position: absolute;
  top: 7px; left: 50%;
  transform: translateX(-50%);
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid rgba(28,28,26,0.18);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
  z-index: 11;
}

.badge-band {
  height: 3px;
  background: var(--ink);
  flex-shrink: 0;
}

.badge-org-strip {
  padding: 0.3rem 0.55rem 0.25rem;
  border-bottom: 1px solid rgba(28,28,26,0.06);
  flex-shrink: 0;
  text-align: center;
}

.badge-org-name {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.42);
}

/* Photo — square crop, full width */
.badge-photo-area {
  padding: 0.55rem 1.1rem 0.4rem;
  flex-shrink: 0;
}

.badge-photo-frame {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #c8c0a8;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.badge-photo-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.badge-ph-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  opacity: 0.3;
}

/* The HTML hidden attribute must beat the display:flex rule above —
   without this override the placeholder renders alongside the real
   photo (visible as a head/body silhouette band on the right). The
   JS only un-hides the placeholder if the img errors out. */
.badge-ph-placeholder[hidden] {
  display: none !important;
}

.badge-ph-head {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(28,28,26,0.5);
}

.badge-ph-body {
  width: 36px; height: 18px;
  border-radius: 50% 50% 0 0;
  background: rgba(28,28,26,0.35);
}

.badge-cred {
  padding: 0.38rem 0.7rem 0.7rem;
  border-top: 1px solid rgba(28,28,26,0.06);
  flex-shrink: 0;
}

.badge-press {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.45);
  margin-bottom: 0.55rem;
  text-align: center;
}

/* Ghost text lines */
.badge-ghost-lines {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 0.1rem;
}
.badge-ghost-line {
  height: 5px;
  background: rgba(28,28,26,0.07);
  border-radius: 1px;
}


/* ── Bio press badge — desktop only, icons-only on mobile ── */
@media (max-width: 1023px) {
  .item-bio { display: none !important; }
}

/* ── Header social icons — shown when badge not in masonry (<1024px) ── */
.header-socials {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 0.75rem;
}

.header-socials .badge-social-link {
  width: 32px;
  height: 32px;
  background: rgba(28,28,26,0.04);
}

.header-socials .badge-social-link svg {
  width: 13px;
  height: 13px;
}

.badge-role {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mid);
  text-align: left;
}

.badge-beat {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.68rem;
  line-height: 1.45;
  color: var(--ink-soft);
  margin-top: 0.2rem;
  text-align: left;
}

.badge-socials {
  display: flex;
  gap: 5px;
  margin-top: 0.65rem;
  flex-wrap: wrap;
  justify-content: center;
}

.badge-social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  color: var(--social-color, rgba(28,28,26,0.7));
  text-decoration: none;
  border: 1px solid rgba(28,28,26,0.2);
  border-color: color-mix(in srgb, var(--social-color, rgba(28,28,26,0.7)) 35%, transparent);
  border-radius: 3px;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}

.badge-social-link:hover {
  background: rgba(28,28,26,0.06);
  background: color-mix(in srgb, var(--social-color, rgba(28,28,26,0.7)) 10%, transparent);
  border-color: color-mix(in srgb, var(--social-color, rgba(28,28,26,0.7)) 60%, transparent);
  transform: translateY(-1px);
}

.badge-social-link svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}


/* Wrapper stacking year + month labels above first item of period */
.date-divider-wrap {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* ── Carousel more card ──────────────────────────────────── */
.carousel-more-card {
  cursor: pointer;
  flex-shrink: 0;
  align-self: stretch;
  width: var(--carousel-item-w, 240px);
  min-width: var(--carousel-item-w, 240px);
}

.carousel-more-inner {
  border: 1px dashed rgba(28,28,26,0.2);
  background: transparent;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: 180px;
  gap: 1rem;
  padding: 2rem 1.5rem;
  transition: border-color 0.2s, background 0.2s;
}

.carousel-more-card:hover .carousel-more-inner {
  border-color: rgba(28,28,26,0.38);
  background: rgba(28,28,26,0.025);
}

.carousel-more-text {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.3);
  text-align: center;
  line-height: 1.8;
  transition: color 0.2s;
}

.carousel-more-arrow {
  font-size: 1.2rem;
  color: rgba(28,28,26,0.2);
  transition: color 0.2s, transform 0.2s;
  display: block;
  line-height: 1;
}

.carousel-more-card:hover .carousel-more-text {
  color: rgba(28,28,26,0.6);
}

.carousel-more-card:hover .carousel-more-arrow {
  color: rgba(28,28,26,0.5);
  transform: translateX(4px);
}

/* Grab cursor on viewport during drag */
.pinned-carousel-viewport {
  cursor: grab;
}
.pinned-carousel-viewport:active {
  cursor: grabbing;
}

/* ── Infinite scroll sentinel ───────────────────────────── */
.load-sentinel {
  width: 100%;
  height: 1px;
}

/* ── Back to top ─────────────────────────────────────────── */
.back-to-top {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  width: 38px;
  height: 38px;
  background: var(--surface);
  border: 1px solid rgba(28,28,26,0.18);
  box-shadow: var(--shadow-md);
  color: var(--ink-mid);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, box-shadow 0.2s;
  z-index: 9999;
  transform: rotate(-0.5deg);
}
.back-to-top.visible {
  opacity: 1;
  pointer-events: auto;
}
.back-to-top:hover {
  box-shadow: var(--shadow-hover);
  color: var(--ink);
}

/* ── Pull quote items ────────────────────────────────────── */
.quote-card {
  background: #fdf8ee;
  padding: 1.6rem 1.5rem 1.4rem 48px;
  border: 1px solid rgba(180,155,100,0.18);
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
  transition: box-shadow 0.22s ease;
}

/* Ruled lines — index card feel */
.quote-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 23px,
    rgba(180,155,100,0.06) 23px,
    rgba(180,155,100,0.06) 24px
  );
  pointer-events: none;
  z-index: 0;
}

/* Red margin line — like a real index card */
.quote-card::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 38px;
  width: 1.5px;
  background: rgba(185,35,35,0.12);
  z-index: 0;
}

.quote-card > * { position: relative; z-index: 1; }

.item-quote:hover .quote-card {
  box-shadow: var(--shadow-hover);
}

/* Opening quotation mark — large decorative element */
.quote-mark {
  font-family: 'Playfair Display', serif;
  font-size: 4rem;
  line-height: 0.6;
  color: rgba(150,65,35,0.15);
  display: block;
  margin-bottom: 0.2rem;
  margin-left: -0.1rem;
  user-select: none;
}

/* The quote text — elevated, expressive */
.quote-text {
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-weight: 400;
  font-size: 1.05rem;
  line-height: 1.65;
  color: rgba(28,22,8,0.82);
  margin: 0;
}

/* Attribution block */
.quote-attribution {
  margin-top: 1rem;
  padding-top: 0.6rem;
  border-top: none;
  position: relative;
}

/* Hand-drawn separator line above attribution */
.quote-attribution::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 50px;
  height: 2px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='50' height='3'%3E%3Cpath d='M0 1.5 Q6 0.5 12 1.8 Q20 3 28 1.2 Q36 0 44 1.5 Q48 2 50 1.5' fill='none' stroke='rgba(150,65,35,0.25)' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat;
  background-size: 50px 3px;
}

/* Person's name — prominent, handwritten feel */
.quote-attr-name {
  font-family: 'Caveat', cursive;
  font-size: 1.1rem;
  font-weight: 700;
  color: rgba(28,22,8,0.7);
  display: block;
  letter-spacing: 0.01em;
}

/* Role / title — small, understated */
.quote-attr-role {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.35);
  display: block;
  margin-top: 0.15rem;
}

/* Context — publication, date */
.quote-attr-context {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.4rem;
  letter-spacing: 0.08em;
  color: rgba(150,65,35,0.45);
  display: block;
  margin-top: 0.25rem;
}

/* Source link */
.item-quote .read-link {
  display: inline-block;
  margin-top: 0.6rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.45);
  text-decoration: none;
  transition: color 0.15s;
}

.item-quote .read-link:hover {
  color: rgba(150,65,35,0.75);
}



/* ── Package inline expansion ───────────────────────────── */
.clipping-expandable {
  cursor: pointer;
}

.clipping-expand-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.8rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(28,28,26,0.08);
}

.clipping-expand-toggle {
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 0.95rem;
  color: rgba(150,65,35,0.5);
  transition: color 0.15s;
  display: inline;
  cursor: pointer;
}

[data-carousel="1"] .clipping-expand-toggle,
.pkg-child .clipping-expand-toggle {
  display: none;
}

[data-carousel="1"] .clipping-expand-foot,
.pkg-child .clipping-expand-foot {
  border-top: none;
  padding-top: 0;
  margin-top: 0.8rem;
  justify-content: flex-end;
}

.clipping-expand-toggle:hover,
.item-clipping.package-open .clipping-expand-toggle {
  color: rgba(150,65,35,0.85);
}


/* ── Notebook annotation marks ───────────────────────────── */

/* Highlight */
.mann-hl {
  background: linear-gradient(
    104deg,
    rgba(255,210,80,0) 0.9%,
    rgba(255,210,80,0.42) 2.4%,
    rgba(255,210,80,0.38) 70%,
    rgba(255,215,80,0.18) 94%,
    rgba(255,210,80,0) 99%
  );
  border-radius: 2px;
  padding: 0.12em 0.05em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  /* Slightly irregular edges like a real highlighter */
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='20'%3E%3Crect x='0' y='0' width='200' height='20' fill='white' rx='1'/%3E%3C/svg%3E");
}

/* Strikethrough — ballpoint pen, slightly wobbly */
.mann-st {
  text-decoration: none;
  position: relative;
}

.mann-st::after {
  content: '';
  position: absolute;
  left: -1px;
  right: -1px;
  top: 48%;
  height: 3px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='5'%3E%3Cpath d='M0 3 Q10 0.5 25 2.5 Q40 4.5 55 1.5 Q68 0 82 3 Q98 4.8 112 2 Q128 0.5 145 3.2 Q160 4.5 180 2' fill='none' stroke='rgba(30,45,90,0.5)' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 180px 5px;
  pointer-events: none;
}

/* Single underline — pencil, hand-drawn */
.mann-ul {
  text-decoration: none;
  position: relative;
}

.mann-ul::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='5'%3E%3Cpath d='M0 2.5 Q8 1 18 3 Q32 4.5 45 2 Q58 0.5 75 3.2 Q88 4 105 2 Q118 0.8 135 3 Q150 4.2 168 2 Q182 0.5 200 2.8' fill='none' stroke='rgba(180,40,20,0.45)' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 200px 5px;
  pointer-events: none;
}

/* Double underline */
.mann-ul2 {
  text-decoration: underline double;
  text-decoration-color: rgba(180,40,20,0.45);
}

/* Wavy underline */
.mann-wavy {
  text-decoration: underline wavy;
  text-decoration-color: rgba(180,40,20,0.45);
  text-decoration-thickness: 1px;
}

/* Heavy scribble-out */
.mann-scribble {
  position: relative;
  display: inline-block;
}
.mann-scribble-text {
  opacity: 0.3;
}
.mann-scribble-svg {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: visible;
}

/* Circle around phrase */
.mann-circ {
  position: relative;
  display: inline;
  padding: 0;
}
.mann-circ-svg {
  position: absolute;
  top: -6px; left: -6px;
  width: calc(100% + 12px);
  height: calc(100% + 12px);
  pointer-events: none;
  overflow: visible;
}

/* Inline annotation draw-on. The .mann-drawing class is added by JS
   when the annotation enters the viewport for the first time. The
   path's stroke-dasharray and dashoffset are set inline via JS to
   the path's measured length, so the animation reveals the stroke
   from start to end. After the animation completes, JS removes the
   class and the inline styles, leaving the path at its rest state. */
.mann-circ-svg.mann-drawing path,
.mann-scribble-svg.mann-drawing path {
  animation: mann-stroke-draw 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* Stagger the layered paths inside scribbles so they cascade
   rather than drawing all at once. */
.mann-scribble-svg.mann-drawing path:nth-child(2) {
  animation-delay: 0.08s;
}
.mann-scribble-svg.mann-drawing path:nth-child(3) {
  animation-delay: 0.16s;
}
.mann-circ-svg.mann-drawing path:nth-child(2) {
  animation-delay: 0.45s;
}

@keyframes mann-stroke-draw {
  to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .mann-circ-svg.mann-drawing path,
  .mann-scribble-svg.mann-drawing path {
    animation: none;
  }
}

/* Inserted word above line */
.mann-ins {
  display: inline;
  font-family: 'Special Elite', cursive;
  font-size: 0.78rem;
  color: rgba(180,40,20,0.65);
  font-style: normal;
}
.mann-ins-word {
  font-family: 'Special Elite', cursive;
  font-size: 0.78rem;
  color: rgba(180,40,20,0.65);
  border-bottom: 1px dashed rgba(180,40,20,0.35);
  padding-bottom: 1px;
}

/* Margin note with arrow */
.mann-mrg {
  display: inline;
}
.mann-mrg-text {
  font-family: 'Special Elite', cursive;
  font-size: 0.68rem;
  color: rgba(30,45,90,0.65);
  transform: rotate(-1.5deg);
  display: inline-block;
  vertical-align: baseline;
  margin: 0 2px;
  padding: 0 2px;
  border-bottom: 1px dashed rgba(30,45,90,0.3);
}
.mann-mrg-arrow {
  display: none;
}

/* ── Active tags — angle:slug, piece:slug ─────────────────────
   Inline structural markers in note text. Distinct from prose so
   you can see they're a tagging convention, but quiet enough not
   to compete with the writing. Monospace for the "this is data"
   feel; subtle coral underline for "this performs a function." */
.mann-tag {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.78em;
  color: rgba(150,65,35,0.78);
  background: rgba(150,65,35,0.04);
  padding: 0.05em 0.32em;
  border-bottom: 1px dotted rgba(150,65,35,0.45);
  border-radius: 2px;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* Per-prefix tints — angle inherits the baseline coral (set above);
   piece gets a moss green so the two read as distinct dimensions
   when both appear in the same note. Same opacity ladder as the
   baseline (0.78 / 0.04 / 0.45) so visual weight stays equal —
   only the hue differs. */
.mann-tag-piece {
  color: rgba(74,107,58,0.85);
  background: rgba(74,107,58,0.05);
  border-bottom-color: rgba(74,107,58,0.5);
}




/* ── Package overlay ─────────────────────────────────────── */
.pkg-overlay {
  position: fixed;
  inset: 0;
  z-index: 8000;
  overflow-y: auto;
  min-height: 100vh;
  min-height: -webkit-fill-available;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  background: rgba(242,240,234,0.97);
  backdrop-filter: blur(5px) brightness(0.98);
  -webkit-backdrop-filter: blur(5px) brightness(0.98);
  background-image: repeating-linear-gradient(0deg,transparent,transparent 23px,rgba(100,90,75,0.025) 23px,rgba(100,90,75,0.025) 24px),repeating-linear-gradient(90deg,transparent,transparent 23px,rgba(100,90,75,0.025) 23px,rgba(100,90,75,0.025) 24px);
}

.pkg-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

/* Header — feels like the board, not a nav bar */
.pkg-overlay-header {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 1.2rem 2rem 1rem;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid rgba(28,28,26,0.08);
  background: rgba(242,240,234,0.98);
  backdrop-filter: blur(4px);
}

/* Red pin in header */
.pkg-overlay-pin {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #c0392b;
  box-shadow: 0 2px 4px rgba(0,0,0,0.25);
  flex-shrink: 0;
  margin-top: 6px;
}

.pkg-overlay-heading {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.pkg-overlay-pub {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.pkg-overlay-title {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.1rem, 2.5vw, 1.5rem);
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
  margin: 0;
}

/* Back button — handwritten feel */
.pkg-overlay-close {
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 1rem;
  color: rgba(150,65,35,0.6);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  margin-top: 4px;
  transition: color 0.15s;
}

.pkg-overlay-close:hover {
  color: rgba(150,65,35,0.9);
}

/* Content */
.pkg-overlay-board {
  padding: 2rem;
  max-width: 1100px;
  margin: 0 auto;
  isolation: isolate;
}

/* Hero article */
.pkg-overlay-hero {
  display: flex;
  justify-content: center;
  margin-bottom: 2rem;
}

.pkg-overlay-hero .item {
  max-width: 460px;
  width: 100%;
}

.pkg-overlay-hero .item-clipping {
  transform: rotate(-0.3deg) !important;
}

/* Divider */
.pkg-overlay-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.25rem 0 1.5rem;
}

.pkg-overlay-divider span {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

.pkg-overlay-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(28,28,26,0.1);
}

/* Items grid */
.pkg-overlay-grid {
  columns: 3;
  column-gap: 1.5rem;
  position: relative;
}

/* Each item must not break across columns */
.pkg-child {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  display: inline-block;
  width: 100%;
  margin-bottom: 1.5rem;
  opacity: 0;
  transform: translateY(12px) rotate(var(--r, 0deg));
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.22,1,0.36,1);
}

.pkg-child.visible {
  opacity: 1;
  transform: translateY(0) rotate(var(--r, 0deg));
}

@media (max-width: 900px) {
  .pkg-overlay-grid { columns: 2; column-gap: 1rem; }
  .pkg-child { margin-bottom: 1rem; }
}

@media (max-width: 600px) {
  .pkg-overlay-grid { columns: 1; column-gap: 0; }
}

/* Decorative thread SVG */
.pkg-thread-svg {
  position: absolute;
  top: 0; left: 0;
  pointer-events: none;
  overflow: visible;
  z-index: 0;
}




/* ── Source notes (private — package overlay) ──────────────
   Logged-in only section under the public package content. Shows the
   piece-in-progress that produced this article + quotes captured during
   reporting. Visually quieter than the public lanes above — about 85% type
   scale, smaller margins, more subdued palette. Same craft as the public
   surface, but a different register: an editorial note section, not a
   showcase lane. */
.pkg-source-notes {
  margin: 3.5rem 0 2rem;
  padding-top: 2rem;
  border-top: 1px solid rgba(150,65,35,0.22);
  position: relative;
}

/* Subtle terracotta accent rule sitting on top of the section break */
.pkg-source-notes::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 50%;
  transform: translateX(-50%);
  width: 80px;
  height: 3px;
  background: rgba(150,65,35,0.4);
  border-radius: 1px;
}

.pkg-source-notes-head {
  text-align: center;
  margin-bottom: 1.75rem;
}

.pkg-source-notes-eyebrow {
  display: inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
  background: rgba(150,65,35,0.06);
  padding: 0.2rem 0.6rem;
  border: 1px solid rgba(150,65,35,0.18);
  border-radius: 999px;
  margin-bottom: 0.6rem;
}

.pkg-source-notes-title {
  font-family: 'Caveat', cursive;
  font-size: 1.6rem;
  color: rgba(28,22,8,0.85);
  margin: 0 0 0.2rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.pkg-source-notes-sub {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.5);
  margin: 0;
}

/* Layout: piece card on the left, quote stack on the right */
.pkg-source-notes-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 1.75rem;
  align-items: start;
}

/* ── Piece card — cream paper, working-document feel ── */
.pkg-source-piece {
  background: #faf6ed;
  border: 1px solid rgba(28,22,8,0.1);
  border-left: 3px solid rgba(150,65,35,0.4);
  padding: 1rem 1.15rem 0.9rem;
  border-radius: 2px;
  box-shadow: 0 2px 6px rgba(28,22,8,0.04);
  position: relative;
}

.pkg-source-piece-eyebrow {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  margin-bottom: 0.35rem;
}

.pkg-source-piece-title {
  font-family: 'Playfair Display', serif;
  font-size: 1rem;
  color: rgba(28,22,8,0.92);
  margin: 0 0 0.4rem;
  line-height: 1.25;
  font-weight: 700;
}

.pkg-source-piece-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: rgba(28,22,8,0.5);
  margin-bottom: 0.5rem;
}

.pkg-source-piece-status {
  background: rgba(150,65,35,0.08);
  color: rgba(150,65,35,0.85);
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.pkg-source-piece-outlet {
  letter-spacing: 0.04em;
}

.pkg-source-piece-note {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.82rem;
  color: rgba(28,22,8,0.7);
  margin: 0 0 0.5rem;
  line-height: 1.45;
}

.pkg-source-piece-notes {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.65);
  line-height: 1.55;
  margin: 0.5rem 0 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px dotted rgba(28,22,8,0.08);
}

.pkg-source-piece-link {
  display: inline-block;
  margin-top: 0.5rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: rgba(150,65,35,0.7);
  text-decoration: none;
  border-bottom: 1px dotted rgba(150,65,35,0.3);
}
.pkg-source-piece-link:hover {
  color: rgba(150,65,35,1);
  border-bottom-color: rgba(150,65,35,0.7);
}

/* ── Quote stack — small index-card style ── */
.pkg-source-quotes {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.pkg-source-quotes-head {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  margin-bottom: 0.1rem;
}

.pkg-source-quote {
  background: #fdfbf5;
  border: 1px solid rgba(28,22,8,0.07);
  border-left: 2px solid rgba(28,22,8,0.18);
  padding: 0.7rem 0.85rem 0.6rem;
  border-radius: 2px;
}

.pkg-source-quote-text {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.82rem;
  line-height: 1.5;
  color: rgba(28,22,8,0.85);
  font-style: italic;
  margin: 0 0 0.35rem;
}

.pkg-source-quote-text::before {
  content: '\201C';
  font-family: 'Playfair Display', serif;
  color: rgba(150,65,35,0.5);
  font-size: 1.05em;
  margin-right: 0.05em;
  font-style: normal;
}

.pkg-source-quote-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.5);
}

.pkg-source-quote-meta .attr { color: rgba(28,22,8,0.7); }
.pkg-source-quote-meta .date { color: rgba(28,22,8,0.4); }
.pkg-source-quote-meta .ctx  { color: rgba(28,22,8,0.45); font-style: italic; }

.pkg-source-quotes-empty {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.4);
  text-align: center;
  padding: 1rem;
  background: rgba(28,22,8,0.02);
  border-radius: 2px;
}
.pkg-source-quotes-empty p { margin: 0; }

/* Mobile: stack piece on top, quotes below */
@media (max-width: 720px) {
  .pkg-source-notes-inner {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  .pkg-source-notes-title { font-size: 1.35rem; }
  .pkg-source-piece-title { font-size: 0.95rem; }
}

/* ── Beat note — pinned sticky with site tagline ─────────── */
.beat-note {
  cursor: default;
}

.beat-note-inner {
  background: #f0f7e6;
  border: 1px solid rgba(28,28,26,0.08);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.2rem 1.2rem;
  position: relative;
}

.beat-note-inner::before {
  content: '';
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%) rotate(-0.8deg);
  width: 44px;
  height: 13px;
  background: rgba(210,200,175,0.55);
  border-radius: 1px;
}

.beat-note-text {
  font-family: 'Caveat', cursive;
  font-size: 1.05rem;
  line-height: 1.5;
  color: rgba(28,28,26,0.7);
}

/* ── Carousel edge item glow ─────────────────────────────── */
.pinned-row-inner .item.carousel-edge-left,
.pinned-row-inner .item.carousel-edge-right {
  transition: box-shadow 0.3s ease, transform 0.18s ease !important;
}

.pinned-row-inner .item.carousel-edge-left {
  box-shadow:
    -8px 0 18px rgba(28,28,26,0.06),
    var(--shadow-md);
}

.pinned-row-inner .item.carousel-edge-right {
  box-shadow:
    8px 0 18px rgba(28,28,26,0.06),
    var(--shadow-md);
}

/* ── Board annotation SVG layer ─────────────────────────── */
/* SVGs are pixel-sized via attributes (so path coordinates match
   board layout), but CSS dimensions are 100%/100% and positioned
   absolute so they never hold the board open at a stale size when
   masonry shrinks (e.g. user collapses several mind notes). */
.board-ann-svg {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.board-ann-back {
  z-index: 0; /* behind items — thread */
}

.board-ann-svg:not(.board-ann-back) {
  z-index: 10; /* over items — local marks */
}

/* Board needs to be a stacking context */
/* ── Audio appearance — cassette inlay card ─────────────── */
.item-audio { cursor: pointer; }

.item-audio a {
  text-decoration: none;
  color: inherit;
  display: block;
}

/* The card: warm paper, like a cassette inlay */
.audio-card {
  background: #f5f0e2;
  border: 1px solid rgba(28,22,14,0.12);
  border-left: none;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: row;
}

.item-audio:hover .audio-card { box-shadow: var(--shadow-hover); }

/* Dark spine — the left edge of the cassette case */
.audio-spine {
  width: 22px;
  background: #4a3f2e;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 0;
  position: relative;
}

/* Thin accent lines on spine */
.audio-spine::before,
.audio-spine::after {
  content: '';
  position: absolute;
  left: 3px; right: 3px;
  height: 1px;
  background: rgba(245,244,240,0.12);
}
.audio-spine::before { top: 8px; }
.audio-spine::after  { bottom: 8px; }

.audio-spine-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245,244,240,0.3);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/* Inlay content */
.audio-inlay {
  flex: 1;
  padding: 0.75rem 0.9rem 0.8rem;
  min-width: 0;
}

.audio-inlay-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.5rem;
  gap: 0.5rem;
}

.audio-medium {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,14,0.35);
}

.audio-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,14,0.28);
  flex-shrink: 0;
}

/* SVG waveform — etched look, ink on paper */
.audio-wave-svg {
  display: block;
  width: 100%;
  height: 22px;
  margin-bottom: 0.6rem;
  opacity: 0.6;
  transition: opacity 0.18s;
}

.item-audio:hover .audio-wave-svg { opacity: 1; }

.audio-show {
  font-family: 'Special Elite', cursive;
  font-size: 0.88rem;
  line-height: 1.3;
  color: rgba(28,22,14,0.85);
  margin-bottom: 0.2rem;
}

.audio-episode {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.7rem;
  line-height: 1.5;
  color: rgba(28,22,14,0.55);
}

.audio-note {
  font-family: 'Caveat', cursive;
  font-size: 0.88rem;
  color: rgba(150,65,35,0.65);
  line-height: 1.35;
  display: block;
  margin-top: 0.35rem;
}

.audio-listen {
  display: inline-block;
  margin-top: 0.6rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,14,0.35);
  border-bottom: 1px solid rgba(28,22,14,0.15);
  padding-bottom: 1px;
  transition: color 0.15s, border-color 0.15s;
}

.item-audio:hover .audio-listen {
  color: rgba(28,22,14,0.65);
  border-color: rgba(28,22,14,0.35);
}

.audio-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 0.6rem;
}

.audio-play {
  width: 26px;
  height: 26px;
  color: rgba(28,22,14,0.3);
  flex-shrink: 0;
  transition: color 0.15s;
}

.audio-play svg {
  width: 100%;
  height: 100%;
}

.item-audio:hover .audio-play {
  color: rgba(150,65,35,0.65);
}

/* ══════════════════════════════════════════════════════════
   NEWSLETTER ISSUE — folded letter
   ══════════════════════════════════════════════════════════ */
.item-newsletter a { text-decoration: none; color: inherit; display: block; }

.newsletter-card {
  background: #faf8f4;
  border: 1px solid rgba(28,26,14,0.1);
  border-top: 2px solid rgba(28,26,14,0.55);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  position: relative;
  overflow: hidden;
}
.item-newsletter:hover .newsletter-card { box-shadow: var(--shadow-hover); }

/* Masthead — newsletter name and issue, warm and typeset */
.newsletter-masthead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.55rem 1rem 0.45rem;
  border-bottom: 1px solid rgba(28,26,14,0.08);
  gap: 0.5rem;
}
.newsletter-name {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.55);
}
.newsletter-issue {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.06em;
  color: rgba(28,26,14,0.28);
  flex-shrink: 0;
}
.newsletter-body {
  padding: 0.7rem 1rem 0.8rem;
}
.newsletter-subject {
  font-family: 'Playfair Display', serif;
  font-weight: 700;
  font-size: clamp(0.95rem, 2vw, 1.2rem);
  line-height: 1.25;
  color: var(--ink);
  margin-bottom: 0.4rem;
}
.newsletter-snippet {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.76rem;
  line-height: 1.6;
  color: var(--ink-mid);
  margin-top: 0.35rem;
}
.newsletter-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.35rem 1rem 0.42rem;
  border-top: 1px solid rgba(28,26,14,0.07);
}
.newsletter-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.06em;
  color: rgba(28,26,14,0.3);
}
.newsletter-read {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.35);
  transition: color 0.15s;
}
.item-newsletter:hover .newsletter-read { color: var(--ink-mid); }


/* ══════════════════════════════════════════════════════════
   PHOTO ESSAY — magazine spread
   ══════════════════════════════════════════════════════════ */
.item-essay a { text-decoration: none; color: inherit; display: block; }

.essay-card {
  background: #1a1810;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
  position: relative;
}
.item-essay:hover .essay-card { box-shadow: var(--shadow-hover); }

.essay-image {
  width: 100%;
  aspect-ratio: 3 / 2;
  overflow: hidden;
}
.essay-image img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}
.item-essay:hover .essay-image img { transform: scale(1.02); }

.essay-image-placeholder {
  background: #2a2820;
  background-image: repeating-linear-gradient(
    45deg, transparent, transparent 10px,
    rgba(245,244,240,0.03) 10px, rgba(245,244,240,0.03) 11px
  );
}

/* Caption strip overlaid on image bottom */
.essay-caption-strip {
  padding: 0.65rem 0.9rem 0.8rem;
  background: var(--ink);
}
.essay-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.3rem;
}
.essay-pub {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245,244,240,0.4);
}
.essay-type {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(245,244,240,0.25);
}
.essay-title {
  font-family: 'Playfair Display', serif;
  font-weight: 700;
  font-style: italic;
  font-size: 1rem;
  line-height: 1.25;
  color: rgba(245,244,240,0.92);
}
.essay-deck {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.7rem;
  line-height: 1.55;
  color: rgba(245,244,240,0.5);
  margin-top: 0.25rem;
}


/* ══════════════════════════════════════════════════════════
   FIELD NOTE — reporter's torn notebook page
   ══════════════════════════════════════════════════════════ */
.fieldnote-card {
  background: #f5f0e4;
  border: 1px solid rgba(180,155,100,0.22);
  border-left: 4px solid rgba(110,80,30,0.55);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  position: relative;
  overflow: hidden;
}

/* Red margin line — like a legal pad */
.fieldnote-card::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  left: 2.8rem;
  width: 1px;
  background: rgba(180,60,50,0.18);
  pointer-events: none;
  z-index: 0;
}

.item-fieldnote:hover .fieldnote-card { box-shadow: var(--shadow-hover); }

/* Torn right edge */


/* Ruled lines — same amber tone as book card */
.fieldnote-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    transparent, transparent 23px,
    rgba(180,155,100,0.24) 23px, rgba(180,155,100,0.24) 24px
  );
  background-size: 100% 24px;
  background-position: 0 0;
  pointer-events: none;
  z-index: 0;
}

.fieldnote-header,
.fieldnote-body,
.fieldnote-footer { position: relative; z-index: 1; }
.item-fieldnote:hover .fieldnote-card { box-shadow: var(--shadow-hover); }

.fieldnote-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.6rem 1rem 0.45rem 1rem;
  border-bottom: 1px solid rgba(180,155,100,0.2);
  gap: 0.5rem;
  position: relative;
  z-index: 1;
}
.fieldnote-location {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,10,0.6);
  font-weight: 500;
}
.fieldnote-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,10,0.32);
  flex-shrink: 0;
}
.mind-piece-badge {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  color: rgba(74,107,58,0.75);
  text-decoration: none;
  margin-left: auto;
  border-bottom: 1px dotted rgba(74,107,58,0.3);
  padding-bottom: 1px;
}
.mind-piece-badge:hover {
  color: rgba(74,107,58,1);
  border-bottom-color: rgba(74,107,58,0.7);
}

/* Unresolved-slug warning pill — fires when a `piece:<slug>` in the
   note body doesn't resolve to any piece. Same visual family as the
   badge (small monospace, dotted border) but in a muted amber so it
   reads as "attention needed" without being alarming. Used on both
   field notes and scrap notes. */
.mind-piece-warning,
.fieldnote-piece-warning {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  color: rgba(160,95,20,0.78);
  background: rgba(160,95,20,0.05);
  border: 1px dotted rgba(160,95,20,0.4);
  border-radius: 2px;
  padding: 0.05em 0.4em;
  margin-left: auto;
  white-space: nowrap;
}
/* Scrap notes have a footer-label on the left already, so push the
   warning pill toward the actions on the right with the same
   margin-left:auto pattern the field-note badge uses. The footer
   already flexes with space-between, so this keeps the layout tidy
   when the actions group is hidden (logged-out view). */
.fieldnote-footer .fieldnote-piece-warning {
  margin-left: 0.5rem;
}
.fieldnote-body {
  font-family: 'Special Elite', cursive;
  font-size: 0.85rem;
  line-height: 1.65;
  color: rgba(28,22,10,0.68);
  padding: 0.75rem 1rem 1rem;
}

.fieldnote-body p,
.fieldnote-body .mind-p {
  margin: 0 0 0.4rem;
}

.fieldnote-body p:last-child,
.fieldnote-body .mind-p:last-child { margin-bottom: 0; }

/* Footer — "Field note" label + read link */
.fieldnote-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.35rem 1rem 0.42rem;
  border-top: 1px solid rgba(180,155,100,0.18);
  position: relative;
  z-index: 1;
}
.fieldnote-footer-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(120,90,40,0.45);
}
/* Torn bottom edge — sits outside card, overlaps its bottom border */
.fieldnote-tear {
  display: block;
  width: 100%;
  height: 22px;
  margin-top: -2px;
  position: relative;
  z-index: 1;
  filter: drop-shadow(0 3px 4px rgba(28,26,14,0.1));
}

.fieldnote-scratches { display: none; }


/* ══════════════════════════════════════════════════════════
   SOURCE DOCUMENT — bureaucratic form
   ══════════════════════════════════════════════════════════ */
.item-source a { text-decoration: none; color: inherit; display: block; }

.source-card {
  background: #f4f2ee;
  border: 1px solid rgba(28,26,14,0.12);
  border-top: none;
  border-left: 4px solid rgba(28,26,14,0.55);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  font-family: 'IBM Plex Mono', monospace;
  position: relative;
}

/* Perforated top edge — like a form torn from a pad */
.source-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: repeating-linear-gradient(
    90deg,
    rgba(28,26,14,0.25) 0px, rgba(28,26,14,0.25) 4px,
    transparent 4px, transparent 10px
  );
}

.item-source:hover .source-card { box-shadow: var(--shadow-hover); }

.source-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.7rem 1rem 0.35rem;
  gap: 0.5rem;
  border-bottom: 1px solid rgba(28,26,14,0.1);
}
.source-type-label {
  font-size: 0.46rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.55);
}
.source-ref {
  font-size: 0.42rem;
  letter-spacing: 0.06em;
  color: rgba(28,26,14,0.3);
  flex-shrink: 0;
}
.source-rule {
  height: 1px;
  background: rgba(28,26,14,0.08);
  margin: 0 1rem;
}
.source-body {
  padding: 0.65rem 1rem 0.5rem;
}
.source-title {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1.45;
  color: rgba(28,26,14,0.88);
  margin-bottom: 0.3rem;
}
.source-org {
  font-size: 0.5rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.4);
  margin-bottom: 0.2rem;
}
/* Note — personal scrawl, small and secondary */
.source-note {
  font-family: 'Caveat', cursive;
  font-size: 0.78rem;
  color: rgba(150,65,35,0.5);
  margin-top: 0.5rem;
  padding-top: 0.4rem;
  border-top: 1px dashed rgba(28,26,14,0.08);
  display: block;
}
/* Classification stamp */
.source-stamp {
  position: absolute;
  bottom: 2.8rem;
  right: 0.8rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(160,40,30,0.5);
  border: 1.5px solid rgba(160,40,30,0.35);
  padding: 0.18rem 0.45rem;
  transform: rotate(2.5deg);
  pointer-events: none;
  white-space: nowrap;
}

/* Redaction bars */
.source-redactions {
  padding: 0.4rem 1rem 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.source-redact {
  height: 6px;
  background: rgba(28,26,14,0.75);
  border-radius: 1px;
}
.source-redact-sm { height: 4px; }
.source-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 1rem 0.55rem;
  margin-top: 0.5rem;
  border-top: 1px solid rgba(28,26,14,0.08);
}
.source-date {
  font-size: 0.42rem;
  letter-spacing: 0.08em;
  color: rgba(28,26,14,0.3);
}
.source-access {
  font-size: 0.46rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.4);
  transition: color 0.15s;
}
.item-source:hover .source-access { color: rgba(28,26,14,0.7); }


/* ══════════════════════════════════════════════════════════
   AWARD — embossed seal card
   ══════════════════════════════════════════════════════════ */
.item-award a { text-decoration: none; color: inherit; display: block; }

.award-card {
  background: #faf5e4;
  border: 1px solid rgba(139,105,20,0.18);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  padding: 1rem 1.1rem 1rem;
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
  position: relative;
  overflow: hidden;
}
.award-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom, transparent, transparent 23px,
    rgba(139,105,20,0.06) 23px, rgba(139,105,20,0.06) 24px
  );
  pointer-events: none;
}
.item-award:hover .award-card { box-shadow: var(--shadow-hover); }

.award-seal-wrap {
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}
.award-seal {
  width: 64px;
  height: 64px;
  display: block;
}
.award-body {
  flex: 1;
  min-width: 0;
  position: relative;
  z-index: 1;
}
.award-org {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(139,105,20,0.6);
  margin-bottom: 0.3rem;
}
.award-title {
  font-family: 'Playfair Display', serif;
  font-weight: 700;
  font-size: 0.92rem;
  line-height: 1.3;
  color: rgba(28,22,10,0.88);
  margin-bottom: 0.2rem;
}
.award-category {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.68rem;
  color: rgba(28,22,10,0.5);
  margin-bottom: 0.25rem;
}
.award-note {
  font-family: 'Caveat', cursive;
  font-size: 0.85rem;
  color: rgba(150,65,35,0.6);
  margin-top: 0.3rem;
}


/* ══════════════════════════════════════════════════════════
   DATA / INTERACTIVE — sparkline card
   ══════════════════════════════════════════════════════════ */
.item-data a { text-decoration: none; color: inherit; display: block; }

.data-card {
  background: #f5f0e0;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease;
  overflow: hidden;
}
.item-data:hover .data-card { box-shadow: var(--shadow-hover); }

.data-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.55rem 1rem 0.3rem;
  gap: 0.5rem;
}
.data-type-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.6);
}
.data-pub {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}
.data-sparkline {
  display: block;
  width: 100%;
  height: 30px;
  padding: 0 1rem;
}
.data-body {
  padding: 0.3rem 1rem 0.5rem;
}
.data-title {
  font-family: 'Playfair Display', serif;
  font-weight: 700;
  font-size: clamp(0.95rem, 2vw, 1.2rem);
  line-height: 1.25;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
.data-deck {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.74rem;
  line-height: 1.6;
  color: var(--ink-mid);
}
.data-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.4rem 1rem 0.5rem;
  border-top: 1px solid rgba(28,28,26,0.07);
}
.data-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}
.data-read {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color 0.15s;
}
.item-data:hover .data-read { color: var(--ink); }


/* ══════════════════════════════════════════════════════════
   LANGUAGE FLAG — on article clippings
   ══════════════════════════════════════════════════════════ */
.article-lang-flag {
  display: inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: rgba(28,28,26,0.08);
  color: rgba(28,28,26,0.55);
  padding: 0.1rem 0.3rem;
  border-radius: 2px;
  margin-left: 0.3rem;
  vertical-align: middle;
}

.article-original-title {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.7rem;
  color: var(--ink-soft);
  margin-bottom: 0.4rem;
  margin-top: -0.2rem;
}

/* ── To-Do list ──────────────────────────────────────────── */
.todo-card {
  background: #f6efde;
  border: 1px solid rgba(28,26,14,0.1);
  border-top: none;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s ease, background 0.22s ease;
  position: relative;
  overflow: hidden;
}

/* Inbox treatment matches other todo cards — solid cream paper fill.
   An earlier iteration set this to transparent on the theory that the
   Inbox is the desk itself rather than material on it. That worked
   when the page substrate was always a single light cream tone, but
   the time-of-day hero wash now extends dark colors down into the
   upper page area (especially at night, when the wash is near-black).
   Transparent then = dark sky bleeding through the inbox text. Back
   to cream paper so the inbox stays legible at every time of day.

   Hierarchy: the Inbox is the centre-of-gravity card on the desk —
   it's what gets opened first and acted on most often. Other cards
   are reference material fanned out around it. To make this read
   visually:

   1. Warmer paper colour (#fbf6e8 vs default #f6efde). The default
      already reads as warm cream; the inbox sits a notch whiter and
      brighter, the way the active page on a real desk is the one
      catching the most light.
   2. Heavier shadow (--shadow-md vs the default --shadow-sm). Lifts
      the card visually so it feels a few millimetres above the desk
      surface, like a notepad placed on top of other papers.
   3. Cancel rotation (--r: 0deg). The masonry randomly rotates cards
      ±1° for the scatter-on-desk feel. The inbox sits flat — front
      and centre, not part of the scatter.
   4. Tag chips hidden by default. The .todo-tag-chip elements in the
      header (#sdgs, #fertilizer, #admin, #cormorants in the screenshot)
      are valuable for filter-by-tag but read as visual noise when
      scanning "what do I need to do today." Hover or focus reveals
      them. Keeps them discoverable, lets the at-a-glance view stay
      legible. */
.item-todo.is-inbox {
  --r: 0deg;
}
.item-todo.is-inbox .todo-card {
  background: #fbf6e8;
  box-shadow: var(--shadow-md);
}
.item-todo.is-inbox .todo-tags {
  opacity: 0;
  transition: opacity 0.18s ease;
  pointer-events: none;
}
.item-todo.is-inbox:hover .todo-tags,
.item-todo.is-inbox:focus-within .todo-tags {
  opacity: 1;
  pointer-events: auto;
}
/* Touch devices have no hover, so the reveal-on-hover gesture is
   inaccessible. Keep chips visible there — losing a 1-line scan
   benefit is a fair trade for not orphaning a feature. */
@media (hover: none) and (pointer: coarse) {
  .item-todo.is-inbox .todo-tags {
    opacity: 1;
    pointer-events: auto;
  }
}

/* Same ruled lines and spiral binding as mind item */
.todo-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 8px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px, transparent 10px,
    rgba(28,28,26,0.08) 10px, rgba(28,28,26,0.08) 14px
  );
  border-bottom: 1px solid rgba(28,28,26,0.08);
  z-index: 2;
}

.todo-card::after {
  content: '';
  position: absolute;
  top: 8px; left: 0; right: 0; bottom: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 21px,
    rgba(100,80,50,0.12) 21px,
    rgba(100,80,50,0.12) 22px
  );
  pointer-events: none;
  z-index: 1;
}

.todo-header {
  padding: 0.9rem 1.2rem 0.4rem;
  border-bottom: 1px solid rgba(180,60,60,0.18);
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.todo-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.32);
}

/* Card-level tag chips — shown in the to-do header for cards where
   individual items are structured rows rather than prose, so there's
   no inline body to render hashtags in. Each chip is a clickable
   .hashtag-link (same href + click handling as inline ones) with
   slight visual differentiation: a touch larger, light pill backing
   so they read as discrete chips rather than free-floating text. */
.todo-tags {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-left: auto;
  margin-right: 0.6rem;
  align-items: center;
}
.todo-tag-chip {
  font-size: 0.62rem;
  padding: 1px 6px;
  border-bottom: none;
  background: rgba(120,80,30,0.07);
  border-radius: 2px;
  letter-spacing: 0.01em;
  font-family: 'IBM Plex Mono', monospace;
  color: rgba(120,80,30,0.75);
  white-space: nowrap;
}
.todo-tag-chip:hover {
  background: rgba(150,65,35,0.12);
  color: rgba(150,65,35,0.95);
}

.todo-list {
  list-style: none;
  padding: 0.6rem 1.2rem 0.9rem;
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.todo-item {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  cursor: pointer;
  user-select: none;
}

.todo-check {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  border: 1.5px solid rgba(28,26,14,0.22);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  top: 1px;
  transition: border-color 0.15s;
}

.todo-check svg {
  width: 12px;
  height: 12px;
  display: block;
}

.todo-item:hover .todo-check {
  border-color: rgba(150,65,35,0.5);
}

.todo-text {
  font-family: 'Special Elite', cursive;
  font-size: 0.85rem;
  line-height: 1.5;
  color: rgba(28,22,8,0.78);
  transition: color 0.2s, text-decoration 0.2s;
  flex: 1;
  min-width: 0;
}

/* Checked state — crossed off */
.todo-checked .todo-check {
  border-color: rgba(150,65,35,0.4);
}

.todo-checked .todo-text {
  text-decoration: line-through;
  text-decoration-color: rgba(150,65,35,0.45);
  text-decoration-thickness: 1.5px;
  color: rgba(28,22,8,0.38);
}

/* ── Private item indicator ──────────────────────────────── */
.item-private-lock {
  position: absolute;
  bottom: 1.1rem;
  right: 0.6rem;
  width: 10px;
  height: 12px;
  color: rgba(28,26,14,0.18);
  z-index: 20;
  pointer-events: none;
}

.item-private-lock svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ── Bio overlay ─────────────────────────────────────────── */
.bio-overlay {
  position: fixed;
  inset: 0;
  z-index: 8000;
  overflow-y: auto;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  background: rgba(242,240,234,0.97);
  backdrop-filter: blur(5px) brightness(0.98);
  -webkit-backdrop-filter: blur(5px) brightness(0.98);
  background-image:
    repeating-linear-gradient(0deg, transparent, transparent 23px, rgba(100,90,75,0.048) 23px, rgba(100,90,75,0.048) 24px),
    repeating-linear-gradient(90deg, transparent, transparent 23px, rgba(100,90,75,0.032) 23px, rgba(100,90,75,0.032) 24px);
}

.bio-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.bio-overlay-header {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 1.2rem 2rem 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  border-bottom: 1px solid rgba(28,28,26,0.08);
  background: rgba(242,240,234,0.98);
  backdrop-filter: blur(4px);
}

.bio-overlay-pin {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--pin);
  box-shadow: 0 2px 4px rgba(0,0,0,0.25);
  flex-shrink: 0;
}

.bio-overlay-org {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  flex: 1;
}

.bio-overlay-close {
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 1rem;
  color: rgba(150,65,35,0.6);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: color 0.15s;
}

.bio-overlay-close:hover { color: rgba(150,65,35,0.9); }

.bio-overlay-body {
  max-width: 760px;
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
}

.bio-overlay-credential {
  background: #faf8f2;
  border: 1px solid rgba(28,28,26,0.1);
  box-shadow: var(--shadow-md);
  margin-bottom: 2rem;
  overflow: hidden;
}

.bio-overlay-credential-band {
  background: #1a1810;
  padding: 0.45rem 1.4rem;
  display: flex;
  align-items: center;
}

.bio-overlay-credential-org {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245,244,240,0.5);
}

.bio-overlay-credential-inner {
  display: flex;
  gap: 2rem;
  padding: 1.5rem 1.4rem;
}

.bio-overlay-credential-left {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}

.bio-overlay-photo-wrap { flex-shrink: 0; }

.bio-overlay-photo {
  width: 100px;
  height: 120px;
  object-fit: cover;
  object-position: top;
  display: block;
  box-shadow: var(--shadow-sm);
}

.bio-overlay-press-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.3);
  border: 1px solid rgba(28,28,26,0.15);
  padding: 0.15rem 0.4rem;
}

.bio-overlay-credential-right {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.3rem;
}

.bio-overlay-name {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.3rem, 3vw, 1.8rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--ink);
  margin-bottom: 0.15rem;
}

.bio-overlay-role {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mid);
}

.bio-overlay-beat {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  font-style: italic;
  color: rgba(28,28,26,0.58);
  line-height: 1.5;
}

.bio-overlay-year {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
}

.bio-overlay-socials {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.bio-overlay-social {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.06em;
  color: var(--social-color, var(--ink-mid));
  text-decoration: none;
  padding: 0.28rem 0.65rem;
  border: 1px solid rgba(28,28,26,0.12);
  background: rgba(28,28,26,0.03);
  transition: background 0.15s, border-color 0.15s;
}

.bio-overlay-social:hover {
  background: rgba(28,28,26,0.07);
  border-color: rgba(28,28,26,0.2);
}

.bio-overlay-pubs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid rgba(28,28,26,0.08);
}

.bio-overlay-pub-chip {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,28,26,0.55);
  padding: 0.2rem 0.55rem;
  background: rgba(28,28,26,0.04);
  border: 1px solid rgba(28,28,26,0.1);
}

.bio-overlay-about {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.92rem;
  line-height: 1.75;
  color: rgba(28,28,26,0.8);
}

.bio-overlay-about p {
  margin-bottom: 1.2em;
}

.bio-overlay-about p:last-child { margin-bottom: 0; }

@media (max-width: 600px) {
  .bio-overlay-credential-inner { flex-direction: column; gap: 1.2rem; }
  .bio-overlay-credential-left { flex-direction: row; align-items: center; }
  .bio-overlay-photo { width: 80px; height: 96px; }
  .bio-overlay-body { padding: 2rem 1.25rem 4rem; }
}

/* ── About page ──────────────────────────────────────────── */
.about-page {
  max-width: 1100px;
  margin: 0 auto;
  padding: 3rem 2.5rem 6rem;
  position: relative;
  overflow: hidden;
}

.about-ann-svg {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}

.about-layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 5rem;
  align-items: start;
  position: relative;
  z-index: 1;
}

/* Badge column — press badge at natural size, slightly rotated */
.about-badge-col {
  position: sticky;
  top: 5rem;
}

.about-badge-wrap {
  transform: rotate(-1.5deg);
  display: block;
  width: 100%;
}

/* Override board-item hidden rules — badge always visible on about
   page, regardless of any .pending / .hidden / display:none rules
   that target .item or .item-bio elsewhere. The badge is rendered
   directly via PHP here, not via the corkboard's JS pipeline, so it
   never receives the .visible class that normally swaps from
   opacity:0 to opacity:1 on corkboard items. We explicitly assert
   the visible state. */
.about-badge-wrap.item-bio {
  display: block !important;
  opacity: 1 !important;
  visibility: visible !important;
  transform: rotate(-1.5deg);
  position: relative;
  z-index: 2;
}
.about-badge-wrap.item-bio .badge-card,
.about-badge-wrap.item-bio .badge-inner,
.about-badge-wrap.item-bio .badge-photo-area,
.about-badge-wrap.item-bio .badge-photo-frame {
  opacity: 1 !important;
  visibility: visible !important;
}

/* Make badge photo taller on about page */
.about-badge-wrap .badge-photo-frame {
  aspect-ratio: 3 / 4;
}

/* Text column */
.about-text-col {
  padding-top: 0.5rem;
}

.about-text-inner {
  position: relative;
}

.about-text-header {
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid rgba(28,28,26,0.1);
}

.about-name {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: 0.5rem;
}

.about-role {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mid);
  margin-bottom: 0.2rem;
}

.about-year {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: var(--ink-soft);
}

/* About body text — Baskerville, readable, with annotation support */
.about-text-body {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.96rem;
  line-height: 1.82;
  color: rgba(28,28,26,0.82);
  margin-bottom: 2.5rem;
  position: relative;
  /* Ruled lines like the mind item */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 29px,
    rgba(100,80,50,0.07) 29px,
    rgba(100,80,50,0.07) 30px
  );
  padding: 0 0 0.5rem;
}

.about-text-body p {
  margin-bottom: 1.6em;
  position: relative;
  z-index: 1;
}

/* H2 — section heading, newspaper style */
.about-text-body h2 {
  font-family: 'Playfair Display', serif;
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
  margin: 2.2em 0 0.7em;
  padding-bottom: 0.45em;
  border-bottom: 1px solid rgba(28,28,26,0.12);
  position: relative;
  z-index: 1;
}

/* H3 — dateline / byline style */
.about-text-body h3 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mid);
  margin: 2em 0 0.6em;
  position: relative;
  z-index: 1;
}

/* H4 — handwritten marginal label */
.about-text-body h4 {
  font-family: 'Caveat', cursive;
  font-size: 1.1rem;
  font-weight: 700;
  color: rgba(150,65,35,0.7);
  margin: 1.8em 0 0.4em;
  position: relative;
  z-index: 1;
}

.about-text-body p:last-child { margin-bottom: 0; }

/* Social links */
.about-socials {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(28,28,26,0.08);
}

.about-social-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--social-color, var(--ink-mid));
  text-decoration: none;
  padding: 0.3rem 0.75rem;
  border: 1px solid rgba(28,28,26,0.12);
  background: rgba(28,28,26,0.03);
  transition: background 0.15s, border-color 0.15s;
}

.about-social-link:hover {
  background: rgba(28,28,26,0.07);
  border-color: rgba(28,28,26,0.2);
}

.about-social-link svg { flex-shrink: 0; }

/* Responsive */
@media (max-width: 900px) {
  .about-layout {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
  .about-badge-col {
    position: static;
    display: flex;
    justify-content: center;
  }
  .about-badge-wrap {
    max-width: 200px;
  }
}

@media (max-width: 600px) {
  .about-page { padding: 2rem 1.25rem 5rem; }
  .about-badge-wrap { max-width: 220px; }
}

/* ── Inline editing ──────────────────────────────────────── */

/* Edit pencil button — appears on hover when logged in */
.inline-edit-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 22px;
  height: 22px;
  background: rgba(245,242,234,0.9);
  border: 1px solid rgba(28,26,14,0.12);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s;
  z-index: 30;
  color: rgba(28,26,14,0.45);
  padding: 0;
}

.inline-edit-btn svg {
  width: 12px;
  height: 12px;
  display: block;
}

.item:hover .inline-edit-btn { opacity: 1; }
.item-editing .inline-edit-btn { opacity: 1; color: rgba(150,65,35,0.7); }

/* Edit zone — sits inside the card, same paper surface */
.inline-edit-zone {
  padding: 0.5rem 0.3rem 0.4rem;
  position: relative;
  z-index: 5;
}

/* Edit bar — label + actions */
.inline-edit-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  padding-bottom: 0.35rem;
  padding-right: 0.2rem;
  border-bottom: 1px solid rgba(180,60,60,0.15);
}

.inline-edit-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.3);
}

.inline-edit-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.inline-edit-err {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(160,40,30,0.7);
}

.inline-edit-cancel,
.inline-edit-save {
  font-family: 'Caveat', cursive;
  font-size: 0.9rem;
  font-weight: 700;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  transition: color 0.12s;
}

.inline-edit-cancel { color: rgba(28,26,14,0.35); }
.inline-edit-cancel:hover { color: rgba(28,26,14,0.65); }
.inline-edit-save { color: rgba(55,95,55,0.65); }
.inline-edit-save:hover { color: rgba(55,95,55,0.9); }

/* Title input for todo */
.inline-edit-title {
  width: 100%;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,26,14,0.5);
  background: transparent;
  border: none;
  border-bottom: 1px dashed rgba(28,26,14,0.15);
  outline: none;
  padding: 0.15rem 0;
  margin-bottom: 0.5rem;
  display: block;
}

/* Textarea — same paper feel */
.inline-edit-ce {
  width: 100%;
  min-height: 80px;
  font-family: 'Special Elite', cursive;
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(28,22,8,0.82);
  background: transparent;
  border: none;
  outline: none;
  display: block;
  caret-color: rgba(150,65,35,0.8);
  word-wrap: break-word;
  white-space: pre-wrap;
}

/* Paragraph spacing when typing — browsers create <div> on Enter */
.inline-edit-ce div,
.inline-edit-ce p {
  margin-top: 0.4em;
}

.inline-edit-ce div:first-child,
.inline-edit-ce p:first-child {
  margin-top: 0;
}

.inline-edit-ce:empty::before {
  content: attr(data-placeholder);
  color: rgba(28,22,8,0.25);
  pointer-events: none;
  font-style: italic;
  white-space: pre;
}

.inline-edit-ce::selection,
.inline-edit-ce *::selection {
  background: rgba(150,65,35,0.15);
}

.fieldnote-edit-ce { font-family: 'Courier New', monospace; font-size: 0.83rem; }
.todo-edit-ce { font-family: 'Special Elite', cursive; font-size: 0.86rem; }

/* Match the padding of the body they replace */
.mind-edit-ce      { padding: 0.9rem 1.4rem 1rem; }
.fieldnote-edit-ce { padding: 0.75rem 1rem 1rem; }
.todo-edit-ce      { padding: 0.5rem 1rem 0.6rem; }

.inline-edit-hint {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.1em;
  color: rgba(28,26,14,0.25);
  margin-top: 0.35rem;
}


/* Save confirmation flash */
.inline-save-confirm {
  position: absolute;
  bottom: 8px;
  right: 8px;
  font-family: 'Caveat', cursive;
  font-size: 0.9rem;
  font-weight: 700;
  color: rgba(55,95,55,0.7);
  pointer-events: none;
  animation: inline-confirm-fade 1.8s ease forwards;
}

@keyframes inline-confirm-fade {
  0%   { opacity: 0; transform: translateY(4px); }
  20%  { opacity: 1; transform: translateY(0); }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Editing state — subtle highlight on the item */
.item-editing {
  z-index: 100;
}

.item-editing .mind-card,
.item-editing .fieldnote-card,
.item-editing .todo-card {
  box-shadow: 0 8px 32px rgba(28,22,8,0.18), 0 2px 8px rgba(28,22,8,0.1);
}

/* ── Annotation heading (## syntax) ─────────────────────── */
.mann-heading {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  border-bottom: 1px solid rgba(100,80,50,0.18);
  padding-bottom: 0.2em;
  margin: 0.9em 0 0.45em;
}

/* Error toast variant */
.inline-save-error {
  color: rgba(160,40,30,0.75) !important;
}

/* Just-saved flash */
.item-just-saved .mind-card,
.item-just-saved .fieldnote-card,
.item-just-saved .todo-card {
  transition: box-shadow 0.4s ease;
  box-shadow: 0 0 0 2px rgba(55,95,55,0.25), var(--shadow-md) !important;
}

/* Todo heading item — no checkbox, just the heading */
.todo-item-heading {
  display: block;
  padding: 0;
  cursor: default;
  margin-top: 0.4rem;
}

.todo-item-heading .mann-heading {
  margin-top: 0.2em;
}

/* ── Notes / Notebook tab — logged-in only ───────────────── */
.filter-btn-notes {
  border-style: dashed;
  opacity: 0.75;
}

.filter-btn-notes:hover,
.filter-btn-notes.active {
  opacity: 1;
  border-style: solid;
}

/* Workflow tabs (Pieces / Quotes / Links) — the private editorial
   workspace tools that feed into pieces. Distinguished from Notebook
   (the public-facing writing surface) with a subtle terracotta accent.
   Notebook stays in regular ink since it serves a different purpose.
   Border kept low-contrast so visual weight matches the public filter
   buttons; the terracotta text alone carries the distinction. */
.filter-btn-workflow {
  color: rgba(150,65,35,0.75);
  border-color: rgba(150,65,35,0.22);
}
.filter-btn-workflow:hover {
  color: rgba(150,65,35,1);
  border-color: rgba(150,65,35,0.5);
}
.filter-btn-workflow.active {
  color: rgba(150,65,35,1);
  border-color: rgba(150,65,35,0.7);
  background: rgba(150,65,35,0.06);
}

/* ── Desk calendar ───────────────────────────────────────── */
.item-calendar {
  cursor: default;
  position: relative;
  z-index: 4;
  /* overflow visible so fanned pages show, but margin keeps space below */
  overflow: visible;
  margin-bottom: 8px;
}

/* Physical page layers — fanning slightly to the sides, not downward */
.cal-page {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  border: 1px solid rgba(28,22,8,0.1);
}

.cal-page-1 {
  background: #f2ede0;
  transform: rotate(1.2deg);
  transform-origin: top center;
  z-index: 1;
  box-shadow: 2px 3px 6px rgba(28,22,8,0.07);
}

.cal-page-2 {
  background: #ede8d8;
  transform: rotate(2.2deg);
  transform-origin: top center;
  z-index: 0;
  box-shadow: 3px 4px 8px rgba(28,22,8,0.06);
}

.cal-page-3 {
  background: #e6e0cc;
  transform: rotate(3.2deg);
  transform-origin: top center;
  z-index: -1;
  box-shadow: 4px 5px 10px rgba(28,22,8,0.05);
}

/* ── Stack-paper depth primitive ──────────────────────────
   Reusable version of the page-fanning effect from the original
   calendar widget. Drop three absolutely-positioned .stack-paper
   divs inside a position:relative container with overflow:visible,
   ahead of the card content. Each rotates progressively more and
   sits one layer deeper in z-order. The container needs
   `overflow: visible` and some margin-bottom so the fanned edges
   show without clipping the next item. */
.stack-paper {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  border: 1px solid rgba(28,22,8,0.1);
}
.stack-paper-1 {
  background: #f2ede0;
  transform: rotate(1.2deg);
  transform-origin: top center;
  z-index: 1;
  box-shadow: 2px 3px 6px rgba(28,22,8,0.07);
}
.stack-paper-2 {
  background: #ede8d8;
  transform: rotate(2.2deg);
  transform-origin: top center;
  z-index: 0;
  box-shadow: 3px 4px 8px rgba(28,22,8,0.06);
}
.stack-paper-3 {
  background: #e6e0cc;
  transform: rotate(3.2deg);
  transform-origin: top center;
  z-index: -1;
  box-shadow: 4px 5px 10px rgba(28,22,8,0.05);
}

.cal-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow:
    0 4px 8px rgba(28,22,8,0.12),
    0 14px 36px rgba(28,22,8,0.14),
    0 28px 56px rgba(28,22,8,0.1);
  position: relative;
  overflow: hidden;
  user-select: none;
  z-index: 2;
}

/* Faint ruled lines on front page */
.cal-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 11px,
    rgba(28,22,8,0.025) 11px,
    rgba(28,22,8,0.025) 12px
  );
  pointer-events: none;
  z-index: 0;
}

/* Worn paper edge */
.cal-card::after {
  content: '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 18px;
  background: linear-gradient(to bottom, transparent, rgba(180,150,80,0.06));
  pointer-events: none;
  z-index: 3;
}

.cal-binding {
  display: block;
  width: 100%;
  height: 18px;
  flex-shrink: 0;
}

.cal-inner {
  padding: 0.6rem 1.2rem 1.1rem;
  text-align: center;
  position: relative;
  z-index: 1;
}



/* Masthead — combined day + month/year row at the top of the card.
   Replaces the previous two-stacked-labels approach (which had a
   centred MAY 2026 line and a centred MONDAY line beneath it). The
   masthead is a single horizontal row: day on the left, month/year
   on the right, separated by a hairline rule below. Saves vertical
   space and reads as a newspaper-style header. */
.cal-masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 0.2rem 0.45rem;
  border-bottom: 1px solid rgba(28,22,8,0.08);
  margin-bottom: 0.35rem;
}

.cal-day-name {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.65);
}

.cal-month-name {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.5);
}

/* Date number with SVG circle */
.cal-date-wrap {
  position: relative;
  display: inline-block;
  margin: 0.1rem 0 0.6rem;
}

.cal-circle {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-54%, -48%) rotate(-4deg);
  width: 130%;
  height: 125%;
  pointer-events: none;
  overflow: visible;
}

.cal-date-num {
  font-family: 'Playfair Display', serif;
  font-size: 3.8rem;
  font-weight: 700;
  line-height: 1;
  color: rgba(28,22,8,0.82);
  position: relative;
  z-index: 1;
  padding: 0.1em 0.15em;
}

/* ────────────────────────────────────────────────────────────────────
   Day-swap transition (cross-fade with vertical drift)
   ────────────────────────────────────────────────────────────────────
   When the user clicks a forecast cell, the click handler:
   1. Adds .cal-swapping to the elements about to swap (date number,
      day name in the masthead, and the whole weather row).
   2. Waits 140ms for the fade-out + drift-down to complete.
   3. Swaps the textContent / icon innerHTML.
   4. Removes .cal-swapping — content fades in + drifts up via the
      same transition reversed.

   Drift is small (5px down, returns to 0). Opacity goes 1 → 0 → 1.
   The transition uses ease-out for the fade-out and ease-in for the
   fade-in via the reversal — actually both use the same single
   transition definition, the direction comes from the class toggle.

   Transitions only apply to these three elements; the rest of the
   card stays put. */
.cal-day-name,
.cal-date-num,
.cal-wx-inline {
  transition: opacity 140ms ease-out, transform 140ms ease-out;
}

.cal-day-name.cal-swapping,
.cal-date-num.cal-swapping,
.cal-wx-inline.cal-swapping {
  opacity: 0;
  transform: translateY(5px);
}

@media (prefers-reduced-motion: reduce) {
  .cal-day-name,
  .cal-date-num,
  .cal-wx-inline {
    transition: none;
  }
  .cal-day-name.cal-swapping,
  .cal-date-num.cal-swapping,
  .cal-wx-inline.cal-swapping {
    opacity: 1;
    transform: none;
  }
}

/* Week grid */
.cal-week {
  display: flex;
  justify-content: space-between;
  gap: 0;
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  border-top: 1px solid rgba(28,22,8,0.07);
}

.cal-week-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.05rem;
  flex: 1;
  padding: 0.15rem 0.05rem;
  border-radius: 2px;
  cursor: pointer;
  /* iOS needs a tap target hint to fire click events reliably on
     non-interactive elements like spans. Without this, taps on
     forecast cells in mobile Safari fail silently. */
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.cal-cell-day {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.4rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.3);
  line-height: 1;
}

.cal-cell-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.45);
  line-height: 1;
}

.cal-cell-icon {
  width: 13px;
  height: 13px;
  opacity: 0.55;
  flex-shrink: 0;
  /* SVG defaults to clipping at the viewBox edge. The animated back
     cloud (only on overcast) translates beyond the original 40-unit
     viewBox during its breath cycle — without this the right edge
     gets clipped where it meets the temperature column. */
  overflow: visible;
}

.cal-cell-icon-placeholder {
  display: block;
  width: 13px;
  height: 13px;
}

.cal-cell-temp {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  color: rgba(28,22,8,0.38);
  line-height: 1;
}

.cal-week-weekend .cal-cell-day,
.cal-week-weekend .cal-cell-date { color: rgba(28,22,8,0.18); }
.cal-week-weekend .cal-cell-temp { color: rgba(28,22,8,0.2); }

.cal-week-today {
  position: relative;
  background: none;
}

/* Terracotta highlighter wash behind today's cell */
.cal-week-today::before {
  content: '';
  position: absolute;
  inset: 1px -2px;
  background: linear-gradient(
    104deg,
    rgba(150,65,35,0) 0.5%,
    rgba(150,65,35,0.06) 2.5%,
    rgba(150,65,35,0.05) 65%,
    rgba(150,65,35,0.02) 92%,
    rgba(150,65,35,0) 99%
  );
  border-radius: 2px;
  pointer-events: none;
  z-index: 0;
  transform: rotate(-0.3deg);
}

.cal-week-today > * { position: relative; z-index: 1; }

.cal-week-today .cal-cell-day  { color: rgba(150,65,35,0.7);  font-weight: 600; }
.cal-week-today .cal-cell-date { color: rgba(150,65,35,0.8);  font-weight: 700; }
.cal-week-today .cal-cell-temp { color: rgba(150,65,35,0.65); }
.cal-week-today .cal-cell-icon { opacity: 0.75; }

/* Subtle hover on non-today cells */
.cal-week-cell:not(.cal-week-today) {
  transition: background 0.15s;
  cursor: pointer;
}

.cal-week-cell:not(.cal-week-today):hover {
  background: rgba(28,22,8,0.05);
  border-radius: 3px;
}

.cal-week-cell:not(.cal-week-today):hover .cal-cell-day,
.cal-week-cell:not(.cal-week-today):hover .cal-cell-date { color: rgba(28,22,8,0.6); }
.cal-week-cell:not(.cal-week-today):hover .cal-cell-temp { color: rgba(28,22,8,0.55); }
.cal-week-cell:not(.cal-week-today):hover .cal-cell-icon { opacity: 0.75; }

/* Today is also clickable — click to return to live mode. */
.cal-week-cell.cal-week-today {
  cursor: pointer;
}

/* Selected state — shown when the user has clicked a forecast day to
   preview it in the main display. Today's cell starts as selected
   (cal-week-today AND cal-week-selected); the existing terracotta
   wash already makes today look selected, so no additional styling
   needed for today.
   Non-today selected cells get a thin underline below the date,
   like a notebook marker, and a slight dim of the rest of the row's
   non-selected cells. */
.cal-week-cell.cal-week-selected:not(.cal-week-today) .cal-cell-date {
  position: relative;
  color: rgba(150,65,35,0.85);
  font-weight: 700;
}
.cal-week-cell.cal-week-selected:not(.cal-week-today) .cal-cell-date::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -3px;
  width: 60%;
  height: 1.5px;
  background: rgba(150,65,35,0.6);
  border-radius: 1px;
  transform: translateX(-50%);
}
.cal-week-cell.cal-week-selected:not(.cal-week-today) .cal-cell-day {
  color: rgba(150,65,35,0.65);
  font-weight: 600;
}
.cal-week-cell.cal-week-selected:not(.cal-week-today) .cal-cell-icon {
  opacity: 0.85;
}
.cal-week-cell.cal-week-selected:not(.cal-week-today) .cal-cell-temp {
  color: rgba(150,65,35,0.7);
  font-weight: 600;
}

/* Focus state for keyboard nav */
.cal-week-cell:focus {
  outline: none;
}
.cal-week-cell:focus-visible {
  outline: 1.5px solid rgba(150,65,35,0.5);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Larger sizes on desktop — calendar is hard to read on 13" screens */
@media (min-width: 768px) {
  .cal-cell-day  { font-size: 0.46rem; }
  .cal-cell-date { font-size: 0.62rem; }
  .cal-cell-temp { font-size: 0.5rem;  }
  .cal-cell-icon,
  .cal-cell-icon-placeholder { width: 15px; height: 15px; }

  /* Today's weather on desktop: bigger icon, slightly larger text
     so the two text columns stay readable at the wider card widths. */
  .cal-wx-icon-sm     { width: 64px; height: 64px; }
  .cal-wx-temp        { font-size: 1.4rem; }
  .cal-wx-condition   { font-size: 0.6rem; }
  .cal-wx-feels       { font-size: 0.62rem; }
  .cal-wx-hilo        { font-size: 0.55rem; }
  .cal-wx-suntimes    { font-size: 0.55rem; }
  .cal-wx-rainpct     { font-size: 0.65rem; }
  .cal-wx-wind        { font-size: 0.6rem; }
  .cal-wx-collabel    { font-size: 0.46rem; }
}

/* Today's weather — icon on left, stacked text column on right.
   Three lines of text (temp, condition, hi/lo) stack vertically next
   to a 44px icon, which gives the icon enough size to host its
   internal animations and gives the text enough room to be readable
   without a single cramped row. */
/* Today's weather — icon on left, then two text columns: NOW
   (current conditions) and TODAY (day's outlook with sunrise/sunset,
   rain timeline, wind callout). The icon stays as the visual anchor
   for both columns. Each column has its own mono-caps label so the
   thematic split is named, not just visual.

   Grid layout instead of flex: easier to keep both columns the same
   width regardless of content. minmax(0, 1fr) prevents long text
   overflow from breaking the grid. */
.cal-wx-inline {
  display: grid;
  /* Three columns: icon, NOW (auto-sized to its content), TODAY (gets
     remaining space). Tighter than before — the TODAY column gets a
     hairline left-border in lieu of a wide gap, so the two text
     panels read as adjacent rather than floating. */
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: start;
  column-gap: 0.7rem;
  margin: 0.4rem 0 0.3rem;
  padding: 0 0.2rem;
  justify-content: center;
}

/* Each weather column — column-stack of small text rows. Tight
   line-height to keep the card compact. */
.cal-wx-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.2;
  gap: 0.1rem;
  min-width: 0; /* allow overflow text to wrap rather than expand grid */
}

/* Subtle vertical hairline separator between NOW and TODAY columns.
   Drawn on the TODAY column's left border so it sits between the
   two without adding extra DOM. The padding compensates so text
   doesn't touch the line. */
.cal-wx-col-today {
  border-left: 1px solid rgba(28,22,8,0.08);
  padding-left: 0.6rem;
  margin-left: 0.05rem;
}

/* Mono-caps label at the top of each column — "NOW" / "TODAY" */
.cal-wx-collabel {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.12em;
  color: rgba(28,22,8,0.38);
  margin-bottom: 0.1rem;
}

/* NOW column fields */
.cal-wx-temp {
  font-family: 'Playfair Display', serif;
  font-size: 1.2rem;
  font-weight: 700;
  color: rgba(28,22,8,0.88);
  line-height: 1;
}
.cal-wx-feels {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.45);
  font-style: italic;
}
.cal-wx-condition {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.55);
  margin-top: 0.1rem;
}
.cal-wx-hilo {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  color: rgba(28,22,8,0.35);
  letter-spacing: 0.03em;
}

/* TODAY column fields */
.cal-wx-suntimes {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  color: rgba(28,22,8,0.5);
  letter-spacing: 0.03em;
}
.cal-wx-rainpct {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.6rem;
  color: rgba(80,100,140,0.85);
  margin-top: 0.05rem;
}
.cal-wx-rainpct em {
  font-style: italic;
  color: rgba(80,100,140,0.7);
}
.cal-wx-sparkline {
  width: 100%;
  height: 11px;
  margin-top: 0.1rem;
}
.cal-wx-sparkline rect {
  fill: rgba(80,100,140,0.55);
}
.cal-wx-wind {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.55rem;
  color: rgba(160,95,20,0.75);
  font-style: italic;
  margin-top: 0.05rem;
}

/* "calm day" note — fills the TODAY column on days with no rain text,
   no sparkline, and no wind callout. Same handwritten feel as the
   marginalia elsewhere on the page; reads as a quiet acknowledgment
   that we checked and there's nothing to flag, rather than leaving
   the column visibly empty. */
.cal-wx-calm {
  font-family: 'Caveat', cursive;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.42);
  letter-spacing: 0.01em;
  line-height: 1;
  margin-top: 0.15rem;
}

/* "as of HH:MM" — freshness timestamp, always shown at the bottom of
   the TODAY column. Smaller and lighter than other rows so it reads
   as metadata rather than weather content. Slightly indented to
   visually associate with the column above rather than asserting
   itself. */
.cal-wx-asof {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.3);
  margin-top: 0.25rem;
}

/* Mobile — narrow corkboard widget. The TODAY column (sunrise/
   sunset, rain timeline, wind callout) gets too cramped at small
   widths, so we drop it entirely on phones and fall back to the
   simpler "icon + NOW" layout — same essential weather info as
   the original single-column version, no overload. The information
   is still available by clicking a forecast cell, since the click
   handler swaps both columns; on mobile it just swaps the NOW
   side and the hidden TODAY column has nothing visible to swap. */
@media (max-width: 480px) {
  .cal-wx-inline {
    grid-template-columns: auto minmax(0, auto);
  }
  .cal-wx-col-today {
    display: none;
  }
}

.cal-wx-loading {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  color: rgba(28,22,8,0.25);
  font-style: italic;
  letter-spacing: 0.06em;
}

.cal-wx-icon-sm {
  width: 56px;
  height: 56px;
  color: rgba(28,22,8,0.55);
  flex-shrink: 0;
  /* SVG defaults to clipping at the viewBox edge. The animated back
     cloud (only on overcast) translates beyond the original 40-unit
     viewBox during its breath cycle. Without this the right edge
     gets clipped where it meets the temperature column. */
  overflow: visible;
}

/* ────────────────────────────────────────────────────────────────────
   Animated weather icons (Harry Potter newspaper style)
   ────────────────────────────────────────────────────────────────────
   Each WX_ICON's internal parts have their own classes and animations.
   The icons stay in their bounding boxes — only the contents move.
   These rules apply to BOTH today's bigger icon (.cal-wx-icon-sm) and
   the small forecast-strip icons (.cal-cell-icon), so the entire
   weather strip comes alive in unison.

   Performance: pure CSS animations on simple SVG paths. Browsers
   throttle automatically when the tab is hidden. No JS bookkeeping.

   Honours prefers-reduced-motion at the bottom of this block.

   Stroke colour comes from the parent's `color` property (the icons
   use stroke="currentColor"), so the animations don't hardcode
   colour and integrate cleanly with the existing today/forecast
   colour scheme.
*/

/* Cloud body — gentle scale-breathing. The transform-origin is the
   approximate centre of mass of the cloud (different per icon, but
   ~17,17 in the 40-unit viewBox covers all of them). */
.wxa-cloud-body {
  animation: wxa-cloud-breathe 6s ease-in-out infinite;
  transform-origin: 17px 17px;
  transform-box: fill-box;
}

/* Secondary back cloud — breathes in OPPOSITE phase to the front
   cloud (negative animation-delay equal to half the duration). The
   asymmetry gives the composite silhouette subtle shape-shift over
   the cycle: sometimes the back peeks out more on the upper-left,
   sometimes the front swallows it. Slightly slower duration so
   the two never lock back into perfect sync. */
.wxa-cloud-back {
  animation: wxa-cloud-breathe-back 7s ease-in-out -2.5s infinite;
  transform-origin: 27px 12px;
  transform-box: fill-box;
}

/* Cloud sway — used by showers icon. Side-to-side rocking layered
   on top of the breathe. Applied to both back and front cloud
   layers via the wxa-cloud-sway class. */
.wxa-cloud-sway {
  animation: wxa-cloud-breathe 4.5s ease-in-out infinite,
             wxa-cloud-sway 3.2s ease-in-out infinite;
  transform-origin: 18px 12px;
  transform-box: fill-box;
}

/* Sun body — subtle scale breathe. Smaller amplitude than the
   cloud since the sun is a tighter shape and over-animating it
   looks twitchy. */
.wxa-sun-body {
  animation: wxa-sun-breathe 5s ease-in-out infinite;
  transform-origin: center;
  transform-box: fill-box;
}

/* Sun halo — concentric ring around the body, breathes opposite
   phase to the body itself. At large sizes this looks like a soft
   glow expanding/contracting; at small sizes it just adds a
   little weight to the icon. */
.wxa-sun-halo {
  animation: wxa-sun-halo-breathe 5s ease-in-out infinite;
  transform-origin: center;
  transform-box: fill-box;
}

/* Sun rays group — slow rotation on top of individual ray flickers.
   Half-degree per second, barely perceptible but adds life. */
.wxa-sun-rays {
  animation: wxa-sun-rotate 60s linear infinite;
  transform-origin: center;
  transform-box: fill-box;
}

/* Sun rays — each one flickers in opacity on its own delay so they
   shimmer rather than pulsing in unison. */
.wxa-sun-ray {
  animation: wxa-ray-flicker 2.8s ease-in-out infinite;
}
.wxa-sun-rays .wxa-sun-ray:nth-child(1) { animation-delay: 0s;     }
.wxa-sun-rays .wxa-sun-ray:nth-child(2) { animation-delay: -0.4s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(3) { animation-delay: -0.8s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(4) { animation-delay: -1.2s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(5) { animation-delay: -1.6s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(6) { animation-delay: -2.0s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(7) { animation-delay: -2.4s;  }
.wxa-sun-rays .wxa-sun-ray:nth-child(8) { animation-delay: -2.8s;  }

/* Rain drops — each falls and resets, fading at top and bottom of
   the cycle. Three main drops + one trailing small drop, staggered
   so it looks like a soft trickle rather than synchronized strokes. */
.wxa-rain-drop {
  animation: wxa-rain-fall 1.8s ease-out infinite;
  transform-box: fill-box;
}
.wxa-rain-drop-1 { animation-delay: 0s;    }
.wxa-rain-drop-2 { animation-delay: -0.6s; }
.wxa-rain-drop-3 { animation-delay: -1.2s; }
.wxa-rain-drop-4 { animation-delay: -0.3s; animation-duration: 2.4s; }

/* Drizzle drops — same idea but lighter cycle and smaller travel. */
.wxa-drizzle-drop {
  animation: wxa-drizzle-fall 2.2s ease-out infinite;
  transform-box: fill-box;
}
.wxa-drizzle-drop-1 { animation-delay: 0s;    }
.wxa-drizzle-drop-2 { animation-delay: -0.7s; }
.wxa-drizzle-drop-3 { animation-delay: -1.5s; }
.wxa-drizzle-drop-4 { animation-delay: -0.4s; animation-duration: 2.6s; }

/* Showers drops — heavier rain, longer fall. Tighter stagger so
   it feels like an intermittent burst. */
.wxa-showers-drop {
  animation: wxa-showers-fall 1.4s ease-out infinite;
  transform-box: fill-box;
}
.wxa-showers-drop-1 { animation-delay: 0s;    }
.wxa-showers-drop-2 { animation-delay: -0.4s; }
.wxa-showers-drop-3 { animation-delay: -0.9s; }

/* Snow flakes — gentle pulse + tiny vertical drift + slow rotation.
   The rotation is only visible at large sizes (where the inner
   cross strokes are perceptible); at forecast-cell scale the flakes
   just appear to pulse. */
.wxa-snow-flake {
  animation: wxa-snow-drift 3.5s ease-in-out infinite,
             wxa-snow-rotate 12s linear infinite;
  transform-box: fill-box;
}
.wxa-snow-flake-1 { animation-delay: 0s,    -3s; }
.wxa-snow-flake-2 { animation-delay: -1.2s, -7s; }
.wxa-snow-flake-3 { animation-delay: -2.4s, -11s; }

/* Fog bars — drift left-right at different speeds. Bars 1 and 3
   drift right, bars 2 and 4 drift left, creating a "rolling"
   feel rather than a "marching" one. Each bar also gets a tiny
   vertical bob layered on (via the second animation in the shorthand). */
.wxa-fog-bar-1 {
  animation: wxa-fog-drift-right 6s ease-in-out infinite,
             wxa-fog-bob 4s ease-in-out infinite;
  transform-box: fill-box;
}
.wxa-fog-bar-2 {
  animation: wxa-fog-drift-left 7s ease-in-out infinite,
             wxa-fog-bob 4.5s ease-in-out -1s infinite;
  transform-box: fill-box;
}
.wxa-fog-bar-3 {
  animation: wxa-fog-drift-right 8s ease-in-out -3s infinite,
             wxa-fog-bob 5s ease-in-out -2s infinite;
  transform-box: fill-box;
}
.wxa-fog-bar-4 {
  animation: wxa-fog-drift-left 6.5s ease-in-out -2s infinite,
             wxa-fog-bob 4.2s ease-in-out -3s infinite;
  transform-box: fill-box;
}

/* Thunder bolt — mostly static with occasional flash. Long cycle
   (9s) with brief opacity spike so it feels sporadic rather than
   rhythmic. */
.wxa-thunder-bolt {
  animation: wxa-thunder-flash 9s ease-in-out infinite;
}

/* Thunder ghost bolt — wider, fainter copy of the bolt that
   brightens during the flash, simulating residual visual
   afterimage from real lightning. */
.wxa-thunder-ghost {
  animation: wxa-thunder-ghost 9s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .wxa-cloud-body,
  .wxa-cloud-back,
  .wxa-cloud-sway,
  .wxa-sun-body,
  .wxa-sun-halo,
  .wxa-sun-rays,
  .wxa-sun-ray,
  .wxa-rain-drop,
  .wxa-drizzle-drop,
  .wxa-showers-drop,
  .wxa-snow-flake,
  .wxa-fog-bar-1,
  .wxa-fog-bar-2,
  .wxa-fog-bar-3,
  .wxa-fog-bar-4,
  .wxa-thunder-bolt,
  .wxa-thunder-ghost {
    animation: none !important;
  }
}

/* ── Weather icon keyframes ──────────────────────────────────────
   Amplitudes calibrated for visibility at 44-50px icon scale.
   Smaller icons (forecast strip) inherit the same animations, where
   the motion is less prominent but still alive. Durations are slow
   enough that motion feels organic rather than frantic — typical
   range 4-8s per cycle. */

@keyframes wxa-cloud-breathe {
  /* Front cloud — gentler animation now that the icon is 56-64px.
     At larger sizes a 4-5% scale change produces visible motion
     without needing the more dramatic drift the smaller icons
     required. Pure scale + tiny rotation reads as a calm breath
     rather than the more agitated wobble we had before. */
  0%, 100% { transform: scale(1.0)  rotate(0deg); }
  50%      { transform: scale(1.04) rotate(-0.5deg); }
}

@keyframes wxa-cloud-breathe-back {
  /* Back cloud — also gentler. Still on a different duration than
     front (7s vs 6s) and offset phase, so the two-cloud composite
     silhouette evolves over time, just more sedately. */
  0%, 100% { transform: scale(1.0)  translateX(0)   rotate(0deg); }
  50%      { transform: scale(1.05) translateX(2px) rotate(0.4deg); }
}

@keyframes wxa-cloud-sway {
  /* Used by showers — heavier rain so the cloud rocks side to side. */
  0%, 100% { transform: translateX(0)    rotate(0deg); }
  25%      { transform: translateX(-1px) rotate(-0.6deg); }
  75%      { transform: translateX(1px)  rotate(0.6deg); }
}

@keyframes wxa-sun-breathe {
  /* Sun pulses scale moderately. Slower than clouds because the
     sun is one tight shape and over-animating it looks twitchy. */
  0%, 100% { transform: scale(0.94); }
  50%      { transform: scale(1.06); }
}
@keyframes wxa-sun-halo-breathe {
  /* Halo expands when body contracts — counter-pulse with bigger
     amplitude than before, plus opacity swing. */
  0%, 100% { transform: scale(1.08); opacity: 0.45; }
  50%      { transform: scale(0.9);  opacity: 0.2; }
}
@keyframes wxa-sun-rotate {
  /* Imperceptibly slow rotation — full 360 over 30 seconds. Doesn't
     register per-second but the rays will be in different positions
     ten seconds later. Charming. */
  to { transform: rotate(360deg); }
}
@keyframes wxa-ray-flicker {
  /* Rays flicker in opacity. Each ray gets its own phase via the
     animation-delay rules in the CSS above. */
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1.0; }
}

@keyframes wxa-rain-fall {
  /* Drops appear at top, fall further than before (8px translate),
     fade out at bottom. Translate matters more at larger icon sizes
     where 5px was barely registering. */
  0%   { opacity: 0;   transform: translateY(-3px); }
  15%  { opacity: 1.0; }
  70%  { opacity: 0.85; }
  100% { opacity: 0;   transform: translateY(8px); }
}
@keyframes wxa-drizzle-fall {
  /* Drizzle drops are softer — shorter travel, lower opacity peak,
     longer fade. */
  0%   { opacity: 0;   transform: translateY(-1px); }
  25%  { opacity: 0.85; }
  70%  { opacity: 0.55; }
  100% { opacity: 0;   transform: translateY(5px); }
}
@keyframes wxa-showers-fall {
  /* Heavier rain — drops fall faster, longer, with sharp opacity
     peak (real shower drops are dense and visible). */
  0%   { opacity: 0;   transform: translateY(-4px); }
  10%  { opacity: 1.0; }
  60%  { opacity: 0.95; }
  100% { opacity: 0;   transform: translateY(10px); }
}

@keyframes wxa-snow-drift {
  /* Flakes pulse and actually drift downward + sideways. Each flake
     also has wxa-snow-rotate applied as a second animation, so they
     rotate slowly while drifting. The 3px vertical drift means
     they noticeably descend (was ~1px before, basically static). */
  0%, 100% { opacity: 0.65; transform: translate(0, 0)    scale(0.95); }
  50%      { opacity: 1.0;  transform: translate(1.2px, 3px) scale(1.15); }
}
@keyframes wxa-snow-rotate {
  to { transform: rotate(360deg); }
}

@keyframes wxa-fog-drift-right {
  /* Fog bars drift further (4-5px) so the motion is visible at
     small sizes too. */
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(4px); }
}
@keyframes wxa-fog-drift-left {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(-4px); }
}
@keyframes wxa-fog-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(1px); }
}

@keyframes wxa-thunder-flash {
  /* Storm-cycle: 4 quick flashes within the first ~600ms then
     8+ seconds of dim quiet. Mimics real lightning where strikes
     come in clusters separated by long silence. */
  0%   { opacity: 0.65; }
  2%   { opacity: 1.0; }
  4%   { opacity: 0.7; }
  5%   { opacity: 1.0; }
  7%   { opacity: 0.75; }
  9%   { opacity: 1.0; }
  11%  { opacity: 0.8; }
  100% { opacity: 0.65; }
}
@keyframes wxa-thunder-ghost {
  /* Ghost (faint afterglow path) brightens during the flash window
     so the lightning leaves a brief visual impression behind it. */
  0%, 1%   { opacity: 0; }
  2%       { opacity: 0.5; }
  4%       { opacity: 0.15; }
  5%       { opacity: 0.45; }
  7%       { opacity: 0.1; }
  9%       { opacity: 0.4; }
  12%      { opacity: 0.05; }
  100%     { opacity: 0; }
}

/* ────────────────────────────────────────────────────────────────────
   App-wide tooltip
   ────────────────────────────────────────────────────────────────────
   Single shared tooltip element used by any [data-tip] element.
   Styled to match the paper aesthetic — sepia background, small
   caption, subtle drop shadow. Positioned by JS (see initTooltips
   in portfolio.js) above the target by default, flipping below when
   there's no room above.

   The .app-tooltip-visible class is what triggers the visible state;
   default state is opacity 0 and pointer-events none, so the
   tooltip never intercepts clicks when hidden. */
.app-tooltip {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10000;
  background: #2a2118;
  color: rgba(245,240,225,0.92);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.02em;
  line-height: 1.35;
  padding: 0.4rem 0.6rem;
  border-radius: 3px;
  max-width: 220px;
  box-shadow:
    0 2px 4px rgba(28,22,8,0.18),
    0 6px 16px rgba(28,22,8,0.18);
  pointer-events: none;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 140ms ease-out, transform 140ms ease-out;
}
.app-tooltip-visible {
  opacity: 1;
  transform: translateY(0);
}
/* Tiny pointer triangle below the tooltip. Indicates it's
   referring to the element below. Flipped when the tooltip is
   shown below the target. */
.app-tooltip::after {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 50%;
  margin-left: -4px;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid #2a2118;
}
.app-tooltip-below::after {
  bottom: auto;
  top: -4px;
  border-top: none;
  border-bottom: 4px solid #2a2118;
}

/* Cursor on tipped elements — implies hover-actionable without
   making it look like a clickable link. */
[data-tip] {
  cursor: help;
}

/* Sparkline bars get a hover effect — they brighten when pointed at
   so it's clear which bar's tooltip you're seeing. */
.cal-wx-sparkline rect {
  transition: fill 120ms ease-out;
}
.cal-wx-sparkline rect:hover {
  fill: rgba(80,100,140,0.85);
}


.item-weather { cursor: default; }

.wx-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.1);
  border-top: none;
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
  font-family: 'IBM Plex Mono', monospace;
}

/* Perforated top edge */
.wx-perf {
  height: 6px;
  background: repeating-linear-gradient(
    90deg,
    rgba(28,22,8,0.12) 0px, rgba(28,22,8,0.12) 3px,
    transparent 3px, transparent 8px
  );
  border-bottom: 1px solid rgba(28,22,8,0.07);
  flex-shrink: 0;
}

/* Faint ruled lines */
.wx-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom, transparent, transparent 21px,
    rgba(28,22,8,0.04) 21px, rgba(28,22,8,0.04) 22px
  );
  pointer-events: none;
  z-index: 0;
}

.wx-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.55rem 1rem 0.4rem;
  border-bottom: 1px solid rgba(28,22,8,0.07);
  position: relative;
  z-index: 1;
}

.wx-location {
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.55);
  font-weight: 500;
}

.wx-time {
  font-size: 0.48rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.28);
}

.wx-body {
  padding: 0.8rem 1rem 0.6rem;
  position: relative;
  z-index: 1;
}

.wx-loading {
  font-size: 0.6rem;
  color: rgba(28,22,8,0.3);
  letter-spacing: 0.08em;
  font-style: italic;
  padding: 0.5rem 0;
}

/* Main reading — symbol + temperature */
.wx-main {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 0.35rem;
}

.wx-symbol {
  width: 38px;
  height: 38px;
  color: rgba(28,22,8,0.55);
  flex-shrink: 0;
}

.wx-temp {
  font-family: 'Playfair Display', serif;
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  color: rgba(28,22,8,0.82);
}

.wx-unit {
  font-size: 1rem;
  font-weight: 400;
  color: rgba(28,22,8,0.45);
  font-family: 'IBM Plex Mono', monospace;
  vertical-align: super;
}

.wx-condition {
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  margin-bottom: 0.55rem;
}

.wx-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.8rem;
}

.wx-meta-item {
  font-size: 0.55rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.35);
}

.wx-footer {
  padding: 0.35rem 1rem 0.55rem;
  border-top: 1px solid rgba(28,22,8,0.06);
  position: relative;
  z-index: 1;
}

.wx-source {
  font-size: 0.45rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.2);
}

/* ── Spotify player ──────────────────────────────────────── */
.song-play-btn {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(30,215,96,0.9);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #000;
  z-index: 10;
  transition: transform 0.15s, background 0.15s;
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}

.song-play-btn:hover { transform: scale(1.08); background: rgba(30,215,96,1); }
.song-play-active { background: rgba(30,215,96,1) !important; }

/* Spotify connect card */
.spotify-connect-wrap {
  width: 100%;
  margin-bottom: 1rem;
}

.spotify-connect-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  padding: 0.9rem 1.1rem;
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.spotify-connect-title {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.82rem;
  font-weight: 700;
  color: rgba(28,22,8,0.8);
  margin-bottom: 0.15rem;
}

.spotify-connect-desc {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.4);
}

.spotify-connect-btn {
  margin-left: auto;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(30,215,96,0.85);
  text-decoration: none;
  border: 1px solid rgba(30,215,96,0.3);
  padding: 0.3rem 0.8rem;
  transition: all 0.15s;
  white-space: nowrap;
}

.spotify-connect-btn:hover {
  background: rgba(30,215,96,0.08);
  color: rgba(30,215,96,1);
  border-color: rgba(30,215,96,0.6);
}.item-song {
  cursor: default;
  position: relative;
  z-index: 3;
}


/* ── Scribble redraw animation — JS-driven, no CSS hover flash ── */

/* Base state — fully drawn */
.cal-circle path,
.link-circle-svg path {
  stroke-dashoffset: 0;
}

@keyframes scribble-draw {
  from { stroke-dashoffset: 800; }
  to   { stroke-dashoffset: 0; }
}

@keyframes scribble-draw-tail {
  from { stroke-dashoffset: 80; }
  to   { stroke-dashoffset: 0; }
}


/* ── RSS newswire — scrollable spool ────────────────────── */
.item-rss { cursor: default; }

.rss-tape {
  background: #f5f0e0;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  position: relative;
  border-left: 11px solid rgba(28,22,8,0.045);
  border-right: 11px solid rgba(28,22,8,0.045);
}

.rss-tape::before {
  content: '';
  position: absolute;
  left: -11px; top: 0; bottom: 0; width: 11px;
  background-image: radial-gradient(circle at 5.5px 8px, rgba(245,240,224,0.9) 2.6px, transparent 2.6px);
  background-size: 11px 13px;
  border-right: 1px dashed rgba(28,22,8,0.08);
}

.rss-tape::after {
  content: '';
  position: absolute;
  right: -11px; top: 0; bottom: 0; width: 11px;
  background-image: radial-gradient(circle at 5.5px 8px, rgba(245,240,224,0.9) 2.6px, transparent 2.6px);
  background-size: 11px 13px;
  border-left: 1px dashed rgba(28,22,8,0.08);
}

.item-rss:hover .rss-tape { box-shadow: var(--shadow-hover); }

.rss-tape-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.5rem 0.8rem 0.4rem;
  border-bottom: 1px solid rgba(28,22,8,0.1);
  background: rgba(245,240,224,0.5);
}

.rss-tape-title-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.rss-tape-stamp {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.62);
  line-height: 1;
}

.rss-tape-meta {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.28);
}

.rss-refresh {
  background: none;
  border: none;
  padding: 0;
  font-size: 0.72rem;
  line-height: 1;
  color: rgba(28,22,8,0.22);
  cursor: pointer;
  flex-shrink: 0;
  transition: color 0.15s;
  display: flex;
  align-items: center;
}

.rss-refresh:hover { color: rgba(28,22,8,0.55); }

@keyframes rss-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.rss-refreshing { animation: rss-spin 0.7s linear infinite; }

/* Scrollable spool */
.rss-body {
  max-height: 320px;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(28,22,8,0.12) transparent;
  position: relative;
  z-index: 2;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 19px,
    rgba(28,22,8,0.018) 19px, rgba(28,22,8,0.018) 20px
  );
}

.rss-body::-webkit-scrollbar { width: 3px; }
.rss-body::-webkit-scrollbar-track { background: transparent; }
.rss-body::-webkit-scrollbar-thumb { background: rgba(28,22,8,0.12); border-radius: 2px; }

/* Fade at bottom to hint scrollability */
.rss-body::after {
  content: '';
  display: block;
  height: 1.5rem;
  background: linear-gradient(transparent, rgba(245,240,224,0.8));
  position: sticky;
  bottom: 0;
  pointer-events: none;
}

/* Each headline */
.rss-line {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.55rem 0.8rem 0.5rem;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid rgba(28,22,8,0.06);
  transition: background 0.12s;
  cursor: pointer;
  position: relative;
  z-index: 2;
}

.rss-line:last-child { border-bottom: none; }
.rss-line:hover { background: rgba(28,22,8,0.035); }

/* Colour dot — the only colour, flush left */
.rss-line-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 0.32rem;
  opacity: 0.8;
}

/* Source + headline stacked */
.rss-line-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.rss-line-source {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
  opacity: 0.85;
}

.rss-line-title {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.8);
  line-height: 1.4;
  transition: color 0.12s;
}

.rss-line:hover .rss-line-title { color: rgba(28,22,8,0.95); }

.rss-line-age {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.4rem;
  color: rgba(28,22,8,0.38);
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: 0.03em;
  padding-top: 0.28rem;
}

/* ── News ticker — paper-tape masonry item, cycles headlines.
   Sits at the top of the notebook column (placement is explicit in
   portfolio.js). The torn top edge signals "this is a strip pulled
   off a continuous roll above" — wire-service ticker tape, the
   masthead of the corkboard.

   Three rows:
     1. Source label + timestamp
     2. Headline (typewriter-typed)
     3. Controls + counter — operator panel
   Same paper-tone family as the sources card. ── */
.item-ticker { cursor: default; }

.ticker-card {
  background: #f0e8d0;
  /* Slightly stronger top border + small shadow above mark this as
     the masthead — the topmost item in the masonry. No additional
     perforation row; the border weight does the work. */
  border: 1px solid rgba(28,22,8,0.14);
  border-top: 1px solid rgba(28,22,8,0.22);
  box-shadow: var(--shadow-sm), 0 -1px 0 rgba(28,22,8,0.05);
  transition: box-shadow 0.22s;
  position: relative;
  border-left: 11px solid rgba(28,22,8,0.045);
  border-right: 11px solid rgba(28,22,8,0.045);
  display: flex;
  align-items: stretch;
  gap: 0.55rem;
  padding: 0.7rem 0.85rem 0.5rem;
  min-height: 4rem;
}

/* Left-edge sprocket holes — mirrors .rss-tape::before exactly */
.ticker-card::before {
  content: '';
  position: absolute;
  left: -11px; top: 0; bottom: 0; width: 11px;
  background-image: radial-gradient(circle at 5.5px 8px, rgba(240,232,208,0.95) 2.6px, transparent 2.6px);
  background-size: 11px 13px;
  border-right: 1px dashed rgba(28,22,8,0.09);
  pointer-events: none;
}

/* Right-edge sprocket holes — mirrors .rss-tape::after exactly */
.ticker-card::after {
  content: '';
  position: absolute;
  right: -11px; top: 0; bottom: 0; width: 11px;
  background-image: radial-gradient(circle at 5.5px 8px, rgba(240,232,208,0.95) 2.6px, transparent 2.6px);
  background-size: 11px 13px;
  border-left: 1px dashed rgba(28,22,8,0.09);
  pointer-events: none;
}

.item-ticker:hover .ticker-card { box-shadow: var(--shadow-hover), 0 -1px 0 rgba(28,22,8,0.05); }

.ticker-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  position: relative;
  z-index: 1;
}

/* Top row: colored source label on the left, timestamp pinned right */
.ticker-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
}

.ticker-source-label {
  color: rgba(28,22,8,0.5);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* color overridden inline by JS to the source's accent */
}

.ticker-age {
  color: rgba(28,22,8,0.32);
  flex-shrink: 0;
  letter-spacing: 0.1em;
}

/* Middle row: the headline. Bounded height + overflow:hidden so the
   paper-feed slide motion is clipped at the row boundaries (old line
   slides up out of view, new line slides up from below). */
.ticker-track {
  min-width: 0;
  overflow: hidden;
  position: relative;
  height: calc(0.74rem * 1.4);
}

.ticker-text {
  display: flex;
  align-items: baseline;
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.74rem;
  line-height: 1.4;
  color: rgba(28,22,8,0.86);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
  transition: color 0.15s ease;
  height: 100%;
}

.ticker-text:hover { color: rgba(150,65,35,0.95); }

.ticker-title-text {
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1;
  position: relative;
  /* Default state — fully in view, no transform. JS animates this
     during paper-feed transitions: -100% (slid up out) → 100%
     (snapped below) → 0 (fed back into view). */
  transform: translateY(0);
}

/* Caret that appears at the end of the headline only while typing */
.ticker-title-text.is-typing::after {
  content: '';
  display: inline-block;
  width: 0.4em;
  height: 0.85em;
  margin-left: 0.12em;
  background: rgba(28,22,8,0.5);
  vertical-align: -0.1em;
  animation: ticker-caret-blink 0.55s steps(2, start) infinite;
}

@keyframes ticker-caret-blink {
  to { visibility: hidden; }
}

/* Bottom row: controls on the left, counter on the right.
   Lean — no live indicator, no extra status text. */
.ticker-foot {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.1rem;
  padding-top: 0.35rem;
  border-top: 1px dashed rgba(28,22,8,0.12);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  line-height: 1;
}

.ticker-foot-spacer {
  flex: 1;
}

.ticker-controls {
  display: flex;
  align-items: center;
  gap: 0.05rem;
  flex-shrink: 0;
}

.ticker-prev,
.ticker-next,
.ticker-pause {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  line-height: 1;
  background: none;
  border: none;
  color: rgba(28,22,8,0.4);
  cursor: pointer;
  padding: 0.1rem 0.3rem;
  transition: color 0.15s ease;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.ticker-pause { font-size: 0.55rem; }

.ticker-prev:hover,
.ticker-next:hover,
.ticker-pause:hover { color: rgba(150,65,35,0.85); }

.ticker-counter {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: rgba(28,22,8,0.32);
}

@media (max-width: 767px) {
  .item-ticker { display: none !important; }
}


/* ── Outlook agenda card ─────────────────────────────────── */
.item-agenda {
  cursor: default;
  /* Container settings for the stack-paper depth treatment: pages
     fan out behind the card, so the container needs overflow:visible
     and some margin-bottom to leave room for the fanned edges. */
  position: relative;
  overflow: visible;
  margin-bottom: 8px;
  z-index: 4;
}

.agenda-card {
  background: #fbf8f1;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow:
    0 4px 8px rgba(28,22,8,0.12),
    0 14px 36px rgba(28,22,8,0.14),
    0 28px 56px rgba(28,22,8,0.1);
  transition: box-shadow 0.22s;
  position: relative;
  overflow: hidden;
  /* Sit above the three .stack-paper layers behind it. */
  z-index: 2;
  /* Off-white paper, just warm enough to read as paper without
     yellowing the whole widget. Sits between the near-white panel
     look and the warmer field-note cream. */
  background-color: #fbf8f1;
  /* Faint horizontal ruled lines — the most paper-like cue, used
     across stationery from yellow legal pads to Moleskines. Very
     low contrast so they read as texture rather than ruling.
     Combined with the perforated top edge from .agenda-card::before. */
  background-image:
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent 23px,
      rgba(28,22,8,0.025) 23px,
      rgba(28,22,8,0.025) 24px
    );
  background-position: 0 18px;
  /* Top padding makes room for the perforated tear-off line. */
  padding-top: 10px;
}

.item-agenda:hover .agenda-card { box-shadow: var(--shadow-hover); }

/* Perforated tear-off edge — a row of small dashes along the top,
   like a desk-pad calendar where each day's page tears away.
   CSS-drawn at integer pixels so it renders crisp on any display.
   Doesn't echo the calendar/weather widget's spiral binding —
   different planner-paper metaphor for visual differentiation. */
.agenda-card::before {
  content: '';
  position: absolute;
  top: 4px;
  left: 0;
  right: 0;
  height: 4px;
  background-image:
    radial-gradient(circle at 2px 2px, rgba(28,22,8,0.32) 1px, transparent 1.5px);
  background-size: 8px 4px;
  background-repeat: repeat-x;
  z-index: 2;
  pointer-events: none;
}

/* No ruled lines — events have their own visual separators */

/* Quiet-stretch marker — a small handwritten margin note for empty-day runs.
   Reads like a journalist's "Thu quiet" or "weekend off" note in the planner. */
.agenda-quiet {
  padding: 0.45rem 0.85rem;
  position: relative;
  z-index: 1;
}

.agenda-quiet-text {
  font-family: 'Caveat', cursive;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.32);
  letter-spacing: 0.01em;
  font-style: italic;
}

.agenda-quiet-text::before {
  content: '· ';
  color: rgba(28,22,8,0.25);
}

.agenda-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.85rem 0.45rem;
  border-bottom: 1px solid rgba(28,22,8,0.1);
  position: relative;
  z-index: 1;
}

.agenda-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  font-weight: 500;
  color: rgba(150,65,35,0.75);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.agenda-updated { display: none; }

/* Month stamp in the header — sits opposite the AGENDA label.
   Identifies which month/year this planner page covers, like the
   header of a real wall calendar. Same mono small caps as the label
   for visual consistency, slightly muted color so it reads as
   secondary information. */
.agenda-month {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  font-weight: 500;
}

.agenda-body {
  position: relative;
  z-index: 1;
  max-height: 320px;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(28,22,8,0.12) transparent;
}

.agenda-body::-webkit-scrollbar { width: 3px; }
.agenda-body::-webkit-scrollbar-track { background: transparent; }
.agenda-body::-webkit-scrollbar-thumb { background: rgba(28,22,8,0.12); border-radius: 2px; }

/* Fade at bottom to hint scrollability — sticky so it stays visible while scrolling */
.agenda-body::after {
  content: '';
  display: block;
  height: 1.5rem;
  background: linear-gradient(transparent, rgba(250,248,244,0.95));
  position: sticky;
  bottom: 0;
  margin-top: -1.5rem;
  pointer-events: none;
  z-index: 3;
}

/* ── Week strip (Option C agenda redesign) ──────────────────
   Replaces the old long sequential day-list. Top of the agenda card
   shows a 7-day forward-looking strip with a small bar per event,
   color-coded by mark type (committee, meeting, brief, travel, etc).
   Click any day to surface its full event list below. The current
   day is visually accented; weekends are gently muted. */
.agenda-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  padding: 0.55rem 0.7rem 0.6rem;
  position: relative;
  z-index: 1;
  border-bottom: 1px solid rgba(28,22,8,0.08);
}
.agenda-strip-day {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: none;
  padding: 0.3rem 0.05rem 0.35rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.12rem;
  border-radius: 2px;
  transition: background 0.15s, color 0.15s;
  font-family: inherit;
  color: inherit;
  position: relative;
}

/* Subtle vertical dotted divider between days — runs through the
   middle band only (around the date numeral), not the full cell
   height. Reads as paper diary section divider, not a spreadsheet
   grid. Skipped on the first cell of the row. */
.agenda-strip-day + .agenda-strip-day::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 28%;
  bottom: 28%;
  width: 0;
  border-left: 1px dotted rgba(28,22,8,0.16);
}
/* When either neighbouring cell is selected, suppress the divider
   so the selection background reads cleanly without a stripe inside it. */
.agenda-strip-day.is-selected + .agenda-strip-day::before,
.agenda-strip-day.is-selected::before {
  border-left-color: transparent;
}

.agenda-strip-day:hover {
  background: rgba(28,22,8,0.035);
}
.agenda-strip-day.is-selected {
  background: rgba(150,65,35,0.075);
}
.agenda-strip-day.is-weekend .agenda-strip-num {
  color: rgba(28,22,8,0.45);
}
.agenda-strip-day.is-empty {
  opacity: 0.65;
}
.agenda-strip-dow {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.42);
  line-height: 1;
}
.agenda-strip-day.is-today .agenda-strip-dow {
  color: rgba(150,65,35,0.8);
}
/* Date numerals — restrained calendar style. Libre Baskerville italic
   keeps continuity with the rest of the site's serif body type rather
   than introducing Playfair Display, which competes with the cards
   below at small sizes. */
.agenda-strip-num {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-weight: 700;
  font-size: 0.92rem;
  line-height: 1;
  color: rgba(28,22,8,0.78);
  margin-top: 0.18rem;
  position: relative;
}
.agenda-strip-day.is-today .agenda-strip-num {
  color: rgba(150,65,35,0.95);
}
/* Today's hand-drawn coral underline — a soft tapered line under the
   numeral, faintly tilted, like marking the current day in a paper
   diary. Tighter than before so it fits the smaller numeral cleanly. */
.agenda-strip-day.is-today .agenda-strip-num::after {
  content: '';
  position: absolute;
  left: -0.1rem;
  right: -0.1rem;
  bottom: -0.13rem;
  height: 1.5px;
  background:
    linear-gradient(90deg,
      rgba(150,65,35,0) 0%,
      rgba(150,65,35,0.5) 25%,
      rgba(150,65,35,0.7) 50%,
      rgba(150,65,35,0.5) 75%,
      rgba(150,65,35,0) 100%);
  border-radius: 2px;
  transform: rotate(-1deg);
}

.agenda-strip-bars {
  display: flex;
  gap: 1.5px;
  align-items: flex-end;
  justify-content: center;
  height: 0.42rem;
  min-height: 0.42rem;
  margin-top: 0.28rem;
}
.agenda-strip-bar {
  width: 0.16rem;
  height: 0.38rem;
  border-radius: 1px;
  background: rgba(28,22,8,0.4);
  flex-shrink: 0;
}
.agenda-strip-overflow {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.45rem;
  color: rgba(28,22,8,0.5);
  line-height: 1;
  margin-left: 1px;
  letter-spacing: 0.04em;
  align-self: center;
}

/* Bar colors per mark type — keep this ramp synced with the icon
   palette so the dot under a day visually predicts what icon will
   appear in the list. Less-distinct categories share a hue (admin
   = neutral grey) to avoid rainbow. Saturated enough to read at
   the bar's small size. */
.agenda-strip-bar-committee,
.agenda-strip-bar-plenary,
.agenda-strip-bar-trilogue,
.agenda-strip-bar-institutional { background: rgba(28,22,8,0.62); }
.agenda-strip-bar-meeting,
.agenda-strip-bar-discussion,
.agenda-strip-bar-call          { background: rgba(30,70,140,0.7); }
.agenda-strip-bar-press,
.agenda-strip-bar-brief         { background: rgba(20,100,55,0.7); }
.agenda-strip-bar-travel,
.agenda-strip-bar-holiday       { background: rgba(150,65,35,0.78); }
.agenda-strip-bar-coffee,
.agenda-strip-bar-meal          { background: rgba(155,110,40,0.7); }
.agenda-strip-bar-deadline,
.agenda-strip-bar-edit,
.agenda-strip-bar-brainstorm    { background: rgba(180,40,30,0.7); }
.agenda-strip-bar-medical,
.agenda-strip-bar-pet,
.agenda-strip-bar-family,
.agenda-strip-bar-birthday      { background: rgba(150,40,80,0.65); }
.agenda-strip-bar-admin,
.agenda-strip-bar-default       { background: rgba(28,22,8,0.35); }

/* ── Selected day pane ──────────────────────────────────────
   Beneath the week strip. Shows the full event list for the
   currently-selected day. Header has a soft italic day name and a
   small mono count on the right. Padding here means the agenda
   card's outer .agenda-card has none — events flow with consistent
   left/right gutters via this container. */
.agenda-day {
  position: relative;
  z-index: 1;
  padding: 0.45rem 0.85rem 0.85rem;
  max-height: 320px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(28,22,8,0.12) transparent;
}
.agenda-day::-webkit-scrollbar { width: 3px; }
.agenda-day::-webkit-scrollbar-track { background: transparent; }
.agenda-day::-webkit-scrollbar-thumb { background: rgba(28,22,8,0.12); border-radius: 2px; }

.agenda-day-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.15rem 0 0.4rem;
  margin-bottom: 0.35rem;
  border-bottom: 1px dashed rgba(28,22,8,0.1);
}
.agenda-day-name {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.7rem;
  color: rgba(28,22,8,0.72);
}
.agenda-day-count {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.42);
}
.agenda-day-empty {
  padding: 0.6rem 0;
  font-family: 'Caveat', cursive;
  font-size: 0.95rem;
  color: rgba(28,22,8,0.32);
  text-align: center;
}

/* Roll-forward "Tomorrow" sub-section — appended below today's list
   when the working day is winding down (after 17:00 with no active
   timed events). Visually quieter than today's heading: lighter
   colour, smaller divider above. The events themselves render at
   full strength — they're real upcoming items, the day-label is
   what reads as secondary. */
.agenda-section-divider {
  height: 0;
  margin: 0.6rem 0 0.55rem;
  border-top: 1px dashed rgba(28,22,8,0.08);
}
.agenda-day-head-tomorrow {
  /* Reuse layout from .agenda-day-head but on a separate selector
     so it composes cleanly with .agenda-day-head if both classes
     were ever applied. */
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.15rem 0 0.4rem;
  margin-bottom: 0.35rem;
  border-bottom: 1px dashed rgba(28,22,8,0.08);
}
.agenda-day-head-tomorrow .agenda-day-head-label {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.65rem;
  color: rgba(28,22,8,0.5);
}
.agenda-day-head-tomorrow .agenda-day-head-count {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.32);
}

.agenda-empty {
  padding: 0.7rem 0.85rem;
  font-family: 'Caveat', cursive;
  font-size: 0.95rem;
  color: rgba(28,22,8,0.28);
  position: relative;
  z-index: 1;
}

/* Section — Today / Tomorrow */
.agenda-section {
  padding: 0.35rem 0 0.2rem;
}

/* Section dividers in handwriting — like a planner where you write
   "— Today" then list events, then "— Tomorrow" and continue */
.agenda-section-label {
  font-family: 'Caveat', cursive;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: rgba(28,22,8,0.45);
  padding: 0.1rem 0.85rem 0.1rem;
  position: relative;
  z-index: 1;
  line-height: 1;
}

.agenda-section-today {
  color: rgba(150,65,35,0.75);
}

/* Individual event row */
.agenda-event {
  display: flex;
  align-items: stretch;
  gap: 0.6rem;
  padding: 0.3rem 0.85rem;
  position: relative;
  z-index: 1;
}

.agenda-event + .agenda-event {
  border-top: 1px dotted rgba(28,22,8,0.07);
}

.agenda-event-left {
  flex-shrink: 0;
  width: 4rem;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Base ::after — vertically centered to the row, matching the time text.
   Each .agenda-mark-* override below sets only the background-image. */
.agenda-event-left::after {
  content: '';
  position: absolute;
  right: -0.1rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.7rem;
  height: 0.7rem;
  background-repeat: no-repeat;
  background-size: contain;
}

/* ─── Semantic margin marks ──────────────────────────────
   Each SVG embeds a turbulence + displacement filter so strokes get genuine
   pseudo-random jitter — actually handdrawn-looking at any render size, not
   just clean curves with bezier wobble. Each glyph uses a different filter
   seed so wobble patterns vary across the page. */

/* Default fallback — small horizontal dash. Less prominent than a filled
   blob; reads as "no specific category" without competing with the real
   semantic icons in attention. */
.agenda-mark-default .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.07' numOctaves='2' seed='1'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 12 Q 9 11.5, 14 12.5 T 22 12' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' opacity='0.55' filter='url(%23r)'/></svg>");
}

/* Call — telephone handset */
.agenda-mark-call .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='2'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 5 Q 4 6, 4 8 Q 5 12, 8 16 Q 12 20, 16 21 Q 18 21, 19 19 L 19.5 16 Q 17 14.5, 15.5 15.5 L 13 13 Q 14 11, 13 9 L 10 5.5 Q 8 4.5, 5 5 Z' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Coffee — mug with steam */
.agenda-mark-coffee .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='3'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 9 L 5 17 Q 5 19.5, 7.5 19.5 L 14 19.5 Q 16.5 19.5, 16.5 17 L 16.5 9 Z M 16.5 11 Q 19.5 11, 19.5 13.5 Q 19.5 16, 16.5 15.5 M 8 4 Q 9 6, 7.5 8 M 11.5 4 Q 12.5 6, 11 8' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Meal — fork and knife */
.agenda-mark-meal .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='4'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M6 3 L 6 11 Q 6 12.5, 7.5 12.5 L 7.5 21 M 9.5 3 L 9.5 11 Q 9.5 12.5, 8 12.5 M 15 3 L 15 9 Q 15 11, 17 11 L 17 21 M 15 3 Q 17 3, 17 6 L 17 11' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Travel — paper plane */
.agenda-mark-travel .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='5'/><feDisplacementMap in='SourceGraphic' scale='1.5'/></filter><path d='M2 12 L 22 4 L 16 21 L 12 13 Z M 12 13 L 22 4' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Press — notepad with lines */
.agenda-mark-press .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='6'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M6 3 L 17 3 Q 19 3, 19 5 L 19 20 Q 19 22, 17 22 L 6 22 Q 4 22, 4 20 L 4 5 Q 4 3, 6 3 Z M 7 9 L 16 9 M 7 13 L 16 13 M 7 17 L 13 17' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Deadline — exclamation, burnt-umber */
.agenda-mark-deadline .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.06' numOctaves='2' seed='7'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><g filter='url(%23r)'><path d='M12 4 Q 11.5 9, 11 14' fill='none' stroke='%23964123' stroke-width='2.8' stroke-linecap='round' opacity='0.9'/><circle cx='10.5' cy='19' r='1.7' fill='%23964123' opacity='0.9'/></g></svg>");
}

/* Edit — pencil */
.agenda-mark-edit .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='8'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M3 21 L 6 20 L 20 6 L 18 4 L 4 18 Z M 17 5 L 19 7 M 3 21 L 5 21' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75' filter='url(%23r)'/></svg>");
}

/* Medical — cross, teal */
.agenda-mark-medical .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.06' numOctaves='2' seed='9'/><feDisplacementMap in='SourceGraphic' scale='1.5'/></filter><path d='M12 4 L 12 20 M 4 12 L 20 12' fill='none' stroke='%233c826e' stroke-width='3' stroke-linecap='round' opacity='0.85' filter='url(%23r)'/></svg>");
}

/* Pet — paw print. Universal cat/dog/any-pet icon. Big rounded pad at
   the bottom, four smaller toe pads above, slightly asymmetric to match
   the hand-drawn aesthetic of the other margin marks. */
.agenda-mark-pet .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='10'/><feDisplacementMap in='SourceGraphic' scale='1.2'/></filter><g filter='url(%23r)' fill='%23491b08' opacity='0.78'><ellipse cx='12' cy='17.5' rx='5' ry='4'/><ellipse cx='6' cy='10' rx='2.2' ry='2.6'/><ellipse cx='10.5' cy='6.5' rx='2' ry='2.6'/><ellipse cx='14.5' cy='6.5' rx='2' ry='2.6'/><ellipse cx='18.5' cy='10' rx='2.2' ry='2.6'/></g></svg>");
}

/* Meeting — two figures facing each other across a table. The literal
   "people in a room having a meeting" gesture: heads + shoulder lines
   + a horizontal bar between them. Reads instantly as "we're meeting"
   regardless of context (editorial planning, sync, bilateral, board). */
.agenda-mark-meeting .agenda-event-left::after,
.agenda-mark-planning .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='11'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><circle cx='6' cy='6' r='2.4' fill='%23491b08' stroke='none'/><path d='M2 13 Q 2 10, 6 10 Q 10 10, 10 13 L 10 14'/><circle cx='18' cy='6' r='2.4' fill='%23491b08' stroke='none'/><path d='M14 13 Q 14 10, 18 10 Q 22 10, 22 13 L 22 14'/><path d='M1 16 L 23 16 M 4 16 L 4 22 M 20 16 L 20 22'/></g></svg>");
}

/* Brainstorm — light bulb */
.agenda-mark-brainstorm .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='12'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M12 3 Q 7 3, 7 9 Q 7 12, 9 14 L 9 17 Q 9 18, 10 18 L 14 18 Q 15 18, 15 17 L 15 14 Q 17 12, 17 9 Q 17 3, 12 3 Z M 10 20 L 14 20 M 11 22 L 13 22'/></g></svg>");
}

/* Admin / performance — clipboard with check lines */
.agenda-mark-admin .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='14'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M6 5 L 6 21 Q 6 22, 7 22 L 17 22 Q 18 22, 18 21 L 18 5 M 9 3 L 15 3 Q 16 3, 16 4 L 16 6 Q 16 7, 15 7 L 9 7 Q 8 7, 8 6 L 8 4 Q 8 3, 9 3 Z M 9 11 L 15 11 M 9 14 L 15 14 M 9 17 L 13 17'/></g></svg>");
}

/* Institutional — pillared building. Triangular pediment + columns + base
   line. Reads as "institution" at small size. For summits, councils,
   committees, parliaments, EU formations. */
.agenda-mark-institutional .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='16'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M2 8 L 12 3 L 22 8 L 22 9 L 2 9 Z M 5 11 L 5 18 M 9.5 11 L 9.5 18 M 14.5 11 L 14.5 18 M 19 11 L 19 18 M 2 19 L 22 19 M 1 21 L 23 21'/></g></svg>");
}

/* Discussion / catch-up — two overlapping speech bubbles, signalling
   informal back-and-forth conversation (different from the structured
   calendar-block of meeting) */
.agenda-mark-discussion .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='15'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M3 4 L 13 4 Q 15 4, 15 6 L 15 11 Q 15 13, 13 13 L 7 13 L 4 16 L 4.5 13 L 3 13 Q 1 13, 1 11 L 1 6 Q 1 4, 3 4 Z'/><path d='M11 9 L 20 9 Q 22 9, 22 11 L 22 16 Q 22 18, 20 18 L 19 18 L 19.5 21 L 16 18 L 11 18 Q 9 18, 9 16'/></g></svg>");
}

/* Today's events — same shapes in burnt-umber accent */
.agenda-today.agenda-mark-default .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.07' numOctaves='2' seed='1'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 12 Q 9 11.5, 14 12.5 T 22 12' fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' opacity='0.78' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-call .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='2'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 5 Q 4 6, 4 8 Q 5 12, 8 16 Q 12 20, 16 21 Q 18 21, 19 19 L 19.5 16 Q 17 14.5, 15.5 15.5 L 13 13 Q 14 11, 13 9 L 10 5.5 Q 8 4.5, 5 5 Z' fill='none' stroke='%23964123' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-coffee .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='3'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M5 9 L 5 17 Q 5 19.5, 7.5 19.5 L 14 19.5 Q 16.5 19.5, 16.5 17 L 16.5 9 Z M 16.5 11 Q 19.5 11, 19.5 13.5 Q 19.5 16, 16.5 15.5 M 8 4 Q 9 6, 7.5 8 M 11.5 4 Q 12.5 6, 11 8' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-meal .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='4'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M6 3 L 6 11 Q 6 12.5, 7.5 12.5 L 7.5 21 M 9.5 3 L 9.5 11 Q 9.5 12.5, 8 12.5 M 15 3 L 15 9 Q 15 11, 17 11 L 17 21 M 15 3 Q 17 3, 17 6 L 17 11' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-travel .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='5'/><feDisplacementMap in='SourceGraphic' scale='1.5'/></filter><path d='M2 12 L 22 4 L 16 21 L 12 13 Z M 12 13 L 22 4' fill='none' stroke='%23964123' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-press .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='6'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M6 3 L 17 3 Q 19 3, 19 5 L 19 20 Q 19 22, 17 22 L 6 22 Q 4 22, 4 20 L 4 5 Q 4 3, 6 3 Z M 7 9 L 16 9 M 7 13 L 16 13 M 7 17 L 13 17' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-edit .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='8'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><path d='M3 21 L 6 20 L 20 6 L 18 4 L 4 18 Z M 17 5 L 19 7 M 3 21 L 5 21' fill='none' stroke='%23964123' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.9' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-meeting .agenda-event-left::after,
.agenda-today.agenda-mark-planning .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='11'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><circle cx='6' cy='6' r='2.4' fill='%23964123' stroke='none'/><path d='M2 13 Q 2 10, 6 10 Q 10 10, 10 13 L 10 14'/><circle cx='18' cy='6' r='2.4' fill='%23964123' stroke='none'/><path d='M14 13 Q 14 10, 18 10 Q 22 10, 22 13 L 22 14'/><path d='M1 16 L 23 16 M 4 16 L 4 22 M 20 16 L 20 22'/></g></svg>");
}
.agenda-today.agenda-mark-brainstorm .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='12'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M12 3 Q 7 3, 7 9 Q 7 12, 9 14 L 9 17 Q 9 18, 10 18 L 14 18 Q 15 18, 15 17 L 15 14 Q 17 12, 17 9 Q 17 3, 12 3 Z M 10 20 L 14 20 M 11 22 L 13 22'/></g></svg>");
}
.agenda-today.agenda-mark-admin .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='14'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M6 5 L 6 21 Q 6 22, 7 22 L 17 22 Q 18 22, 18 21 L 18 5 M 9 3 L 15 3 Q 16 3, 16 4 L 16 6 Q 16 7, 15 7 L 9 7 Q 8 7, 8 6 L 8 4 Q 8 3, 9 3 Z M 9 11 L 15 11 M 9 14 L 15 14 M 9 17 L 13 17'/></g></svg>");
}
.agenda-today.agenda-mark-institutional .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='16'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M2 8 L 12 3 L 22 8 L 22 9 L 2 9 Z M 5 11 L 5 18 M 9.5 11 L 9.5 18 M 14.5 11 L 14.5 18 M 19 11 L 19 18 M 2 19 L 22 19 M 1 21 L 23 21'/></g></svg>");
}
.agenda-today.agenda-mark-discussion .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='15'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 4 L 13 4 Q 15 4, 15 6 L 15 11 Q 15 13, 13 13 L 7 13 L 4 16 L 4.5 13 L 3 13 Q 1 13, 1 11 L 1 6 Q 1 4, 3 4 Z'/><path d='M11 9 L 20 9 Q 22 9, 22 11 L 22 16 Q 22 18, 20 18 L 19 18 L 19.5 21 L 16 18 L 11 18 Q 9 18, 9 16'/></g></svg>");
}

/* ── Newer marks added for journalist's beat-specific events ────────── */

/* Birthday — layered cake with a candle. Reads as celebration without
   being saccharine. Tier separation lines + single candle + flame. */
.agenda-mark-birthday .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='17'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 21 L 21 21 M 4 21 L 4 14 Q 4 13, 5 13 L 19 13 Q 20 13, 20 14 L 20 21 M 4 17 L 20 17 M 12 13 L 12 8'/><path d='M11 8 Q 12 6, 13 8 Q 12 10, 11 8 Z' fill='%23964123' stroke='%23964123'/></g></svg>");
}
.agenda-today.agenda-mark-birthday .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='17'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 21 L 21 21 M 4 21 L 4 14 Q 4 13, 5 13 L 19 13 Q 20 13, 20 14 L 20 21 M 4 17 L 20 17 M 12 13 L 12 8'/><path d='M11 8 Q 12 6, 13 8 Q 12 10, 11 8 Z' fill='%23964123' stroke='%23964123'/></g></svg>");
}

/* Holiday — tent, signaling time off / personal trip. Distinct from
   work travel (paper plane). A-frame canvas with door slit + ground line. */
.agenda-mark-holiday .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='18'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 20 L 12 4 L 21 20 Z M 12 4 L 12 20 M 9 20 L 12 14 L 15 20 M 2 20 L 22 20'/></g></svg>");
}
.agenda-today.agenda-mark-holiday .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='18'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 20 L 12 4 L 21 20 Z M 12 4 L 12 20 M 9 20 L 12 14 L 15 20 M 2 20 L 22 20'/></g></svg>");
}

/* Family — heart. Used for partner-related events (Paula's stuff,
   anniversaries, in-laws). Auto-detected only on "anniversary"/"rocznica";
   most uses come via the icon picker. */
.agenda-mark-family .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='19'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M12 21 Q 4 15, 4 9 Q 4 5, 8 5 Q 11 5, 12 8 Q 13 5, 16 5 Q 20 5, 20 9 Q 20 15, 12 21 Z' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78' filter='url(%23r)'/></svg>");
}
.agenda-today.agenda-mark-family .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='19'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><path d='M12 21 Q 4 15, 4 9 Q 4 5, 8 5 Q 11 5, 12 8 Q 13 5, 16 5 Q 20 5, 20 9 Q 20 15, 12 21 Z' fill='%23964123' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.85' filter='url(%23r)'/></svg>");
}

/* Committee — calendar grid icon. Structured agenda-driven body that
   works through scheduled items (ENVI, AGRI, ITRE, komisje). The
   calendar grid signals "scheduled, structured, agenda-driven" — what
   committees do. Distinguished from meeting (two figures at a table —
   smaller, more conversational), plenary (rows of seats — large body),
   and institutional (pillared building — symbol of state). */
.agenda-mark-committee .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='20'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M4 5 L 20 5 Q 21 5, 21 6 L 21 20 Q 21 21, 20 21 L 4 21 Q 3 21, 3 20 L 3 6 Q 3 5, 4 5 Z M 3 10 L 21 10 M 9 5 L 9 21 M 15 5 L 15 21 M 8 3 L 8 7 M 16 3 L 16 7'/></g></svg>");
}
.agenda-today.agenda-mark-committee .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='20'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M4 5 L 20 5 Q 21 5, 21 6 L 21 20 Q 21 21, 20 21 L 4 21 Q 3 21, 3 20 L 3 6 Q 3 5, 4 5 Z M 3 10 L 21 10 M 9 5 L 9 21 M 15 5 L 15 21 M 8 3 L 8 7 M 16 3 L 16 7'/></g></svg>");
}

/* Plenary — ranks of seats. Stylized parliamentary chamber: rows of
   horizontal lines arching subtly. Suggests scale (large gathering)
   without specifically reading as EU vs Polish. */
.agenda-mark-plenary .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='21'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 7 Q 12 5, 21 7 M 3 11 Q 12 9, 21 11 M 3 15 Q 12 13, 21 15 M 3 19 Q 12 17, 21 19'/><circle cx='12' cy='4' r='1.2' fill='%23491b08' stroke='none' opacity='0.8'/></g></svg>");
}
.agenda-today.agenda-mark-plenary .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='21'/><feDisplacementMap in='SourceGraphic' scale='1.4'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 7 Q 12 5, 21 7 M 3 11 Q 12 9, 21 11 M 3 15 Q 12 13, 21 15 M 3 19 Q 12 17, 21 19'/><circle cx='12' cy='4' r='1.2' fill='%23964123' stroke='none' opacity='0.95'/></g></svg>");
}

/* Trilogue — three converging arrows (one from each direction) meeting
   at a central node. The closed-door three-way negotiation between
   Council, Parliament, and Commission. Distinct enough event to deserve
   its own visual — none of the existing icons captured "three sides
   meeting in private to make a deal." */
.agenda-mark-trilogue .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='22'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 5 L 11 11 M 7 5 L 11 5 L 11 9 M 21 5 L 13 11 M 17 5 L 21 5 L 21 9 M 12 21 L 12 13 M 8 18 L 12 22 L 16 18'/><circle cx='12' cy='12' r='2' fill='%23491b08' stroke='none' opacity='0.85'/></g></svg>");
}
.agenda-today.agenda-mark-trilogue .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='22'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 5 L 11 11 M 7 5 L 11 5 L 11 9 M 21 5 L 13 11 M 17 5 L 21 5 L 21 9 M 12 21 L 12 13 M 8 18 L 12 22 L 16 18'/><circle cx='12' cy='12' r='2' fill='%23964123' stroke='none' opacity='0.95'/></g></svg>");
}

/* Brief — microphone. Distinct from press (notepad). Press is delivering;
   brief is receiving — Commission spokesperson briefings, doorsteps,
   stake-outs, where a journalist is on the listening end. */
.agenda-mark-brief .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='23'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M12 3 Q 9 3, 9 6 L 9 12 Q 9 15, 12 15 Q 15 15, 15 12 L 15 6 Q 15 3, 12 3 Z M 6 11 Q 6 16, 12 16 Q 18 16, 18 11 M 12 16 L 12 20 M 9 21 L 15 21'/></g></svg>");
}
.agenda-today.agenda-mark-brief .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.05' numOctaves='2' seed='23'/><feDisplacementMap in='SourceGraphic' scale='1.3'/></filter><g filter='url(%23r)' fill='none' stroke='%23964123' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M12 3 Q 9 3, 9 6 L 9 12 Q 9 15, 12 15 Q 15 15, 15 12 L 15 6 Q 15 3, 12 3 Z M 6 11 Q 6 16, 12 16 Q 18 16, 18 11 M 12 16 L 12 20 M 9 21 L 15 21'/></g></svg>");
}

/* The previous "today's events without a mark variation" fallback rule
   was removed: every event gets a mark class from agendaMarkForEvent
   (defaulting to agenda-mark-default if no rule matches), so a generic
   today fallback is never needed. The fallback was also actively wrong
   for marks without today-variants (pet, deadline, medical) — same
   specificity as their base rule but appearing later in the cascade,
   which silently overrode the actual icon with a generic dot. */

/* All-day events keep both the asterisk + "all day" text (in the time
   column) AND the semantic mark (at the column's right edge). The asterisk
   signals timing (no specific hour); the semantic mark signals what kind
   of thing it is. Two slots, both used. */

/* Time as bare mono text — like a number written in a planner margin */
.agenda-time-pill {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  /* 0.65rem (~10.4px) is the sweet spot for IBM Plex Mono on
     non-retina displays — small enough to read as secondary metadata,
     big enough that antialiasing produces clean glyph edges instead
     of the soft mush that 0.55rem caused on external monitors.
     Letter-spacing dropped to 0 because at small mono sizes any
     non-zero spacing forces sub-pixel character positioning, which
     softens edges further on non-retina displays. */
  font-size: 0.65rem;
  letter-spacing: 0;
  color: rgba(28,22,8,0.5);
  white-space: nowrap;
  font-weight: 500;
}

.agenda-today .agenda-time-pill {
  color: rgba(150,65,35,0.75);
}

/* "Right now" — events whose start/end window covers the current
   moment. The time pill gets a small pulse (opacity, not scale, so
   the type doesn't shift) and a tiny "● now" suffix appears beside
   it. The class is toggled live by JS every 30s, so events crossing
   into or out of the now-window during a long browser session
   update without needing a page reload. */
.agenda-now .agenda-time-pill {
  color: rgba(150,65,35,0.95);
  font-weight: 600;
}

/* Clear out the row-level positioning since we're moving the
   annotation inline with the title text. */
.agenda-now {
  position: relative;
  overflow: visible;
}

/* "Happening now" annotation — sits inline AFTER the event title
   text, so its position naturally tracks the actual title length.
   Short title → annotation sits closer to the left. Long title →
   farther right. Reads like a real margin scribble: positioned
   relative to where the line of text actually ends, not floating
   in the row's right gutter.

   The arrow points back-and-slightly-up at the title text just to
   its left, like a journalist's pen-stroke from "now" curving back
   to the active line. The whole thing is tilted up and rises
   slightly above the title baseline, breaking the agenda's grid
   alignment to feel hand-drawn rather than typeset.

   DELIBERATELY SINGULAR. The margin-note voice is reserved for the
   agenda specifically — it works here because the row has natural
   horizontal room next to event titles for the annotation to land.
   Extending this voice to other widgets (the song widget being the
   obvious candidate) was attempted but the layouts don\'t
   accommodate the curve-back-at-content pattern: titles get
   truncated, columns are narrow, the annotation can\'t point AT
   anything specific. Better to keep this as a designed singular
   gesture than dilute it across widgets where it doesn\'t fit. */
.agenda-now .agenda-title::after {
  content: 'now';
  display: inline-block;
  margin-left: 0.4rem;
  /* Padding-left holds the arrow with a small breathing gap before
     "now" begins. */
  padding-left: 2.3rem;
  font-family: 'Caveat', cursive;
  font-size: 1rem;
  font-weight: 500;
  line-height: 1;
  color: rgba(150,65,35,0.85);
  letter-spacing: 0.01em;
  vertical-align: top;
  position: relative;
  /* More tilt — pushes the annotation further from "typeset" toward
     "scribbled in the margin". */
  transform: rotate(-9deg) translateY(-0.3rem);
  transform-origin: left bottom;
  pointer-events: none;
  animation: agenda-now-pulse 3.5s ease-in-out infinite;

  /* Curving hand-drawn arrow. SVG sits in the padding-left zone via
     `background-position: left center`. The arrow has a subtle
     downward tilt baked into the path: rear (right, near "now")
     starts slightly higher, head (left, at title) ends slightly
     lower. Like the natural hand-stroke of someone scribbling a
     pointer line on paper — pen starts up high and lands lower as
     it moves outward. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 18'><path d='M 33,13 C 28,14 18,15 10,15 C 7,15 5,15 4,14' fill='none' stroke='rgba(150,65,35,0.78)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/><path d='M 4,14 L 9,12' fill='none' stroke='rgba(150,65,35,0.78)' stroke-width='1.5' stroke-linecap='round'/><path d='M 4,14 L 9,17' fill='none' stroke='rgba(150,65,35,0.78)' stroke-width='1.5' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 36px auto;
}

.agenda-now .agenda-event-right {
  /* No more padding override needed — annotation flows inline with
     the title, so it can never overlap or disappear. */
  padding-right: 0.5rem;
}

@keyframes agenda-now-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
  .agenda-now .agenda-time-pill::before,
  .agenda-now .agenda-time-pill::after {
    animation: none;
  }
}

/* Cancelled events — strikethrough title + a strike-out mark in the
   margin (replacing whatever semantic icon was there). We keep the
   time pill so you still see "this slot was at 14:30" as context,
   but the whole row visually recedes. Hand-drawn-feeling strike SVG
   matches the turbulence-filtered aesthetic of the other margin marks. */
.agenda-cancelled .agenda-title {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(28,22,8,0.45);
  color: rgba(28,22,8,0.4);
}
.agenda-cancelled .agenda-event-loc {
  color: rgba(28,22,8,0.3);
  text-decoration: line-through;
  text-decoration-color: rgba(28,22,8,0.25);
}
.agenda-cancelled .agenda-time-pill {
  color: rgba(28,22,8,0.28);
  text-decoration: line-through;
  text-decoration-color: rgba(28,22,8,0.2);
}
/* Override the margin mark with a strike-out — higher specificity
   (.agenda-event.agenda-cancelled) wins regardless of which mark
   variant the row also has. */
.agenda-event.agenda-cancelled .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.06' numOctaves='2' seed='4'/><feDisplacementMap in='SourceGraphic' scale='1.6'/></filter><path d='M3 12 Q 9 11.5, 14 12.5 T 21 12' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' opacity='0.55' filter='url(%23r)'/></svg>");
  opacity: 1;
}
/* Today's cancelled rows get a slightly more saturated strike to match
   the today-row attention treatment used elsewhere */
.agenda-today.agenda-cancelled .agenda-event-left::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><filter id='r'><feTurbulence baseFrequency='0.06' numOctaves='2' seed='4'/><feDisplacementMap in='SourceGraphic' scale='1.6'/></filter><path d='M3 12 Q 9 11.5, 14 12.5 T 21 12' fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' opacity='0.7' filter='url(%23r)'/></svg>");
}

/* Stacked time range: start time on top, end time below (smaller, quieter)
   — like a planner entry written by hand in the margin */
.agenda-time-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1;
  gap: 0.1rem;
}

.agenda-time-stack .agenda-time-start {
  /* inherits from .agenda-time-pill — full size, full color */
}

.agenda-time-stack .agenda-time-end {
  font-size: 0.46rem;
  color: rgba(28,22,8,0.32);
  letter-spacing: 0.04em;
  position: relative;
  padding-left: 0.5rem;
}

/* Small dash before the end time, like writing "↳ 10:30" in a planner */
.agenda-time-stack .agenda-time-end::before {
  content: '–';
  position: absolute;
  left: 0;
  top: 0;
  color: inherit;
  opacity: 0.6;
}

.agenda-today .agenda-time-stack .agenda-time-end {
  color: rgba(150,65,35,0.55);
}

/* All-day combo: hand-drawn asterisk above "all day" text */
.agenda-time-allday {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  line-height: 1;
}

/* Asterisk is hidden — every event now has a semantic mark in the margin
   that does the "this needs attention" job, plus the "all day" text below
   covers the timing. The asterisk became redundant. */
.agenda-allday-mark {
  display: none;
}

.agenda-allday-text {
  font-family: 'Caveat', cursive;
  font-size: 0.72rem;
  color: rgba(28,22,8,0.5);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.agenda-today .agenda-allday-text {
  color: rgba(150,65,35,0.7);
}

.agenda-event-right {
  flex: 1;
  min-width: 0;
}

.agenda-title {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.72rem;
  color: rgba(28,22,8,0.78);
  line-height: 1.35;
}

.agenda-today .agenda-title {
  color: rgba(28,22,8,0.88);
  font-weight: 700;
}

.agenda-loc {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  color: rgba(28,22,8,0.28);
  margin-top: 0.05rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Torn bottom edge */
.agenda-card::before {
  content: '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 3px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px, transparent 4px,
    rgba(28,22,8,0.06) 4px, rgba(28,22,8,0.06) 8px
  );
  z-index: 2;
}

/* ── RSS collapsible ─────────────────────────────────────── */
.rss-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  color: rgba(28,22,8,0.3);
  line-height: 1;
  transition: color 0.15s;
  flex-shrink: 0;
  margin-left: auto;
}

.rss-header:hover .rss-toggle { color: rgba(28,22,8,0.55); }

.rss-body {
  overflow: hidden;
}

/* cal-forecast strip removed — forecast is now in week grid */

/* ── Word / character counter ────────────────────────────── */
.item-counter { cursor: default; }

.counter-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  display: flex;
  flex-direction: column;
}

.item-counter:hover .counter-card { box-shadow: var(--shadow-hover); }

.counter-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.45rem 0.8rem 0.4rem;
  border-bottom: 1px solid rgba(28,22,8,0.08);
  gap: 0.5rem;
}

.counter-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.62);
}

.counter-target-wrap {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.counter-target {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  width: 62px;
  border: none;
  border-bottom: 1px solid rgba(28,22,8,0.15);
  background: transparent;
  color: rgba(28,22,8,0.55);
  letter-spacing: 0.06em;
  text-align: right;
  padding: 0.1rem 0.2rem;
  outline: none;
}

.counter-target:focus { border-bottom-color: rgba(150,65,35,0.4); }
.counter-target::placeholder { color: rgba(28,22,8,0.2); }

/* Hide number spinners */
.counter-target::-webkit-inner-spin-button,
.counter-target::-webkit-outer-spin-button { -webkit-appearance: none; }
.counter-target { -moz-appearance: textfield; }

.counter-textarea {
  font-family: 'Special Elite', cursive;
  font-size: 0.82rem;
  line-height: 1.55;
  color: rgba(28,22,8,0.78);
  background: transparent;
  border: none;
  resize: none;
  padding: 0.7rem 0.8rem;
  min-height: 90px;
  outline: none;
  width: 100%;
  box-sizing: border-box;
}

.counter-textarea::placeholder { color: rgba(28,22,8,0.2); font-style: italic; }

/* Progress bar */
.counter-bar {
  height: 2px;
  background: rgba(28,22,8,0.07);
  margin: 0 0.8rem;
  border-radius: 1px;
  overflow: hidden;
}

.counter-bar-fill {
  height: 100%;
  width: 0;
  background: rgba(28,22,8,0.25);
  border-radius: 1px;
  transition: width 0.15s, background 0.2s;
}

.counter-bar-fill.counter-warn { background: rgba(180,110,20,0.6); }
.counter-bar-fill.counter-over { background: rgba(160,30,30,0.65); }

.counter-foot {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  padding: 0.45rem 0.8rem 0.5rem;
  border-top: 1px solid rgba(28,22,8,0.06);
  margin-top: 0.3rem;
}

.counter-stat {
  font-family: 'Playfair Display', serif;
  font-size: 0.9rem;
  font-weight: 700;
  color: rgba(28,22,8,0.7);
  line-height: 1;
}

.counter-unit {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.4rem;
  font-weight: 400;
  color: rgba(28,22,8,0.3);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-left: 0.15rem;
}

.counter-status {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.45rem;
  color: rgba(28,22,8,0.35);
  margin-left: auto;
  letter-spacing: 0.06em;
}

.counter-status-warn { color: rgba(180,110,20,0.75); }
.counter-status-over { color: rgba(160,30,30,0.7); }

/* ── Source reminder — matches mind card aesthetic ──────── */
.item-sources { cursor: default; }

.sources-card {
  background: #f0ead8;
  border: 1px solid rgba(28,22,8,0.12);
  border-top: none;
  border-bottom: none;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  position: relative;
  overflow: hidden;
  padding: 0 0 0.4rem;
}

.item-sources:hover .sources-card { box-shadow: var(--shadow-hover); }

/* Spiral perforation at top — same as mind card */
.sources-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 8px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px, transparent 10px,
    rgba(28,28,26,0.08) 10px, rgba(28,28,26,0.08) 14px
  );
  border-bottom: 1px solid rgba(28,28,26,0.08);
  z-index: 2;
}

/* Ruled lines */
.sources-card::after {
  content: '';
  position: absolute;
  top: 8px; left: 0; right: 0; bottom: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 28px,
    rgba(100,80,50,0.1) 28px, rgba(100,80,50,0.1) 29px
  );
  pointer-events: none;
  z-index: 1;
}

.sources-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 1rem 1.2rem 0.35rem;
  border-bottom: 1px solid rgba(180,60,60,0.18);
  position: relative;
  z-index: 2;
}

.sources-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.55);
}

.src-add-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.08em;
  color: rgba(150,65,35,0.6);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: color 0.15s;
}

.src-add-btn:hover { color: rgba(150,65,35,0.9); }

.src-list {
  list-style: none;
  margin: 0;
  padding: 0.3rem 0 0.3rem;
  position: relative;
  z-index: 2;
}

.src-row {
  display: grid;
  grid-template-columns: 2.2rem 1fr 1fr auto;
  align-items: baseline;
  padding: 0.3rem 1.2rem 0.3rem 0.4rem;
  border-bottom: 1px dotted rgba(100,80,50,0.12);
  gap: 0.5rem;
}

.src-row:last-child { border-bottom: none; }

.src-check {
  background: none;
  border: none;
  cursor: pointer;
  width: 14px;
  height: 14px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-left: 1.2rem;
  border: 1px solid rgba(28,22,8,0.18);
  border-radius: 2px;
  transition: border-color 0.15s;
}

.src-check:hover { border-color: rgba(150,65,35,0.5); }

.src-name {
  font-family: 'Special Elite', cursive;
  font-size: 0.82rem;
  color: rgba(28,22,8,0.78);
  line-height: 1.3;
  outline: none;
  min-width: 0;
  transition: color 0.15s;
}

.src-name:focus { color: rgba(28,22,8,0.92); }

.src-note {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  color: rgba(28,22,8,0.35);
  letter-spacing: 0.04em;
  outline: none;
  min-width: 0;
  font-style: italic;
}

.src-note:empty::before {
  content: 'note…';
  color: rgba(28,22,8,0.15);
}

.src-delete {
  background: none;
  border: none;
  font-size: 0.8rem;
  color: rgba(28,22,8,0.18);
  cursor: pointer;
  padding: 0 0.3rem;
  line-height: 1;
  transition: color 0.15s;
  flex-shrink: 0;
}

.src-delete:hover { color: rgba(160,30,30,0.5); }

/* Checked state */
.src-done .src-name {
  color: rgba(28,22,8,0.3);
  text-decoration: line-through;
  text-decoration-color: rgba(28,22,8,0.2);
}

.src-done .src-note { color: rgba(28,22,8,0.2); }

/* ── Notebook focus mode — full-screen paper ────────────── */

body.focus-mode {
  overflow: hidden;
}

/* Board recedes */
body.focus-mode #board,
body.focus-mode header,
body.focus-mode .filter-bar {
  opacity: 0.06;
  filter: blur(2px);
  transition: opacity 0.3s, filter 0.3s;
  pointer-events: none;
  user-select: none;
}

/* Full-screen layer — the paper IS the screen */
.focus-layer {
  position: fixed;
  inset: 0;
  z-index: 8999;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Paper background fills the viewport */
  background: #faf6ea;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 27px,
    rgba(100,80,50,0.07) 27px, rgba(100,80,50,0.07) 28px
  );
}

.focus-layer.focus-in {
  opacity: 1;
  pointer-events: all;
}

/* Subtle top border only — no pin */
.focus-layer::before {
  content: '';
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: rgba(150,65,35,0.18);
  z-index: 10;
  pointer-events: none;
}

/* Outer wrap — centred reading column */
.focus-wrap {
  position: relative;
  width: 100%;
  max-width: 780px;
  margin: 0 auto;
  padding: 3.5rem 5vw 8rem;
  box-sizing: border-box;
  min-height: 100vh;
}

/* focus-mind-surface — the clean writing container */
.focus-mind-surface {
  padding: 0;
}

/* Suppress pin on focus wrap — layer::after has the pin */
.focus-wrap .item::before { display: none !important; }

/* Header row */
.focus-edit-zone { position: relative; }

.focus-zone-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 0 0.5rem;
  border-bottom: 1px solid rgba(180,60,60,0.15);
  margin-bottom: 0;
}

.focus-zone-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.3);
}

.focus-zone-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  color: rgba(28,22,8,0.22);
  letter-spacing: 0.08em;
}

/* Writing surface */
.focus-mind-ce {
  font-size: 1.1rem !important;
  line-height: 28px !important;
  cursor: text !important;
  min-height: 60vh !important;
  padding: 1.2rem 0 4rem !important;
  color: rgba(28,22,8,0.84) !important;
  width: 100% !important;
}

.focus-mind-ce div,
.focus-mind-ce p {
  margin-top: 0.5em;
}

.focus-mind-ce div:first-child,
.focus-mind-ce p:first-child {
  margin-top: 0;
}

/* Sticky save bar — full width, paper-toned */
.focus-save-bar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: rgba(250,246,234,0.97);
  border-top: 1px solid rgba(28,22,8,0.12);
  backdrop-filter: blur(8px);
  z-index: 9001;
}

.focus-bar-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.55rem max(5vw, calc(50% - 390px));
}

.focus-wc {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.35);
  white-space: nowrap;
  flex-shrink: 0;
}

.focus-bar-slot {
  flex: 1;
  display: flex;
  justify-content: center;
  min-width: 0;
}

/* Compact override for the piece picker when it's mounted in the
   focus save bar. Removes the dotted top-border the inline version
   has (the bar provides its own boundary), shrinks the label, and
   constrains width so it doesn't bully the action buttons. */
.focus-bar-piece-picker {
  margin: 0 !important;
  padding: 0 !important;
  border-top: none !important;
  width: auto;
  max-width: 420px;
}
.focus-bar-piece-picker label {
  font-size: 0.55rem !important;
  color: rgba(28,22,8,0.35) !important;
}
.focus-bar-piece-picker .inline-piece-select {
  font-size: 0.7rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}

@media (max-width: 760px) {
  .focus-bar-piece-picker label { display: none; }
}

.focus-bar-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-shrink: 0;
  margin-left: auto;
}

.focus-preview-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.35);
  background: none;
  border: 1px solid rgba(28,22,8,0.12);
  padding: 0.28rem 0.7rem;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
  border-radius: 1px;
}

.focus-preview-btn:hover { color: rgba(28,22,8,0.62); border-color: rgba(28,22,8,0.26); }

.focus-preview-btn.focus-preview-active {
  color: rgba(150,65,35,0.75);
  border-color: rgba(150,65,35,0.28);
  background: rgba(150,65,35,0.05);
}

.focus-save-btn-inner {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(252,249,240,0.97);
  background: rgba(28,22,8,0.75);
  border: 1px solid rgba(28,22,8,0.75);
  padding: 0.36rem 1rem;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}

.focus-save-btn-inner:hover { background: rgba(28,22,8,0.9); border-color: rgba(28,22,8,0.9); }

/* Preview pane */
.focus-preview-pane {
  font-family: 'Special Elite', cursive !important;
  font-size: 1.1rem !important;
  line-height: 28px !important;
  color: rgba(28,22,8,0.84) !important;
  padding: 1.2rem 0 4rem !important;
  min-height: 60vh;
  cursor: default;
}

.focus-preview-pane p,
.focus-preview-pane .mind-p {
  font-family: 'Special Elite', cursive;
  font-size: 1.1rem;
  line-height: 28px;
  margin: 0 0 0.6rem;
}

.focus-preview-pane p:last-child,
.focus-preview-pane .mind-p:last-child { margin-bottom: 0; }

.focus-esc-hint {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.14);
  text-align: center;
  margin: 0.5rem 0 0;
  pointer-events: none;
}

/* Focus trigger */
.focus-trigger {
  position: absolute;
  bottom: 1.1rem; left: 0.6rem;
  width: 18px; height: 18px;
  background: none; border: none;
  color: rgba(28,22,8,0.18);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 5; opacity: 0;
  transition: opacity 0.15s, color 0.15s;
  pointer-events: none; padding: 0;
}

@media (min-width: 900px) {
  .filter-notes .board-col .item:hover .focus-trigger {
    opacity: 1; pointer-events: all;
  }
}

.focus-trigger:hover { color: rgba(150,65,35,0.6); }
.filter-notes .board-col .item { cursor: default; position: relative; }

/* ── Pin-to-top trigger ──────────────────────────────────── */
/* Small thumbtack icon at the top-left of each tag-aware card.
   Hover-only when unpinned (subtle utility); always-visible when
   pinned so the state reads at a glance and the user can unpin
   without hunting. The pin glyph fills with warm-red when active. */
.pin-trigger {
  position: absolute;
  top: 0.5rem; left: 0.5rem;
  width: 18px; height: 18px;
  background: none; border: none;
  color: rgba(28,22,8,0.25);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 5; opacity: 0;
  transition: opacity 0.15s, color 0.15s;
  pointer-events: none; padding: 0;
}
@media (min-width: 900px) {
  .filter-notes .board-col .item:hover .pin-trigger {
    opacity: 1; pointer-events: all;
  }
}
.pin-trigger:hover { color: rgba(150,65,35,0.7); }
/* Pinned state: always visible, warm-red icon. */
.pin-trigger.pinned {
  opacity: 1;
  pointer-events: all;
  color: rgba(150,65,35,0.85);
}
.pin-trigger.pinned:hover { color: rgba(150,65,35,1); }

/* Pinned card visual indicator — a small ribbon-like accent at the
   top edge so even without the button visible (mobile, list view)
   the pinned state is communicated by the card itself. */
.board-col .item._has_pinned_visual {
  /* Reserved for future visual treatment if needed. */
}

/* mind-p paragraph — give paragraphs room to breathe */
.mind-p { margin: 0 0 0.5rem; display: block; line-height: 1.65; }

/* Word counter widget */
.counter-words, .counter-chars { font-size: 1.1rem !important; }

/* ── Markdown — typewriter + hand-annotation aesthetic ──── */

/* # Big heading — fresh ribbon, pressed harder */
.mind-md-h1 {
  font-family: 'Playfair Display', serif;
  font-size: 1.15rem;
  font-weight: 700;
  color: rgba(28,22,8,0.88);
  margin: 0.6rem 0 0.2rem;
  line-height: 1.3;
  display: block;
}

/* ## Section heading — typed in caps, underlined with a ruler */
.mind-md-h2 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.5);
  margin: 0.7rem 0 0.2rem;
  display: block;
  border-bottom: 1.5px solid rgba(28,22,8,0.12);
  padding-bottom: 0.15rem;
}

/* ### Sub-section */
.mind-md-h3 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.32);
  margin: 0.5rem 0 0.1rem;
  display: block;
}

/* **bold** — double-struck key, slightly heavier impression */
.mind-p strong,
.mind-md-h1 strong,
.mind-md-bq strong,
.fieldnote-body strong {
  font-weight: 700;
  color: rgba(28,22,8,0.95);
  text-shadow: 0.3px 0 0 rgba(28,22,8,0.15);
  letter-spacing: -0.01em;
}

/* *italic* — switched to handwriting, a different person's annotation */
.mind-p em,
.mind-md-h1 em,
.mind-md-bq em,
.fieldnote-body em {
  font-style: italic;
  color: rgba(28,22,8,0.7);
  font-family: 'Caveat', cursive;
  font-size: 1.08em;
  letter-spacing: 0.01em;
}

/* > blockquote — indented with a hand-drawn vertical line */
.mind-md-bq {
  margin: 0.5rem 0 0.5rem 0.2rem;
  padding-left: 0.85rem;
  color: rgba(28,22,8,0.55);
  font-style: italic;
  display: block;
  position: relative;
  border-left: none;
}

.mind-md-bq::before {
  content: '';
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 2px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='5' height='100'%3E%3Cpath d='M2.5 0 Q1 8 2.8 15 Q4 24 2 32 Q0.5 42 3 50 Q4.2 58 2 68 Q0.8 78 2.5 85 Q3.8 92 2 100' fill='none' stroke='rgba(150,65,35,0.35)' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") repeat-y;
  background-size: 5px 100px;
}

/* --- horizontal rule — rough hand-drawn line */
.mind-md-hr {
  border: none;
  height: 4px;
  margin: 0.7rem 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='5'%3E%3Cpath d='M0 2.5 Q8 1 20 2.8 Q35 4 50 2 Q62 0.8 80 3 Q95 4.2 110 2 Q125 0.5 145 3.2 Q160 4.5 180 2 Q195 0.8 215 3 Q230 4 250 2.5 Q268 1 285 3 Q295 4 300 2.5' fill='none' stroke='rgba(28,22,8,0.12)' stroke-width='1.2'/%3E%3C/svg%3E") repeat-x center;
  background-size: 300px 5px;
}

/* - list item — hand-drawn em dash */
.mind-md-li {
  display: block;
  padding-left: 1.1rem;
  text-indent: -1.1rem;
  margin: 0.2rem 0;
}

.mind-md-li::before {
  content: '—\00a0';
  color: rgba(150,65,35,0.45);
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 1.1em;
}

/* 1. numbered list — handwritten number */
.mind-md-oli {
  display: block;
  padding-left: 1.6rem;
  text-indent: -1.6rem;
  margin: 0.2rem 0;
}

.mind-md-oli::before {
  content: attr(data-n) '.\00a0';
  color: rgba(150,65,35,0.5);
  font-family: 'Caveat', cursive;
  font-weight: 700;
  font-size: 1.1em;
}

/* `code` — correction tape over typewriter */
.mind-md-code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.82em;
  background: rgba(28,22,8,0.05);
  padding: 0.05em 0.3em;
  border-radius: 1px;
  color: rgba(28,22,8,0.72);
  border-bottom: 1.5px dashed rgba(28,22,8,0.15);
}

/* ~~strikethrough~~ — wobbly hand-drawn line through text */
.mind-md-del {
  text-decoration: none;
  color: rgba(28,22,8,0.35);
  position: relative;
  display: inline;
}

.mind-md-del::after {
  content: '';
  position: absolute;
  left: -2px;
  right: -2px;
  top: 45%;
  height: 4px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='5'%3E%3Cpath d='M0 3.5 Q12 1 22 2.8 Q35 4.2 48 1.5 Q58 0.5 72 3 Q88 4.5 98 2 Q112 0 125 3.2 Q138 4.8 150 2.5 Q165 0.8 180 2' fill='none' stroke='rgba(150,65,35,0.5)' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 180px 5px;
  transform: rotate(-0.3deg);
  pointer-events: none;
}

/* ── Desktop notebook toolbar ────────────────────────────── */
.notebook-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0 0.8rem;
  justify-content: flex-start;
}

.nb-add-btn {
  display: flex;
  align-items: center;
  gap: 0.32rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.32);
  background: none;
  border: 1px solid rgba(28,22,8,0.1);
  padding: 0.28rem 0.65rem;
  cursor: pointer;
  border-radius: 2px;
  transition: all 0.15s;
}

.nb-add-btn:hover {
  color: rgba(150,65,35,0.65);
  border-color: rgba(150,65,35,0.22);
  background: rgba(150,65,35,0.04);
}

.nb-add-btn svg { flex-shrink: 0; color: inherit; }

/* ── Inline edit delete button ───────────────────────────── */
.inline-edit-delete {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(180,40,40,0.45);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 0.3rem;
  margin-right: auto;
  transition: color 0.15s;
}

.inline-edit-delete:hover { color: rgba(180,40,40,0.8); }

/* ── Todo archive button ─────────────────────────────────── */
.todo-archive-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.22);
  background: none;
  border: 1px solid rgba(28,22,8,0.1);
  padding: 0.15rem 0.5rem;
  cursor: pointer;
  border-radius: 1px;
  transition: all 0.15s;
  margin-left: auto;
}

.todo-archive-btn:hover {
  color: rgba(150,65,35,0.6);
  border-color: rgba(150,65,35,0.25);
}

/* ── Todo inline add (desktop) ───────────────────────────── */
.todo-inline-add {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 1.2rem 6px;
  border-top: 1px solid rgba(28,22,8,0.06);
  cursor: pointer;
}

.todo-inline-plus {
  font-size: 13px;
  line-height: 1;
  color: rgba(150,65,35,0.38);
  flex-shrink: 0;
}

.todo-inline-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.28);
  transition: color 0.15s;
}

.todo-inline-add:hover .todo-inline-label { color: rgba(150,65,35,0.5); }
.todo-inline-add:hover .todo-inline-plus { color: rgba(150,65,35,0.6); }

.todo-inline-input {
  font-family: 'Special Elite', cursive;
  font-size: 0.82rem;
  color: rgba(28,22,8,0.84);
  background: transparent;
  border: none;
  outline: none;
  flex: 1;
  caret-color: rgba(150,65,35,0.8);
}

.todo-inline-input::placeholder { color: rgba(28,22,8,0.22); font-style: italic; }

.todo-inline-type {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.28);
  background: none;
  border: 1px solid rgba(28,22,8,0.1);
  padding: 2px 5px;
  cursor: pointer;
  border-radius: 1px;
  flex-shrink: 0;
  transition: all 0.15s;
}

.todo-inline-type:hover,
.todo-inline-type-heading {
  color: rgba(150,65,35,0.65);
  border-color: rgba(150,65,35,0.25);
}

/* ── Mobile notebook dashboard ───────────────────────────── */
@media (max-width: 639px) {

  /* Board columns hidden only when mobile dashboard is active (class added by JS) */
  .board.mob-active .board-col { display: none !important; }

  .mob-dash {
    padding: 10px 12px 40px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.28s ease, transform 0.28s ease;
  }

  .mob-dash.mob-dash-in { opacity: 1; transform: translateY(0); }

  .mob-ctx {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 4px 2px 6px;
  }

  .mob-ctx-date {
    font-family: 'Playfair Display', serif;
    font-size: 14px;
    font-weight: 700;
    color: rgba(28,22,8,0.55);
  }

  .mob-ctx-wx {
    font-family: 'Libre Baskerville', serif;
    font-size: 10px;
    font-style: italic;
    color: rgba(150,65,35,0.6);
  }

  .mob-widget {
    background: #f8f4e8;
    border: 1px solid rgba(28,22,8,0.09);
    border-radius: 2px;
    box-shadow: 0 1px 0 rgba(255,255,255,0.7), 0 2px 8px rgba(28,22,8,0.06);
    overflow: hidden;
  }

  .mob-whead {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 8px 12px 6px;
    border-bottom: 1px solid rgba(180,60,60,0.12);
  }

  .mob-wlabel {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.38);
    font-weight: 500;
  }

  .mob-wmeta {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7.5px;
    letter-spacing: 0.05em;
    color: rgba(28,22,8,0.28);
  }

  .mob-widget-foot {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.08em;
    color: rgba(150,65,35,0.5);
    text-transform: uppercase;
    padding: 5px 12px 7px;
    border-top: 1px solid rgba(28,22,8,0.05);
    cursor: pointer;
  }

  .mob-todo-body { padding: 2px 0 0; }

  .mob-todo-section {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.32);
    padding: 6px 12px 2px;
  }

  .mob-todo-row {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 6px 12px;
    border-bottom: 1px solid rgba(28,22,8,0.04);
    cursor: pointer;
    -webkit-tap-highlight-color: rgba(150,65,35,0.06);
  }

  .mob-todo-row:last-of-type { border-bottom: none; }
  .mob-todo-row:active { background: rgba(150,65,35,0.04); }

  /* Per-row mobile actions (edit/delete). No tray, no background, no
     rounded boxes — earlier versions had a tinted "control panel"
     feel that read as bolt-on iOS UI against the paper-and-typewriter
     vocabulary of the rest of the row. Here the icons just hang at
     the right edge as quiet marginalia: same warm-ink color as the
     typewriter text, minimal padding, no visible chrome at rest. */
  .mob-todo-actions {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
  }
  .mob-todo-action {
    background: none;
    border: none;
    cursor: pointer;
    /* Generous padding still gives a comfortable tap target (~28×26)
       — the tap target is invisible (no background) but it's there. */
    padding: 6px 7px;
    color: rgba(28,22,8,0.35);
    display: inline-flex;
    align-items: center;
    -webkit-tap-highlight-color: transparent;
  }
  .mob-todo-action svg {
    /* Slightly smaller than before (was 13×13) so the icons read as
       quiet marks rather than control glyphs. */
    width: 11px;
    height: 11px;
    display: block;
  }
  /* On press: faint warm-red wash inside a soft round area, no
     visible button frame. Just enough feedback to confirm a tap
     happened. */
  .mob-todo-action:active {
    color: rgba(150,65,35,0.85);
  }
  .mob-todo-delete:active {
    color: rgba(180,40,30,0.85);
  }

  /* Inline edit input — appears in place of .mob-todo-text when the
     user taps the pencil. Matches the row's typography so the swap
     feels like editing the same content, not opening a separate
     dialog. The .mob-todo-text and .mob-todo-actions next to it are
     set to display:none by the JS while editing, so the input takes
     the row's full available width. */
  .mob-todo-edit-input {
    flex: 1;
    min-width: 0;
    font-family: 'Special Elite', cursive;
    font-size: 13px;
    line-height: 1.38;
    color: rgba(28,22,8,0.92);
    background: rgba(255, 250, 235, 0.85);
    border: 1px solid rgba(150,65,35,0.25);
    border-radius: 3px;
    padding: 4px 7px;
    margin: -3px 0;
    /* Soft warm focus ring instead of the browser default. */
    outline: none;
    box-shadow: 0 0 0 2px rgba(150,65,35,0.08);
    -webkit-appearance: none;
            appearance: none;
  }
  .mob-todo-edit-input:focus {
    border-color: rgba(150,65,35,0.5);
    box-shadow: 0 0 0 2px rgba(150,65,35,0.14);
  }

  .mob-chk {
    width: 14px;
    height: 14px;
    border: 1px solid rgba(28,22,8,0.2);
    border-radius: 2px;
    flex-shrink: 0;
    margin-top: 1px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .mob-chk-done {
    border-color: rgba(150,65,35,0.35);
    background: rgba(150,65,35,0.05);
  }

  .mob-chk svg { width: 10px; height: 10px; }

  .mob-todo-text {
    font-family: 'Special Elite', cursive;
    font-size: 13px;
    line-height: 1.38;
    color: rgba(28,22,8,0.84);
  }

  /* ── Mobile annotation transforms ──
     Desktop uses elaborate hand-drawn SVG markup for ((circle)), %%scribble%%,
     etc. On mobile these would be cluttered, so we hide the SVG layer and
     reduce each marker to a subtle text-level treatment. The result still
     conveys emphasis without the visual noise. */

  /* Hide all decorative SVGs inside todo items on mobile */
  .mob-todo-text .mann-circ-svg,
  .mob-todo-text .mann-scribble-svg,
  .mob-todo-text .mann-mrg-arrow { display: none; }

  /* ((circle)) — became a subtle warm tint pill on mobile */
  .mob-todo-text .mann-circ {
    background: rgba(150,65,35,0.10);
    color: rgba(150,65,35,0.95);
    padding: 1px 5px;
    border-radius: 2px;
    font-weight: inherit;
  }

  /* ==highlight== — keep the yellow but slightly muted for the typewriter feel */
  .mob-todo-text .mann-hl {
    background: rgba(255,220,90,0.4);
    padding: 0 2px;
  }

  /* __underline__ — keep as a thin underline */
  .mob-todo-text .mann-ul {
    text-decoration: underline;
    text-decoration-color: rgba(28,22,8,0.4);
    text-underline-offset: 2px;
  }

  /* __*double underline*__ — slightly heavier */
  .mob-todo-text .mann-ul2 {
    text-decoration: underline;
    text-decoration-color: rgba(28,22,8,0.55);
    text-decoration-thickness: 2px;
    text-underline-offset: 2px;
  }

  /* ~_wavy_~ — wavy underline */
  .mob-todo-text .mann-wavy {
    text-decoration: underline wavy rgba(150,65,35,0.5);
    text-underline-offset: 2px;
  }

  /* ~~strikethrough~~ */
  .mob-todo-text .mann-st {
    text-decoration: line-through;
    text-decoration-color: rgba(28,22,8,0.5);
  }

  /* %%scribble-out%% — render as strikethrough on mobile (the scribble SVG is hidden) */
  .mob-todo-text .mann-scribble {
    text-decoration: line-through;
    text-decoration-color: rgba(28,22,8,0.6);
    text-decoration-thickness: 1.5px;
  }
  .mob-todo-text .mann-scribble-text {
    color: rgba(28,22,8,0.55);
  }

  /* ^^inserted^^ word — keep visible but inline */
  .mob-todo-text .mann-ins {
    color: rgba(180,40,20,0.75);
  }
  .mob-todo-text .mann-ins-word {
    border-bottom: 1px dashed rgba(180,40,20,0.4);
  }

  /* >>margin note<< — keep inline italic since margins aren't a thing on mobile */
  .mob-todo-text .mann-mrg {
    font-style: italic;
    color: rgba(150,65,35,0.65);
    font-size: 0.9em;
  }
  .mob-todo-text .mann-mrg-text {
    border-left: 2px solid rgba(150,65,35,0.3);
    padding-left: 4px;
    margin-left: 2px;
  }

  /* When the whole row is done, fade the markup along with the text */
  .mob-done .mob-todo-text .mann-circ {
    background: rgba(28,22,8,0.05);
    color: rgba(28,22,8,0.32);
  }
  .mob-done .mob-todo-text .mann-hl {
    background: rgba(28,22,8,0.04);
  }

  .mob-done .mob-todo-text {
    text-decoration: line-through;
    color: rgba(28,22,8,0.28);
  }

  /* Deadline + completion pills — copied verbatim from the desktop
     .todo-text via innerHTML in the mobile renderer. Without these
     mobile rules they render as plain text, making "today" /
     "tomorrow" / "17:30 today" look like part of the task name
     rather than a deadline annotation. Sized down slightly from
     desktop since mobile rows are narrower. */
  .mob-todo-text .todo-deadline-pill,
  .mob-todo-text .todo-completed-pill {
    display: inline-block;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 1px 5px;
    margin-left: 0.35em;
    border-radius: 2px;
    vertical-align: 0.05em;
    white-space: nowrap;
  }
  .mob-todo-text .todo-deadline-pill {
    background: rgba(240,210,90,0.45);
    color: rgba(80,55,15,0.85);
  }
  .mob-todo-text .todo-deadline-today {
    background: rgba(240,210,90,0.55);
  }
  .mob-todo-text .todo-deadline-overdue {
    background: rgba(200,80,50,0.25);
    color: rgba(150,40,20,0.95);
  }
  .mob-todo-text .todo-deadline-soon {
    background: rgba(240,180,90,0.4);
  }
  .mob-todo-text .todo-deadline-future {
    background: rgba(28,22,8,0.06);
    color: rgba(28,22,8,0.55);
  }
  .mob-todo-text .todo-completed-pill {
    background: rgba(28,22,8,0.05);
    color: rgba(28,22,8,0.4);
  }

  .mob-todo-add {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px 8px;
    border-top: 1px solid rgba(28,22,8,0.06);
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    letter-spacing: 0.08em;
    color: rgba(150,65,35,0.45);
    cursor: pointer;
  }

  .mob-add-plus { font-size: 15px; line-height: 1; color: rgba(150,65,35,0.4); }

  .mob-add-wrap {
    display: flex;
    align-items: center;
    background: rgba(150,65,35,0.04);
    border-top: 1px solid rgba(150,65,35,0.12);
  }

  .mob-todo-input {
    flex: 1;
    padding: 7px 12px;
    font-family: 'Special Elite', cursive;
    font-size: 13px;
    color: rgba(28,22,8,0.84);
    background: transparent;
    border: none;
    outline: none;
    caret-color: rgba(150,65,35,0.8);
  }

  .mob-todo-input::placeholder { color: rgba(28,22,8,0.25); font-style: italic; }

  .mob-add-type-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.08em;
    color: rgba(28,22,8,0.3);
    background: none;
    border: none;
    border-left: 1px solid rgba(28,22,8,0.1);
    padding: 8px 10px;
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: color 0.15s;
  }

  .mob-add-type-btn.mob-add-type-heading { color: rgba(150,65,35,0.7); }

  .mob-archive-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.22);
    background: none;
    border: 1px solid rgba(28,22,8,0.1);
    padding: 3px 7px;
    cursor: pointer;
    border-radius: 1px;
    margin-left: auto;
    transition: all 0.15s;
    -webkit-tap-highlight-color: transparent;
  }

  .mob-archive-btn:active { color: rgba(150,65,35,0.7); border-color: rgba(150,65,35,0.3); }

  .mob-agenda-body { padding: 2px 0 4px; }

  .mob-agenda-loading, .mob-rss-loading {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.1em;
    color: rgba(28,22,8,0.28);
    padding: 10px 12px;
    font-style: italic;
  }

  .mob-src-bar {
    height: 2px;
    background: rgba(28,22,8,0.08);
    margin: 0 12px 2px;
  }

  .mob-src-bar-fill {
    height: 100%;
    background: rgba(150,65,35,0.4);
    border-radius: 1px;
    transition: width 0.4s ease;
  }

  .mob-note-list { padding: 2px 0 2px; }

  .mob-note-row {
    position: relative;
    overflow: hidden;
    border-bottom: 1px solid rgba(28,22,8,0.04);
    cursor: pointer;
    -webkit-tap-highlight-color: rgba(150,65,35,0.06);
  }

  /* Rows without swipe wrapper (logged-out) keep direct grid */
  .mob-note-row:not(:has(.mob-note-row-inner)) {
    display: grid;
    grid-template-columns: 52px 1fr;
    gap: 8px;
    padding: 6px 12px;
    align-items: baseline;
  }

  .mob-note-row:last-child { border-bottom: none; }
  .mob-note-row:active { background: rgba(150,65,35,0.04); }

  .mob-note-date {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.04em;
    color: rgba(28,22,8,0.35);
    line-height: 1.4;
  }

  .mob-note-loc { font-size: 8px; color: rgba(28,22,8,0.45); font-weight: 500; }
  .mob-note-dsmall { font-size: 7px; color: rgba(28,22,8,0.25); }

  .mob-note-preview {
    font-family: 'Special Elite', cursive;
    font-size: 12px;
    line-height: 1.38;
    color: rgba(28,22,8,0.78);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .mob-new-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(150,65,35,0.55);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
  }

  .mob-rss-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 6px 12px;
    border-bottom: 1px solid rgba(28,22,8,0.04);
    cursor: pointer;
  }

  .mob-rss-row:last-child { border-bottom: none; }
  .mob-rss-row:active { background: rgba(28,22,8,0.03); }

  .mob-rss-hl {
    font-family: 'Libre Baskerville', serif;
    font-size: 11.5px;
    line-height: 1.38;
    color: rgba(28,22,8,0.82);
  }

  .mob-rss-src {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7.5px;
    letter-spacing: 0.05em;
    color: rgba(28,22,8,0.32);
    margin-top: 2px;
    text-transform: uppercase;
  }

  /* ── Mobile full-screen editor ── */
  .mob-editor-overlay {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    /* Use dvh to account for iOS keyboard shrinking viewport */
    height: 100dvh;
    z-index: 9500;
    background: #faf6ea;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.22s cubic-bezier(0.4,0,0.2,1);
    /* Ensure it covers everything including board */
    isolation: isolate;
  }

  .mob-editor-overlay:not(.mob-editor-out) { transform: translateX(0); }
  .mob-editor-out { transform: translateX(100%); }

  .mob-editor-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 52px 20px 10px;
    border-bottom: 1px solid rgba(28,22,8,0.08);
    background: rgba(250,246,234,0.97);
    flex-shrink: 0;
    gap: 8px;
  }

  .mob-editor-back {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(150,65,35,0.6);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    white-space: nowrap;
  }

  .mob-editor-meta {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.06em;
    color: rgba(28,22,8,0.3);
    flex: 1;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .mob-editor-priv {
    font-size: 14px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0 2px;
    opacity: 0.5;
    transition: opacity 0.15s;
    flex-shrink: 0;
  }

  .mob-editor-priv:hover, .mob-editor-priv.mob-priv-on { opacity: 1; }

  .mob-editor-save {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(150,65,35,0.8);
    background: none;
    border: 1px solid rgba(150,65,35,0.25);
    padding: 4px 12px;
    cursor: pointer;
    flex-shrink: 0;
  }

  .mob-editor-paper {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    background-color: #faf6ea;
    background-image: repeating-linear-gradient(
      to bottom, transparent, transparent 27px,
      rgba(100,80,50,0.08) 27px, rgba(100,80,50,0.08) 28px
    );
    /* Prevent masonry showing through on iOS */
    position: relative;
    z-index: 1;
  }

  .mob-editor-ce {
    font-family: 'Special Elite', cursive;
    font-size: 16px;
    line-height: 28px;
    color: rgba(28,22,8,0.84);
    padding: 12px 22px 40px;
    min-height: 100%;
    outline: none;
    caret-color: rgba(150,65,35,0.8);
    white-space: pre-wrap;
    word-wrap: break-word;
  }

  .mob-editor-ce div,
  .mob-editor-ce p {
    margin-top: 0.4em;
  }

  .mob-editor-ce div:first-child,
  .mob-editor-ce p:first-child {
    margin-top: 0;
  }

  .mob-editor-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 16px;
    padding-bottom: max(6px, env(safe-area-inset-bottom));
    border-top: 1px solid rgba(28,22,8,0.07);
    background: rgba(250,246,234,0.97);
    flex-shrink: 0;
    /* Above everything */
    position: relative;
    z-index: 2;
  }

  .mob-editor-wc {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    letter-spacing: 0.06em;
    color: rgba(28,22,8,0.4);
  }

  .mob-editor-hint {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8.5px;
    letter-spacing: 0.04em;
    color: rgba(28,22,8,0.22);
  }

  /* Calendar and spotify — suppress pin */
  .mob-calendar-widget .item::before,
  .mob-spotify-widget .item::before { display: none !important; }

  .mob-calendar-widget .item,
  .mob-spotify-widget .item { transform: none !important; box-shadow: none !important; background: transparent !important; }

  /* Filter bar */
  .filter-bar {
    flex-wrap: wrap;
    overflow-x: visible;
    justify-content: center;
    padding: 0.75rem 1rem 0.5rem;
    gap: 0.35rem;
  }

  .filter-btn { font-size: 0.58rem; padding: 0.3rem 0.75rem; white-space: nowrap; }
  .filter-btn-about { margin-left: 0; }

  /* Board */
  .board { padding: 0.75rem 0.75rem 3rem; gap: 1.2rem; }
  /* Reduce tilt on mobile via --final-tilt; the keyframe picks this up
     so cards settle at the smaller mobile angle, not desktop. */
  .item { --final-tilt: calc(var(--r, 0deg) * 0.4); }
  .item:hover { transform: translateY(0) rotate(calc(var(--r, 0deg) * 0.4)) !important; }

  #board { overflow: visible !important; }
  .mob-dash { padding-top: 16px; }
  .mob-calendar-widget,
  .mob-spotify-widget { overflow: visible; position: relative; }
  /* Calendar widget: disable the generic mob-widget wrapper styling
     so it doesn't conflict with the calendar's own card/pages */
  .mob-calendar-widget {
    background: none;
    border: none;
    box-shadow: none;
    padding-bottom: 12px;
  }
  /* Restore stacked paper pages on mobile */
  .mob-calendar-widget .cal-card {
    box-shadow:
      0 4px 8px rgba(28,22,8,0.1),
      0 12px 28px rgba(28,22,8,0.08);
  }
  /* All other widgets clip their content */
  .mob-widget:not(.mob-calendar-widget):not(.mob-spotify-widget) { overflow: hidden; }

  /* Desktop-only */
  .site-header { padding: 2rem 1rem 1rem; }
  .header-card { padding: 1.4rem 2rem 1.2rem; }
  .header-card .site-title { font-size: 1.9rem; }
  .board-annotations-svg { display: none; }
}

/* ── Focus mode save bar preview pane ───────────────────── */
.focus-preview-pane {
  font-family: 'Special Elite', cursive !important;
  font-size: 1.1rem !important;
  line-height: 28px !important;
  color: rgba(28,22,8,0.84) !important;
  padding: 1.2rem 0 4rem !important;
  min-height: 60vh;
  cursor: default;
}

.focus-preview-pane p, .focus-preview-pane .mind-p {
  font-family: 'Special Elite', cursive;
  font-size: 1.1rem;
  line-height: 28px;
  margin: 0 0 0.1rem;
}

/* ── Markdown rendering ──────────────────────────────────── */
.mind-p { margin: 0 0 0.1rem; display: block; }
.mind-md-h1 { font-family:'Playfair Display',serif; font-size:1.15rem; font-weight:700; color:rgba(28,22,8,0.88); margin:0.6rem 0 0.2rem; line-height:1.3; display:block; }
.mind-md-h2 { font-family:'IBM Plex Mono',monospace; font-size:0.58rem; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:rgba(28,22,8,0.45); margin:0.7rem 0 0.2rem; display:block; }
.mind-md-h3 { font-family:'IBM Plex Mono',monospace; font-size:0.52rem; letter-spacing:0.12em; text-transform:uppercase; color:rgba(28,22,8,0.32); margin:0.5rem 0 0.1rem; display:block; }
.mind-md-bq { border-left:2px solid rgba(150,65,35,0.32); margin:0.35rem 0 0.35rem 0.2rem; padding-left:0.85rem; color:rgba(28,22,8,0.55); font-style:italic; display:block; }
.mind-md-hr { border:none; border-top:1px solid rgba(28,22,8,0.1); margin:0.7rem 0; }
.mind-md-li { display:block; padding-left:1.1rem; text-indent:-1.1rem; margin:0.12rem 0; }
.mind-md-li::before { content:'–\00a0'; color:rgba(150,65,35,0.5); }
.mind-md-oli { display:block; padding-left:1.6rem; text-indent:-1.6rem; margin:0.12rem 0; }
.mind-md-oli::before { content:attr(data-n) '.\00a0'; color:rgba(150,65,35,0.5); font-family:'IBM Plex Mono',monospace; font-size:0.88em; }
.mind-md-code { font-family:'IBM Plex Mono',monospace; font-size:0.82em; background:rgba(28,22,8,0.06); padding:0.05em 0.25em; border-radius:2px; color:rgba(28,22,8,0.72); }
.mind-md-del { text-decoration:line-through; color:rgba(28,22,8,0.38); }

/* Counter numbers */
.counter-words, .counter-chars { font-size: 1.1rem !important; }

/* ── Focus autosave status ───────────────────────────────── */
.focus-wc-pending { color: rgba(28,22,8,0.25) !important; }
.focus-wc-saving  { color: rgba(28,22,8,0.35) !important; font-style: italic; }
.focus-wc-saved   { color: rgba(80,130,80,0.7) !important; }
.focus-wc-error   { color: rgba(180,40,40,0.6) !important; }

/* ── Mobile new list button ──────────────────────────────── */
@media (max-width: 639px) {
  .mob-new-list-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 8px 12px;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(150,65,35,0.5);
    background: none;
    border: 1px dashed rgba(150,65,35,0.2);
    border-radius: 2px;
    cursor: pointer;
    transition: all 0.15s;
    -webkit-tap-highlight-color: transparent;
  }

  .mob-new-list-btn span {
    font-size: 14px;
    line-height: 1;
    color: rgba(150,65,35,0.4);
  }

  .mob-new-list-btn:active {
    background: rgba(150,65,35,0.05);
    border-color: rgba(150,65,35,0.35);
    color: rgba(150,65,35,0.75);
  }
}

/* ── Focus bar — privacy toggle + archive ────────────────── */
.focus-priv-btn {
  font-size: 12px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 2px;
  opacity: 0.35;
  transition: opacity 0.15s;
  line-height: 1;
}

.focus-priv-btn:hover { opacity: 0.8; }

.focus-archive-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.25);
  background: none;
  border: 1px solid rgba(28,22,8,0.1);
  padding: 0.18rem 0.55rem;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
  border-radius: 1px;
}

.focus-archive-btn:hover {
  color: rgba(150,65,35,0.5);
  border-color: rgba(150,65,35,0.2);
}

/* ── Mind markdown link — hand-drawn underline ─────────── */
.mind-md-link {
  color: rgba(150,65,35,0.75);
  text-decoration: none;
  position: relative;
  display: inline;
  cursor: pointer;
}

.mind-md-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='5'%3E%3Cpath d='M0 3 Q4 1 11 2.5 Q21 4 28 2 Q38 0.5 52 3 Q60 4 68 2.5 Q78 1 92 3.5 Q103 4.5 115 2 Q128 0 138 2.8 Q148 4 162 2 Q175 0.5 185 3 Q195 4.2 200 2.5' fill='none' stroke='rgba(150,65,35,0.35)' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 200px 5px;
  pointer-events: none;
}

.mind-md-link:hover {
  color: rgba(150,65,35,1);
}

/* ── Hashtag inline links ────────────────────────────────── */
/* Rendered by parseHashtagLinks() in body text of mind cards,
   fieldnote cards, and todo items. Visual style: muted enough not
   to compete with the surrounding writing, but recognizable as a
   click target on hover. Color picks up the same warm-red family
   used by .mind-md-link to keep the link vocabulary unified. */
.hashtag-link {
  color: rgba(120,80,30,0.75);
  text-decoration: none;
  border-bottom: 1px dotted rgba(120,80,30,0.25);
  padding-bottom: 0;
  /* Faint ink-bleed effect — like the warm-brown ink soaked slightly
     into the paper fiber. Same hue as the text, low alpha, soft blur.
     Stacked twice (small + larger) for a more organic bleed gradient
     rather than a uniform halo. */
  text-shadow:
    0 0 0.5px rgba(120,80,30,0.30),
    0 0 2px rgba(120,80,30,0.18);
  transition: color 0.15s, border-color 0.15s, text-shadow 0.20s;
  cursor: pointer;
  /* Don't break a #long-tag onto two lines */
  white-space: nowrap;
}
.hashtag-link:hover {
  color: rgba(150,65,35,0.95);
  border-bottom-color: rgba(150,65,35,0.5);
  /* On hover the bleed deepens — like the pen pressed harder and
     the ink spread further into the fiber. */
  text-shadow:
    0 0 0.5px rgba(150,65,35,0.45),
    0 0 3px rgba(150,65,35,0.28),
    0 0 6px rgba(150,65,35,0.12);
}

/* ── Tag autocomplete dropdown ───────────────────────────── */
/* Appears above (or below, if no room above) any input where the
   user types #foo. List of matching existing tags with usage counts.
   Positioned via inline styles (JS sets left/top/bottom on the fly);
   visual style here is the paper-card vocabulary of the rest of the
   workspace. */
.tag-autocomplete {
  position: fixed;
  z-index: 9999;
  background: #faf6e8;
  border: 1px solid rgba(28,22,8,0.18);
  border-radius: 3px;
  box-shadow:
    0 2px 8px rgba(28,22,8,0.08),
    0 12px 32px rgba(28,22,8,0.12);
  padding: 0.25rem 0;
  max-height: 200px;
  overflow-y: auto;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
}

.tag-autocomplete-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  transition: background 0.08s;
  gap: 1rem;
}
.tag-autocomplete-item:hover,
.tag-autocomplete-item.selected {
  background: rgba(150,65,35,0.08);
}
.tag-autocomplete-item.selected {
  background: rgba(150,65,35,0.13);
}

.tag-autocomplete-slug {
  color: rgba(120,80,30,0.95);
  letter-spacing: 0.01em;
}
.tag-autocomplete-count {
  color: rgba(28,22,8,0.35);
  font-size: 0.6rem;
  flex-shrink: 0;
}

/* When the board is tag-filtered, render a small chip above the
   masonry showing the active tag with an × to clear. CSS-only —
   the dataset.tagFilter attribute on .board.tag-filtered carries
   the slug, which we surface via a ::before pseudo-element.

   The chip is positioned absolutely above the first column so it
   reads as a state banner without disturbing the masonry layout.
   Click handling for the × is wired via a small JS hook in
   portfolio.js (see the document click delegation). */
.board.tag-filtered {
  position: relative;
  padding-top: 3rem;
}
.board.tag-filtered::before {
  content: attr(data-tag-filter) ' ×';
  position: absolute;
  top: 0.8rem;
  left: 50%;
  transform: translateX(-50%);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  color: rgba(120,80,30,0.85);
  background: rgba(248,243,230,0.92);
  border: 1px solid rgba(120,80,30,0.3);
  padding: 4px 10px;
  border-radius: 2px;
  pointer-events: none;
  z-index: 10;
  box-shadow: 0 1px 3px rgba(28,22,8,0.08);
}
/* Invisible clickable region for the ::before chip (since CSS-generated
   content can't receive clicks reliably across browsers). The board's
   click handler picks up clicks in this region and clears the tag. */
.board.tag-filtered .board-tag-clear {
  position: absolute;
  top: 0.5rem;
  left: 50%;
  transform: translateX(-50%);
  /* Width sized to comfortably cover multi-tag chips ("#poland + #mercosur ×"). */
  width: 20rem;
  max-width: 90vw;
  height: 2rem;
  cursor: pointer;
  z-index: 11;
}

.mind-md-link:hover::after {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='5'%3E%3Cpath d='M0 3 Q4 1 11 2.5 Q21 4 28 2 Q38 0.5 52 3 Q60 4 68 2.5 Q78 1 92 3.5 Q103 4.5 115 2 Q128 0 138 2.8 Q148 4 162 2 Q175 0.5 185 3 Q195 4.2 200 2.5' fill='none' stroke='rgba(150,65,35,0.6)' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 200px 5px;
}

/* ── Mobile RSS meta row ─────────────────────────────────── */
@media (max-width: 639px) {
  .mob-rss-meta-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 1px;
  }

  .mob-rss-age {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7px;
    letter-spacing: 0.05em;
    color: rgba(28,22,8,0.25);
    text-transform: uppercase;
    margin-left: auto;
  }

  /* Private lock — keep inside mobile editor header */
  .mob-editor-header {
    flex-wrap: nowrap;
    overflow: hidden;
  }

  /* Mobile todo archive — bottom right of widget */
  .mob-archive-btn {
    display: block;
    margin: 0 12px 8px auto;
    align-self: flex-end;
  }

  /* Move archive btn after body in todo widget */
  .mob-todo-body + .mob-archive-btn {
    margin-top: -2px;
  }
}

/* ── Mobile news ticker ──────────────────────────────────── */
@media (max-width: 639px) {
  .mob-ticker {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    background: #f8f4e8;
    border: 1px solid rgba(28,22,8,0.1);
    border-left: 3px solid rgba(150,65,35,0.4);
    border-radius: 2px;
    box-shadow: 0 1px 0 rgba(255,255,255,0.7), 0 2px 6px rgba(28,22,8,0.06);
    overflow: hidden;
  }

  .mob-ticker-label {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(150,65,35,0.7);
    flex-shrink: 0;
    white-space: nowrap;
    font-weight: 600;
  }

  .mob-ticker-track {
    flex: 1;
    overflow: hidden;
    position: relative;
    height: 1.4em;
  }

  .mob-ticker-text {
    font-family: 'Libre Baskerville', serif;
    font-size: 11px;
    line-height: 1.38;
    color: rgba(28,22,8,0.85);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
    transition: opacity 0.35s ease, transform 0.35s ease;
  }
}

/* ── Mind card actions (archive) ─────────────────────────── */
.mind-card-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0.3rem 1rem 0.5rem;
  border-top: 1px solid rgba(28,22,8,0.05);
  opacity: 0;
  transition: opacity 0.2s;
}

.item-mind:hover .mind-card-actions { opacity: 1; }

.mind-archive-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.22);
  background: none;
  border: 1px solid rgba(28,22,8,0.1);
  padding: 0.12rem 0.45rem;
  cursor: pointer;
  border-radius: 1px;
  transition: all 0.15s;
}

.mind-archive-btn:hover {
  color: rgba(150,65,35,0.6);
  border-color: rgba(150,65,35,0.25);
}

/* ── Ticker overflow fix ─────────────────────────────────── */
@media (max-width: 639px) {
  .mob-ticker {
    overflow: hidden;
    max-width: 100%;
  }

  .mob-ticker-track {
    overflow: hidden;
    min-width: 0;
  }

  .mob-ticker-text {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }

  /* RSS body overflow fix — prevent page stretch */
  .mob-rss-body {
    overflow: hidden;
  }

  .mob-rss-row {
    overflow: hidden;
    max-width: 100%;
  }

  .mob-rss-hl {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Mobile focus — show preview button */
  .focus-preview-btn {
    display: inline-flex;
  }

  /* Mobile focus bar — compact */
  .focus-bar-row {
    padding: 0.5rem 1.2rem;
    gap: 0.5rem;
  }

  .focus-save-bar {
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
}

/* ── Mobile width overflow fixes ─────────────────────────── */
@media (max-width: 639px) {

  /* Root containment — nothing bleeds past viewport */
  #board {
    max-width: 100vw;
    overflow-x: hidden !important;
  }

  .mob-dash {
    max-width: 100%;
    box-sizing: border-box;
    overflow-x: hidden;
  }

  /* Every widget clipped to its container */
  .mob-widget {
    max-width: 100%;
    box-sizing: border-box;
  }

  /* Agenda body — clamp event titles */
  .mob-agenda-body .agenda-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    display: block;
  }

  /* Exception: rows currently marked "now" have an inline ::after with
     the handwritten "now" annotation + arrow. The single-line ellipsis
     clamp above eats it. Lift the clamp on those rows so the annotation
     can render in full; the title itself is short enough to fit on a
     single line in nearly all cases, and if it does wrap, that's a
     better outcome than losing the "now" pointer. */
  .mob-agenda-body .agenda-now .agenda-title {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
  }

  .mob-agenda-body .agenda-event {
    overflow: visible;
    max-width: 100%;
  }

  /* Ticker — fixed height, no reflow */
  .mob-ticker {
    height: 36px;
    flex-shrink: 0;
    box-sizing: border-box;
    align-items: center;
  }

  .mob-ticker-track {
    height: 18px;
    overflow: hidden;
    flex: 1;
    min-width: 0;
    position: relative;
  }

  .mob-ticker-text {
    position: absolute;
    top: 0; left: 0; right: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 18px;
  }

  /* RSS rows — clamp headline text */
  .mob-rss-row > div {
    min-width: 0;
    overflow: hidden;
  }

  /* Sources widget */
  .mob-widget .sources-card {
    max-width: 100%;
    overflow: hidden;
  }

  .mob-widget .src-name,
  .mob-widget .src-note {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Calendar and spotify cloned widgets */
  .mob-calendar-widget,
  .mob-spotify-widget {
    max-width: 100%;
    box-sizing: border-box;
    overflow: hidden;
  }

  .mob-calendar-widget .item,
  .mob-spotify-widget .item {
    max-width: 100% !important;
    box-sizing: border-box !important;
  }
}

/* ── Mobile editor — undo, preview, preview pane ─────────── */
@media (max-width: 639px) {

  .mob-editor-wc {
    flex: 1;
    min-width: 0;
  }

  .mob-editor-undo {
    font-size: 14px;
    background: none;
    border: none;
    color: rgba(28,22,8,0.35);
    cursor: pointer;
    padding: 0 4px;
    flex-shrink: 0;
    line-height: 1;
  }

  .mob-editor-undo:active { color: rgba(150,65,35,0.7); }

  .mob-editor-prev-btn {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.38);
    background: none;
    border: 1px solid rgba(28,22,8,0.12);
    padding: 3px 9px;
    cursor: pointer;
    flex-shrink: 0;
    border-radius: 1px;
  }

  .mob-editor-prev-btn:active {
    color: rgba(150,65,35,0.7);
    border-color: rgba(150,65,35,0.3);
  }

  .mob-editor-preview-pane {
    font-family: 'Special Elite', cursive;
    font-size: 16px;
    line-height: 28px;
    color: rgba(28,22,8,0.84);
    padding: 12px 22px 40px;
    min-height: 100%;
    background-image: repeating-linear-gradient(
      to bottom, transparent, transparent 27px,
      rgba(100,80,50,0.08) 27px, rgba(100,80,50,0.08) 28px
    );
  }

  .mob-editor-preview-pane p,
  .mob-editor-preview-pane .mind-p {
    font-family: 'Special Elite', cursive;
    font-size: 16px;
    line-height: 28px;
    margin: 0;
  }

  /* Archive button in mobile notes list */
  .mob-note-row .mob-archive-note {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7px;
    color: rgba(28,22,8,0.2);
    background: none;
    border: none;
    padding: 2px 4px;
    cursor: pointer;
    flex-shrink: 0;
  }
}

/* ── Agenda source differentiation ──────────────────────── */

/* Personal (Google Calendar) — soft teal/sage left border */
/* Personal (Google Calendar) — teal left border only, no title recolouring */
/* Personal events — distinguished by a handwritten "p." prefix in Caveat,
   like a journalist's shorthand for "personal, not work". Different in *form*
   from a work entry, not just in color. */
.agenda-personal-prefix {
  font-family: 'Caveat', cursive;
  font-size: 1em;
  font-weight: 600;
  color: rgba(60,130,110,0.85);
  letter-spacing: 0.01em;
  margin-right: 0.05rem;
}

/* Multi-day all-day events: small mono "day N/M" suffix appears next to the
   title every day the event spans, so it reads as the same vacation/trip
   continuing rather than repeated entries. */
.agenda-span-suffix {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  font-weight: 500;
  color: rgba(28,22,8,0.4);
  letter-spacing: 0.04em;
  margin-left: 0.4rem;
  vertical-align: 0.05rem;
}

/* Continuation entries (days 2..N of a multi-day event) read more quietly —
   the start day is the event's "real" entry, follow-ups are echoes. */
.agenda-continuation .agenda-title {
  opacity: 0.7;
}
.agenda-continuation .agenda-allday-mark,
.agenda-continuation .agenda-allday-text {
  opacity: 0.55;
}

/* All-day events — already marked by the asterisk + "all day" in the time column,
   no extra border needed */

/* Hover state. Events with an override-key are clickable to open the icon
   picker — pointer cursor signals that. */
.agenda-event {
  cursor: default;
  transition: background 0.12s;
  position: relative;
}

.agenda-event[data-override-key] {
  cursor: pointer;
}

.agenda-event:hover {
  background: rgba(28,22,8,0.03);
}

.agenda-today:hover {
  background: rgba(150,65,35,0.04);
}

.agenda-personal:hover {
  background: rgba(60,130,110,0.04);
}

/* Mobile agenda card shim — wraps the cloned agenda content to give the
   icon picker modal a positioned ancestor. Visually transparent so it
   doesn't add any new styling on top of the existing mobile layout. */
.mob-agenda-card-shim {
  position: relative;
  background: transparent;
  border: none;
  box-shadow: none;
  overflow: visible;
}

/* ─── Icon picker modal ─────────────────────────────────────
   Click an event in the agenda to open this; choose a mark to override the
   auto-detected category. Stored per event title in localStorage so the
   override applies across all instances. Renders as a modal with backdrop
   inside the agenda card (not the event row) — solves z-index conflicts
   with adjacent events and prevents click-through. */
.agenda-icon-picker-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(28,22,8,0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  cursor: pointer;
}

.agenda-icon-picker {
  background: #faf6ed;
  border: 1px solid rgba(28,22,8,0.18);
  border-radius: 2px;
  padding: 0.7rem 0.75rem 0.55rem;
  box-shadow: 0 8px 24px rgba(28,22,8,0.18), 0 2px 4px rgba(28,22,8,0.08);
  font-family: 'Libre Baskerville', serif;
  cursor: default;
  width: 100%;
  max-width: 360px;
  position: relative;
}

.agenda-icon-picker-head {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.5);
  text-transform: uppercase;
  margin-bottom: 0.6rem;
  padding-right: 1.2rem;
  position: relative;
}

.agenda-icon-picker-head em {
  font-family: 'Libre Baskerville', serif;
  font-style: italic;
  font-size: 0.7rem;
  color: rgba(28,22,8,0.85);
  text-transform: none;
  letter-spacing: 0;
  display: block;
  margin-top: 0.1rem;
}

.agenda-icon-picker-close {
  position: absolute;
  top: -0.15rem;
  right: -0.25rem;
  background: transparent;
  border: none;
  font-size: 1.1rem;
  line-height: 1;
  color: rgba(28,22,8,0.4);
  cursor: pointer;
  padding: 0.15rem 0.35rem;
  -webkit-tap-highlight-color: transparent;
}

.agenda-icon-picker-close:hover {
  color: rgba(28,22,8,0.8);
}

.agenda-icon-picker-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.25rem;
}

.agenda-icon-picker-opt {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 2px;
  padding: 0.4rem 0.2rem 0.3rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.6);
  transition: background 0.1s, border-color 0.1s;
  -webkit-tap-highlight-color: transparent;
  /* Without this, the intrinsic min-content width of the longest label
     ("Institutional", "Brainstorm") forces the grid track wider than its
     1fr share and the label spills over the right edge of the modal. */
  min-width: 0;
}

.agenda-icon-picker-opt:hover {
  background: rgba(28,22,8,0.04);
  border-color: rgba(28,22,8,0.1);
  color: rgba(28,22,8,0.85);
}

/* Glyph slot inside each picker option */
.agenda-icon-picker-glyph {
  position: relative;
  width: 1.1rem;
  height: 1.1rem;
  display: block;
}

.agenda-icon-picker-glyph::after {
  content: '';
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* Map each option to its glyph by reusing the agenda mark SVGs. The CSS
   below copies the background-image data URLs from the main mark rules
   so the picker swatches match the actual rendered marks. */
.agenda-icon-picker-opt.agenda-mark-default .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12 Q 9 11.5, 14 12.5 T 22 12' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' opacity='0.6'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-call .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 5 Q 4 6, 4 8 Q 5 12, 8 16 Q 12 20, 16 21 Q 18 21, 19 19 L 19.5 16 Q 17 14.5, 15.5 15.5 L 13 13 Q 14 11, 13 9 L 10 5.5 Q 8 4.5, 5 5 Z' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-coffee .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 9 L 5 17 Q 5 19.5, 7.5 19.5 L 14 19.5 Q 16.5 19.5, 16.5 17 L 16.5 9 Z M 16.5 11 Q 19.5 11, 19.5 13.5 Q 19.5 16, 16.5 15.5 M 8 4 Q 9 6, 7.5 8 M 11.5 4 Q 12.5 6, 11 8' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-meal .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 6 11 Q 6 12.5, 7.5 12.5 L 7.5 21 M 9.5 3 L 9.5 11 Q 9.5 12.5, 8 12.5 M 15 3 L 15 9 Q 15 11, 17 11 L 17 21 M 15 3 Q 17 3, 17 6 L 17 11' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-travel .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M2 12 L 22 4 L 16 21 L 12 13 Z M 12 13 L 22 4' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-press .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 17 3 Q 19 3, 19 5 L 19 20 Q 19 22, 17 22 L 6 22 Q 4 22, 4 20 L 4 5 Q 4 3, 6 3 Z M 7 9 L 16 9 M 7 13 L 16 13 M 7 17 L 13 17' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-deadline .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 4 Q 11.5 9, 11 14' fill='none' stroke='%23964123' stroke-width='3' stroke-linecap='round' opacity='0.9'/><circle cx='10.5' cy='19' r='1.8' fill='%23964123' opacity='0.9'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-edit .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M3 21 L 6 20 L 20 6 L 18 4 L 4 18 Z M 17 5 L 19 7 M 3 21 L 5 21' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-medical .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 4 L 12 20 M 4 12 L 20 12' fill='none' stroke='%233c826e' stroke-width='3.2' stroke-linecap='round' opacity='0.85'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-pet .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='%23491b08' opacity='0.78'><ellipse cx='12' cy='17.5' rx='5' ry='4'/><ellipse cx='6' cy='10' rx='2.3' ry='2.7'/><ellipse cx='10.5' cy='6.5' rx='2.1' ry='2.7'/><ellipse cx='14.5' cy='6.5' rx='2.1' ry='2.7'/><ellipse cx='18.5' cy='10' rx='2.3' ry='2.7'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-meeting .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><circle cx='6' cy='6' r='2.4' fill='%23491b08' stroke='none'/><path d='M2 13 Q 2 10, 6 10 Q 10 10, 10 13 L 10 14'/><circle cx='18' cy='6' r='2.4' fill='%23491b08' stroke='none'/><path d='M14 13 Q 14 10, 18 10 Q 22 10, 22 13 L 22 14'/><path d='M1 16 L 23 16 M 4 16 L 4 22 M 20 16 L 20 22'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-discussion .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M3 4 L 13 4 Q 15 4, 15 6 L 15 11 Q 15 13, 13 13 L 7 13 L 4 16 L 4.5 13 L 3 13 Q 1 13, 1 11 L 1 6 Q 1 4, 3 4 Z'/><path d='M11 9 L 20 9 Q 22 9, 22 11 L 22 16 Q 22 18, 20 18 L 19 18 L 19.5 21 L 16 18 L 11 18 Q 9 18, 9 16'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-brainstorm .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M12 3 Q 7 3, 7 9 Q 7 12, 9 14 L 9 17 Q 9 18, 10 18 L 14 18 Q 15 18, 15 17 L 15 14 Q 17 12, 17 9 Q 17 3, 12 3 Z M 10 20 L 14 20 M 11 22 L 13 22'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-admin .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M6 5 L 6 21 Q 6 22, 7 22 L 17 22 Q 18 22, 18 21 L 18 5 M 9 3 L 15 3 Q 16 3, 16 4 L 16 6 Q 16 7, 15 7 L 9 7 Q 8 7, 8 6 L 8 4 Q 8 3, 9 3 Z M 9 11 L 15 11 M 9 14 L 15 14 M 9 17 L 13 17'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-institutional .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M2 8 L 12 3 L 22 8 L 22 9 L 2 9 Z M 5 11 L 5 18 M 9.5 11 L 9.5 18 M 14.5 11 L 14.5 18 M 19 11 L 19 18 M 2 19 L 22 19 M 1 21 L 23 21'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-birthday .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 21 L 21 21 M 4 21 L 4 14 Q 4 13, 5 13 L 19 13 Q 20 13, 20 14 L 20 21 M 4 17 L 20 17 M 12 13 L 12 8'/><path d='M11 8 Q 12 6, 13 8 Q 12 10, 11 8 Z' fill='%23964123' stroke='%23964123'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-holiday .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 20 L 12 4 L 21 20 Z M 12 4 L 12 20 M 9 20 L 12 14 L 15 20 M 2 20 L 22 20'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-family .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21 Q 4 15, 4 9 Q 4 5, 8 5 Q 11 5, 12 8 Q 13 5, 16 5 Q 20 5, 20 9 Q 20 15, 12 21 Z' fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'/></svg>");
}
.agenda-icon-picker-opt.agenda-mark-committee .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M4 5 L 20 5 Q 21 5, 21 6 L 21 20 Q 21 21, 20 21 L 4 21 Q 3 21, 3 20 L 3 6 Q 3 5, 4 5 Z M 3 10 L 21 10 M 9 5 L 9 21 M 15 5 L 15 21 M 8 3 L 8 7 M 16 3 L 16 7'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-plenary .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 7 Q 12 5, 21 7 M 3 11 Q 12 9, 21 11 M 3 15 Q 12 13, 21 15 M 3 19 Q 12 17, 21 19'/><circle cx='12' cy='4' r='1.2' fill='%23491b08' stroke='none'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-trilogue .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 5 L 11 11 M 7 5 L 11 5 L 11 9 M 21 5 L 13 11 M 17 5 L 21 5 L 21 9 M 12 21 L 12 13 M 8 18 L 12 22 L 16 18'/><circle cx='12' cy='12' r='2' fill='%23491b08' stroke='none' opacity='0.85'/></g></svg>");
}
.agenda-icon-picker-opt.agenda-mark-brief .agenda-icon-picker-glyph::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M12 3 Q 9 3, 9 6 L 9 12 Q 9 15, 12 15 Q 15 15, 15 12 L 15 6 Q 15 3, 12 3 Z M 6 11 Q 6 16, 12 16 Q 18 16, 18 11 M 12 16 L 12 20 M 9 21 L 15 21'/></g></svg>");
}

.agenda-icon-picker-text {
  font-size: 0.45rem;
  white-space: normal;
  letter-spacing: 0.06em;
  text-align: center;
  line-height: 1.15;
  word-break: break-word;
  hyphens: auto;
}

.agenda-icon-picker-reset {
  margin-top: 0.5rem;
  background: transparent;
  border: none;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.08em;
  color: rgba(150,65,35,0.65);
  cursor: pointer;
  padding: 0.25rem 0;
  display: block;
  text-align: left;
}

.agenda-icon-picker-reset:hover {
  color: rgba(150,65,35,0.9);
}

/* On mobile, the backdrop covers the entire viewport rather than the
   agenda card (which sits inside a scrollable, max-height container —
   centring inside the card means the picker may render outside the
   visible window when the user has scrolled). The picker still centres
   to the backdrop, but now the backdrop is the screen. */
@media (max-width: 639px) {
  .agenda-icon-picker-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(28,22,8,0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
  }
  .agenda-icon-picker {
    padding: 0.6rem 0.6rem 0.5rem;
    max-width: 320px;
  }
  .agenda-icon-picker-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 0.2rem;
  }
  .agenda-icon-picker-opt {
    padding: 0.45rem 0.15rem 0.35rem;
  }
}

/* Work (Outlook) — no extra styling, uses existing terracotta */

/* Legend hint in agenda header */
.agenda-legend { display: none; }

/* ── Suppress transitions during resize to prevent flash ─── */
body.resizing *,
body.resizing *::before,
body.resizing *::after {
  transition: none !important;
  animation: none !important;
}

/* During resize: force board-column items visible (not mobile widget clones) */
body.resizing .board-col .item.pending,
body.resizing .board-col .item {
  opacity: 1 !important;
  transform: translateY(0) rotate(var(--r, -0.8deg)) !important;
}

body.resizing .board-col {
  display: flex !important;
  flex-direction: column !important;
  opacity: 1 !important;
}

/* ── Todo section add button ─────────────────────────────── */
.todo-item-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.todo-section-add {
  font-size: 11px;
  line-height: 1;
  color: rgba(150,65,35,0.3);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 0 0 4px;
  transition: color 0.15s;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.15s;
}

.todo-item-heading:hover .todo-section-add { opacity: 1; }
.todo-section-add:hover { color: rgba(150,65,35,0.7) !important; }

/* ── Completed-section fold/unfold ───────────────────────── */
/* Chevron button on the auto-injected "Completed" divider.
   Always visible (unlike the per-section + button which only
   shows on hover) — the affordance to fold is a primary action,
   not a secondary one. Chevron rotates 180° in the collapsed
   state, mirroring the header-collapse chevron at the top of
   the page for consistency. */
.todo-completed-toggle {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 0 0 4px;
  color: rgba(28,22,8,0.4);
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  transition: color 0.15s;
}
.todo-completed-toggle:hover { color: rgba(150,65,35,0.7); }
.todo-completed-toggle-svg {
  width: 10px;
  height: 10px;
  transition: transform 0.25s cubic-bezier(.4, 0, .2, 1);
}
.todo-list.todo-completed-collapsed .todo-completed-toggle-svg {
  transform: rotate(-90deg);
}

/* Touch: make the COMPLETED divider a generous tap target.
   On desktop the 10px chevron is fine; on touch it's tiny, and
   a thumb aimed at it often drifts up onto the open task above
   and accidentally toggles its check. Three changes together:
   1. Bigger chevron (14px) + bigger button padding so the chevron
      itself is reasonably easy to hit.
   2. The whole divider row is the tap target (JS handler accepts
      clicks anywhere on .todo-divider-completed), so the user
      doesn't need to aim at the chevron specifically.
   3. Extra top margin on the divider creates a vertical "dead zone"
      between the last open task and the divider, so a slightly-high
      tap aimed at the divider lands on padding rather than the
      task row above. */
@media (hover: none) and (pointer: coarse) {
  .todo-divider-completed {
    /* Cursor hint that the row itself is tappable. */
    cursor: pointer;
    /* Extra top breathing room — separates the divider from the
       last open task so accidental high-aimed taps don't hit it. */
    margin-top: 1.1rem !important;
    /* Vertical padding extends the row's hit area so a tap near
       the chevron is forgiving. The label inside stays the same
       visual size; only the row's tap region grows. */
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
  }
  .todo-completed-toggle {
    /* Push the chevron's hit area out without enlarging the glyph
       too much. Padding all around so the button has a substantial
       tap region. */
    padding: 10px 12px;
  }
  .todo-completed-toggle-svg {
    width: 14px;
    height: 14px;
  }
}

/* Collapsed state: hide all checked items AND any "Completed"-pill
   completed entries. The divider itself stays visible (with its
   rotated chevron) so the user can re-expand. Using max-height + 
   opacity for a soft transition rather than display:none, so the
   hide animates.

   The negative margin-top is critical: .todo-list is a flex column
   with gap: 0.5rem, which reserves space between EVERY pair of
   children regardless of whether each child has visible content.
   Without canceling that gap, several collapsed items stack up as
   phantom whitespace beneath the Completed divider. Margin-top of
   -0.5rem on each collapsed row pulls it up by exactly the gap. */
/* During the strike-hold pause after checking an item in a collapsed
   Completed section, keep the row visible so the user sees the
   strikethrough + completion pill register. The .todo-just-checked
   class is added on click and removed after ~900ms by the JS in
   portfolio.js, right before reorderTodoSection runs. After removal,
   the regular collapse rule below takes over and the row fades +
   collapses smoothly.

   Only the properties that the collapse rule sets need to be undone:
   max-height, opacity, overflow, pointer-events. padding/margin/border
   stay natural — the collapse rule zeroes them too, but they're tied
   to max-height transitions and revert correctly when max-height
   returns to none. Earlier attempt used `inherit` which incorrectly
   pulled values from the <ul> parent and expanded the row. */
.todo-list.todo-completed-collapsed .todo-item.todo-checked.todo-just-checked {
  max-height: none;
  opacity: 1;
  overflow: visible;
  pointer-events: auto;
  /* Reset margin/padding to the .todo-item defaults (0) so the flex
     gap on the parent <ul> creates normal spacing between siblings.
     Without these, the collapse rule's `margin: -0.5rem 0 0 0` would
     still apply and pull the row up over the previous sibling. */
  margin: 0;
  padding: 0;
  border-bottom: none;
}

/* Default behavior: checked items inside a collapsed Completed
   section fade and collapse to zero height. See main rule below. */
.todo-list.todo-completed-collapsed .todo-item.todo-checked {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin: -0.5rem 0 0 0;
  border: none;
  overflow: hidden;
  pointer-events: none;
  transition:
    max-height 0.3s cubic-bezier(.4, 0, .2, 1),
    opacity 0.18s ease,
    padding 0.3s cubic-bezier(.4, 0, .2, 1),
    margin 0.3s cubic-bezier(.4, 0, .2, 1);
}
.todo-list .todo-item.todo-checked {
  transition:
    max-height 0.3s cubic-bezier(.4, 0, .2, 1),
    opacity 0.18s ease,
    margin 0.3s cubic-bezier(.4, 0, .2, 1);
}

/* ── Per-row edit/delete actions ─────────────────────────── */
/* Hover-revealed icons on each task row. Hidden at rest so the
   to-do list stays calm; brighten when the row is hovered.
   On touch devices, they're always faintly visible since there
   is no hover state to reveal them.
   Touch detection: we use the body.is-touch class set by JS at
   startup (see portfolio.js). This was previously done with
   @media (hover: none) and (pointer: coarse), but that media
   query reports incorrectly in several real-world cases (iOS
   Request Desktop Site, in-app webviews, etc.), leaving the
   buttons permanently invisible on phones. Direct runtime
   detection via 'ontouchstart' / maxTouchPoints is reliable. */
.todo-item-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  margin-left: auto;
  padding-left: 0.4rem;
  opacity: 0;
  transition: opacity 0.15s;
  flex-shrink: 0;
}
.todo-item:hover .todo-item-actions {
  opacity: 0.85;
}
.todo-item-actions button {
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 3px;
  color: rgba(28,22,8,0.5);
  display: inline-flex;
  align-items: center;
  border-radius: 2px;
  transition: color 0.12s, background 0.12s;
}
.todo-item-actions button svg {
  width: 12px;
  height: 12px;
  display: block;
}
.todo-item-actions button:hover {
  color: rgba(150,65,35,0.85);
  background: rgba(150,65,35,0.06);
}
.todo-item-delete:hover {
  color: rgba(180,40,30,0.85) !important;
  background: rgba(180,40,30,0.07) !important;
}

/* Touch — body.is-touch set by JS at startup. Always-visible
   icons, tinted tray background, larger hit targets. */
body.is-touch .todo-item-actions {
  opacity: 0.6;
  /* Tinted "tray" tells the thumb where the controls zone lives.
     Click handler already excludes clicks inside .todo-item-actions
     from toggling the check; this just makes that safe-tap region
     visually obvious. */
  background: rgba(28,22,8,0.045);
  border-radius: 3px;
  /* Small left margin: visual seam + physical buffer between text
     and tray for near-miss thumb taps. */
  margin-left: 0.5rem;
}
body.is-touch .todo-item-actions button {
  /* Larger tap targets — 12px icons in 9×8 padding gives a hit
     area of ~30×28, closer to the 44px convention without growing
     the visible glyph. */
  padding: 9px 8px;
}

/* Inline edit input — appears in-place of the row text when the
   user clicks the pencil. Matches the section-add input's typography
   so editing feels like the same affordance, just attached to one
   existing row instead of a new one. */
.todo-item-edit-input {
  flex: 1;
  font-family: 'Special Elite', cursive;
  font-size: 0.85rem;
  line-height: 1.5;
  color: rgba(28,22,8,0.85);
  background: rgba(255,253,245,0.6);
  border: none;
  border-bottom: 1px solid rgba(150,65,35,0.4);
  outline: none;
  padding: 2px 4px;
  margin: -2px 0;
  width: 100%;
}

.todo-section-input-row {
  list-style: none;
  padding: 3px 0.8rem 3px 1.6rem;
  background: rgba(150,65,35,0.03);
}

.todo-section-input {
  width: 100%;
  font-family: 'Special Elite', cursive;
  font-size: 0.82rem;
  color: rgba(28,22,8,0.84);
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(150,65,35,0.25);
  outline: none;
  padding: 2px 0;
  caret-color: rgba(150,65,35,0.8);
}

.todo-section-input::placeholder { color: rgba(28,22,8,0.22); font-style: italic; }

/* ── Mobile todo section add button ─────────────────────── */
@media (max-width: 639px) {
  .mob-todo-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
  }

  .mob-todo-section-label {
    flex: 1;
    min-width: 0;
  }

  .mob-section-add-btn {
    font-size: 13px;
    line-height: 1;
    color: rgba(150,65,35,0.35);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0 4px;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
  }

  .mob-section-add-btn:active { color: rgba(150,65,35,0.8); }

  /* Completed-section fold/unfold on mobile. Mirrors the desktop
     .todo-completed-toggle pattern: rotates -90° when collapsed,
     same chevron, same icon. State shared with desktop via
     meta.todo_completed_collapsed. */
  .mob-completed-toggle {
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px 6px;
    margin: -4px 0;
    color: rgba(28,22,8,0.4);
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    -webkit-tap-highlight-color: rgba(150,65,35,0.06);
  }
  .mob-completed-toggle:active { color: rgba(150,65,35,0.8); }
  .mob-completed-toggle-svg {
    width: 11px;
    height: 11px;
    transition: transform 0.25s cubic-bezier(.4, 0, .2, 1);
  }
  .mob-completed-collapsed .mob-completed-toggle-svg,
  /* Allow the toggle to find its body via section-as-sibling: when the
     toggle sits inside .mob-todo-section, the collapsed state lives on
     .mob-todo-body which is the section's parent. Selector below covers
     the rotation when the body is collapsed. */
  .mob-todo-body.mob-completed-collapsed .mob-completed-toggle-svg {
    transform: rotate(-90deg);
  }

  /* Collapsed state: hide all checked rows. Uses the same max-height
     + opacity transition pattern as desktop. The Completed section
     header itself stays visible (with its rotated chevron) so the
     user can re-expand. Negative margin cancels the body's vertical
     rhythm so the hidden rows don't leave phantom space behind. */
  .mob-todo-body.mob-completed-collapsed .mob-todo-row.mob-done {
    max-height: 0;
    opacity: 0;
    padding-top: 0;
    padding-bottom: 0;
    border: none;
    overflow: hidden;
    pointer-events: none;
    margin: 0;
    transition:
      max-height 0.3s cubic-bezier(.4, 0, .2, 1),
      opacity 0.18s ease,
      padding 0.3s cubic-bezier(.4, 0, .2, 1);
  }
  .mob-todo-body .mob-todo-row.mob-done {
    transition:
      max-height 0.3s cubic-bezier(.4, 0, .2, 1),
      opacity 0.18s ease;
  }

  .mob-section-input-wrap {
    display: flex;
    background: rgba(150,65,35,0.04);
    border-top: 1px solid rgba(150,65,35,0.12);
  }
}

/* ── Mobile body height — let content determine height ───── */
@media (max-width: 639px) {
  body {
    min-height: 0;
  }
}

/* ── Fieldnote archive button ────────────────────────────── */
.fieldnote-archive-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.2);
  background: none;
  border: 1px solid rgba(28,22,8,0.08);
  padding: 0.1rem 0.4rem;
  cursor: pointer;
  border-radius: 1px;
  transition: color 0.15s, border-color 0.15s;
}

.fieldnote-archive-btn:hover {
  color: rgba(150,65,35,0.6);
  border-color: rgba(150,65,35,0.25);
}

/* Privacy toggle in inline editor */
.inline-priv-btn {
  font-size: 13px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 6px;
  opacity: 0.5;
  transition: opacity 0.15s;
  display: block;
  margin-top: 4px;
}

.inline-priv-btn:hover { opacity: 1; }

/* Piece picker in fieldnote inline editor — appears below the edit area
   when a fieldnote is being edited. Lets the user attach the note to an
   active piece. Visually quiet so it doesn't dominate the editing
   surface. */
/* Piece picker in field-note inline editor — appears below the editor
   when a fieldnote is being edited. Lets the user attach the note to an
   active piece. Quiet but deliberately styled to feel of-a-piece with
   the editorial workspace rather than a stock browser widget. */
.inline-piece-picker {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px dotted rgba(28,22,8,0.12);
  font-family: 'IBM Plex Mono', monospace;
}
.inline-piece-picker label {
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  flex-shrink: 0;
}
.inline-piece-select {
  flex: 1;
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  background-color: rgba(255,255,255,0.6);
  border: 1px solid rgba(28,22,8,0.18);
  padding: 0.35rem 1.6rem 0.35rem 0.55rem;
  border-radius: 2px;
  color: rgba(28,22,8,0.85);
  max-width: 360px;
  /* Custom dropdown chevron — small terracotta caret, replaces the
     stock browser arrow */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'><path fill='none' stroke='%23964123' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round' d='M1 1l4 4 4-4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 0.65rem 0.4rem;
  cursor: pointer;
}
.inline-piece-select:hover {
  border-color: rgba(28,22,8,0.32);
}
.inline-piece-select:focus {
  outline: none;
  border-color: rgba(150,65,35,0.65);
  background-color: rgba(255,255,255,0.85);
}

/* ── Link item archive button ────────────────────────────── */
.item-link {
  position: relative;
}

.link-archive-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 18px;
  height: 18px;
  font-size: 13px;
  line-height: 1;
  color: rgba(28,22,8,0.25);
  background: rgba(245,242,234,0.85);
  border: 1px solid rgba(28,22,8,0.1);
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, border-color 0.15s;
  z-index: 20;
}

.item-link:hover .link-archive-btn { opacity: 1; }

.link-archive-btn:hover {
  color: rgba(150,65,35,0.7);
  border-color: rgba(150,65,35,0.3);
}

/* Mobile reading list widget */
@media (max-width: 639px) {
  .mob-link-list {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  .mob-link-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid rgba(28,22,8,0.06);
    text-decoration: none;
    color: inherit;
  }

  .mob-link-row:last-child { border-bottom: none; }

  .mob-link-body {
    flex: 1;
    min-width: 0;
  }

  .mob-link-title {
    font-family: 'Libre Baskerville', serif;
    font-size: 11px;
    line-height: 1.3;
    color: rgba(28,22,8,0.85);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .mob-link-domain {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 7px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.4);
    margin-top: 2px;
    display: block;
  }

  .mob-link-archive {
    font-size: 11px;
    color: rgba(28,22,8,0.25);
    background: none;
    border: none;
    padding: 0 4px;
    cursor: pointer;
    flex-shrink: 0;
    line-height: 1;
  }

  .mob-link-archive:active { color: rgba(150,65,35,0.7); }

  .mob-link-empty {
    padding: 16px 12px;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(28,22,8,0.3);
    text-align: center;
  }
}

/* ── Reading list widget (desktop notebook) ──────────────── */
.rl-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
}

.rl-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.8rem 0.4rem;
  border-bottom: 1px solid rgba(28,22,8,0.06);
}

.rl-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
}

.rl-count {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  color: rgba(28,22,8,0.28);
  background: rgba(28,22,8,0.04);
  padding: 0.08rem 0.35rem;
  border-radius: 8px;
}

.rl-body {
  max-height: 260px;
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.rl-body::-webkit-scrollbar { display: none; }

.rl-row {
  display: block;
  padding: 0.45rem 0.8rem;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px dotted rgba(28,22,8,0.06);
  transition: background 0.12s;
  cursor: pointer;
  position: relative;
  z-index: 2;
}

.rl-row:last-child { border-bottom: none; }
.rl-row:hover { background: rgba(28,22,8,0.03); }

.rl-title {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.68rem;
  color: rgba(28,22,8,0.78);
  line-height: 1.3;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rl-row:hover .rl-title { color: rgba(28,22,8,0.95); }

.rl-note {
  font-family: 'Special Elite', cursive;
  font-size: 0.55rem;
  color: rgba(150,65,35,0.5);
  font-style: italic;
  display: block;
  margin-top: 0.1rem;
}

.rl-domain {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.4);
  text-transform: lowercase;
  display: block;
  margin-top: 0.08rem;
}

.rl-empty {
  padding: 1.2rem 0.8rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.25);
  text-align: center;
}

/* ── Reading list row with archive ───────────────────────── */
.rl-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.8rem;
  border-bottom: 1px dotted rgba(28,22,8,0.06);
  transition: background 0.12s;
}

.rl-row:last-child { border-bottom: none; }
.rl-row:hover { background: rgba(28,22,8,0.03); }

.rl-link {
  flex: 1;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  position: relative;
  z-index: 2;
}

.rl-archive-btn {
  font-size: 13px;
  line-height: 1;
  color: rgba(28,22,8,0.2);
  background: none;
  border: none;
  padding: 0 2px;
  cursor: pointer;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}

.rl-row:hover .rl-archive-btn { opacity: 1; }
.rl-archive-btn:hover { color: rgba(150,65,35,0.7); }

/* "see all →" footer linking to /reading. Same treatment as
   .qv-card-seeall and .pv-card-seeall — small monospace, right
   aligned, dim by default, terracotta on hover. Sits inside the
   card as the last child below the body. */
.rl-card-seeall {
  display: block;
  text-align: right;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.45);
  text-decoration: none;
  padding: 0.5rem 0.8rem 0.6rem;
  border-top: 1px dotted rgba(28,22,8,0.06);
  position: relative;
  z-index: 2;
  transition: color 0.15s;
}

.rl-card-seeall:hover { color: rgba(150,65,35,0.85); }

/* ── Quote vault widget (notebook card) ────────────────────
   Compact card showing the 3 most recent quotes captured. Click "+ new"
   to capture, "see all" to navigate to the full /quotes archive. */
.item-quotes { cursor: default; }

.qv-card {
  background: #faf6ed;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  position: relative;
  padding: 0.6rem 0.85rem 0.7rem;
  overflow: hidden;
}

.item-quotes:hover .qv-card { box-shadow: var(--shadow-hover); }

/* Decorative oversized quotation mark in the bottom-right corner —
   subtle paper texture detail, helps the card read as "quotes" at a
   glance without a header icon. */
.qv-card::after {
  content: '\201D';
  position: absolute;
  bottom: -0.4rem;
  right: 0.5rem;
  font-family: 'Playfair Display', serif;
  font-size: 4.5rem;
  line-height: 1;
  color: rgba(150,65,35,0.07);
  pointer-events: none;
}

.qv-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  position: relative;
  z-index: 1;
}

.qv-card-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
}

.qv-card-add {
  background: transparent;
  /* See .pv-card-add for the rationale — neutral at rest, warm-red
     only on hover, so red stays reserved for urgency signals. */
  border: 1px solid rgba(28,22,8,0.18);
  color: rgba(28,22,8,0.55);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.55rem;
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.qv-card-add:hover {
  background: rgba(150,65,35,0.85);
  color: #faf6ed;
  border-color: rgba(150,65,35,0.85);
}

.qv-card-body {
  position: relative;
  z-index: 1;
  margin-bottom: 0.4rem;
}

.qv-card-quote {
  padding: 0.4rem 0;
  border-bottom: 1px dotted rgba(28,22,8,0.07);
}

.qv-card-quote:last-child { border-bottom: none; }

.qv-card-text {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  line-height: 1.45;
  color: rgba(28,22,8,0.85);
  margin: 0 0 0.15rem;
  font-style: italic;
}

.qv-card-attr {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.5);
  display: block;
}

/* Piece badge on the notebook quote widget — small accented link
   indicating this quote is attached to a piece. The arrow glyph reads as
   "filed under" without taking too much space. */
.qv-card-piece-link {
  display: inline-block;
  margin-top: 0.15rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(150,65,35,0.75);
  text-decoration: none;
  border-bottom: 1px dotted rgba(150,65,35,0.3);
}
.qv-card-piece-link:hover {
  color: rgba(150,65,35,0.95);
  border-bottom-color: rgba(150,65,35,0.7);
}

.qv-card-empty {
  font-family: 'Caveat', cursive;
  font-size: 0.85rem;
  color: rgba(28,22,8,0.35);
  padding: 0.5rem 0;
  text-align: center;
}

.qv-card-seeall {
  display: block;
  text-align: right;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.45);
  text-decoration: none;
  position: relative;
  z-index: 1;
}

.qv-card-seeall:hover { color: rgba(150,65,35,0.85); }

/* ── Quote capture modal (shared desktop + mobile) ──────────
   Body-level overlay opened from the notebook "+ new" button or the
   mobile FAB. Same structure as the /quotes page modal but injected
   ad-hoc so it can render anywhere. */
.qv-capture-bg {
  position: fixed;
  inset: 0;
  background: rgba(28,22,8,0.45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.qv-capture {
  background: #faf6ed;
  border-radius: 4px;
  padding: 1.4rem;
  max-width: 520px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 12px 36px rgba(0,0,0,0.3);
}

.qv-capture h2 {
  font-family: 'Playfair Display', serif;
  font-size: 1.2rem;
  margin: 0 0 1rem;
  color: rgba(28,22,8,0.9);
}

.qv-capture label {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.6);
  margin: 0.7rem 0 0.2rem;
}

.qv-capture textarea,
.qv-capture input[type=text],
.qv-capture input[type=date],
.qv-capture select {
  width: 100%;
  border: 1px solid rgba(28,22,8,0.15);
  background: white;
  padding: 0.5rem 0.6rem;
  font-family: 'Libre Baskerville', serif;
  font-size: 0.95rem;
  border-radius: 2px;
  box-sizing: border-box;
  color: rgba(28,22,8,0.9);
}

.qv-capture select {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.85rem;
}

.qv-capture textarea {
  min-height: 110px;
  resize: vertical;
  line-height: 1.4;
}

.qv-capture input:focus,
.qv-capture textarea:focus,
.qv-capture select:focus {
  outline: none;
  border-color: rgba(150,65,35,0.6);
}

/* "Show all" toggle inside the linked-piece label — inline checkbox that
   flips the picker between active/waiting and all pieces. Identical to the
   /quotes page toggle so the UI feels the same in both places. */
.qv-capture .qv-piece-toggle {
  float: right;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.4);
  cursor: pointer;
  user-select: none;
}
.qv-capture .qv-piece-toggle input[type=checkbox] {
  width: auto;
  vertical-align: middle;
  margin: 0 0.3em 0 0;
  cursor: pointer;
}
.qv-capture .qv-piece-toggle-label { vertical-align: middle; }

.qv-capture-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1.2rem;
}

.qv-capture-buttons button {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  padding: 0.5rem 1rem;
  border-radius: 2px;
  cursor: pointer;
  border: 1px solid rgba(28,22,8,0.15);
  background: white;
  color: rgba(28,22,8,0.85);
}

.qv-capture-buttons .qvc-save {
  background: rgba(150,65,35,0.85);
  border-color: rgba(150,65,35,0.85);
  color: #faf6ed;
}

.qv-capture-buttons .qvc-save:hover { background: rgba(150,65,35,1); }
.qv-capture-buttons .qvc-cancel:hover { background: rgba(28,22,8,0.04); }

@media (max-width: 639px) {
  .qv-capture { padding: 1.1rem; }
  .qv-capture h2 { font-size: 1.05rem; }
}

/* ── Pieces in progress widget (notebook card) ────────────
   Three-section card showing active / waiting / done(recent) pieces with
   urgency cues. Items are dense one-liners; full details on /pieces. */
.item-pieces { cursor: default; }

.pv-card {
  background: #faf6ed;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  position: relative;
  padding: 0.6rem 0.85rem 0.7rem;
  overflow: hidden;
}

.item-pieces:hover .pv-card { box-shadow: var(--shadow-hover); }

.pv-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.pv-card-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
}

.pv-card-add {
  background: transparent;
  /* Neutral at rest — warm-red is reserved for urgency signals
     (deadlines, active tag chip, highlights). A create-new affordance
     isn\'t urgent. Red appears on hover instead, so the button still
     reads as "something active will happen" when interacted with. */
  border: 1px solid rgba(28,22,8,0.18);
  color: rgba(28,22,8,0.55);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.55rem;
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.pv-card-add:hover {
  background: rgba(150,65,35,0.85);
  color: #faf6ed;
  border-color: rgba(150,65,35,0.85);
}

.pv-card-section {
  margin-bottom: 0.6rem;
}
.pv-card-section:last-child { margin-bottom: 0; }

.pv-card-section-head {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  padding: 0.2rem 0;
  border-bottom: 1px dotted rgba(28,22,8,0.1);
  margin-bottom: 0.3rem;
}

.pv-card-section-count {
  color: rgba(28,22,8,0.3);
  margin-left: 0.2em;
}

.pv-card-piece {
  position: relative;
  border-left: 2px solid rgba(28,22,8,0.12);
  padding: 0.45rem 0 0.45rem 0.6rem;
  margin-bottom: 0.4rem;
  transition: background 0.15s, border-left-color 0.15s;
}

/* Urgency cues. Thicker stripe + a soft background tint on the most
   pressing states, so the user's eye locks onto overdue/today pieces
   when scanning the column. "soon" and "this_week" get medium weight;
   "later" and "" stay quiet. Done pieces — published — read as muted
   so they don't compete with active work. */
.pv-card-piece.urgency-overdue {
  border-left: 3px solid rgba(192,57,43,0.95);
  background: linear-gradient(90deg, rgba(192,57,43,0.07), transparent 80%);
}
.pv-card-piece.urgency-today {
  border-left: 3px solid rgba(192,57,43,0.8);
  background: linear-gradient(90deg, rgba(192,57,43,0.04), transparent 80%);
}
.pv-card-piece.urgency-soon {
  border-left: 3px solid rgba(217,140,30,0.85);
}
.pv-card-piece.urgency-this_week {
  border-left: 2px solid rgba(150,130,60,0.65);
}
.pv-card-piece.status-published {
  opacity: 0.72;
}

.pv-card-piece-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.pv-card-piece-title {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.85);
  line-height: 1.3;
  font-weight: 600;
  flex: 1;
  min-width: 0;
}

.pv-card-piece-note {
  font-family: 'Libre Baskerville', serif;
  font-size: 0.7rem;
  color: rgba(28,22,8,0.55);
  font-style: italic;
  display: block;
  margin-top: 0.15rem;
}

/* Deadline label sits in the head, right-aligned. Color is driven by
   urgency state, same family as the left-border tint. */
.pv-card-piece-deadline {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.45);
  flex-shrink: 0;
  font-weight: 500;
  white-space: nowrap;
}
.pv-card-piece.urgency-overdue   .pv-card-piece-deadline { color: rgba(192,57,43,0.95); }
.pv-card-piece.urgency-today     .pv-card-piece-deadline { color: rgba(192,57,43,0.85); }
.pv-card-piece.urgency-soon      .pv-card-piece-deadline { color: rgba(217,140,30,0.95); }
.pv-card-piece.urgency-this_week .pv-card-piece-deadline { color: rgba(150,130,60,0.9); }

.pv-card-piece-filed {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.4);
  flex-shrink: 0;
}

/* Foot row: progress dots + stage label on the left, research counts
   on the right. Visually similar weight to the deadline above —
   secondary information that fills out the picture without competing
   with the title. */
.pv-card-piece-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.25rem;
}
.pv-card-piece-foot-left {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}

/* Progress dots — four small circles, fills left-to-right as the
   piece advances through reporting → drafting → with_editor → published.
   Unfilled = outlined neutral, filled = warm-red to match the editorial
   warm-brand palette. Subtle but readable; the eye learns the pattern
   fast. */
.pv-card-piece-progress {
  display: inline-flex;
  gap: 3px;
  flex-shrink: 0;
}
.pv-card-piece-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  border: 1px solid rgba(28,22,8,0.25);
  background: transparent;
}
.pv-card-piece-dot.filled {
  background: rgba(150,65,35,0.7);
  border-color: rgba(150,65,35,0.85);
}
/* For published pieces, all four dots are filled and a touch quieter
   so the card reads as completed but the visual hierarchy stays calm. */
.pv-card-piece.status-published .pv-card-piece-dot.filled {
  background: rgba(28,22,8,0.4);
  border-color: rgba(28,22,8,0.5);
}

.pv-card-piece-stage {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
  white-space: nowrap;
}

/* Research counts on the right of the foot row — small monospace,
   subtle. Whole strip omitted when no linked material exists, so
   thin pieces don't get a guilt-inducing zero everywhere. */
.pv-card-piece-research {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.4);
  flex-shrink: 0;
  white-space: nowrap;
}

.pv-card-more {
  display: block;
  text-align: right;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.4);
  text-decoration: none;
  padding: 0.2rem 0;
}
.pv-card-more:hover { color: rgba(150,65,35,0.85); }

.pv-card-empty {
  font-family: 'Caveat', cursive;
  font-size: 0.85rem;
  color: rgba(28,22,8,0.35);
  padding: 0.5rem 0;
  text-align: center;
}

.pv-card-seeall {
  display: block;
  text-align: right;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.45);
  text-decoration: none;
}

.pv-card-seeall:hover { color: rgba(150,65,35,0.85); }

/* ── Tag index widget ────────────────────────────────────── */
/* Lives at the bottom of the right column. Header is a button that
   toggles the chip grid open/closed; the chevron rotates 180° when
   expanded. Visual idiom mirrors other widgets (paper, monospace
   label) so it reads as part of the chrome family. */
.ti-card {
  background: #faf6ed;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow: var(--shadow-sm);
  padding: 0;
  position: relative;
  overflow: hidden;
}

.ti-card-header {
  width: 100%;
  background: transparent;
  border: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
  cursor: pointer;
  font-family: 'IBM Plex Mono', monospace;
  color: inherit;
  text-align: left;
  transition: background 0.12s;
}
.ti-card-header:hover {
  background: rgba(150,65,35,0.04);
}

.ti-card-label {
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
}

.ti-card-count {
  font-size: 0.6rem;
  color: rgba(28,22,8,0.4);
  margin-left: auto;
}

/* Chevron rotates 180° when expanded — same easing as similar
   toggles elsewhere in the workspace. */
.ti-card-chev {
  width: 10px;
  height: 10px;
  color: rgba(28,22,8,0.4);
  transition: transform 0.18s;
  flex-shrink: 0;
}
.ti-card.ti-expanded .ti-card-chev {
  transform: rotate(180deg);
}

/* Body collapses to zero height when not expanded. Using max-height
   for transition (rather than display:none) keeps the open/close
   animation smooth. opacity layered on top so it fades cleanly. */
.ti-card-body {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.25s ease, opacity 0.18s ease;
  padding: 0 0.85rem;
}
.ti-card.ti-expanded .ti-card-body {
  max-height: 600px;
  opacity: 1;
  padding: 0 0.85rem 0.75rem;
}

.ti-card-empty {
  font-family: 'Caveat', cursive;
  font-size: 0.78rem;
  color: rgba(28,22,8,0.4);
  padding: 0.5rem 0;
  text-align: center;
  line-height: 1.4;
}
.ti-card-empty code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  color: rgba(120,80,30,0.85);
  background: rgba(120,80,30,0.06);
  padding: 1px 4px;
  border-radius: 2px;
}

/* Chip grid: flex-wrap so chips flow naturally. Each chip is a
   .hashtag-link with the ti-chip class adding a pill backing and
   an inline usage count. Bigger and more affordance-y than the
   inline .hashtag-link in body text — this is a navigation surface,
   not an annotation. */
.ti-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding-top: 0.2rem;
}

.ti-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  padding: 0.18rem 0.45rem;
  background: rgba(120,80,30,0.07);
  color: rgba(120,80,30,0.85);
  border-radius: 2px;
  border-bottom: none;  /* override .hashtag-link's dotted underline */
  letter-spacing: 0.01em;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.ti-chip:hover {
  background: rgba(150,65,35,0.15);
  color: rgba(150,65,35,0.95);
  border-bottom: none;
}

.ti-chip-count {
  font-size: 0.55rem;
  color: rgba(28,22,8,0.4);
  font-weight: normal;
}
.ti-chip:hover .ti-chip-count {
  color: rgba(150,65,35,0.6);
}

/* ── Piece capture modal (shared desktop + mobile) ──────────
   Same shape as quote capture modal, with an extra row for status + outlet. */
.pv-capture-bg {
  position: fixed;
  inset: 0;
  background: rgba(28,22,8,0.45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.pv-capture {
  background: #faf6ed;
  border-radius: 4px;
  padding: 1.4rem;
  max-width: 540px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 12px 36px rgba(0,0,0,0.3);
}

.pv-capture h2 {
  font-family: 'Playfair Display', serif;
  font-size: 1.2rem;
  margin: 0 0 1rem;
  color: rgba(28,22,8,0.9);
}

.pv-capture label {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.6);
  margin: 0.7rem 0 0.2rem;
}

.pv-capture input,
.pv-capture select {
  width: 100%;
  border: 1px solid rgba(28,22,8,0.15);
  background: white;
  padding: 0.5rem 0.6rem;
  font-family: 'Libre Baskerville', serif;
  font-size: 0.95rem;
  border-radius: 2px;
  box-sizing: border-box;
  color: rgba(28,22,8,0.9);
}

.pv-capture select { font-family: 'IBM Plex Mono', monospace; font-size: 0.85rem; }

.pv-capture-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
}

.pv-capture-row > div { min-width: 0; }

.pv-capture input:focus,
.pv-capture select:focus {
  outline: none;
  border-color: rgba(150,65,35,0.6);
}

.pv-capture-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1.2rem;
}

.pv-capture-buttons button {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  padding: 0.5rem 1rem;
  border-radius: 2px;
  cursor: pointer;
  border: 1px solid rgba(28,22,8,0.15);
  background: white;
  color: rgba(28,22,8,0.85);
}

.pv-capture-buttons .pvc-save {
  background: rgba(150,65,35,0.85);
  border-color: rgba(150,65,35,0.85);
  color: #faf6ed;
}

.pv-capture-buttons .pvc-save:hover { background: rgba(150,65,35,1); }
.pv-capture-buttons .pvc-cancel:hover { background: rgba(28,22,8,0.04); }

@media (max-width: 639px) {
  .pv-capture { padding: 1.1rem; }
  .pv-capture h2 { font-size: 1.05rem; }
  .pv-capture-row { grid-template-columns: 1fr; }
}

/* ── Gmail-style swipe to archive on mobile note rows ───── */
@media (max-width: 639px) {
  .mob-note-row {
    position: relative;
    overflow: hidden;
  }

  .mob-note-row-inner {
    display: grid;
    grid-template-columns: 52px 1fr;
    gap: 8px;
    padding: 6px 12px;
    align-items: baseline;
    background: #faf8f4;
    position: relative;
    z-index: 1;
    will-change: transform;
  }

  /* When swipe is active, the row inner moves and shows the bg underneath */
  .mob-note-swipe-bg {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    background: rgba(150,65,35,0.82);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 20px;
    opacity: 0;
    transition: opacity 0.1s;
    z-index: 0;
  }

  .mob-note-swipe-label {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 8px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: 600;
    color: #faf6ea;
  }

  /* Rows with swipe inner need no padding on the outer row */
  .mob-note-row:has(.mob-note-row-inner) {
    padding: 0;
  }
}

/* ── Article headline link ───────────────────────────────── */
.clipping-headline-link {
  text-decoration: none;
  color: inherit;
  display: block;
  cursor: pointer;
}

.clipping-headline-link h2 {
  transition: color 0.15s;
}

/* All hover effects activate on the entire card hover */
.item-clipping:hover .clipping-headline-link h2 {
  color: rgba(28,22,8,0.65);
}

.item-clipping:hover .clipping-expand-foot .read-link,
.item-clipping:hover .clipping-foot .read-link {
  color: rgba(28,22,8,0.55);
  border-color: rgba(28,22,8,0.14);
}

.item-clipping:hover .clipping-expand-toggle {
  color: rgba(150,65,35,0.85);
}

/* Deck and masthead remain selectable */
.clipping-deck,
.clipping-masthead {
  user-select: text;
  -webkit-user-select: text;
  cursor: text;
}

.clipping-expand-foot .read-link,
.clipping-foot .read-link {
  text-decoration: none;
  color: var(--ink);
  border-bottom-color: rgba(28,28,26,0.18);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, opacity 0.15s;
}

/* ── Non-package article foot — matches expand-foot layout ── */
.clipping-foot {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  margin-top: 0.8rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(28,28,26,0.08);
}

/* ── No headline hover on mobile ─────────────────────────── */
@media (max-width: 639px) {
/* No mobile-specific headline hover override — works on both */
}

/* ── Hide back-to-top in focus mode and mobile editor ───── */
body.focus-mode .back-to-top,
body:has(.mob-editor-overlay) .back-to-top { display: none !important; }

/* ── Scrap note collapsed / read more ────────────────────── */
.fieldnote-body.collapsed {
  max-height: 120px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
  mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}

.fieldnote-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.35);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.2rem 0;
  display: block;
  margin: 0 auto;
  transition: color 0.15s;
}

.fieldnote-toggle:hover { color: rgba(150,65,35,0.6); }

/* ── Mobile newswire scrollable body ─────────────────────── */
@media (max-width: 639px) {
  .mob-rss-body {
    max-height: 320px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE/Edge */
  }
  .mob-rss-body::-webkit-scrollbar { display: none; } /* Chrome/Safari */

  /* Mobile reading list scrollable */
  .mob-link-list {
    max-height: 240px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .mob-link-list::-webkit-scrollbar { display: none; }

  /* Mobile agenda scrollable */
  .mob-agenda-body {
    max-height: 280px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    scrollbar-width: none;
    -ms-overflow-style: none;
    position: relative;
  }
  .mob-agenda-body::-webkit-scrollbar { display: none; }
}

/* ── Calendar unknown weather placeholder ────────────────── */
.cal-cell-icon-unknown {
  opacity: 0.7;
}

.cal-cell-temp-unknown {
  color: rgba(28,22,8,0.25);
}

/* ── Notebook toolbar privacy toggle ─────────────────────── */
.nb-priv-toggle {
  font-size: 11px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 4px;
  opacity: 0.4;
  transition: opacity 0.15s;
  line-height: 1;
  flex-shrink: 0;
}

.nb-priv-toggle:hover { opacity: 0.8; }

/* ── Custom prompt modal ─────────────────────────────────── */
.custom-prompt-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(28,22,8,0.3);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.custom-prompt-overlay.custom-prompt-in { opacity: 1; }

.custom-prompt-box {
  background: #faf6ea;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow: 0 8px 32px rgba(28,22,8,0.18), 0 2px 8px rgba(28,22,8,0.1);
  width: 90%;
  max-width: 380px;
  padding: 1.4rem 1.5rem 1.2rem;
  position: relative;
  transform: translateY(8px);
  transition: transform 0.2s ease;
  /* Ruled lines background */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 27px,
    rgba(100,80,50,0.06) 27px, rgba(100,80,50,0.06) 28px
  );
}

.custom-prompt-in .custom-prompt-box { transform: translateY(0); }

.custom-prompt-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  display: block;
  margin-bottom: 0.35rem;
}

.custom-prompt-label-second {
  margin-top: 0.9rem;
}

.custom-prompt-input {
  width: 100%;
  font-family: 'Special Elite', cursive;
  font-size: 0.9rem;
  color: rgba(28,22,8,0.82);
  background: transparent;
  border: none;
  border-bottom: 1.5px solid rgba(28,22,8,0.15);
  padding: 0.3rem 0;
  outline: none;
  caret-color: rgba(150,65,35,0.8);
  box-sizing: border-box;
  transition: border-color 0.15s;
}

.custom-prompt-input:focus {
  border-bottom-color: rgba(150,65,35,0.45);
}

.custom-prompt-input::placeholder {
  color: rgba(28,22,8,0.2);
  font-style: italic;
}

.custom-prompt-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 1.2rem;
}

.custom-prompt-cancel {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.35);
  background: none;
  border: none;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
  transition: color 0.15s;
}

.custom-prompt-cancel:hover { color: rgba(28,22,8,0.6); }

.custom-prompt-ok {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
  background: rgba(150,65,35,0.06);
  border: 1px solid rgba(150,65,35,0.2);
  padding: 0.3rem 0.8rem;
  cursor: pointer;
  transition: all 0.15s;
  border-radius: 1px;
}

.custom-prompt-ok:hover {
  background: rgba(150,65,35,0.1);
  border-color: rgba(150,65,35,0.35);
  color: rgba(150,65,35,0.9);
}

/* ── Extended link prompt: tags, collection, favorite, piece autocomplete ── */

/* Wider variant for the link prompt with all the extra fields */
.custom-prompt-box-link { max-width: 460px; }

/* Smaller hint text inline within labels (e.g. "comma-separated") */
.custom-prompt-hint {
  font-size: 0.42rem;
  text-transform: none;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.32);
  font-weight: normal;
  margin-left: 0.3rem;
}

.custom-prompt-hint code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  background: rgba(150,65,35,0.05);
  padding: 0.05rem 0.25rem;
  border-radius: 1px;
  color: rgba(150,65,35,0.7);
}

/* Native <select> styling to match the inputs */
select.custom-prompt-input {
  font-family: 'Special Elite', cursive;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, rgba(28,22,8,0.4) 50%),
                    linear-gradient(135deg, rgba(28,22,8,0.4) 50%, transparent 50%);
  background-position: calc(100% - 12px) center, calc(100% - 7px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 1.5rem;
}

/* Favorite checkbox row */
.custom-prompt-checkbox-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.55);
  cursor: pointer;
  user-select: none;
}

.custom-prompt-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border: 1.5px solid rgba(28,22,8,0.25);
  background: transparent;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: border-color 0.15s, background 0.15s;
}

.custom-prompt-checkbox:checked {
  border-color: rgba(150,65,35,0.5);
  background: rgba(150,65,35,0.1);
}

.custom-prompt-checkbox:checked::after {
  content: '★';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -52%);
  font-size: 11px;
  color: rgba(150,65,35,0.85);
  line-height: 1;
}

.custom-prompt-checkbox-row:hover .custom-prompt-checkbox {
  border-color: rgba(28,22,8,0.45);
}

/* Piece autocomplete menu — positioned absolute, anchored under tags input */
.custom-prompt-piece-wrap {
  position: relative;
  height: 0;
}

.custom-prompt-piece-menu {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background: #faf6ea;
  border: 1px solid rgba(28,22,8,0.18);
  box-shadow: 0 4px 14px rgba(28,22,8,0.14);
  z-index: 10001;
  max-height: 180px;
  overflow-y: auto;
  margin-top: 2px;
}

.custom-prompt-piece-opt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px dotted rgba(28,22,8,0.08);
  padding: 0.4rem 0.6rem;
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: background 0.1s;
}

.custom-prompt-piece-opt:last-child { border-bottom: none; }
.custom-prompt-piece-opt:hover { background: rgba(150,65,35,0.05); }

.custom-prompt-piece-slug {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  color: rgba(150,65,35,0.7);
}

.custom-prompt-piece-title {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.62rem;
  color: rgba(28,22,8,0.7);
}

/* ── Public Spotify widget (no controls) ─────────────────── */
.song-controls-public {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.2rem;
}

.song-spotify-link {
  display: flex;
  align-items: center;
  opacity: 0.6;
  transition: opacity 0.15s;
}

.song-spotify-link:hover { opacity: 1; }

/* ── Hide from homepage buttons ──────────────────────────── */
.link-hide-btn {
  position: absolute;
  top: 6px;
  right: 26px;
  width: 18px;
  height: 18px;
  font-size: 12px;
  line-height: 1;
  color: rgba(28,22,8,0.25);
  background: rgba(245,242,234,0.85);
  border: 1px solid rgba(28,22,8,0.1);
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
  z-index: 20;
}

.item-link:hover .link-hide-btn { opacity: 1; }
.link-hide-btn:hover { color: rgba(28,22,8,0.5); }

.mind-hide-btn,
.fieldnote-hide-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.2);
  background: none;
  border: 1px solid rgba(28,22,8,0.08);
  padding: 0.12rem 0.45rem;
  cursor: pointer;
  border-radius: 1px;
  transition: color 0.15s, border-color 0.15s;
}

.mind-hide-btn:hover,
.fieldnote-hide-btn:hover {
  color: rgba(28,22,8,0.45);
  border-color: rgba(28,22,8,0.18);
}

/* Hide buttons only visible on All tab — not needed on notebook */
.filter-notes .mind-hide-btn,
.filter-notes .fieldnote-hide-btn,
.filter-notes .link-hide-btn { display: none; }

/* ── 404 Page ────────────────────────────────────────────── */
.error-404-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  padding: 4rem 2rem;
}

.error-404-card {
  background: #faf8f4;
  border: 1px solid rgba(28,22,8,0.1);
  box-shadow:
    0 4px 12px rgba(28,22,8,0.08),
    0 12px 32px rgba(28,22,8,0.06);
  max-width: 480px;
  width: 100%;
  position: relative;
  overflow: hidden;
  transform: rotate(-0.5deg);
  /* Ruled lines */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 27px,
    rgba(100,80,50,0.05) 27px,
    rgba(100,80,50,0.05) 28px
  );
}

/* Red margin line */
.error-404-card::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 38px;
  width: 1.5px;
  background: rgba(185,35,35,0.1);
  z-index: 0;
}

.error-404-body {
  padding: 2.5rem 2rem 2rem 52px;
  position: relative;
  z-index: 1;
}

.error-404-num {
  font-family: 'Playfair Display', serif;
  font-size: 4rem;
  font-weight: 700;
  color: rgba(28,22,8,0.12);
  line-height: 1;
  display: block;
  margin-bottom: 0.5rem;
  position: relative;
}

.error-404-circle {
  position: absolute;
  top: 1.8rem;
  left: 36px;
  width: 160px;
  height: 80px;
  pointer-events: none;
}

.error-404-text {
  font-family: 'Special Elite', cursive;
  font-size: 0.95rem;
  line-height: 1.7;
  color: rgba(28,22,8,0.65);
  margin: 1.2rem 0 0;
}

.error-404-note {
  font-family: 'Caveat', cursive;
  font-size: 1.3rem;
  color: rgba(150,65,35,0.4);
  margin: 1rem 0 0;
  transform: rotate(-2deg);
  display: inline-block;
}

.error-404-link {
  display: inline-block;
  margin-top: 1.5rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.6);
  text-decoration: none;
  border-bottom: 1px solid rgba(150,65,35,0.2);
  padding-bottom: 2px;
  transition: color 0.15s, border-color 0.15s;
}

.error-404-link:hover {
  color: rgba(150,65,35,0.85);
  border-color: rgba(150,65,35,0.4);
}

@media (max-width: 639px) {
  .error-404-card { transform: rotate(0); }
  .error-404-num { font-size: 3rem; }
  .error-404-body { padding: 2rem 1.5rem 1.5rem 48px; }
}

/* ── Hide archive buttons on mobile — use swipe-to-archive instead ── */
@media (max-width: 639px) {
  .mind-card-actions { display: none; }
  .fieldnote-archive-btn { display: none; }
  .link-archive-btn,
  .link-hide-btn { display: none; }
}

/* ── Carousel mobile fixes ───────────────────────────────── */
@media (max-width: 639px) {
  .pinned-carousel-viewport {
    -webkit-mask-image: linear-gradient(to right, transparent 0%, black 4%, black 96%, transparent 100%);
    mask-image: linear-gradient(to right, transparent 0%, black 4%, black 96%, transparent 100%);
    padding-bottom: 3rem;
  }
  .pinned-row-inner .item {
    max-width: 100% !important;
  }
}

/* ── (scribble feature removed) ───────────────────────────── */

/* ── Footer actions group — hide + archive side by side ──── */
.fieldnote-footer-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  opacity: 0;
  transition: opacity 0.2s;
}

.item-fieldnote:hover .fieldnote-footer-actions { opacity: 1; }

/* Mind card actions gap between buttons */
.mind-card-actions {
  gap: 0.5rem;
}

/* ── Live markdown styling in contenteditable ────────────── */

/* Markdown syntax characters — faded so content stands out */
.ce-md-marker {
  color: rgba(28,22,8,0.15);
  font-weight: 400;
  font-style: normal;
  font-family: inherit;
  font-size: inherit;
  letter-spacing: inherit;
}

/* Bold */
.ce-md-bold {
  font-weight: 700;
  color: rgba(28,22,8,0.95);
  text-shadow: 0.3px 0 0 rgba(28,22,8,0.12);
}

/* Italic */
.ce-md-italic {
  font-family: 'Caveat', cursive;
  font-size: 1.1em;
  color: rgba(28,22,8,0.7);
}

/* Bold italic */
.ce-md-bolditalic {
  font-weight: 700;
  font-family: 'Caveat', cursive;
  font-size: 1.1em;
  color: rgba(28,22,8,0.9);
}

/* Strikethrough */
.ce-md-strike {
  color: rgba(28,22,8,0.35);
  text-decoration: line-through;
  text-decoration-color: rgba(150,65,35,0.4);
}

/* Code */
.ce-md-code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.88em;
  color: rgba(28,22,8,0.7);
  background: rgba(28,22,8,0.04);
  padding: 0 0.2em;
  border-radius: 1px;
}

/* Link */
.ce-md-link {
  color: rgba(150,65,35,0.75);
  text-decoration-line: underline;
  text-decoration-style: wavy;
  text-decoration-color: rgba(150,65,35,0.3);
  text-underline-offset: 2px;
}

.ce-md-link-url {
  color: rgba(150,65,35,0.4);
  font-size: 0.9em;
}

/* Circle annotation */
.ce-md-circle {
  background: rgba(150,65,35,0.06);
  border-radius: 2px;
  padding: 0 0.15em;
}

/* Highlight */
.ce-md-highlight {
  background: linear-gradient(
    104deg,
    rgba(255,210,80,0) 0.9%,
    rgba(255,210,80,0.38) 2.4%,
    rgba(255,210,80,0.35) 70%,
    rgba(255,210,80,0.15) 94%,
    rgba(255,210,80,0) 99%
  );
  padding: 0.05em 0;
}

/* Blockquote */
.ce-md-bq {
  font-style: italic;
  color: rgba(28,22,8,0.55);
}

/* Heading */
.ce-md-heading {
  font-weight: 700;
  color: rgba(28,22,8,0.88);
}

/* List markers */
.ce-md-list-marker {
  font-family: 'Caveat', cursive !important;
  font-weight: 700 !important;
  font-size: 1.15em !important;
  color: rgba(150,65,35,0.4) !important;
}

.ce-md-num-marker {
  font-family: 'Caveat', cursive !important;
  font-weight: 700 !important;
  font-size: 1.1em !important;
  color: rgba(150,65,35,0.4) !important;
}

/* HR line */
.ce-md-hr {
  color: rgba(28,22,8,0.15);
  text-decoration: line-through;
  text-decoration-color: rgba(28,22,8,0.12);
}

/* ── Additional live markdown styles ─────────────────────── */

/* Underline: __text__ */
.ce-md-underline {
  text-decoration: underline;
  text-decoration-color: rgba(180,40,20,0.4);
  text-decoration-style: solid;
  text-underline-offset: 2px;
}

/* Double underline: __*text*__ */
.ce-md-dblunderline {
  text-decoration: underline;
  text-decoration-color: rgba(180,40,20,0.5);
  text-decoration-style: double;
  text-underline-offset: 2px;
}

/* Scribble-out: %%text%% */
.ce-md-scribble {
  color: rgba(28,22,8,0.3);
  text-decoration: line-through;
  text-decoration-color: rgba(28,22,8,0.5);
  text-decoration-thickness: 3px;
}

/* Margin note: >>text<< */
.ce-md-margin {
  font-family: 'Caveat', cursive;
  font-size: 1.05em;
  color: rgba(150,65,35,0.6);
  font-style: italic;
}

/* Insert: ^^text^^ */
.ce-md-insert {
  color: rgba(180,40,20,0.6);
  font-size: 0.85em;
  vertical-align: super;
  font-family: 'Caveat', cursive;
}

/* ── Trash buttons ───────────────────────────────────────── */
.mind-trash-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(180,40,20,0.2);
  background: none;
  border: 1px solid rgba(180,40,20,0.08);
  padding: 0.12rem 0.45rem;
  cursor: pointer;
  border-radius: 1px;
  transition: all 0.15s;
}

.mind-trash-btn:hover {
  color: rgba(180,40,20,0.6);
  border-color: rgba(180,40,20,0.25);
}

.fieldnote-trash-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.38rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(180,40,20,0.2);
  background: none;
  border: 1px solid rgba(180,40,20,0.08);
  padding: 0.1rem 0.4rem;
  cursor: pointer;
  border-radius: 1px;
  transition: all 0.15s;
}

.fieldnote-trash-btn:hover {
  color: rgba(180,40,20,0.6);
  border-color: rgba(180,40,20,0.25);
}

/* Hide all action buttons on mobile — swipe handles it */
@media (max-width: 639px) {
  .mind-trash-btn,
  .fieldnote-trash-btn { display: none; }
}
/* ─────────────────────────────────────────────
   DEPESZA — Daily Briefing Sheet
   A typed briefing torn from a pad and pinned
   to the corkboard. Perforated top, ruled lines,
   red margin, slight paper aging.
   ───────────────────────────────────────────── */

.item-depesza {
  cursor: default;
  /* Override the default item pin — depesza has its own treatment */
}

.item-depesza::before {
  /* Move pin to top-left to feel like a working document */
  left: 12%;
  transform: none;
}

.depesza-card {
  background: #fdfaf4;
  border: 1px solid rgba(28,22,8,0.09);
  box-shadow:
    var(--shadow-sm),
    inset 0 0 60px rgba(28,22,8,0.012);
  transition: box-shadow 0.22s;
  position: relative;
  overflow: hidden;
  font-family: 'Libre Baskerville', Georgia, serif;
  color: rgba(28,22,8,0.78);
}

.item-depesza:hover .depesza-card {
  box-shadow:
    var(--shadow-hover),
    inset 0 0 60px rgba(28,22,8,0.012);
}

/* ── Perforated top edge — torn from a wire service printout ── */
.depesza-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 5px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px, transparent 3px,
    rgba(28,22,8,0.05) 3px, rgba(28,22,8,0.05) 4px,
    transparent 4px, transparent 7px
  );
  z-index: 3;
}

/* ── Red margin rule — kept for compatibility with the JS that injects it,
   but rendered invisible. Remove the JS injection in a future cleanup. ── */
.depesza-margin-rule { display: none; }

/* ── Perforated bottom edge ── */
.depesza-footer::after {
  content: '';
  display: block;
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 3px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px, transparent 4px,
    rgba(28,22,8,0.05) 4px, rgba(28,22,8,0.05) 8px
  );
}

/* ─── HEADER — masthead strip ─── */
.depesza-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 1rem 0.45rem 1rem;
  background: rgba(28,22,8,0.025);
  border-bottom: 1px solid rgba(28,22,8,0.08);
  position: relative;
  z-index: 1;
}

.depesza-classification {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  font-weight: 600;
  color: rgba(150,65,35,0.85);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  background: rgba(150,65,35,0.07);
  border: 1px solid rgba(150,65,35,0.2);
  padding: 0.15rem 0.55rem 0.12rem;
  display: inline-block;
}

.depesza-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.4) !important;
  background: none;
  background-color: transparent;
  border: none;
  cursor: pointer;
  padding: 2px 4px;
  letter-spacing: 0.06em;
  line-height: 1;
  transition: color 0.15s;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  outline: none;
  text-decoration: none;
}

.depesza-toggle:hover,
.depesza-toggle:focus,
.depesza-toggle:active { color: rgba(150,65,35,0.75) !important; text-decoration: none; }

/* ─── META ─── */
.depesza-meta {
  display: flex;
  justify-content: space-between;
  padding: 0.35rem 1rem 0.35rem 1rem;
  border-bottom: 1px dashed rgba(28,22,8,0.07);
  position: relative;
  z-index: 1;
  background: rgba(28,22,8,0.012);
}

.depesza-meta-item {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  color: rgba(28,22,8,0.32);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* ─── HEADLINE — the day's lead, dominant ─── */
.depesza-headline {
  padding: 0.85rem 1rem 0.8rem 1rem;
  font-family: 'Playfair Display', serif;
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.28;
  color: rgba(28,22,8,0.88);
  border-bottom: 1px solid rgba(28,22,8,0.07);
  position: relative;
  z-index: 1;
  letter-spacing: -0.005em;
}

.depesza-card.collapsed .depesza-headline {
  border-bottom: none;
  cursor: pointer;
}

/* ─── BODY — scrollable ─── */
.depesza-body {
  position: relative;
  z-index: 1;
  max-height: 400px;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.depesza-body::-webkit-scrollbar { display: none; }

/* Bottom fade to hint scrollability */
.depesza-body::after {
  content: '';
  display: block;
  height: 1.2rem;
  background: linear-gradient(transparent, rgba(253,250,244,0.92));
  position: sticky;
  bottom: 0;
  pointer-events: none;
}

/* ─── SECTIONS ─── */
.depesza-section {
  padding: 0.6rem 1rem 0.6rem 1rem;
  border-bottom: 1px dashed rgba(28,22,8,0.08);
}

.depesza-section:last-child { border-bottom: none; }

.depesza-section-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
  margin-bottom: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.depesza-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(150,65,35,0.15);
}

/* ─── AGENDA ITEMS ─── */
.depesza-agenda-item {
  display: flex;
  gap: 0.6rem;
  padding: 0.35rem 0;
  align-items: baseline;
}

.depesza-agenda-item + .depesza-agenda-item {
  border-top: 1px dotted rgba(28,22,8,0.06);
}

.depesza-time {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(150,65,35,0.65);
  width: 3.8rem;
  min-width: 3.8rem;
  flex-shrink: 0;
  font-weight: 500;
  letter-spacing: 0.04em;
}

.depesza-event {
  font-size: 0.7rem;
  line-height: 1.45;
  color: rgba(28,22,8,0.78);
}

.depesza-event-link {
  font-size: 0.7rem;
  line-height: 1.45;
  color: rgba(28,22,8,0.78);
  text-decoration: none;
  border-bottom: 1px dotted rgba(28,22,8,0.22);
  transition: color 0.15s, border-color 0.15s;
}

.depesza-event-link:hover {
  color: rgba(150,65,35,0.85);
  border-bottom-color: rgba(150,65,35,0.45);
}

.depesza-event-location {
  font-size: 0.58rem;
  color: rgba(28,22,8,0.42);
  font-style: italic;
}

.depesza-event-relevance {
  font-size: 0.58rem;
  color: rgba(28,22,8,0.5);
  margin-top: 0.2rem;
  padding-left: 0.5rem;
  border-left: 1.5px solid rgba(150,65,35,0.3);
  line-height: 1.5;
}

/* ─── NEWS ITEMS ─── */
.depesza-news-item { padding: 0.45rem 0; }

.depesza-news-item + .depesza-news-item {
  border-top: 1px dotted rgba(28,22,8,0.06);
}

.depesza-news-headline {
  font-family: 'Playfair Display', serif;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: 0.25rem;
  color: rgba(28,22,8,0.85);
}

.depesza-news-summary {
  font-size: 0.62rem;
  line-height: 1.55;
  color: rgba(28,22,8,0.6);
}

.depesza-news-source {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  color: rgba(28,22,8,0.35);
  margin-top: 0.25rem;
  display: inline-block;
  letter-spacing: 0.06em;
}

.depesza-news-source a {
  color: rgba(150,65,35,0.65);
  text-decoration: none;
  border-bottom: 1px dotted rgba(150,65,35,0.25);
}

.depesza-news-source a:hover {
  color: rgba(150,65,35,0.9);
  border-bottom-color: rgba(150,65,35,0.5);
}

/* ─── RADAR ─── */
.depesza-radar-item {
  display: flex;
  gap: 0.4rem;
  padding: 0.35rem 0;
  align-items: baseline;
  font-size: 0.62rem;
  line-height: 1.45;
  flex-wrap: wrap;
}

.depesza-radar-item + .depesza-radar-item {
  border-top: 1px dotted rgba(28,22,8,0.06);
}

.depesza-radar-name {
  font-family: 'Playfair Display', serif;
  font-weight: 700;
  white-space: nowrap;
  flex-shrink: 0;
  color: rgba(28,22,8,0.85);
  font-size: 0.7rem;
}

.depesza-radar-role {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  color: rgba(28,22,8,0.38);
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.depesza-radar-status {
  color: rgba(28,22,8,0.6);
  font-size: 0.62rem;
}

/* ─── BRUSSELS WATCH ─── */
.depesza-brussels {
  font-size: 0.66rem;
  line-height: 1.6;
  color: rgba(28,22,8,0.7);
  padding: 0.4rem 0 0.4rem 0.7rem;
  border-left: 2px solid rgba(0,51,153,0.32);
  background: rgba(0,51,153,0.02);
}

/* ─── EDITOR'S NOTE ─── */
.depesza-editors-note {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-size: 0.7rem;
  line-height: 1.6;
  color: rgba(28,22,8,0.62);
  padding: 0.2rem 0;
}

/* ─── DATA GAPS — transparency about what's missing ─── */
.depesza-data-gap {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  line-height: 1.55;
  color: rgba(28,22,8,0.32);
  padding: 0.12rem 0;
  letter-spacing: 0.04em;
}

/* ─── FOOTER ─── */
.depesza-footer {
  padding: 0.4rem 1rem 0.4rem 1rem;
  border-top: 1px solid rgba(28,22,8,0.07);
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;
  z-index: 1;
  background: rgba(28,22,8,0.012);
}

.depesza-footer-text {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.42rem;
  color: rgba(28,22,8,0.28);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.depesza-refresh-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.45rem;
  color: rgba(28,22,8,0.3);
  background: none;
  background-color: transparent;
  border: 1px solid rgba(28,22,8,0.08);
  padding: 0.12rem 0.35rem;
  cursor: pointer;
  letter-spacing: 0.03em;
  transition: all 0.15s;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.depesza-refresh-btn:hover {
  background: rgba(28,22,8,0.03);
  color: rgba(28,22,8,0.5);
  border-color: rgba(28,22,8,0.15);
}

.depesza-refresh-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

/* "↻ new edition" pill — appears in the footer-left slot when the
   freshness check detects a newer edition than the one rendered.
   Hidden by default (HTML `hidden` attribute), revealed by JS, and
   mutually exclusive with the plain refresh button. Coral accent so
   it pulls eyes — this is a call-to-action, not a passive control. */
.depesza-new-edition-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(150,65,35,0.85);
  background: rgba(150,65,35,0.06);
  border: 1px solid rgba(150,65,35,0.2);
  border-radius: 1px;
  cursor: pointer;
  padding: 2px 6px;
  letter-spacing: 0.06em;
  line-height: 1;
  transition: background 0.15s, color 0.15s;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}
.depesza-new-edition-btn:hover {
  background: rgba(150,65,35,0.12);
  color: rgba(150,65,35,1);
}
.depesza-new-edition-btn:disabled {
  opacity: 0.5;
  cursor: wait;
}

/* ─── READ FULL BRIEFING LINK ─── */
.depesza-read-full {
  padding: 0.6rem 1rem 0.5rem 1rem;
  text-align: right;
  position: relative;
  z-index: 1;
  border-top: 1px solid rgba(28,22,8,0.05);
  background: rgba(150,65,35,0.018);
}

.depesza-read-full-link {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.85);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.15s ease;
}

.depesza-read-full-link:hover {
  color: rgba(150,65,35,1);
}

/* ─── POLICY PIPELINE TYPE TAG ─── */
.depesza-pipeline-type {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.65);
  background: rgba(150,65,35,0.07);
  padding: 0.12rem 0.4rem;
  border-radius: 1px;
  margin-left: 0.35rem;
  vertical-align: middle;
  font-weight: 500;
}

/* ─── COLLAPSED STATE ─── */
/* Body and right-side metadata are hidden when collapsed; the footer
   strip itself stays visible so the ↻ refresh button (or "↻ new
   edition" pill, when applicable) remains one click away without
   unfurling the card. Mirrors the symmetry the user noticed: just
   like "Read full briefing →" sits on the right when the body is
   visible, "↻ refresh" sits on the left when collapsed. */
.depesza-card.collapsed .depesza-body { display: none; }
.depesza-card.collapsed .depesza-footer-text { display: none; }
.depesza-card.collapsed .depesza-footer {
  padding-top: 0.3rem;
  padding-bottom: 0.3rem;
}

/* Two-slot footer — left holds the action button (refresh OR the
   new-edition pill, mutually exclusive), right holds metadata. */
.depesza-footer-left {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* ─── LOADING ─── */
.depesza-loading {
  padding: 0.85rem 1rem 0.85rem 1rem;
  position: relative;
  z-index: 1;
}

.depesza-loading-pulse {
  display: block;
  height: 7px;
  background: linear-gradient(90deg, rgba(28,22,8,0.03) 25%, rgba(28,22,8,0.06) 50%, rgba(28,22,8,0.03) 75%);
  background-size: 200% 100%;
  animation: depesza-shimmer 1.5s infinite;
  margin: 0.3rem 0;
}

@keyframes depesza-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ─── ERROR / EMPTY ─── */
.depesza-error,
.depesza-empty {
  padding: 0.85rem 1rem 0.85rem 1rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.3);
  text-align: center;
  position: relative;
  z-index: 1;
}

.depesza-error-detail {
  font-size: 0.45rem;
  color: rgba(192,57,43,0.55);
  margin-top: 0.2rem;
}

.depesza-empty-generate { margin-top: 0.35rem; }

/* ─── RESPONSIVE ─── */
@media (max-width: 639px) {
  .depesza-agenda-item { flex-direction: column; gap: 0.08rem; }
  .depesza-radar-item { flex-wrap: wrap; }

  .depesza-header,
  .depesza-meta,
  .depesza-headline,
  .depesza-section,
  .depesza-read-full,
  .depesza-footer,
  .depesza-loading,
  .depesza-error,
  .depesza-empty {
    padding-left: 0.85rem;
    padding-right: 0.85rem;
  }
}

/* ─── PREVENT HORIZONTAL OVERFLOW ─── */
.depesza-card { overflow-x: hidden; }
.depesza-event,
.depesza-event-link,
.depesza-news-summary,
.depesza-radar-status,
.depesza-brussels,
.depesza-editors-note,
.depesza-headline,
.depesza-event-relevance {
  word-break: break-word;
  overflow-wrap: break-word;
}

/* ─── Mobile agenda marks ──────────────────────────────────
   On mobile, the turbulence filter applied to SVG marks renders fuzzy at
   low pixel density. Replace with crisp filter-free versions, slightly
   thicker strokes, for sharp legibility on phones. */
@media (max-width: 639px) {
  .agenda-mark-default .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12 Q 9 11.5, 14 12.5 T 22 12' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' opacity='0.6'/></svg>");
  }
  .agenda-mark-call .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 5 Q 4 6, 4 8 Q 5 12, 8 16 Q 12 20, 16 21 Q 18 21, 19 19 L 19.5 16 Q 17 14.5, 15.5 15.5 L 13 13 Q 14 11, 13 9 L 10 5.5 Q 8 4.5, 5 5 Z' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-coffee .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 9 L 5 17 Q 5 19.5, 7.5 19.5 L 14 19.5 Q 16.5 19.5, 16.5 17 L 16.5 9 Z M 16.5 11 Q 19.5 11, 19.5 13.5 Q 19.5 16, 16.5 15.5 M 8 4 Q 9 6, 7.5 8 M 11.5 4 Q 12.5 6, 11 8' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-meal .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 6 11 Q 6 12.5, 7.5 12.5 L 7.5 21 M 9.5 3 L 9.5 11 Q 9.5 12.5, 8 12.5 M 15 3 L 15 9 Q 15 11, 17 11 L 17 21 M 15 3 Q 17 3, 17 6 L 17 11' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-travel .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M2 12 L 22 4 L 16 21 L 12 13 Z M 12 13 L 22 4' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-press .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 17 3 Q 19 3, 19 5 L 19 20 Q 19 22, 17 22 L 6 22 Q 4 22, 4 20 L 4 5 Q 4 3, 6 3 Z M 7 9 L 16 9 M 7 13 L 16 13 M 7 17 L 13 17' fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-deadline .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 4 Q 11.5 9, 11 14' fill='none' stroke='%23964123' stroke-width='3' stroke-linecap='round' opacity='0.9'/><circle cx='10.5' cy='19' r='1.8' fill='%23964123' opacity='0.9'/></svg>");
  }
  .agenda-mark-edit .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M3 21 L 6 20 L 20 6 L 18 4 L 4 18 Z M 17 5 L 19 7 M 3 21 L 5 21' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'/></svg>");
  }
  .agenda-mark-medical .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 4 L 12 20 M 4 12 L 20 12' fill='none' stroke='%233c826e' stroke-width='3.2' stroke-linecap='round' opacity='0.85'/></svg>");
  }
  .agenda-mark-pet .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='%23491b08' opacity='0.8'><ellipse cx='12' cy='17.5' rx='5' ry='4'/><ellipse cx='6' cy='10' rx='2.3' ry='2.7'/><ellipse cx='10.5' cy='6.5' rx='2.1' ry='2.7'/><ellipse cx='14.5' cy='6.5' rx='2.1' ry='2.7'/><ellipse cx='18.5' cy='10' rx='2.3' ry='2.7'/></g></svg>");
  }
  .agenda-mark-meeting .agenda-event-left::after,
  .agenda-mark-planning .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><circle cx='6' cy='6' r='2.5' fill='%23491b08' stroke='none'/><path d='M2 13 Q 2 10, 6 10 Q 10 10, 10 13 L 10 14'/><circle cx='18' cy='6' r='2.5' fill='%23491b08' stroke='none'/><path d='M14 13 Q 14 10, 18 10 Q 22 10, 22 13 L 22 14'/><path d='M1 16 L 23 16 M 4 16 L 4 22 M 20 16 L 20 22'/></g></svg>");
  }
  .agenda-mark-brainstorm .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M12 3 Q 7 3, 7 9 Q 7 12, 9 14 L 9 17 Q 9 18, 10 18 L 14 18 Q 15 18, 15 17 L 15 14 Q 17 12, 17 9 Q 17 3, 12 3 Z M 10 20 L 14 20 M 11 22 L 13 22'/></g></svg>");
  }
  .agenda-mark-admin .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M6 5 L 6 21 Q 6 22, 7 22 L 17 22 Q 18 22, 18 21 L 18 5 M 9 3 L 15 3 Q 16 3, 16 4 L 16 6 Q 16 7, 15 7 L 9 7 Q 8 7, 8 6 L 8 4 Q 8 3, 9 3 Z M 9 11 L 15 11 M 9 14 L 15 14 M 9 17 L 13 17'/></g></svg>");
  }
  .agenda-mark-institutional .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M2 8 L 12 3 L 22 8 L 22 9 L 2 9 Z M 5 11 L 5 18 M 9.5 11 L 9.5 18 M 14.5 11 L 14.5 18 M 19 11 L 19 18 M 2 19 L 22 19 M 1 21 L 23 21'/></g></svg>");
  }
  .agenda-mark-discussion .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M3 4 L 13 4 Q 15 4, 15 6 L 15 11 Q 15 13, 13 13 L 7 13 L 4 16 L 4.5 13 L 3 13 Q 1 13, 1 11 L 1 6 Q 1 4, 3 4 Z'/><path d='M11 9 L 20 9 Q 22 9, 22 11 L 22 16 Q 22 18, 20 18 L 19 18 L 19.5 21 L 16 18 L 11 18 Q 9 18, 9 16'/></g></svg>");
  }
  /* Today's mobile marks — burnt-umber accent */
  .agenda-today.agenda-mark-default .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12 Q 9 11.5, 14 12.5 T 22 12' fill='none' stroke='%23964123' stroke-width='2.6' stroke-linecap='round' opacity='0.85'/></svg>");
  }
  .agenda-today.agenda-mark-call .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 5 Q 4 6, 4 8 Q 5 12, 8 16 Q 12 20, 16 21 Q 18 21, 19 19 L 19.5 16 Q 17 14.5, 15.5 15.5 L 13 13 Q 14 11, 13 9 L 10 5.5 Q 8 4.5, 5 5 Z' fill='none' stroke='%23964123' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-coffee .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 9 L 5 17 Q 5 19.5, 7.5 19.5 L 14 19.5 Q 16.5 19.5, 16.5 17 L 16.5 9 Z M 16.5 11 Q 19.5 11, 19.5 13.5 Q 19.5 16, 16.5 15.5 M 8 4 Q 9 6, 7.5 8 M 11.5 4 Q 12.5 6, 11 8' fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-meal .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 6 11 Q 6 12.5, 7.5 12.5 L 7.5 21 M 9.5 3 L 9.5 11 Q 9.5 12.5, 8 12.5 M 15 3 L 15 9 Q 15 11, 17 11 L 17 21 M 15 3 Q 17 3, 17 6 L 17 11' fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-travel .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M2 12 L 22 4 L 16 21 L 12 13 Z M 12 13 L 22 4' fill='none' stroke='%23964123' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-press .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 3 L 17 3 Q 19 3, 19 5 L 19 20 Q 19 22, 17 22 L 6 22 Q 4 22, 4 20 L 4 5 Q 4 3, 6 3 Z M 7 9 L 16 9 M 7 13 L 16 13 M 7 17 L 13 17' fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-edit .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M3 21 L 6 20 L 20 6 L 18 4 L 4 18 Z M 17 5 L 19 7 M 3 21 L 5 21' fill='none' stroke='%23964123' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }
  .agenda-today.agenda-mark-meeting .agenda-event-left::after,
  .agenda-today.agenda-mark-planning .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><circle cx='6' cy='6' r='2.5' fill='%23964123' stroke='none'/><path d='M2 13 Q 2 10, 6 10 Q 10 10, 10 13 L 10 14'/><circle cx='18' cy='6' r='2.5' fill='%23964123' stroke='none'/><path d='M14 13 Q 14 10, 18 10 Q 22 10, 22 13 L 22 14'/><path d='M1 16 L 23 16 M 4 16 L 4 22 M 20 16 L 20 22'/></g></svg>");
  }
  .agenda-today.agenda-mark-brainstorm .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M12 3 Q 7 3, 7 9 Q 7 12, 9 14 L 9 17 Q 9 18, 10 18 L 14 18 Q 15 18, 15 17 L 15 14 Q 17 12, 17 9 Q 17 3, 12 3 Z M 10 20 L 14 20 M 11 22 L 13 22'/></g></svg>");
  }
  .agenda-today.agenda-mark-admin .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M6 5 L 6 21 Q 6 22, 7 22 L 17 22 Q 18 22, 18 21 L 18 5 M 9 3 L 15 3 Q 16 3, 16 4 L 16 6 Q 16 7, 15 7 L 9 7 Q 8 7, 8 6 L 8 4 Q 8 3, 9 3 Z M 9 11 L 15 11 M 9 14 L 15 14 M 9 17 L 13 17'/></g></svg>");
  }
  .agenda-today.agenda-mark-institutional .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M2 8 L 12 3 L 22 8 L 22 9 L 2 9 Z M 5 11 L 5 18 M 9.5 11 L 9.5 18 M 14.5 11 L 14.5 18 M 19 11 L 19 18 M 2 19 L 22 19 M 1 21 L 23 21'/></g></svg>");
  }
  .agenda-today.agenda-mark-discussion .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 4 L 13 4 Q 15 4, 15 6 L 15 11 Q 15 13, 13 13 L 7 13 L 4 16 L 4.5 13 L 3 13 Q 1 13, 1 11 L 1 6 Q 1 4, 3 4 Z'/><path d='M11 9 L 20 9 Q 22 9, 22 11 L 22 16 Q 22 18, 20 18 L 19 18 L 19.5 21 L 16 18 L 11 18 Q 9 18, 9 16'/></g></svg>");
  }

  /* New marks — same crisp filter-free treatment for mobile */

  .agenda-mark-birthday .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 21 L 21 21 M 4 21 L 4 14 Q 4 13, 5 13 L 19 13 Q 20 13, 20 14 L 20 21 M 4 17 L 20 17 M 12 13 L 12 8'/><path d='M11 8 Q 12 6, 13 8 Q 12 10, 11 8 Z' fill='%23964123' stroke='%23964123'/></g></svg>");
  }
  .agenda-today.agenda-mark-birthday .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 21 L 21 21 M 4 21 L 4 14 Q 4 13, 5 13 L 19 13 Q 20 13, 20 14 L 20 21 M 4 17 L 20 17 M 12 13 L 12 8'/><path d='M11 8 Q 12 6, 13 8 Q 12 10, 11 8 Z' fill='%23964123' stroke='%23964123'/></g></svg>");
  }

  .agenda-mark-holiday .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 20 L 12 4 L 21 20 Z M 12 4 L 12 20 M 9 20 L 12 14 L 15 20 M 2 20 L 22 20'/></g></svg>");
  }
  .agenda-today.agenda-mark-holiday .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 20 L 12 4 L 21 20 Z M 12 4 L 12 20 M 9 20 L 12 14 L 15 20 M 2 20 L 22 20'/></g></svg>");
  }

  .agenda-mark-family .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21 Q 4 15, 4 9 Q 4 5, 8 5 Q 11 5, 12 8 Q 13 5, 16 5 Q 20 5, 20 9 Q 20 15, 12 21 Z' fill='none' stroke='%23491b08' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'/></svg>");
  }
  .agenda-today.agenda-mark-family .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21 Q 4 15, 4 9 Q 4 5, 8 5 Q 11 5, 12 8 Q 13 5, 16 5 Q 20 5, 20 9 Q 20 15, 12 21 Z' fill='%23964123' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'/></svg>");
  }

  .agenda-mark-committee .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.75'><path d='M4 5 L 20 5 Q 21 5, 21 6 L 21 20 Q 21 21, 20 21 L 4 21 Q 3 21, 3 20 L 3 6 Q 3 5, 4 5 Z M 3 10 L 21 10 M 9 5 L 9 21 M 15 5 L 15 21 M 8 3 L 8 7 M 16 3 L 16 7'/></g></svg>");
  }
  .agenda-today.agenda-mark-committee .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M4 5 L 20 5 Q 21 5, 21 6 L 21 20 Q 21 21, 20 21 L 4 21 Q 3 21, 3 20 L 3 6 Q 3 5, 4 5 Z M 3 10 L 21 10 M 9 5 L 9 21 M 15 5 L 15 21 M 8 3 L 8 7 M 16 3 L 16 7'/></g></svg>");
  }

  .agenda-mark-plenary .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 7 Q 12 5, 21 7 M 3 11 Q 12 9, 21 11 M 3 15 Q 12 13, 21 15 M 3 19 Q 12 17, 21 19'/><circle cx='12' cy='4' r='1.3' fill='%23491b08' stroke='none' opacity='0.85'/></g></svg>");
  }
  .agenda-today.agenda-mark-plenary .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 7 Q 12 5, 21 7 M 3 11 Q 12 9, 21 11 M 3 15 Q 12 13, 21 15 M 3 19 Q 12 17, 21 19'/><circle cx='12' cy='4' r='1.3' fill='%23964123' stroke='none' opacity='0.95'/></g></svg>");
  }

  .agenda-mark-trilogue .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M3 5 L 11 11 M 7 5 L 11 5 L 11 9 M 21 5 L 13 11 M 17 5 L 21 5 L 21 9 M 12 21 L 12 13 M 8 18 L 12 22 L 16 18'/><circle cx='12' cy='12' r='2.1' fill='%23491b08' stroke='none' opacity='0.9'/></g></svg>");
  }
  .agenda-today.agenda-mark-trilogue .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M3 5 L 11 11 M 7 5 L 11 5 L 11 9 M 21 5 L 13 11 M 17 5 L 21 5 L 21 9 M 12 21 L 12 13 M 8 18 L 12 22 L 16 18'/><circle cx='12' cy='12' r='2.1' fill='%23964123' stroke='none' opacity='0.95'/></g></svg>");
  }

  .agenda-mark-brief .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23491b08' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round' opacity='0.78'><path d='M12 3 Q 9 3, 9 6 L 9 12 Q 9 15, 12 15 Q 15 15, 15 12 L 15 6 Q 15 3, 12 3 Z M 6 11 Q 6 16, 12 16 Q 18 16, 18 11 M 12 16 L 12 20 M 9 21 L 15 21'/></g></svg>");
  }
  .agenda-today.agenda-mark-brief .agenda-event-left::after {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><g fill='none' stroke='%23964123' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' opacity='0.9'><path d='M12 3 Q 9 3, 9 6 L 9 12 Q 9 15, 12 15 Q 15 15, 15 12 L 15 6 Q 15 3, 12 3 Z M 6 11 Q 6 16, 12 16 Q 18 16, 18 11 M 12 16 L 12 20 M 9 21 L 15 21'/></g></svg>");
  }
}

/* ─────────────────────────────────────────────
   ANGLES — working hypothesis tracker
   ───────────────────────────────────────────── */

.item-angles { cursor: default; }

.ang-card {
  background: #f5f0e0;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.22s;
  position: relative;
  padding: 0.7rem 0.95rem 0.8rem;
  font-family: 'Libre Baskerville', Georgia, serif;
  color: rgba(28,22,8,0.85);
}

.item-angles:hover .ang-card { box-shadow: var(--shadow-hover); }

.ang-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.55rem;
  padding-bottom: 0.45rem;
  border-bottom: 1px dashed rgba(28,22,8,0.14);
}

.ang-header-actions {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

/* Collapse/expand toggle — small mono caret matching depesza-toggle */
.ang-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  color: rgba(28,22,8,0.4);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.18rem 0.35rem;
  line-height: 1;
  transition: color 0.15s;
  -webkit-appearance: none;
  appearance: none;
}

.ang-toggle:hover { color: rgba(150,65,35,0.75); }

/* Collapsed state — hide body, tighten header to single-row "header pill" */
.ang-card.is-collapsed .ang-header {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}
.ang-card.is-collapsed .ang-body { display: none; }

.ang-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.78);
  font-weight: 500;
}

.ang-new {
  background: transparent;
  /* See .pv-card-add — neutral at rest, warm-red only on hover. */
  border: 1px solid rgba(28,22,8,0.18);
  color: rgba(28,22,8,0.55);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.06em;
  padding: 0.18rem 0.5rem;
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.ang-new:hover {
  background: rgba(150,65,35,0.85);
  color: #f5f0e0;
  border-color: rgba(150,65,35,0.85);
}

.ang-empty {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(28,22,8,0.4);
  padding: 0.7rem 0;
  text-align: center;
}

/* ── Each angle item ── */

.ang-item {
  padding: 0.6rem 0;
  border-bottom: 1px dotted rgba(28,22,8,0.1);
  transition: opacity 0.2s;
}

.ang-item:last-child { border-bottom: none; }

.ang-item.is-stale { opacity: 0.55; }

.ang-item:not(.is-focused) {
  cursor: pointer;
  transition: background 0.15s, opacity 0.2s;
}

.ang-item:not(.is-focused):hover {
  background: rgba(28,22,8,0.025);
  margin: 0 -0.45rem;
  padding-left: 0.45rem;
  padding-right: 0.45rem;
}

.ang-item-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.3rem;
}

.ang-age {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
}

.ang-drop {
  background: none;
  border: none;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.32);
  cursor: pointer;
  padding: 0.1rem 0.3rem;
  transition: color 0.15s;
}
.ang-drop:hover { color: rgba(150,65,35,0.85); }

/* Actions wrapper (edit + drop) on focused angle's top row */
.ang-item-actions {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
}

/* Edit link — opens wp-admin edit screen for this angle in a new tab.
   Same visual treatment as drop, slightly different colour to read as
   an external/secondary action. */
.ang-edit {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.32);
  text-decoration: none;
  padding: 0.1rem 0.3rem;
  transition: color 0.15s;
}
.ang-edit:hover { color: rgba(28,22,8,0.7); }

.ang-question {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.85rem;
  line-height: 1.4;
  color: rgba(28,22,8,0.92);
  margin-bottom: 0.4rem;
}

.ang-item:not(.is-focused) .ang-question {
  font-size: 0.75rem;
  color: rgba(28,22,8,0.78);
  margin-bottom: 0.25rem;
}

/* ── Slug pill — click to copy "angle:slug" to clipboard ── */
.ang-slug-row {
  margin-top: -0.15rem;
  margin-bottom: 0.4rem;
}

.ang-slug-copy {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  background: rgba(28,22,8,0.04);
  border: 1px dashed rgba(28,22,8,0.18);
  border-radius: 2px;
  padding: 0.15rem 0.45rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  color: rgba(28,22,8,0.55);
  cursor: pointer;
  transition: all 0.15s;
}

.ang-slug-copy:hover {
  background: rgba(28,22,8,0.07);
  border-color: rgba(28,22,8,0.3);
  color: rgba(28,22,8,0.85);
}

.ang-slug-copy.is-copied {
  background: rgba(20,100,55,0.1);
  border-color: rgba(20,100,55,0.4);
  border-style: solid;
  color: rgba(20,100,55,0.85);
}

.ang-slug-prefix { opacity: 0.55; }
.ang-slug-value  { font-weight: 500; }
.ang-slug-icon {
  font-size: 0.65rem;
  margin-left: 0.1rem;
  opacity: 0.7;
}

/* ── Counts on collapsed cards ── */

.ang-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.08em;
  color: rgba(28,22,8,0.45);
}

.ang-count-confirms    { color: rgba(20,100,55,0.7); }
.ang-count-complicates { color: rgba(150,65,35,0.7); }
.ang-count-needs       { color: rgba(28,22,8,0.4); }
.ang-count-empty       { font-style: italic; color: rgba(28,22,8,0.32); }

/* ── Evidence list ── */

.ang-evidence {
  margin: 0.5rem 0 0.45rem;
  padding-top: 0.3rem;
}

.ang-evidence-empty {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.65rem;
  color: rgba(28,22,8,0.42);
  padding: 0.2rem 0 0.3rem;
}

.ang-evidence-item {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.7rem;
  line-height: 1.4;
  color: rgba(28,22,8,0.78);
  padding: 0.25rem 0;
  position: relative;
}

.ang-evidence-item + .ang-evidence-item {
  border-top: 1px dotted rgba(28,22,8,0.06);
}

.ang-ev-glyph {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  font-weight: 600;
  flex-shrink: 0;
  width: 0.85rem;
  text-align: center;
  line-height: 1;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  transition: transform 0.12s, color 0.15s;
}

.ang-ev-glyph:hover {
  transform: scale(1.4);
}

.ang-ev-confirms .ang-ev-glyph    { color: rgba(20,100,55,0.85); }
.ang-ev-complicates .ang-ev-glyph { color: rgba(150,65,35,0.85); }
.ang-ev-needs .ang-ev-glyph       { color: rgba(28,22,8,0.5); }
.ang-ev-needs .ang-ev-text        { color: rgba(28,22,8,0.55); font-style: italic; }

.ang-ev-text {
  flex: 1;
  font-style: italic;
}

.ang-ev-remove {
  background: none;
  border: none;
  color: rgba(28,22,8,0.25);
  font-size: 0.85rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: pointer;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}

.ang-evidence-item:hover .ang-ev-remove { opacity: 1; }
.ang-ev-remove:hover { color: rgba(150,65,35,0.85); }

/* ── Quick-add row ── */

.ang-add {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  border-top: 1px dashed rgba(28,22,8,0.12);
}

.ang-add-types {
  display: flex;
  gap: 0.15rem;
  flex-shrink: 0;
}

.ang-add-type {
  width: 1.3rem;
  height: 1.3rem;
  border: 1px solid rgba(28,22,8,0.15);
  background: transparent;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  border-radius: 2px;
  padding: 0;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  color: rgba(28,22,8,0.55);
}

.ang-add-confirms:hover {
  border-color: rgba(20,100,55,0.5);
  background: rgba(20,100,55,0.08);
  color: rgba(20,100,55,0.85);
}
.ang-add-complicates:hover {
  border-color: rgba(150,65,35,0.5);
  background: rgba(150,65,35,0.08);
  color: rgba(150,65,35,0.85);
}
.ang-add-needs:hover {
  border-color: rgba(28,22,8,0.4);
  background: rgba(28,22,8,0.05);
  color: rgba(28,22,8,0.75);
}

/* Selected (sticky) type — solid fill, indicates "the next evidence
   you commit will be of this type". Clicking the input or pressing
   Enter commits with this type. */
.ang-add-confirms.is-selected {
  border-color: rgba(20,100,55,0.7);
  background: rgba(20,100,55,0.85);
  color: #f5f0e0;
}
.ang-add-complicates.is-selected {
  border-color: rgba(150,65,35,0.7);
  background: rgba(150,65,35,0.85);
  color: #f5f0e0;
}
.ang-add-needs.is-selected {
  border-color: rgba(28,22,8,0.7);
  background: rgba(28,22,8,0.7);
  color: #f5f0e0;
}

.ang-add-text {
  flex: 1;
  min-width: 0;
  font-family: 'Special Elite', cursive;
  font-size: 0.75rem;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(28,22,8,0.15);
  padding: 0.2rem 0;
  outline: none;
  color: rgba(28,22,8,0.85);
  caret-color: rgba(150,65,35,0.8);
}

.ang-add-text:focus {
  border-bottom-color: rgba(150,65,35,0.45);
}

.ang-add-text::placeholder {
  color: rgba(28,22,8,0.28);
  font-style: italic;
}

/* ── Promote button ── */

/* ── Attached: field notes + Raindrops linked via angle:slug ── */

.ang-attached {
  margin: 0.55rem 0 0.3rem;
  padding-top: 0.4rem;
  border-top: 1px dashed rgba(28,22,8,0.12);
}

.ang-attached-head {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  width: 100%;
  background: none;
  border: none;
  padding: 0.1rem 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: opacity 0.15s;
}

.ang-attached-head:hover { opacity: 0.7; }

.ang-attached-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.45);
}

.ang-attached-label.ang-attached-empty {
  color: rgba(28,22,8,0.32);
  font-style: normal;
  text-transform: none;
  letter-spacing: 0.04em;
  font-size: 0.58rem;
}

.ang-attached-hint {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  color: rgba(28,22,8,0.32);
  letter-spacing: 0.02em;
}

.ang-attached-hint code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  background: rgba(28,22,8,0.05);
  padding: 0.05rem 0.2rem;
  border-radius: 1px;
  color: rgba(150,65,35,0.7);
}

.ang-attached-refresh {
  margin-left: auto;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  color: rgba(28,22,8,0.3);
  line-height: 1;
}

.ang-attached-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 0.3rem;
  /* Cap the visible attached-items area so a busy angle (lots of
     linked notes/raindrops) doesn't blow up the column height and
     leave a giant whitespace trail at the bottom of the page on
     iPad-width 2-column layouts. Beyond this height the user scrolls
     within the widget itself. */
  max-height: 18rem;
  overflow-y: auto;
}

.ang-attached-item {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.3rem 0;
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.65rem;
  line-height: 1.35;
  color: rgba(28,22,8,0.72);
  text-decoration: none;
  border-top: 1px dotted rgba(28,22,8,0.08);
  transition: background 0.12s, color 0.12s;
}

.ang-attached-item:first-child { border-top: none; }

.ang-attached-item:hover {
  color: rgba(150,65,35,0.85);
  background: rgba(28,22,8,0.025);
  margin: 0 -0.45rem;
  padding-left: 0.45rem;
  padding-right: 0.45rem;
}

.ang-attached-type {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  flex-shrink: 0;
  width: 2.2rem;
  padding-top: 0.1rem;
}

.ang-attached-fn .ang-attached-type { color: rgba(30,70,140,0.65); }
.ang-attached-rd .ang-attached-type { color: rgba(150,65,35,0.6); }

.ang-attached-snippet {
  flex: 1;
  min-width: 0;
  max-height: 2.7rem;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  /* Word-break on overflow protects against long unbroken URLs or
     Polish words breaking the layout when the line-clamp doesn't
     engage (some older Safari versions ignore -webkit-line-clamp
     on flex children). */
  word-break: break-word;
  overflow-wrap: anywhere;
}

.ang-attached-date {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.44rem;
  letter-spacing: 0.06em;
  color: rgba(28,22,8,0.32);
  flex-shrink: 0;
  padding-top: 0.15rem;
}

.ang-promote-row {
  text-align: right;
  margin-top: 0.5rem;
}

.ang-promote {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.7);
  background: rgba(150,65,35,0.06);
  border: 1px solid rgba(150,65,35,0.22);
  padding: 0.25rem 0.7rem;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.15s;
}

.ang-promote:hover {
  background: rgba(150,65,35,0.95);
  color: #f5f0e0;
  border-color: rgba(150,65,35,0.95);
}

.ang-promote:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── Sublabel for the new-angle dialog (used in custom prompt) ── */
.custom-prompt-sublabel {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.7rem;
  color: rgba(28,22,8,0.5);
  margin: 0 0 0.5rem;
  line-height: 1.4;
}

/* ═══════════════════════════════════════════════════════════
   NOTEBOOK CAPTURE BAR
   
   Sticky bar at the viewport bottom of the notebook view (only when
   logged in and activeFilter === 'notes'). Mirrors the new notebook's
   capture-bar pattern but in the portfolio's paper aesthetic, not the
   dark "command palette" treatment.
   
   Each button opens a modal with type-specific fields. Save routes
   to the correct typed post:
     + quote → portfolio_quote
     + link  → Raindrop (via /raindrops/create)
     + task  → appended to the "Inbox" portfolio_todo
     + note  → portfolio_mind
   ═══════════════════════════════════════════════════════════ */

.nb-cap-bar {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  z-index: 5000;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.8rem;
  background: #f5f0e0;
  border: 1px solid rgba(28,22,8,0.14);
  box-shadow:
    0 1px 2px rgba(28,22,8,0.06),
    0 10px 30px rgba(28,22,8,0.10),
    0 -8px 24px rgba(28,22,8,0.04);
  border-radius: 3px;
  /* Subtle ruled-paper pattern to match the rest of the portfolio */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 19px,
    rgba(100,80,50,0.05) 19px, rgba(100,80,50,0.05) 20px
  );
  padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
  max-width: 92vw;
}

.nb-cap-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  padding: 0 0.35rem 0 0.1rem;
  white-space: nowrap;
}

.nb-cap-btn {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  background: rgba(28,22,8,0.04);
  border: 1px solid rgba(28,22,8,0.10);
  color: rgba(28,22,8,0.72);
  padding: 0.35rem 0.7rem;
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.12s;
  white-space: nowrap;
}

.nb-cap-btn:hover {
  background: rgba(150,65,35,0.08);
  border-color: rgba(150,65,35,0.30);
  color: rgba(150,65,35,0.95);
  transform: translateY(-1px);
}

/* Grouped button + chevron — the main button keeps its full pill
   shape on the left, with a small chevron pill snug against it on
   the right. Visually reads as one widget but the two halves have
   different click targets. */
.nb-cap-btn-group {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
}
.nb-cap-btn-group .nb-cap-btn-main {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
  padding-right: 0.5rem;
}
.nb-cap-chevron {
  font-family: inherit;
  background: rgba(28,22,8,0.04);
  border: 1px solid rgba(28,22,8,0.10);
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-top-right-radius: 2px;
  border-bottom-right-radius: 2px;
  color: rgba(28,22,8,0.55);
  padding: 0 0.4rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.nb-cap-chevron svg {
  width: 8px;
  height: 8px;
  display: block;
}
.nb-cap-chevron:hover {
  background: rgba(150,65,35,0.08);
  border-color: rgba(150,65,35,0.30);
  color: rgba(150,65,35,0.95);
}

/* Popover that the chevron opens — floats above the bar with the
   alternative-action choices stacked vertically. */
.nb-cap-popover {
  background: #faf8f1;
  border: 1px solid rgba(28,22,8,0.18);
  border-radius: 3px;
  box-shadow:
    0 4px 10px rgba(28,22,8,0.12),
    0 12px 32px rgba(28,22,8,0.10);
  padding: 0.25rem;
  min-width: 220px;
  font-family: 'IBM Plex Mono', monospace;
}
.nb-cap-popover-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  width: 100%;
  background: transparent;
  border: none;
  text-align: left;
  padding: 0.5rem 0.7rem;
  cursor: pointer;
  border-radius: 2px;
  transition: background 0.12s;
}
.nb-cap-popover-item:hover {
  background: rgba(150,65,35,0.08);
}
.nb-cap-popover-label {
  font-size: 0.66rem;
  color: rgba(28,22,8,0.85);
  letter-spacing: 0.02em;
}
.nb-cap-popover-item:hover .nb-cap-popover-label {
  color: rgba(150,65,35,0.95);
}
.nb-cap-popover-hint {
  font-size: 0.52rem;
  color: rgba(28,22,8,0.45);
  letter-spacing: 0.05em;
  text-transform: lowercase;
}

.nb-cap-shortcut {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.48rem;
  letter-spacing: 0.14em;
  color: rgba(28,22,8,0.32);
  padding-left: 0.55rem;
  white-space: nowrap;
}

/* ── Capture-bar search ──────────────────────────────────── */
/* A vertical hairline that separates the capture buttons from the
   search input. Just enough to read as "two groups in one bar"
   without a hard boundary. */
.nb-cap-divider {
  width: 1px;
  height: 1.3rem;
  background: rgba(28,22,8,0.14);
  margin: 0 0.3rem;
  flex-shrink: 0;
}

/* The little magnifying glass icon sitting just before the input. */
.nb-cap-search-icon {
  width: 13px;
  height: 13px;
  color: rgba(28,22,8,0.42);
  flex-shrink: 0;
}

/* The input itself. Borderless, transparent — sits flush inside the
   bar so the whole strip reads as one tool, not a search box pinned
   to the side. Grows to fill available width up to a cap. */
.nb-cap-search-input {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  letter-spacing: 0.02em;
  color: rgba(28,22,8,0.85);
  background: transparent;
  border: none;
  outline: none;
  padding: 0.3rem 0.2rem;
  width: 16rem;
  max-width: 30vw;
  min-width: 0;
}
.nb-cap-search-input::placeholder {
  color: rgba(28,22,8,0.35);
  /* Upright mono, not italic — keeps the placeholder in the same
     typographic register as the rest of the bar. The opacity at 0.35
     already communicates "placeholder, not active text"; italic on
     top of that reads as off-register in a strict mono context. */
}
.nb-cap-search-input:focus {
  color: rgba(150,65,35,0.95);
}
/* Focused-state ambient cue on the bar: a slight warm-red tint to the
   shortcut hint and search icon, so it's clear the bar is in
   search mode. Subtle enough to not feel like a state machine. */
.nb-cap-search-input:focus ~ .nb-cap-shortcut,
.nb-cap-bar:has(.nb-cap-search-input:focus) .nb-cap-search-icon {
  color: rgba(150,65,35,0.7);
}

/* Search-result count chip — floats above the masonry, similar to the
   tag-filter chip but on the right rather than centered. Carries the
   query in monospace so the user sees exactly what's being matched. */
.board-search-count {
  position: absolute;
  top: 0.8rem;
  right: 1.2rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: rgba(120,80,30,0.85);
  background: rgba(248,243,230,0.92);
  border: 1px solid rgba(120,80,30,0.25);
  padding: 4px 10px;
  border-radius: 2px;
  z-index: 10;
  box-shadow: 0 1px 3px rgba(28,22,8,0.08);
  pointer-events: none;
  white-space: nowrap;
  max-width: 28rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.board.search-active {
  position: relative;
  padding-top: 3rem;
}

/* Related-tag co-occurrence strip. Shown when a tag filter is active
   and other tags appear frequently in the same posts. Sits below the
   active-tag chip in the masonry top area. */
.board-related-tags {
  position: absolute;
  top: 2.6rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  max-width: 90vw;
  flex-wrap: wrap;
  justify-content: center;
}
.board-related-label {
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  white-space: nowrap;
}
.board-related-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 2px 7px;
  background: rgba(120,80,30,0.06);
  color: rgba(120,80,30,0.78);
  border-radius: 2px;
  border-bottom: none;
  font-size: 0.6rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.board-related-chip:hover {
  background: rgba(150,65,35,0.12);
  color: rgba(150,65,35,0.95);
  border-bottom: none;
}
.board-related-count {
  font-size: 0.5rem;
  color: rgba(28,22,8,0.35);
}
.board-related-chip:hover .board-related-count {
  color: rgba(150,65,35,0.55);
}

/* When the related-tag strip is present, push the masonry down a
   bit more so it doesn\'t overlap the first row of cards. */
.board.tag-filtered:has(.board-related-tags) {
  padding-top: 4.5rem;
}

/* Search-match highlight. Driven by the CSS Custom Highlight API
   (window.CSS.highlights.set('search-match', new Highlight(...))).
   Mint/teal green specifically so it doesn\'t read as the same thing
   as the warm-yellow ==text== annotation highlight (.mann-hl). This
   one is transient — appears while a search is active, disappears
   when cleared. The annotation highlight is permanent content. */
::highlight(search-match) {
  background-color: rgba(120, 200, 160, 0.45);
  color: rgba(28, 22, 8, 0.95);
}

/* Hide capture bar on narrow viewports — mobile notebook has its own
   add affordances built into each card */
@media (max-width: 720px) {
  .nb-cap-bar { display: none; }
}

/* ── Capture modal — opened by clicking a capture button ──────
   Sits over the page, paper-styled, larger than .custom-prompt-box
   because it can have multiple fields (quotes have text + attribution
   + context). Uses the same overlay treatment for visual consistency. */
.nb-cap-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(28,22,8,0.36);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.nb-cap-overlay.nb-cap-in { opacity: 1; }

.nb-cap-box {
  background: #faf6ea;
  border: 1px solid rgba(28,22,8,0.12);
  box-shadow: 0 8px 32px rgba(28,22,8,0.18), 0 2px 8px rgba(28,22,8,0.1);
  width: 92%;
  max-width: 480px;
  padding: 1.4rem 1.5rem 1.2rem;
  position: relative;
  transform: translateY(8px);
  transition: transform 0.2s ease;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent, transparent 27px,
    rgba(100,80,50,0.06) 27px, rgba(100,80,50,0.06) 28px
  );
  max-height: 86vh;
  overflow-y: auto;
}

.nb-cap-in .nb-cap-box { transform: translateY(0); }

.nb-cap-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 400;
  font-size: 1.15rem;
  color: rgba(28,22,8,0.85);
  margin: 0 0 1rem;
  padding-right: 2rem;
}

.nb-cap-field {
  margin-bottom: 0.85rem;
}

.nb-cap-field-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  display: block;
  margin-bottom: 0.3rem;
}

.nb-cap-input,
.nb-cap-textarea {
  width: 100%;
  font-family: 'Special Elite', cursive;
  font-size: 0.9rem;
  color: rgba(28,22,8,0.82);
  background: transparent;
  border: none;
  border-bottom: 1.5px solid rgba(28,22,8,0.15);
  padding: 0.3rem 0;
  outline: none;
  caret-color: rgba(150,65,35,0.8);
  box-sizing: border-box;
  transition: border-color 0.15s;
  font-family: 'Libre Baskerville', Georgia, serif;
}

.nb-cap-textarea {
  resize: vertical;
  min-height: 4rem;
  line-height: 1.5;
}

.nb-cap-input:focus,
.nb-cap-textarea:focus {
  border-bottom-color: rgba(150,65,35,0.45);
}

.nb-cap-input::placeholder,
.nb-cap-textarea::placeholder {
  color: rgba(28,22,8,0.2);
  font-style: italic;
}

.nb-cap-help {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.7rem;
  color: rgba(28,22,8,0.45);
  margin: 0.2rem 0 0;
  line-height: 1.4;
}

.nb-cap-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.3rem;
}

.nb-cap-cancel {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.35);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.4rem 0.6rem;
  transition: color 0.15s;
}

.nb-cap-cancel:hover { color: rgba(28,22,8,0.7); }

.nb-cap-save {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(150,65,35,0.85);
  background: rgba(150,65,35,0.06);
  border: 1px solid rgba(150,65,35,0.22);
  padding: 0.4rem 0.95rem;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.15s;
}

.nb-cap-save:hover {
  background: rgba(150,65,35,0.95);
  color: #f5f0e0;
  border-color: rgba(150,65,35,0.95);
}

.nb-cap-save:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.nb-cap-error {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-style: italic;
  font-size: 0.68rem;
  color: rgba(192,57,43,0.9);
  margin: 0.4rem 0 0;
}

/* Body gets a bottom padding when on notebook view so content doesn't
   hide behind the fixed capture bar. Applied via JS via .nb-cap-active
   on body, so other filter views aren't affected. */
body.nb-cap-active { padding-bottom: 100px; }
@media (max-width: 720px) {
  body.nb-cap-active { padding-bottom: 0; }
}

/* ═══════════════════════════════════════════════════════════
   TO-DO ENHANCEMENTS — deadline marks, completion marks,
   auto-dividers ("Open-ended", "Completed").
   
   The deadline/completion indicators try to feel like marks made
   in a real notebook, not chips in a software UI. Urgent states
   use the same warm highlighter swipe pattern as the existing
   annotation system (.mann-hl); quieter states are just colored
   ink with no decoration.
   
   Auto-dividers are visually quieter than user-authored ##
   headings so the eye reads them as structure, not content.
   ═══════════════════════════════════════════════════════════ */

/* ── Deadline + completion marks — base typography ─────────
   Both use IBM Plex Mono in tight uppercase, like the publisher
   labels in the newswire (.rss-line-source). Inline with text. */
.todo-deadline-pill,
.todo-completed-pill {
  display: inline-block;
  margin-left: 0.45rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.4;
  vertical-align: 1px;
  white-space: nowrap;
}

/* ── Default (later) — colored text only, no box ──────────
   The publisher labels in newswire (FAKT, TVN24, RP) earn
   distinction through color + typography alone, no chip. Same
   approach here for non-urgent deadlines. */
.todo-deadline-pill {
  color: rgba(28,22,8,0.42);
  padding: 0;
}

/* ── Soon (1–3 days) — warm highlight swipe ──────────────
   Mirrors .mann-hl: a horizontal gradient that fades at the edges,
   irregular SVG mask for hand-drawn feel. Tinted warmer than the
   yellow highlight so it reads as "deadline" not "highlighted text." */
.todo-deadline-pill.todo-deadline-soon {
  color: rgba(140,80,30,0.88);
  padding: 0.12em 0.4em;
  background: linear-gradient(
    104deg,
    rgba(220,170,80,0) 0.9%,
    rgba(220,170,80,0.32) 2.4%,
    rgba(220,170,80,0.28) 70%,
    rgba(220,175,80,0.14) 94%,
    rgba(220,170,80,0) 99%
  );
  border-radius: 2px;
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='20'%3E%3Crect x='0' y='0' width='200' height='20' fill='white' rx='1'/%3E%3C/svg%3E");
}

/* ── Today — saturated warm swipe ────────────────────────
   Same gradient pattern, stronger color. */
.todo-deadline-pill.todo-deadline-today {
  color: rgba(165,70,25,0.95);
  padding: 0.12em 0.4em;
  background: linear-gradient(
    104deg,
    rgba(210,130,55,0) 0.9%,
    rgba(210,130,55,0.36) 2.4%,
    rgba(210,130,55,0.32) 70%,
    rgba(215,135,60,0.16) 94%,
    rgba(210,130,55,0) 99%
  );
  border-radius: 2px;
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='20'%3E%3Crect x='0' y='0' width='200' height='20' fill='white' rx='1'/%3E%3C/svg%3E");
}

/* ── Overdue — rust swipe, slight underline like red-pen ─
   Same gradient pattern, deeper rust. The underline emulates a
   journalist's red-pen mark for "this is past due." */
.todo-deadline-pill.todo-deadline-overdue {
  color: rgba(150,40,20,0.95);
  padding: 0.12em 0.4em;
  background: linear-gradient(
    104deg,
    rgba(190,70,35,0) 0.9%,
    rgba(190,70,35,0.32) 2.4%,
    rgba(190,70,35,0.28) 70%,
    rgba(195,75,35,0.14) 94%,
    rgba(190,70,35,0) 99%
  );
  border-radius: 2px;
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='20'%3E%3Crect x='0' y='0' width='200' height='20' fill='white' rx='1'/%3E%3C/svg%3E");
  position: relative;
}
/* Red-pen underline mark on overdue, hand-drawn wavy stroke */
.todo-deadline-pill.todo-deadline-overdue::after {
  content: '';
  position: absolute;
  left: 0.2em;
  right: 0.2em;
  bottom: -1px;
  height: 3px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='3'%3E%3Cpath d='M0 1.5 Q8 0.4 16 1.6 Q24 2.8 32 1.2 Q42 0.4 52 1.8 Q60 2.6 68 1.2 Q76 0.4 80 1.5' fill='none' stroke='rgba(150,40,20,0.55)' stroke-width='1' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
  background-size: 80px 3px;
  pointer-events: none;
}

/* ── Completed mark — same family as deadline marks, quieter ──
   Reads as a small margin note. Same monospace uppercase as the
   deadline marks so they belong to the same system. */
.todo-completed-pill {
  color: rgba(28,22,8,0.30);
  font-weight: 500;
  font-size: 0.42rem;
  letter-spacing: 0.16em;
  padding: 0;
}

/* ── Auto-dividers ("Open-ended", "Completed") ──────────
   Quieter than user-authored ## headings. */
.todo-auto-divider {
  margin-top: 0.4rem;
  margin-bottom: 0.05rem;
  opacity: 0.55;
}
.todo-auto-divider .mann-heading {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28,22,8,0.4);
  font-weight: 500;
  border-bottom: none;
}

/* ── Override line-through on marks inside completed items ──
   The pill is its own visual element, shouldn't be struck out
   with the task text. */
.todo-checked .todo-text .todo-completed-pill,
.todo-checked .todo-text .todo-deadline-pill {
  text-decoration: none;
}

/* ═══════════════════════════════════════════════════════════
   NOTEBOOK HERO — time-of-day greeting + landscape illustration
   
   Sits at the top of the board on the notebook view, full width
   above the masonry columns. Background gradient and SVG illustration
   shift by time of day: morning, afternoon, evening, night. The
   greeting reads "Good afternoon, Bartosz." with italic name.
   
   Visible only when logged in and activeFilter === 'notes'. On
   mobile, this hero is suppressed; the mobile notebook has its
   own dashboard treatment.
   ═══════════════════════════════════════════════════════════ */

/* ── Hero: atmosphere, not artifact ──────────────────────────
   The hero has no background, no shadow, no border. It's structural
   space at the top of the masonry where the greeting text lives.
   The day's atmospheric color comes from the body-level wash (see
   .nb-time-X selectors near the body declaration); the hero
   doesn't carry it. */
.nb-hero {
  flex-basis: 100%;
  position: relative;
  padding: 2rem 2.2rem 1.8rem;
  margin-bottom: 0.8rem;
  min-height: 200px;
  overflow: visible;
  z-index: 2;
}

/* The illustration wrapper has become ambient atmosphere rather than
   a rendered scene. The sky gradient lives on the body (see
   .nb-time-X selectors below), so .nb-hero-illustration is just the
   container for the faint hill silhouettes which suggest "distant
   terrain seen through the morning haze" rather than asserting a
   pictorial landscape. Position is full-width and absolute, anchored
   to the top of the page so the hills sit BEHIND/AT the hero
   without claiming a rectangular region for themselves.

   The wrapper extends ABOVE the hero's top edge (top: -120px) so the
   sun's soft radial halo has room to spread without being clipped at
   the hero boundary. The mask now fades both at the top and the
   bottom so neither edge introduces a hard cutoff. */
.nb-hero-illustration {
  position: absolute;
  left: 50%;
  top: -120px;
  bottom: 0;
  width: 100vw;
  max-width: 100vw;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 0;
  opacity: 0.45;
  /* Vertical fade-out at BOTH ends:
     - Top: the extra 120px above the hero needs to feather in so
       the sky halo doesn't suddenly start mid-page
     - Bottom: the wash dissolves into the desk
     Otherwise, hills/trees/tent would cut off at a hard horizontal
     line wherever the ground SVG ends, and the new top extension
     would also have a visible edge. */
  -webkit-mask-image: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0.3) 15%,
    rgba(0,0,0,1) 35%,
    rgba(0,0,0,1) 65%,
    rgba(0,0,0,0.5) 85%,
    rgba(0,0,0,0) 100%);
          mask-image: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0.3) 15%,
    rgba(0,0,0,1) 35%,
    rgba(0,0,0,1) 65%,
    rgba(0,0,0,0.5) 85%,
    rgba(0,0,0,0) 100%);
}
.nb-time-evening .nb-hero-illustration,
.nb-time-night .nb-hero-illustration {
  /* Dark times: bump a bit more since the silhouettes blend into
     the wash more readily. */
  opacity: 0.55;
}

/* Sky SVG — its sun/clouds/stars now read as ambient atmosphere
   (faint birds in the morning haze, faint stars in evening light). */
.nb-hero-sky {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}

/* Ground SVG — the hills/tent/trees rendered as low-contrast
   silhouettes drifting along the bottom of the hero region. */
.nb-hero-ground {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  width: 100%; height: 70%;
  pointer-events: none;
  display: block;
}

/* Content sits above the ambient layer. With no rectangle behind
   the text, the greeting reads as words landing on the page's
   morning/evening light itself. */
.nb-hero-content {
  position: relative;
  z-index: 2;
}

/* ── Extended-ground bleed ────────────────────────────────
   The bleed sits BEHIND the hero (z-index 1, hero is z-index 2),
   extending past the rectangle on left, right, and downward. The
   hero\'s rounded rectangle covers the bleed\'s center area; the
   bleed only becomes visible in the side gutters and below the
   hero\'s bottom edge.
   The bleed\'s hills are positioned in the SVG to align vertically
   with where the hero\'s ground sits (roughly bottom third of the
   hero rectangle), so they read as one continuous landscape.
   Pointer-events disabled so it never intercepts clicks. */
/* Bleed disabled — the new feathered .nb-hero-illustration extends
   past the column edges itself (via negative offsets) and dissolves
   into the desk through its radial mask. A separate bleed element
   with its own rectangular bounds would fight the soft-edge concept. */
.nb-hero-bleed {
  display: none !important;
}

/* (Time-of-day gradients moved to .nb-hero-X .nb-hero-sky-pane —
   see above. The hero itself is transparent now.) */

/* Text colors per time of day. */
.nb-hero-morning, .nb-hero-afternoon {
  color: #3D2914;
}
.nb-hero-golden_hour { color: #3A1F0A; }
.nb-hero-evening { color: #FAF1E5; }
.nb-hero-night { color: #F0E6D8; }

/* Time-of-day overrides for greeting em (the italic name like "Bartosz"),
   summary, and edition. Without these, the em and summary stay at their
   default warm-dark colors (which work against cream desk but disappear
   against the evening/night sky). */
.nb-hero-evening .nb-hero-greeting em,
.nb-hero-night .nb-hero-greeting em {
  /* Warm coral that reads as the personal accent against dark sky.
     Brighter than the daytime muted terracotta because dark backgrounds
     swallow desaturated warm tones. */
  color: rgba(240, 165, 130, 0.95);
}

.nb-hero-evening .nb-hero-summary,
.nb-hero-night .nb-hero-summary {
  /* Light cream so the summary line stays legible on the dark sky.
     Daytime is nearly-black on cream; nighttime is cream on dark. */
  color: rgba(240, 230, 216, 0.85);
}

.nb-hero-evening .nb-hero-summary .nb-hero-strong,
.nb-hero-night .nb-hero-summary .nb-hero-strong {
  /* The bolded element within the summary ("2 things") — full cream
     opacity so it pops against the dark sky. */
  color: rgba(250, 241, 229, 1);
}

.nb-hero-evening .nb-hero-edition,
.nb-hero-night .nb-hero-edition {
  /* Edition stamp (THURSDAY NIGHT · 14 MAY 2026 · 9° MAINLY CLEAR) — */
  /* dimmer cream so it's a quiet header rather than a competing line. */
  color: rgba(240, 230, 216, 0.62);
}

/* Subnav (Notebook · Pieces · Transcripts · Quotes · Reading) sits in
   the workspace-head, which on the home page floats over the hero sky.
   Default subnav color is dark warm ink at 42% alpha — fine on cream
   desk, but invisible against the dark evening/night sky. Override
   per time-of-day so the labels stay legible. The active item's warm-red
   accent also brightens because saturated darks like terracotta lose
   contrast against deep night sky. */
body.nb-time-evening .nb-subnav-item,
body.nb-time-night .nb-subnav-item {
  color: rgba(240, 230, 216, 0.58) !important;
}
body.nb-time-evening .nb-subnav-item:hover,
body.nb-time-night .nb-subnav-item:hover {
  color: rgba(245, 200, 165, 1) !important;
}
body.nb-time-evening .nb-subnav-item.is-active,
body.nb-time-night .nb-subnav-item.is-active {
  color: rgba(245, 195, 160, 1) !important;
}
body.nb-time-evening .nb-subnav-item.is-active::after,
body.nb-time-night .nb-subnav-item.is-active::after {
  border-bottom-color: rgba(245, 195, 160, 0.72) !important;
}
/* Subnav separator dots, also need cream tone at night */
body.nb-time-evening .nb-subnav-sep,
body.nb-time-night .nb-subnav-sep {
  color: rgba(240, 230, 216, 0.32) !important;
}

/* ── Hero refresh button ────────────────────────────────── */
/* Top-right corner of the hero. Quiet circular-arrow icon — clearly
   clickable on hover but doesn't compete with the greeting. Triggers
   a full page reload so the masonry pulls in fresh data (useful when
   you've made changes elsewhere — admin, mobile, another tab). */
/* Refresh button — embedded-looking circle in the hero\'s top-right.
   The circle is filled with a warm-cream rgba slightly lighter than
   the hero sky, with a subtle inset shadow so it reads as embedded
   into the sky surface rather than sitting on top of it. Uses the
   Unicode ↻ glyph (matching the newswire widget for vocabulary
   consistency) — character is symmetric around its center, so the
   rotate animation doesn\'t wobble. */
.nb-hero-refresh {
  position: absolute;
  top: 1rem;
  right: 1.2rem;
  z-index: 2;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Filled circle, slightly lighter than the hero sky. The button
     should always be a subtle, barely-there indication at rest —
     visible enough to find but quiet enough to not compete with
     the illustration. Hover brings it forward. */
  background: rgba(255, 250, 235, 0.22);
  border: none;
  border-radius: 50%;
  /* No box-shadow. Earlier this had `inset 0 1px 1px rgba(28,22,8,0.06)`
     plus `0 1px 0 rgba(255,255,255,0.3)` — meant to be a subtle skeuomorphic
     bevel. The outer white-edge shadow sits as a faint crescent below the
     button, and against the cream sky reads as a second concentric ring
     (the "double circle" effect). On a flat atmospheric hero the bevel was
     fighting the rest of the visual language anyway. */
  cursor: pointer;
  color: rgba(28,22,8,0.45);
  transition: background 0.18s, color 0.18s;
  padding: 0;
}
.nb-hero-refresh-glyph {
  font-size: 16px;
  line-height: 1;
  display: block;
  margin-top: -1px;
}
.nb-hero-refresh:hover {
  background: rgba(255, 250, 235, 0.45);
  color: rgba(28,22,8,0.85);
}

/* Spin animation: applies to the GLYPH inside, not the button itself.
   This keeps the embedded-circle background stationary while the
   arrow rotates inside it — looks like a control responding rather
   than the whole widget spinning. */
.nb-hero-refresh.spinning .nb-hero-refresh-glyph {
  animation: nb-hero-refresh-spin 0.7s linear infinite;
}
@keyframes nb-hero-refresh-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* (Earlier evening/night refresh override removed. With the new
   atmospheric hero, the corner where this button sits is feathered
   to the cream desk on all time-of-day variants — there's no longer
   a "dark sky in the corner" case that needs light-on-dark styling.) */

/* (Duplicate .nb-hero-sky and .nb-hero-content blocks removed —
   already defined in the unified hero structure above.) */

.nb-hero-edition {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 0.8rem;
  opacity: 0.7;
}

/* (Evening/night text-shadow overrides removed — the hero no longer
   has a defined sky behind the text, so halos were creating glow
   rather than legibility against a backdrop. Text reads against the
   cream desk and the body wash directly, no halo needed.) */
/* Weather follows the edition date — slightly lighter so it reads as
   a secondary annotation rather than competing with the date. Shown
   on both desktop and mobile now that the standalone calendar widget
   has been removed; the hero is the canonical place for "right now".
   Extra margin-left creates the visual break instead of a bullet — the
   eye reads time/date as primary, weather as supporting. */
.nb-hero-wx {
  font-weight: 400;
  opacity: 0.62;
  margin-left: 0.6em;
}

.nb-hero-greeting {
  /* Playfair Display — the editorial display font used elsewhere
     for headlines (briefing card, field-notes titles, section
     headers). The hero is the page's front-page masthead; this
     font makes it part of the site's headline vocabulary rather
     than a field note. (Previous: Special Elite typewriter. That
     belonged to the field-note vocabulary — wrong family for the
     hero, which is editorial display, not handwritten capture.) */
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 500;
  /* Larger than before — Playfair has a finer stroke than Special
     Elite, so it needs more size to claim the same visual weight.
     Hero is the largest type on the page. */
  font-size: 2.1rem;
  line-height: 1.1;
  /* Playfair benefits from a small negative letter-spacing at
     display sizes — tightens the optical rhythm. */
  letter-spacing: -0.01em;
  margin: 0 0 0.7rem;
  max-width: 90%;
}

/* Evening/night text gets a faint dark shadow to anchor letterforms
   against the now-opaque sky behind them. Subtle — not a glow halo,
   just enough to give the text edge integrity. */
.nb-hero-evening .nb-hero-greeting,
.nb-hero-night .nb-hero-greeting {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.nb-hero-greeting em {
  /* Matched Playfair italic. Earlier iterations used Caveat (a casual
     handwriting font) for the name, treating "Good evening, BARTOSZ."
     as a typed template with a handwritten signature. At display
     size next to Playfair's refined serif, Caveat's rounded informal
     letterforms read cartoonish — like classroom marker on a typeset
     headline. The mismatch overstates the "personalized" effect.
     Editorial publications setting a personal greeting use ITALIC of
     the same family, not a font swap: "Good evening, /Bartosz/." in
     one continuous serif voice. The warm-red color still carries
     the personal accent without needing a typographic gesture. */
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
  font-weight: 500;
  /* Same size as the rest of the greeting — no bump needed since the
     font matches. (Caveat needed +30% to compensate for its smaller
     x-height; Playfair italic does not.) */
  font-size: 1em;
  letter-spacing: -0.01em;
  /* Muted warm terracotta — the previous rgba(180, 60, 50, 0.92)
     was too saturated at display size: "Bartosz" shouted while
     "Good morning," whispered. Pulled toward a softer, more
     desaturated warm-brown-red that reads as a quiet accent rather
     than a highlight. Matches the warmth of other red accents
     elsewhere on the site (field-note circled annotations, etc.)
     without competing for visual weight with the rest of the line. */
  color: rgba(155, 80, 65, 0.78);
  /* No baseline shift — the italic sits on the same baseline as the
     surrounding roman, the way italic text should. */
}

.nb-hero-summary {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 0.95rem;
  line-height: 1.55;
  max-width: 85%;
  font-weight: 400;
  margin: 0;
  /* Slightly softened body color so .nb-hero-strong (which uses full
     opacity 0.95 warm ink) reads as the lead within the line. Without
     this, the body is too dark for the title's gentle weight+color
     accent to do any work. */
  color: rgba(28, 22, 8, 0.78);
  /* Smooth transition from waiting-state to real summary so the swap
     isn\'t a hard pop. */
  transition: opacity 0.4s ease, font-style 0.4s ease;
}

/* (Summary text-shadow halos removed — see notes above for greeting
   and edition. No defined sky, no need for halos.) */

/* Waiting state — shown while async data sources are loading. Italic
   + muted color so it reads as a placeholder distinct from the real
   summary that will replace it. */
.nb-hero-summary-waiting {
  font-style: italic;
  opacity: 0.5;
}

/* Two quiet emphasis registers in the hero summary. Earlier versions
   tried italic Playfair for the title and mono for times — too many
   typeface changes in one line, the summary read as a font sampler
   instead of a sentence. Pulled back to a single restrained shift:
   the title gets weight + a touch of warm ink, the trailer stays
   muted. Times render as plain text, same as the prose around them. */

/* Strong — primary noun phrase (event title, count of things). Same
   Baskerville as the rest of the line, just heavier and with the
   warm ink color used elsewhere for accents. No italic, no font
   swap — this is editorial emphasis, not a separate font. */
.nb-hero-strong {
  font-weight: 600;
  /* Slight warm darkening so the title reads as the lead even
     without changing typeface. */
  color: rgba(28, 22, 8, 0.95);
}

/* Time markers — no styling, plain text. The class is kept so the
   JS doesn't break, but it does nothing visually. Mono treatment
   for a six-character "2pm" inside an italic surround was too
   much font-juggling for too little payoff. */
.nb-hero-time { /* intentionally empty */ }

/* Trailers — quiet supporting detail like ", then 2 more." Muted
   opacity so the lead reads first and the rest reads as aside. */
.nb-hero-trailer {
  opacity: 0.6;
}

/* Event/piece titles set as italic. The titles often carry their own
   internal punctuation — calendar entries like "Pro Scoops - How to
   beat the competition", piece titles like "EU food safety agency
   undercuts Brussels case for scrapping pesticide safety checks" —
   and reading them as plain prose forces the eye to parse the
   internal grammar as if it were sentence structure. Italics flag
   the whole span as "this is the name of the thing"; the reader can
   absorb it as a unit and move on. Slight color warmth so the title
   still feels like the lead, mirroring .nb-hero-strong. */
.nb-hero-event-title {
  font-style: italic;
  color: rgba(28, 22, 8, 0.92);
}
/* Dark hero variants: lift the title color the way .nb-hero-strong
   gets lifted (see .nb-hero-evening/.nb-hero-night blocks above). */
.nb-hero-evening .nb-hero-summary .nb-hero-event-title,
.nb-hero-night   .nb-hero-summary .nb-hero-event-title {
  color: rgba(245, 235, 215, 0.92);
}

/* Mobile hero — compact version with smaller type and tighter padding. */
@media (max-width: 720px) {
  .nb-hero {
    padding: 1.1rem 1.2rem 1.1rem;
    /* min-height removed — in atmosphere mode the hero has no
       visible background, so any fixed height beyond the natural
       text height just creates empty space between the greeting
       and the first card. Let content drive the height. */
    min-height: 0;
    border-radius: 0;
    margin-bottom: 0.5rem;
  }
  .nb-hero-edition {
    font-size: 0.5rem;
    margin-bottom: 0.55rem;
  }
  .nb-hero-greeting {
    font-size: 1.45rem;
    margin-bottom: 0.5rem;
    max-width: 100%;
  }
  .nb-hero-summary {
    font-size: 0.78rem;
    max-width: 100%;
    line-height: 1.45;
  }
  .nb-hero-refresh {
    top: 0.6rem;
    right: 0.7rem;
    width: 24px;
    height: 24px;
  }
  .nb-hero-refresh-glyph {
    font-size: 13px;
  }
  /* Mobile ground: kept proportional rather than fixed-px so it
     scales with whatever content height the hero ends up with. */
  .nb-hero-ground {
    height: 55%;
  }
}
