@font-face {
  font-family: "Intern Sans";
  src: url("/fonts/InternSans-Regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

/* Freight Text Pro, licensed via Adobe Fonts (kit vuz2uue, loaded on
   sunday-letter pages in BaseLayout). Aliased to "Freight Text" — the name
   the type jig already persists in jig.css — from the same hosted font
   files Adobe serves under "freight-text-pro", so renaming the jig's face
   list doesn't orphan values already saved in jig.css/localStorage. */
@font-face {
  font-family: "Freight Text";
  src:
    url("https://use.typekit.net/af/a9e142/00000000000000007735d61f/31/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff2"),
    url("https://use.typekit.net/af/a9e142/00000000000000007735d61f/31/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Freight Text";
  src:
    url("https://use.typekit.net/af/aa0b66/00000000000000007735d626/31/l?subset_id=2&fvd=i4&v=3") format("woff2"),
    url("https://use.typekit.net/af/aa0b66/00000000000000007735d626/31/d?subset_id=2&fvd=i4&v=3") format("woff");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Freight Text";
  src:
    url("https://use.typekit.net/af/390dad/000000000000000077359fcb/31/l?subset_id=2&fvd=n6&v=3") format("woff2"),
    url("https://use.typekit.net/af/390dad/000000000000000077359fcb/31/d?subset_id=2&fvd=n6&v=3") format("woff");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Freight Text";
  src:
    url("https://use.typekit.net/af/9e97d3/00000000000000007735d62a/31/l?subset_id=2&fvd=n7&v=3") format("woff2"),
    url("https://use.typekit.net/af/9e97d3/00000000000000007735d62a/31/d?subset_id=2&fvd=n7&v=3") format("woff");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

:root {
  color-scheme: light;
  /* The paper stock and its dots are derived from two tunable knobs (the dev
     jig exposes them as Warmth + Paper): a hue offset and a saturation
     multiplier. Defaults — 0deg / 1 — reproduce the original #f8f7f3 stock and
     #d8d0c2 rule exactly, so nothing changes until the jig moves them. Warmth
     shifts hue (warmer/cooler), Paper scales the cream tint (flatter/richer).
     Lightness is fixed per token so only the paper's color character moves. */
  --paper-warmth: 0deg;
  --paper-tint: 1;
  --bg: hsl(calc(48deg + var(--paper-warmth)) calc(26% * var(--paper-tint)) 96.3%);
  --text: #1d1a16;
  --muted: #6d665c;
  --rule: hsl(calc(38deg + var(--paper-warmth)) calc(22% * var(--paper-tint)) 80.2%);
  --accent: #2d6557;
  --text-soft: #3c342d;
  --surface: #ffffff;
  --inset-photo-bg: color-mix(in srgb, var(--rule) 14%, var(--bg));
  --base-font-size: 18px;
  --base-line-height: 1.5555555556;
  --rhythm: 28px;
  --baseline: var(--rhythm);
  --space-quarter: calc(var(--rhythm) / 4);
  --space-third: calc(var(--rhythm) / 3);
  --space-half: calc(var(--rhythm) / 2);
  --space-three-quarter: calc(var(--space-half) + var(--space-quarter));
  --space-1: var(--rhythm);
  --space-1-5: calc(var(--space-1) + var(--space-half));
  --space-2: calc(var(--space-1) + var(--space-1));
  --site-measure: 760px;
  --site-shell-gutter: max(16px, calc((100vw - var(--site-measure)) / 2));
  --dot-grid-size: var(--baseline);
  --main-padding-lane-offset: calc(var(--dot-grid-size) / 2);
  --dot-grid-writing-offset: 0px;
  --dot-grid-dot-size: 1px;
  --dot-grid-dot-extent: calc(var(--dot-grid-dot-size) + 0.5px);
  --dot-grid-strength: 68%;
  /* The dots share the paper stock's exact hue and tint (just darker), rather
     than the slightly pinker --rule hue, so the grid reads as a tonal shade of
     the same stock. Follows the Warmth/Paper jig knobs with the paper. */
  --dot-grid-ink: hsl(calc(48deg + var(--paper-warmth)) calc(26% * var(--paper-tint)) 80.2%);
  --dot-grid-color: color-mix(in srgb, var(--dot-grid-ink) var(--dot-grid-strength), transparent);
  --dot-grid-sheet-columns: 34;
  --dot-grid-sheet-max-width: calc(var(--dot-grid-size) * var(--dot-grid-sheet-columns));
  --dot-grid-sheet-available-width: calc(100vw - var(--app-inset-right, 0px) - 32px);
  --dot-grid-sheet-width: min(var(--dot-grid-sheet-available-width), var(--dot-grid-sheet-max-width));
  --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
  --font-display: var(--font-serif);
  --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* Typographic-scale roles — a face + size per tier, so the dev jig can tune
     each item on the scale site-wide (and override per page template) the way
     site styles cascade. Defaults equal the values already in use, so wiring a
     selector to a role token changes nothing until the jig moves it. */
  --type-title-face: var(--font-display);
  --type-title-size: 31px;
  --type-heading-face: var(--font-display);
  --type-heading-size: 25px;
  --type-subhead-face: var(--font-display);
  --type-subhead-size: 20px;
  --type-body-face: var(--font-sans);
  --type-body-size: var(--base-font-size);
  --type-meta-face: var(--font-sans);
  --type-meta-size: 14px;
  --type-meta-line-height: calc(var(--rhythm) * 0.75);
  --type-small-face: var(--font-sans);
  --type-small-size: 13px;
  /* Per-role weight, tuned by the jig. Defaults to 400, so a role renders the
     same until the jig moves it. Only meaningful for faces with real extra
     weights (variable web fonts, the separate Cako weight files). */
  --type-title-weight: 400;
  --type-heading-weight: 400;
  --type-subhead-weight: 400;
  --type-body-weight: 400;
  --type-meta-weight: 400;
  --type-small-weight: 400;
  font-size: var(--base-font-size);
  font-family: var(--font-sans);
  line-height: var(--base-line-height);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

@supports (width: 1rlh) {
  :root {
    --rhythm: 1rlh;
  }
}

@supports (width: round(down, 100px, 1px)) {
  :root {
    --dot-grid-sheet-width: max(
      var(--dot-grid-size),
      round(
        down,
        min(var(--dot-grid-sheet-available-width), var(--dot-grid-sheet-max-width)),
        var(--dot-grid-size)
      )
    );
  }
}

* {
  box-sizing: border-box;
}

/* Visually hidden but kept in the DOM for click targets / microformats. */
.is-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

body {
  margin: 0;
  background-color: var(--bg);
  color: var(--text);
  line-height: var(--base-line-height);
}

/* Inverted arrangement on regular pages: the page (nav/footer) is blank white
   stock, and the dot-grid "desk" is a centered sheet on <main> — the same
   width as the Sunday sheets (breaking out of the site-shell exactly the way
   they do), while the content inside still respects the reading measure. */
body:not(.sunday-index):not(.sunday-letter) {
  /* Same stock as the dot-grid desk — the chrome is just dot-free. */
  background-color: var(--bg);
}
body:not(.sunday-index):not(.sunday-letter) main {
  background-color: var(--bg);
  background-image:
    radial-gradient(
      circle at calc(100% - var(--dot-grid-dot-extent)) calc(100% - var(--dot-grid-dot-extent)),
      var(--dot-grid-color) var(--dot-grid-dot-size),
      transparent var(--dot-grid-dot-extent)
    ),
    radial-gradient(
      circle at calc(100% - var(--dot-grid-dot-extent)) var(--dot-grid-dot-extent),
      var(--dot-grid-color) var(--dot-grid-dot-size),
      transparent var(--dot-grid-dot-extent)
    ),
    radial-gradient(
      circle at var(--dot-grid-dot-extent) calc(100% - var(--dot-grid-dot-extent)),
      var(--dot-grid-color) var(--dot-grid-dot-size),
      transparent var(--dot-grid-dot-extent)
    ),
    linear-gradient(var(--bg), var(--bg)),
    linear-gradient(var(--bg), var(--bg)),
    radial-gradient(
      circle at var(--dot-grid-dot-extent) var(--dot-grid-dot-extent),
      var(--dot-grid-color) var(--dot-grid-dot-size),
      transparent var(--dot-grid-dot-extent)
    );
  background-position:
    0 0,
    0 0,
    0 0,
    right top,
    left bottom,
    0 0;
  background-size:
    100% 100%,
    100% var(--dot-grid-size),
    var(--dot-grid-size) 100%,
    var(--dot-grid-dot-extent) 100%,
    100% var(--dot-grid-dot-extent),
    var(--dot-grid-size) var(--dot-grid-size);
  background-repeat:
    no-repeat,
    repeat-y,
    repeat-x,
    no-repeat,
    no-repeat,
    repeat;
  width: var(--dot-grid-sheet-width);
  margin-left: 50%;
  transform: translateX(-50%);
  border-radius: 0;
}
body:not(.sunday-index):not(.sunday-letter) main > * {
  max-width: var(--site-measure);
  margin-inline: auto;
}

/* The whole Sunday section sits on blank stock — no dots anywhere. */
body.sunday-index main,
body.sunday-letter main {
  background-image: none;
}

/* The Sunday sheets get more room than the default reading measure, but the
   header/footer shouldn't grow with them — so <main> breaks out of the
   site-shell's width and re-centers on the viewport independently (the
   shell is itself centered on the viewport, so margin-left: 50% of the
   shell's width + translateX(-50%) of main's own width lands on the same
   center point regardless of how much wider main is than its parent).
   The index and letter sheets share this same width: 34 dot-grid columns at
   full size, rounded down to a whole number of columns in narrower viewports.
   That keeps the grid's x-origin aligned to the sheet so its left/right edges
   sit on dot columns instead of cutting through a partial column. */
body.sunday-index main,
body.sunday-letter main {
  width: var(--dot-grid-sheet-width);
  margin-left: 50%;
  transform: translateX(-50%);
}
/* No page heading or emblem sits above the sheet here, so the usual top
   padding on <main> just leaves an oversized gap under the header. Applies
   to both the index and letter sheets so their top gap is consistent. */
body.sunday-index main,
body.sunday-letter main {
  padding-top: 0;
}

.letter-intro-break {
  display: none;
}
@media (min-width: 561px) {
  .letter-intro-break {
    display: inline;
  }
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-display);
  font-weight: var(--type-heading-weight);
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

/* Everywhere but Sunday, a hand-drawn horizontal squiggle replaces the
   underline on hover — matching the frequency of the blockquote rail's very
   first hand-drawn pass (7-8 waves per 2-grid-unit tile, amplitude ±1.82px)
   rather than the later straightened-out/lower-frequency rail, transposed
   from vertical to horizontal so a long link's squiggle repeats without a
   visible seam. A background-image (not the rail's mask trick): mask cuts
   the whole element, including the text glyphs, down to the squiggle's
   shape, while background paints behind the text and leaves it untouched.
   The stroke color is --accent's literal value baked in, since
   background-image can't reference a custom property. */
body:not(.sunday-index):not(.sunday-letter) a:hover:not(.site-nav-link):not(.post-title a):not(.book-link):not(.membership-cta-button) {
  text-decoration: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 14'%3E%3Cpath d='M 0,7.92 C 0.39,8.19 0.78,8.36 1.17,8.32 C 1.56,8.28 1.94,7.97 2.33,7.68 C 2.72,7.39 3.11,6.89 3.5,6.6 C 3.89,6.3 4.28,6 4.67,5.91 C 5.06,5.83 5.44,5.92 5.83,6.08 C 6.22,6.24 6.61,6.61 7,6.88 C 7.39,7.15 7.78,7.51 8.17,7.69 C 8.56,7.87 8.94,7.98 9.33,7.96 C 9.72,7.94 10.11,7.76 10.5,7.57 C 10.89,7.37 11.28,7.04 11.67,6.81 C 12.06,6.59 12.44,6.32 12.83,6.21 C 13.22,6.1 13.61,6.06 14,6.14 C 14.39,6.21 14.78,6.44 15.17,6.65 C 15.56,6.87 15.94,7.22 16.33,7.44 C 16.72,7.66 17.11,7.91 17.5,7.97 C 17.89,8.04 18.28,7.98 18.67,7.83 C 19.06,7.67 19.44,7.32 19.83,7.03 C 20.22,6.75 20.61,6.33 21,6.13 C 21.39,5.93 21.78,5.77 22.17,5.82 C 22.56,5.87 22.94,6.14 23.33,6.44 C 23.72,6.73 24.11,7.26 24.5,7.58 C 24.89,7.9 25.28,8.27 25.67,8.35 C 26.06,8.44 26.44,8.32 26.83,8.07 C 27.22,7.82 27.61,7.26 28,6.86 C 28.39,6.46 28.78,5.9 29.17,5.68 C 29.56,5.45 29.94,5.37 30.33,5.53 C 30.72,5.68 31.11,6.19 31.5,6.62 C 31.89,7.04 32.28,7.74 32.67,8.09 C 33.06,8.44 33.44,8.74 33.83,8.71 C 34.22,8.68 34.61,8.31 35,7.91 C 35.39,7.51 35.78,6.75 36.17,6.31 C 36.56,5.86 36.94,5.36 37.33,5.25 C 37.72,5.14 38.11,5.33 38.5,5.65 C 38.89,5.97 39.28,6.7 39.67,7.19 C 40.06,7.68 40.44,8.34 40.83,8.58 C 41.22,8.83 41.61,8.86 42,8.65 C 42.39,8.44 42.78,7.82 43.17,7.34 C 43.56,6.86 43.94,6.12 44.33,5.77 C 44.72,5.42 45.11,5.17 45.5,5.24 C 45.89,5.31 46.28,5.76 46.67,6.18 C 47.06,6.6 47.44,7.35 47.83,7.76 C 48.22,8.17 48.61,8.59 49,8.66 C 49.39,8.73 49.78,8.49 50.17,8.17 C 50.56,7.86 50.94,7.2 51.33,6.77 C 51.72,6.35 52.11,5.82 52.5,5.64 C 52.89,5.45 53.28,5.47 53.67,5.65 C 54.06,5.83 54.44,6.34 54.83,6.72 C 55.22,7.1 55.61,7.66 56,7.92' fill='none' stroke='%232d6557' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: repeat-x;
  background-position: 0 100%;
  background-size: 56px 14px;
  /* padding-bottom, not a background-position offset past 100%: vertical
     padding on a non-replaced inline element is painted but doesn't add to
     the line box's height, so this pulls the squiggle's 0.35em drop inside
     the link's own box instead of past it. That keeps the whole squiggle
     inside the area background-clip paints, rather than relying on
     position/z-index to win a paint-order fight against the next line's
     text — a fight some engines (Safari in particular) still lost even
     after box-decoration-break: clone fixed the per-line positioning. */
  padding-bottom: 0.35em;
  /* Without this, a wrapped link's background is positioned against the
     union of all its line boxes, not each line: earlier lines' squiggle
     lands far below them and only the last line looks right. Cloning the
     background per fragment fixes that without touching line-height. */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

.site-shell {
  width: min(100% - 32px, var(--site-measure));
  margin: 0 auto;
}

/* Fixed px, not rem/var(--rhythm): the header is site chrome, not body copy —
   it must render identically everywhere regardless of whatever base size or
   rhythm a page (or the dev Grid jig, per rhythm-context) has tuned for its
   own reading text. Previously it inherited --rhythm/rem, so a page whose
   context had a different saved base size showed a differently-sized header. */
.site-header {
  display: flex;
  align-items: baseline;
  justify-content: center;
  font-size: 14px;
  gap: 16px;
  line-height: 28px;
  padding: 28px 0;
}

.site-nav {
  align-items: start;
  display: flex;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 28px;
}

.site-nav-link {
  align-items: center;
  color: var(--text);
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-decoration: none;
  /* Fixed width (sized to the widest label, "Newsletter") rather than sizing
     to each item's own label — otherwise a longer label widens that one
     item's box, and a uniform gap between differently-sized boxes puts the
     icons at uneven intervals rather than an even one. */
  width: 72px;
}

/* The hand-circled mark below is the hover/current-page treatment for nav
   items — a plain underline on the label would be a second, conflicting
   mark, so hover is explicitly kept underline-free here (a:hover elsewhere
   in this file supplies the site-wide default that would otherwise win). */
.site-nav-link:hover {
  text-decoration: none;
}

/* Inner wrapper sizes to its own content (icon/label), independent of the
   outer link's fixed 72px box — this is what the hand-circled mark below
   sizes against, so the circle hugs each item's actual width instead of the
   uniform link box. */
.site-nav-content {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: relative;
}

/* A hand-circled loop around the current page's nav item, in the spirit of
   marking a page by pen rather than a color change or underline rule. */
.site-nav-mark {
  height: calc(100% + 38px);
  left: 50%;
  pointer-events: none;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% + 34px);
}

/* Every item carries its own circle path, but it's only ever visible on the
   current page's item (drawn, at rest) or while hovering any item (drawn in
   live, as a preview of "this is where you'd land").
   The dash length is a device-space value comfortably longer than the longest
   rendered circle perimeter (~271px for the widest item). It can't use the
   old pathLength="100" normalization: vector-effect: non-scaling-stroke (which
   keeps the stroke a uniform weight across items) makes the browser measure
   the dash in rendered pixels and ignore pathLength — so 100 fell short of a
   stretched circle's real perimeter and the loop never closed. */
.site-nav-mark path {
  stroke-dasharray: 320;
  stroke-dashoffset: 320;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.site-nav-link.is-active .site-nav-mark path {
  stroke-dashoffset: 0;
  opacity: 1;
  /* No transition here: the active item's mark must be fully drawn on the
     very first paint, not fade in — the opacity transition below exists only
     for hover in/out on inactive items. Without this override, the browser
     treats the initial base->active style resolution as a transition too,
     which reads as a flicker while the page finishes loading (worst on
     slower/mobile paints). */
  transition: none;
}

/* Hovering re-traces the circle, like the pen drawing it again — on the
   current item that's a replay; on any other item it's a live preview. The
   fill-mode keeps it fully drawn for as long as the hover lasts, rather than
   reverting to hidden the moment the animation finishes. pathLength="100"
   on the path normalizes its length so this dash animation works the same
   regardless of each item's geometry.
   The easing mimics a hand circling an item: the pen eases in at the start,
   then accelerates around the loop (an ease-in curve), rather than the
   machine-like fast-start/slow-stop of ease-out. */
.site-nav-link:not(.is-active):hover .site-nav-mark path {
  animation: site-nav-mark-draw 0.36s cubic-bezier(0.5, 0, 0.75, 0) forwards;
}

@keyframes site-nav-mark-draw {
  from {
    stroke-dashoffset: 320;
    opacity: 1;
  }
  to {
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

.site-nav-glyph {
  align-items: flex-end;
  display: flex;
  height: 24px;
  justify-content: center;
}

.site-nav-icon {
  color: var(--muted);
}

/* Labels ignore the link's fixed 72px box (like .site-nav-content already
   does) rather than wrap at a space — "Shop Notes" would otherwise break
   into two lines while single-word labels like "Newsletter" never do,
   just because they have no break opportunity. */
.site-nav-label {
  white-space: nowrap;
}

/* No color change on hover: the hand-drawn circle is the whole hover effect. */

main {
  min-height: var(--main-min-height, 0px);
  padding: calc(var(--space-1-5) + var(--space-1) + var(--main-padding-lane-offset)) 0 var(--space-2);
  position: relative;
}

.page-heading {
  font-size: 25px;
  line-height: var(--rhythm);
  margin: 0 0 var(--space-1);
}

/* Spacing between posts comes entirely from .post-preview's own padding
   (2 units top + 1 unit bottom, zeroed at the list's outer edges) — no grid
   gap here. A gap on top of that padding was stacking additively, so two
   posts ended up 3 units apart (1 padding + 1 gap + 1 padding) instead of
   the intended 3 via padding alone. The note+note rule below zeros the top
   unit so a run of short posts keeps its original tighter 1-unit gap. */
.post-list {
  display: grid;
}

.post-meta {
  color: var(--muted);
  font-family: var(--type-meta-face);
  font-weight: var(--type-meta-weight);
  font-size: var(--type-meta-size);
  font-variant-numeric: tabular-nums;
  line-height: var(--rhythm);
  margin: 0;
}

/* Title-less permalink pages open on the date with no heading above it,
   so it needs its own top margin rather than relying on a title's spacing. */
.post-meta--lead {
  margin-top: var(--space-half);
}

.post-title {
  margin: 0 0 var(--space-quarter);
  font-family: var(--type-heading-face);
  font-weight: var(--type-heading-weight);
  font-size: var(--type-heading-size);
  line-height: var(--rhythm);
  letter-spacing: 0;
  overflow-wrap: anywhere;
}

.post-title a {
  color: var(--text);
  text-decoration: none;
}

.post-content {
  font-family: var(--type-body-face);
  font-weight: var(--type-body-weight);
  font-size: var(--type-body-size);
  line-height: var(--rhythm);
  overflow-wrap: anywhere;
}

.post-content > *:first-child {
  margin-top: 0;
}

.post-content > *:last-child {
  margin-bottom: 0;
}

.post-content p,
.post-content ul,
.post-content ol,
.post-content blockquote {
  margin: 0 0 var(--space-1);
}

.post-content h2 {
  margin: var(--space-2) 0 var(--space-half);
}

.post-content figure,
.post-content img {
  margin: var(--space-1) 0;
}
/* The figure owns the block spacing; its image sits flush inside it. */
.post-content figure img {
  display: block;
  margin: 0;
}
.post-content figcaption {
  color: var(--muted);
  font-family: var(--type-meta-face);
  font-weight: var(--type-meta-weight);
  font-size: var(--type-meta-size);
  line-height: var(--rhythm);
  margin-top: var(--space-half);
}

/* Dev-only inline page editor (BaseLayout injects the controls only on the
   dev server for imported static pages). Never present in production. */
.page-admin {
  display: flex;
  align-items: baseline;
  gap: var(--space-half);
  font-family: var(--font-sans);
  font-size: 13px;
  inset-block-start: var(--space-half);
  inset-inline-start: 50%;
  opacity: 0;
  pointer-events: none;
  position: absolute;
  transform: translateX(-50%);
  transition: opacity 120ms ease;
  visibility: hidden;
  z-index: 2;
}
main:hover > .page-admin,
.page-admin:focus-within {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
}
.page-admin-link {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--muted);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.page-admin-link:hover {
  color: var(--accent);
}
.page-admin-status {
  color: var(--muted);
}
.post-content--editing {
  outline: none;
}
.page-title--editing {
  outline: none;
}
.editable-text--editing {
  outline: none;
}

/* Dev-only link popover for the page editor (cmd+K on a selection). */
.page-link-pop {
  position: fixed;
  z-index: 2147483000;
  width: 290px;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 8px 22px rgba(29, 26, 22, 0.12);
  padding: 6px;
  font-family: var(--font-sans);
  font-size: 13px;
}
.page-link-pop input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 6px 8px;
  font: inherit;
  outline: none;
}
.page-link-pop input:focus {
  border-color: var(--accent);
}
.page-link-pop-results {
  margin-top: 4px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  max-height: 236px;
  overflow-y: auto;
}
.page-link-pop-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
  padding: 5px 8px;
  border: 0;
  border-radius: 4px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.page-link-pop-row > span:first-child {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.page-link-pop-row.is-active,
.page-link-pop-row:hover {
  background: color-mix(in srgb, var(--accent) 10%, #fff);
}
.page-link-pop-path {
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 45%;
}

/* A hand-drawn rail rather than a straight ruled border, in the same pen
   language as the nav marks (stroke-width 2, --accent). Drawn as a
   background-image, not a mask, so the stroke color is --accent's literal
   value baked in (background-image can't reference a custom property) —
   matching why the link-hover squiggle above avoids mask too. The wave tile
   lives inside an SVG <pattern> (patternUnits="userSpaceOnUse") rather than
   being repeated via CSS background-repeat/mask-repeat: both of those tile
   at the CSS box level and visibly seam in Chromium once an element needs
   more than one tile (the earlier "disconnected for long quotes" bug — a
   raw double-drawn canvas has no such seam, so it's the CSS-level tiling
   at fault, not the path). Stretching one copy of the wave across the full
   height avoided the seam but stopped tiling — the wobble slowed on long
   quotes and, per report, the single stretched copy sometimes fell short of
   covering the actual quote height. Baking the repeat into the SVG's own
   pattern fill instead lets the browser's SVG renderer do the tiling (a
   different code path from CSS background-repeat, so no seam) while the
   outer <svg> has no viewBox — so with background-size: 14px 100% the
   pattern's absolute units map 1:1 to real pixels and the wave frequency
   never varies, and a background-size-driven <rect width="100%"
   height="100%"> always reaches the true bottom of the element regardless
   of how tall the quote is. Positioned a quarter grid unit left of the
   content column — the dot column the rail would fall on if it had been
   drawn freehand using the dot grid as a guide — and starts level with the
   blockquote's own top edge, matching the first line of text. */
.post-content blockquote {
  position: relative;
  color: var(--text-soft);
  padding-left: var(--space-half);
}

.post-content blockquote::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-1 * var(--space-quarter) - 7px);
  width: 14px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='r' width='14' height='280' patternUnits='userSpaceOnUse'%3E%3Cpath d='M 7.45,0 C 7.45,1.94 7.45,3.89 7.45,5.83 C 7.45,7.78 7.42,9.72 7.42,11.67 C 7.44,13.61 7.47,15.56 7.49,17.5 C 7.5,19.44 7.55,21.39 7.54,23.33 C 7.52,25.28 7.45,27.22 7.38,29.17 C 7.3,31.11 7.14,33.06 7.08,35 C 7.01,36.94 6.96,38.89 6.99,40.83 C 7.02,42.78 7.15,44.72 7.25,46.67 C 7.34,48.61 7.49,50.56 7.57,52.5 C 7.65,54.44 7.68,56.39 7.7,58.33 C 7.72,60.28 7.68,62.22 7.68,64.17 C 7.68,66.11 7.69,68.06 7.7,70 C 7.71,71.94 7.74,73.89 7.74,75.83 C 7.74,77.78 7.71,79.72 7.69,81.67 C 7.67,83.61 7.62,85.56 7.62,87.5 C 7.61,89.44 7.65,91.39 7.67,93.33 C 7.69,95.28 7.75,97.22 7.73,99.17 C 7.71,101.11 7.64,103.06 7.54,105 C 7.42,106.94 7.21,108.89 7.06,110.83 C 6.91,112.78 6.73,114.72 6.65,116.67 C 6.58,118.61 6.56,120.56 6.56,122.5 C 6.56,124.44 6.62,126.39 6.65,128.33 C 6.65,130.28 6.65,132.22 6.63,134.17 C 6.62,136.11 6.58,138.06 6.55,140 C 6.55,141.94 6.55,143.89 6.55,145.83 C 6.55,147.78 6.58,149.72 6.58,151.67 C 6.56,153.61 6.53,155.56 6.51,157.5 C 6.5,159.44 6.45,161.39 6.46,163.33 C 6.48,165.28 6.55,167.22 6.62,169.17 C 6.7,171.11 6.86,173.06 6.92,175 C 6.99,176.94 7.04,178.89 7.01,180.83 C 6.98,182.78 6.85,184.72 6.75,186.67 C 6.66,188.61 6.51,190.56 6.43,192.5 C 6.35,194.44 6.32,196.39 6.3,198.33 C 6.28,200.28 6.32,202.22 6.32,204.17 C 6.32,206.11 6.31,208.06 6.3,210 C 6.29,211.94 6.26,213.89 6.26,215.83 C 6.26,217.78 6.29,219.72 6.31,221.67 C 6.33,223.61 6.38,225.56 6.38,227.5 C 6.39,229.44 6.35,231.39 6.33,233.33 C 6.31,235.28 6.25,237.22 6.27,239.17 C 6.29,241.11 6.36,243.06 6.46,245 C 6.58,246.94 6.79,248.89 6.94,250.83 C 7.09,252.78 7.27,254.72 7.35,256.67 C 7.42,258.61 7.44,260.56 7.44,262.5 C 7.44,264.44 7.38,266.39 7.35,268.33 C 7.35,270.28 7.35,272.22 7.37,274.17 C 7.38,276.11 7.42,278.06 7.45,280' fill='none' stroke='%232d6557' stroke-width='2' stroke-linecap='round'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='100%25' height='100%25' fill='url(%23r)'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 14px 100%;
  pointer-events: none;
}

.post-content code {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

.post-content pre {
  overflow-x: auto;
  padding: var(--space-half);
  background: #211f1c;
  color: #f4eee3;
}

.post-preview {
  padding: var(--space-2) 0 var(--space-1);
}

.post-preview:first-child {
  padding-top: 0;
}

.post-preview:last-child {
  padding-bottom: 0;
}

.post-preview--note + .post-preview--note {
  padding-top: 0;
}

.post-preview .post-title {
  font-family: var(--type-heading-face);
  font-size: var(--type-heading-size);
  font-weight: var(--type-heading-weight);
  line-height: var(--rhythm);
  margin-bottom: 0;
}

.post-preview .post-meta {
  margin-bottom: 0;
}

/* Titled entries show the date after the title (matching the permalink
   page's title → date order), so the date needs its own gap above the
   content that follows — same one-grid-unit gap the permalink page uses. */
.post-preview .post-meta--after-title {
  margin-bottom: var(--space-1);
}

.post-preview--note .post-content {
  color: var(--text-soft);
  font-size: var(--type-body-size);
}

/* notes have no title link, so the date link stretches over the whole entry */
.post-preview--note {
  position: relative;
}

.post-preview--note .post-date-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.post-preview--note .post-content a {
  position: relative;
  z-index: 1;
}

.post-summary {
  color: var(--text-soft);
  font-family: var(--type-body-face);
  font-weight: var(--type-body-weight);
  font-size: var(--type-body-size);
  line-height: var(--rhythm);
  margin: 0;
  max-width: 38rem;
  overflow-wrap: anywhere;
}

figure figcaption,
figcaption.post-content,
figcaption.post-summary {
  font-family: var(--type-meta-face);
  font-weight: var(--type-meta-weight);
  font-size: var(--type-body-size);
  line-height: var(--rhythm);
}

.read-more-link {
  white-space: nowrap;
}

.post-date-link {
  color: inherit;
  text-decoration: none;
}

.post-date-link:hover {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.post-meta-tag {
  color: inherit;
}

.tag-hash {
  margin-right: 0.08em;
}

.photo-entry-link {
  appearance: none;
  background: none;
  border: 0;
  color: var(--text);
  cursor: pointer;
  display: block;
  font: inherit;
  margin: 0;
  outline: none;
  padding: 0;
  text-align: left;
  text-decoration: none;
  width: 100%;
}

.photo-entry {
  margin: 0;
}

.photo-entry-image {
  border: 1px solid var(--rule);
  outline: none;
  width: 100%;
}

.photo-entry-media--inset {
  background: var(--inset-photo-bg);
  display: block;
  margin: 0 0 var(--space-quarter);
  padding: 0;
}

.photo-entry-media--inset .photo-entry-image {
  margin-inline: auto;
  width: auto;
}

.post-content .post-image-wrap--inset {
  background: var(--inset-photo-bg);
  margin: var(--space-1) 0;
  padding: var(--space-half);
  text-align: center;
}

.post-content .post-image-wrap--inset > .post-image--inset {
  display: block;
  margin: 0 auto;
  width: auto;
}

.photo-entry-link + .post-summary {
  display: block;
  margin-top: var(--space-quarter);
}

.photo-entry-media--inset + .post-summary {
  margin-top: 0;
}

.photo-entry-grid {
  display: grid;
  gap: 4px;
}

.photo-entry-grid--2,
.photo-entry-grid--4 {
  grid-template-columns: repeat(2, 1fr);
}

.photo-entry-grid--3 {
  grid-template-columns: repeat(3, 1fr);
}

.photo-entry-image--tile {
  aspect-ratio: 1 / 1;
  object-fit: cover;
  width: 100%;
}

.video-entry {
  margin: 0;
}

.video-entry .post-content,
.post-detail--video .post-content {
  color: var(--text-soft);
}

.video-embed {
  aspect-ratio: var(--video-aspect-ratio);
  background: #000;
  border: 1px solid var(--rule);
  margin: 0 0 var(--space-quarter);
  overflow: hidden;
  position: relative;
  width: 100%;
}

.video-embed iframe {
  border: 0;
  height: 100%;
  inset: 0;
  position: absolute;
  width: 100%;
}

.imported-article .kg-video-container {
  background: #000;
  border: 1px solid var(--rule);
  overflow: hidden;
}

.imported-article .kg-video-card video {
  display: block;
  height: auto;
  max-width: 100%;
  width: 100%;
}

.imported-article .kg-video-overlay,
.imported-article .kg-video-player-container {
  display: none;
}

.post-detail .post-title {
  font-size: var(--type-title-size);
  font-weight: var(--type-title-weight, 400);
  line-height: var(--space-1-5);
  margin-bottom: 0;
}

/* Static-page title treatment (About, and other imported pages that opt out
   of the blog post-title treatment above by using .page-title instead of
   .post-title on their h1). */
.imported-article .page-title {
  font: var(--type-title-weight, 400) var(--type-title-size)/var(--rhythm) var(--type-title-face);
  margin: 0 0 var(--space-half);
}

.post-detail .post-meta {
  margin-bottom: var(--space-1);
}

/* Book detail page: cover, recognition list, and purchase links sit in a
   sidebar beside the review copy. <main> already breaks out to the
   dot-grid sheet width for every page (see the rules above), so there's
   room beside the reading measure — this just opts the book article out of
   the max-width: var(--site-measure) collapse applied to main's other
   children, without widening main itself or the header/footer. */
body:not(.sunday-index):not(.sunday-letter) main > article.book-detail {
  max-width: calc(200px + var(--space-1-5) + var(--site-measure));
}

.book-detail-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  column-gap: var(--space-1-5);
  align-items: start;
}

.book-detail-sidebar {
  grid-column: 2;
  grid-row: 1;
}

.book-detail-body {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
}

@media (max-width: 860px) {
  body:not(.sunday-index):not(.sunday-letter) main > article.book-detail {
    max-width: var(--site-measure);
  }
  .book-detail-layout {
    display: block;
  }
  .book-detail-sidebar {
    margin-bottom: var(--space-1);
  }
}

.post-footer {
  border-top: 1px solid var(--rule);
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin-top: var(--space-1-5);
  padding-top: calc(var(--space-half) - 1px);
}

.archive-list {
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}

.archive-row {
  display: grid;
  grid-template-columns: 136px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  border-top: 1px solid var(--rule);
  padding: var(--space-third) 0 calc(var(--space-third) - 1px);
}

.archive-row:first-child {
  border-top: 0;
  padding-top: 0;
}

.archive-date {
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.archive-link {
  color: var(--text);
  display: grid;
  gap: 0;
  min-width: 0;
  text-decoration: none;
}

.archive-link:hover .archive-title {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.archive-link--with-image {
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 12px;
}

.archive-image-wrap {
  display: inline-block;
  position: relative;
}

.archive-image {
  aspect-ratio: 4 / 3;
  border: 1px solid var(--rule);
  object-fit: cover;
  width: 88px;
}

.archive-photo-count {
  position: absolute;
  right: 4px;
  bottom: 4px;
  background: rgba(29, 26, 22, 0.78);
  color: #f8f7f3;
  font-family: var(--font-sans);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  padding: 2px 5px;
  border-radius: 2px;
}

.archive-text,
.archive-title,
.archive-summary {
  display: block;
}

.archive-text {
  min-width: 0;
}

.archive-title {
  font-family: var(--font-display);
  line-height: var(--rhythm);
  overflow-wrap: anywhere;
}

.archive-title--untitled {
  font-weight: 400;
}

.archive-summary {
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: var(--space-three-quarter);
  margin-top: 0;
  overflow-wrap: anywhere;
}

.site-footer {
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 0.86rem;
  padding: var(--space-1) 0;
  text-align: center;
}

.feature-page {
  width: min(100% - 32px, 860px);
}

.feature-page .post-title {
  font-size: 31px;
  line-height: var(--space-1-5);
  max-width: 16ch;
}

.feature-page .post-content {
  font-size: 18px;
  max-width: 680px;
}

@media (max-width: 560px) {
  .site-header {
    display: block;
  }

  .site-nav {
    flex-wrap: wrap;
    justify-content: center;
    margin-top: var(--space-1);
    row-gap: 0;
  }

  .archive-row {
    grid-template-columns: 1fr;
    gap: 4px;
  }

  .photo-entry-link {
    display: block;
  }

  .archive-link--with-image {
    grid-template-columns: 84px minmax(0, 1fr);
  }

  .archive-image {
    width: 76px;
  }
}
