*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  scroll-behavior: smooth;
  /* iOS inflates text on rotation to landscape. WebKit's text-inflation
     algorithm enlarges any text block that spans ~100% of the screen width,
     without touching the layout, so on an iPhone the ledger perexes, ask
     Q&A, captions, footer tagline, post paragraphs and masthead kicker all
     grew while the column width stayed put – reported from device
     2026-09-22. The elements that escaped are the ones that never form a
     full-width block: `.ledger-date` is nowrap in a narrow grid track, and
     the titles are clamp()ed large enough not to qualify.

     100%, not `none`: it leaves the algorithm enabled at a multiplier of 1,
     which suppresses the inflation without touching the user's own
     pinch-zoom. The -webkit- prefix is the load-bearing one – per MDN's
     compat data, iOS Safari implements only the prefixed property and
     ignores the standard one. Desktop Safari ignores both, so this is inert
     everywhere but the phone. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

:root {
  --paper: #ece8de;          /* page bg */
  --ink: #2a2218;            /* text */
  --ink-soft: #6b5a4a;       /* muted */
  --hairline: rgba(42,34,24,.28);
  --hairline-faint: rgba(42,34,24,.19);  /* in-ledger rules only */
  /* --hairline pre-composited on --paper, opaque: the entry-nav arrow mask
     paints over the entry-nav rule at each end, and two stacked 28% alphas
     there double-darken to ~48% — an opaque color makes that overlap a
     no-op instead of a visible knot. */
  --hairline-opaque: #b6b0a7;
  /* THE accent. 4.89:1 on paper, so it clears WCAG AA for normal text; the
     old #c8392b was 4.21:1 and failed at every size below 24px. Darkened in
     LCh, not RGB: the obvious RGB ramp bleeds chroma (69 -> 65 by the time it
     passes), and chroma loss is what makes a red read as brick rather than
     vermilion. This holds the original's chroma (69.5 vs 69.1) and spends the
     distance on lightness alone (L 46.2 -> 42.1), which is why it stays hot
     at 9px where there is no area to show saturation. */
  --cinnabar: #bb2d20;

  --column: 810px;
  --gutter: clamp(3rem, 7vw, 9rem);
  /* Plate width. Two limits. The narrow one is the bleed formula: text may
     cover at most 30% of the plate, and the drawing's left 30% is blank. The
     wide cap stops the plate growing so it cannot eat its own sky: at 82vh
     the top crop is 18.7% of the image, and the first real ink in the master
     sits at 21.9%, so there is 3.2 points of margin. 85vh would leave 0.3. */
  --plate-w: min(82vh, calc((100vw - var(--gutter) - var(--column)) / 0.7));
  /* Left edge of the column, and of everything that must line up with it:
     the masthead and the footer. One definition, because three copies of
     the gutter is how they silently drifted 741px apart at 2560. */
  --column-left: var(--gutter);
  --font-display: "Playfair Display", Georgia, serif;
  --font-prose: Georgia, "Times New Roman", serif;
  --font-doc: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-cn: "PingFang SC", "Heiti SC", "Microsoft YaHei", sans-serif;
  --font-cn-display: "Noto Serif TC", var(--font-cn);
  --radius: 2px;
  --gap: 14px;
  --transition-fast: 150ms ease;   /* hover feedback: color, background-color, opacity */
  --transition-base: 300ms ease;   /* reserved for page-scale motion */
}

@font-face {
  font-family: "Playfair Display";
  src: url('/fonts/playfair-display-bold-subset.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Serif TC";
  src: url('/fonts/noto-serif-tc-bold-subset.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* min-height is load-bearing for the sticky footer (see .site-footer): it is
   what gives the footer's containing block a floor to be clamped against.
   svh, not vh: on iOS `vh` is the *large* viewport height, measured with the
   toolbar hidden, so a short page overflowed by the toolbar's height and
   showed a small overscroll. svh is the toolbar-visible height and, unlike
   dvh, does not change as the toolbar hides, so nothing shifts mid-scroll.
   The vh line stays as a fallback for browsers without svh. */
body { font-family: var(--font-prose); color: var(--ink); min-height: 100vh; min-height: 100svh; background: var(--paper); }

/* ── Visually hidden ────────────────────────────── */
/* Present for screen readers and search engines, absent on screen. Used for
   the gallery detail <h1>: its caption is already visible in the entry kicker,
   so a second visible copy would duplicate it and change a settled layout.
   Not `display: none` — that would hide it from assistive tech too, which is
   the one audience the heading exists for. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── Document label ─────────────────────────────── */
/* Metadata lines follow one rule: caps for the genre label, lowercase for the
   values beside it (date, photo count, tags). A line that is *only* a label
   keeps its whole-element transform instead — .ledger-video-caption ("VIDEO"),
   the two CHINATRIP masthead lockups, .chapter-name. This class supplies the
   stamp where the label had no span of its own; .entry-kicker-type is the same
   idea but stays separate because it is also the cinnabar one.
   Why: uppercasing the whole line uppercased the value too, so a Czech
   long-form date read "1. ZÁŘÍ 2016" in one place and "1. září 2016" in
   another — and ~30 uppercased dates down the ledger read as a customs form
   rather than a ledger. */
.doc-label { text-transform: uppercase; }

/* ── Page column ─────────────────────────────────────────────────────
   810px: sized against the widest real ledger row (a 10-photo plate —
   lead print + strip + gaps + the "+N" badge), which originally needed
   exactly 800px before its strip dropped below the lead. The lead print
   has since shrunk from 220px to 160px (too dominant against the rest of
   the ledger), which only loosens that fit further — no reason to revisit
   810px on its account. Sized for the ledger format (chapter I today,
   every chapter eventually), not the chapter II–IV card grid, which is
   unaffected either way and scheduled for the same ledger conversion.

   Left-anchored, not centered, on wide screens: the Great Wall etching is
   anchored bottom-right and already claims that side, so a centered column
   used to both leave the left margin dead AND overlap the etching's most
   detailed area (the watchtower, buried under the feed at ~1800px). Left-
   anchoring turns it into a book-spread — verso text column, recto plate —
   instead of splitting leftover space into two symmetric, mostly-empty
   margins. Below 810px there's no leftover space either way; the column is
   full-bleed exactly as before. ── */
main { max-width: var(--column); margin: 0 auto; position: relative; }
@media (min-width: 810px) {
  main { margin: 0 auto 0 var(--column-left); }
}
/* Past the cap the plate stops growing, so the surplus width has to go
   somewhere: between column and plate (the gap that made the two read as
   unrelated objects) or to the left. It goes left, where a book's outer
   margin is. The column's right edge lands 22% into the plate's blank left
   30%, so ink starts 8% of the plate's width after the last line of text. */
@media (min-width: 1200px) {
  :root { --column-left: max(var(--gutter), calc(100vw - var(--column) - 0.78 * var(--plate-w))); }
}

.site-bg {
  position: fixed; inset: 0;
  background: var(--paper);
  z-index: -1;
  overflow: hidden;
}
/* The recto plate. Black ink on white, multiplied into the paper: white
   times paper is paper, so the blank areas are a mathematical no-op and the
   asset needs no alpha channel and shows no rectangle edge. (The old asset
   was cool grey on a knocked-out background, which is what produced the
   tint seam.) The box may start inside the text column by at most 30% of
   its own width, and the drawing's left 30% is blank by construction, so
   text never lands on linework. */
.site-bg::after {
  content: '';
  position: absolute; top: 0; bottom: 0; right: 0;
  width: var(--plate-w);
  background: url('/plate.webp') right bottom / 100% auto no-repeat;
  background-image: image-set(url('/plate.avif') type('image/avif'),
                              url('/plate.webp') type('image/webp'));
  mix-blend-mode: multiply;
  opacity: .4;
  pointer-events: none;
}
/* Below 1200px there is no recto margin to put a plate in, so it stops
   being a background and becomes a tailpiece: in flow after the article,
   full bleed, full ink, with nothing printed over it. A phone cannot have a
   facing page, and a book closes a chapter this way. */
@media (max-width: 1199px) {
  .site-bg {
    inset: auto; z-index: auto; overflow: visible;
    /* 150vw would be the plate's own 2:3 at full bleed. 122vw instead, with
       the image anchored bottom, drops the top 18.7% -- which is blank, the
       master's first ink is at 21.9% -- so nothing drawn is lost and the
       colophon is not left sitting above a band of empty paper. It is the
       same crop the desktop 82vh cap takes, and it holds at every width, so
       there is no cap and no mask: top is the drawing's own sky, left and
       right run off the viewport, the bottom is the end of the page. */
    width: 100%;
    height: 122vw;
    margin-top: 1rem;
    /* Keep the plate's foot on the foot of the page. On a narrow tall
       viewport the document can be shorter than the screen (body's
       min-height stretches it), which left paper below the drawing and made
       it read as cut off. `bottom: 0` is the mirror of the footer's old
       `top: 100svh`: it forbids the plate's bottom edge from sitting above
       the scrollport's bottom, so on a short page it slides down flush and
       the slack moves above it, where it is just margin. On a normal page
       the constraint is never violated and nothing moves.
       The paper background is required, not decorative: sticky creates a
       stacking context, which isolates the ::after's multiply, and without a
       backdrop to multiply into the drawing's white would paint as opaque
       white over the cream. */
    position: sticky;
    top: calc(100vh - 122vw);
    top: calc(100svh - 122vw);
    background: var(--paper);
  }
  /* Nothing on this site is in a box, so the plate must not become one.
     Left, right and bottom run off the page, which is an honest bleed; the
     top and bottom would otherwise be ruled cuts through the linework, so
     both are dissolved into the paper instead. The mask sits on the ::after, not on
     .site-bg: masking the parent would isolate it and break the multiply. */
  .site-bg::after {
    left: 0; width: auto;
    background-size: cover;
    background-position: center bottom;
    opacity: .55;
  }

}

/* ── Feed ───────────────────────────────────────── */
/* Single column: every direct child (a chapter-opener or a chapter's
   .ledger) is full-width, now that every chapter uses the ledger — the
   auto-fill card grid this used to size is gone. */
.feed {
  display: grid;
  /* minmax(0, …) not 1fr: a bare `1fr` is `minmax(auto, 1fr)`, so the track
     floors at its content's min-content width and the whole feed stops
     shrinking. That pinned the homepage at 342px of content (372px total)
     while every detail page went on narrowing, so a 320px phone scrolled
     sideways on the homepage alone. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
  padding: var(--gap) 1.75rem 3rem;
  align-items: start;
}

/* ── Homepage opening — "První věta": no photo, the diary's own first line ── */
.pc-opening {
  display: block;
  margin: calc(var(--gap) * 2) 1.75rem calc(var(--gap) * 3);
  text-decoration: none;
  color: var(--ink);
}
.pc-opening-id {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin-bottom: 1rem;
  transition: color var(--transition-fast);
}
.pc-opening-id-en {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.1rem, 2.2vw, 1.5rem);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.pc-opening-id-cn {
  font-family: var(--font-cn-display);
  font-weight: 700;
  font-size: clamp(1.1rem, 2.2vw, 1.5rem);
}
.pc-opening-sentence {
  font-family: var(--font-prose);
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  line-height: 1.5;
  max-width: 46ch;
  overflow: hidden;   /* contains the floated drop cap */
}
.pc-opening-dropcap {
  float: left;
  font-family: var(--font-prose);
  font-size: 3.4em;
  line-height: .8;
  font-weight: 700;
  color: var(--cinnabar);
  padding-right: .12em;
}
/* The block is 754x149 of prose, so it cannot turn cinnabar wholesale, and
   the grey 1px underline it used to get was a screen-link idiom nobody saw.
   Instead the two non-prose parts rubricate, which is what a printer would
   colour: the lockup (the same object .page-masthead a:hover already reddens
   on every other page) and the attribution line, which names where the link
   goes. The sentence and its already-cinnabar drop cap stay put. */
.pc-opening:hover .pc-opening-id,
.pc-opening:hover .pc-opening-attribution { color: var(--cinnabar); }
/* Hung initial — as soon as `main`'s own left gutter exists (same
   breakpoint as the gutter itself, below), not a separately-guessed
   threshold: measured ~85px of clearance to the sentence at 812px, well
   over the ~65px the glyph needs, so there's no reason to wait past where
   the gutter first appears. Below this the float above is the whole
   design; this is pure addition. Anchored to the sentence itself, not
   `main` — `main` would put the letter at the *column's* edge, ignoring
   .pc-opening's own left margin, and detach it from the word it's the
   first letter of. */
@media (min-width: 810px) {
  .pc-opening-sentence { overflow: visible; position: relative; }
  .pc-opening-dropcap {
    float: none;
    position: absolute;
    top: 0;
    right: 100%;
    margin-right: .6rem;
    padding-right: 0;
  }
}
.pc-opening-attribution {
  font-family: var(--font-doc);
  font-size: .72rem;
  color: var(--ink-soft);
  letter-spacing: .04em;
  margin-top: .75rem;
  transition: color var(--transition-fast);
}
/* Front matter — sits outside the opening's own link so clicking the
   about line never navigates to Den 1; fills what was dead air before
   chapter I's rule with content instead of shrinking it away. */
/* Only the horizontal inset, to line the deck up with .pc-opening above it.
   Vertical margins belong to .site-tagline; declaring them here just lost a
   cascade fight with it. */
.pc-opening-subtitle {
  margin-left: 1.75rem;
  margin-right: 1.75rem;
  margin-bottom: 1.25rem;
}

/* ── Chapter openers — "Titulní list": bare paper, ruled, typographic.
   Replaces the solid lacquer bands; same type pairing as the homepage
   opening so the site gains one voice instead of a second artifact. ── */
.chapter-opener {
  grid-column: 1 / -1;
  position: relative;
  margin: calc(var(--gap) * 5) 0 calc(var(--gap) * 1.5);
}
.chapter-rule {
  border-top: 1px solid var(--ink);
  height: 1px;
}
.chapter-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .7rem;
  /* Right padding must clear the chop's actual footprint, not guess at it:
     chop sits `right: 1.1rem` and is `2.2rem` square, so its left edge is
     1.1 + 2.2 = 3.3rem from the edge — and its `rotate(-6deg)` grows that
     square's bounding box to ~2.42rem, pushing the true edge to ~3.52rem.
     2.6rem (the old value) was short of even the unrotated footprint, so
     long content (a wide date range, a longer title) had no real safe
     area and could run under the stamp. 4rem clears the rotated footprint
     with ~0.5rem of breathing room to spare. */
  padding: .85rem 4rem .85rem 0;
}
/* Nested as the chapter name's own first inline child (not a preceding
   flex sibling) so it wraps as part of the title's own text — "I. HONG
   KONG &" / "MACAU" — instead of flex-wrap stranding a tiny item alone on
   its own line at very narrow widths, with the title starting fresh below
   it. Bonus: the numeral is now part of the heading's accessible name. */
.chapter-num {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 4vw, 2.4rem);   /* matches .chapter-name at every width */
  color: var(--cinnabar);
}
/* Trailing period ("I.", "II."...) isn't decoration: it's the correct Czech
   form for an ordinal Roman numeral, and it stops chapter I's bare "I" from
   misreading as an extra initial glued onto "HONG KONG" once sized to match
   the chapter name. */
/* Folio numeral, hung into the left margin. Same breakpoint as `main`'s own
   gutter (below) and the dropcap above: all three are one left-margin
   apparatus, appearing the moment there's margin to hang into, not at a
   separately-tuned width.

   `right: 100%` right-aligns the numeral against the chapter name's left
   edge, which is the actual requirement here: I./II./III./IV. are different
   widths and must all end at the same x. `top`/`bottom` are left `auto` on
   purpose, so the box takes its *static* position vertically, i.e. exactly
   where inline flow would have put it, on the chapter name's own baseline.
   No guessed offset, nothing to drift when a font size changes.

   This replaces a `width: 0` + `direction: rtl` box whose text overflowed
   leftward, which also needed `unicode-bidi: isolate; direction: ltr` on an
   inner span or the numeral rendered ".I" instead of "I.". An earlier version
   of this comment rejected `position: absolute` on the grounds that the
   baseline would have to be reproduced with a guessed `top`; that is only
   true if you set `top`. Verified at 0 differing pixels.

   Taking the numeral out of flow is also what lets the markup separate it
   from the title with a real space: the leading whitespace collapses at the
   start of the line box, so the title stays flush while the text content
   reads "I. Hong Kong" rather than "I.Hong Kong" to a screen reader, to
   copy-paste, and with CSS off. Below this breakpoint the numeral is inline
   and that same space is the gap, replacing a .3em margin, which shifts the
   title by 0.5 CSS px. */
@media (min-width: 810px) {
  .chapter-name { position: relative; }
  .chapter-num {
    position: absolute;
    right: 100%;
    margin-right: .6rem;
  }
}
.chapter-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 4vw, 2.4rem);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink);
}
.chapter-cn {
  font-family: var(--font-cn-display);
  font-weight: 700;
  font-size: clamp(1.3rem, 3vw, 1.9rem);
  color: var(--ink);
}
.chapter-dates {
  font-family: var(--font-doc);
  font-size: .78rem;
  color: var(--ink-soft);
  letter-spacing: .04em;
}
.chapter-chop {
  position: absolute;
  top: 50%; right: 1.1rem;
  transform: translateY(-50%) rotate(-6deg);
  width: 2.2rem; height: 2.2rem;
  border: 1.5px solid var(--cinnabar);
  border-radius: 3px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-cn-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--cinnabar);
}
/* The chop used to be hidden here, because absolute positioning plus a
   guessed `padding-right` either wasted measure or let the chop land on the
   chapter name. A grid track cannot be overlapped, so giving the chop its
   own column makes collision impossible whatever the name's length. It costs
   49px of a 390px measure and buys back the only ink that recurs down a
   phone's scroll: the plate is printed once, the chop four times. */
@media (max-width: 600px) {
  .chapter-opener {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 2.2rem;
    column-gap: .9rem;
    margin-top: calc(var(--gap) * 2.5);
  }
  /* Every item placed explicitly: grid only lets the chop span rows 1-3 in
     column 2 while the rules span both columns if all of them have definite
     positions. Auto-placement would shove the first rule to row 4. */
  .chapter-rule { grid-column: 1 / -1; }
  .chapter-opener > .chapter-rule:first-child { grid-row: 1; }
  .chapter-head + .chapter-rule { grid-row: 3; }
  /* The head stops being a flex row here and becomes one inline run. As flex
     items the Latin name and the CN name could not share a line: a flex item
     cannot flow into another item's line box, so once the name wrapped to two
     lines the CN went to a third, even with room to spare beside "MACAU".
     Inline, they are one bilingual lockup that wraps as a unit. The name is
     `display: inline` so its own line boxes are in the same formatting
     context; the CN is `nowrap` because it is a phrase and must not split at
     the interpunct; and the gap is a spacer on the name rather than a margin
     on the CN, because a margin would still indent the CN when it does start
     a line, while a trailing spacer stays with the line it ends. */
  .chapter-head { grid-column: 1; grid-row: 2; display: block; padding-right: 0; }
  .chapter-name { display: inline; }
  .chapter-name::after { content: ""; display: inline-block; width: .45rem; }
  .chapter-cn { white-space: nowrap; }
  .chapter-dates { display: block; margin-top: .3rem; }
  .chapter-chop {
    position: static;
    grid-column: 2;
    grid-row: 1 / 4;
    align-self: center;
    transform: rotate(-6deg);
  }
}


/* ── Chapter I ledger prototype — Direction 3 from the Fable feed brainstorm:
   ruled index rows instead of cards, photo "plates" instead of gallery
   cards, one-line marginalia instead of ask cards. Rows abut inside this
   wrapper (one shared rule between entries, not a floating underline per
   row + a dead grid gap) and group visually by day: a lead ("Den N") row
   owns the day gutter; everything after it indents to the same left edge
   until the next lead, so galleries/asks read as that day's attachments
   instead of misaligned strangers. ── */
.ledger {
  grid-column: 1 / -1;
  list-style: none;   /* a <ul>: the rows are a chronological list, but the
                         markers are the D.N gutter codes, not bullets */
}
.ledger-row {
  display: block;
  text-decoration: none;
  color: var(--ink);
  padding: 1.05rem .2rem;
}
.ledger-row:not(.ledger-row--indented) { border-top: 1px solid var(--hairline-faint); }
.ledger > li:first-child > .ledger-row { border-top: none; }
/* Must equal a lead row's own actual title offset: the base .2rem left
   padding from .ledger-row (below) is still in effect on lead rows too
   (only grid-template-columns changes there) — so it's .2rem row padding +
   3rem day gutter + 1rem grid gap = 4.2rem, not just gutter+gap. 4rem left
   indented titles 0.2rem short of where a lead row's title actually starts. */
.ledger-row--indented { padding-left: 4.2rem; }
.ledger-row--diary { display: block; }
.ledger-row--lead {
  display: grid;
  grid-template-columns: 3rem 1fr;
  align-items: baseline;
  gap: 1rem;
}
.ledger-day {
  font-family: var(--font-doc);
  font-size: .78rem;
  font-weight: 700;
  color: var(--cinnabar);
  white-space: nowrap;   /* multi-day marks ("D.19–21") must not wrap at the
                             dash. They fit inside the track at both
                             breakpoints (widest is 52.6px against a 54.4px
                             mobile track) and overflow at most into the grid
                             gap, never the title column. */
}
.ledger-main { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
/* Date sits beside the heading, not off in a right-hand column — a diary
   entry's date is part of its title line, the way a letter's dateline sits
   next to the salutation, not filed off to the margin. */
.ledger-title-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .6rem;
}
.ledger-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1rem, 1.8vw, 1.2rem);
  line-height: 1.2;
  transition: color var(--transition-fast);
}
/* The whole ledger answers hover the same way: the row's heading turns
   cinnabar. Gallery and video rows already did this on their caption; diary
   and ask rows only ever shifted the paper by 7 of 255, which was both
   imperceptible and a contrast cost (cinnabar 4.89 -> 4.58 under it). Paper
   does not grey when a finger rests on it; ink changing is the thing print
   can actually do, and it is what every other hover here does. */
.ledger-row--diary:hover .ledger-title,
.ledger-row--ask:hover .ledger-ask-q { color: var(--cinnabar); }
/* Tip rows (undated-pattern diary posts) carry no badge to say "this is
   diary text" — scale does that instead, fixed at the lead title's clamp
   floor, the way a book sets subheads smaller rather than labelling them. */
.ledger-row--indented .ledger-title { font-size: 1rem; }
.ledger-date {
  font-family: var(--font-doc);
  font-size: .68rem;
  color: var(--ink-soft);
  white-space: nowrap;
}
.ledger-excerpt {
  font-family: var(--font-prose);
  font-style: italic;
  font-size: .85rem;
  color: var(--ink-soft);
  line-height: 1.4;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* Gallery → photo plate: prints pasted directly on the page, no card shell.
   A larger lead print carries the row; the rest sit as a smaller contact
   strip beside it, so photography keeps real presence instead of shrinking
   to uniform postage stamps. */
.ledger-row--plate {
  display: flex;
  flex-direction: column;
  gap: .6rem;
}
.ledger-plate-caption {
  font-family: var(--font-doc);
  font-size: .68rem;
  letter-spacing: .06em;
  font-weight: 400;   /* an <h3>: neutralise the UA bold */
  color: var(--ink-soft);
  transition: color var(--transition-fast);
}
.ledger-plate-body {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  flex-wrap: wrap;
}
.ledger-plate-lead,
.ledger-plate-strip img {
  background: #fff;
  object-fit: cover;
  box-shadow: 0 1px 2px rgba(42,34,24,.18);   /* a pasted print casts a shadow, it isn't drawn with an outline */
  transition: box-shadow var(--transition-fast);
}
/* Was 220×165 — right against the old starved uniform-tile version in a
   single-chapter mockup, too loud once it repeats at every gallery down a
   full page that got quieter everywhere else. 160×120 keeps the "one
   chosen print" hierarchy (still bigger than the 100×76 strip tiles —
   shrinking further would make it just another tile) while landing closer
   to a diary row's own weight instead of dwarfing it. */
.ledger-plate-lead {
  width: 160px;
  height: 120px;
  padding: 4px;
  flex-shrink: 0;
}
.ledger-plate-strip {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 6px;
}
.ledger-plate-strip img {
  width: 100px;
  height: 76px;
  padding: 3px;
}
.ledger-plate-more {
  display: flex;
  align-items: center;
  padding: 0 .3rem;
  font-family: var(--font-doc);
  font-size: .78rem;
  font-weight: 700;
  color: var(--ink-soft);
}
/* A gallery or video row's heading is the .68rem mono caption, the smallest
   type on the site, while its mass is 120px of thumbnails. Reddening the
   caption alone left the eye's actual target inert. So the prints lift: a
   pasted thing that answers a finger raises off the page and its shadow
   moves out. The print itself does not move, deliberately: a transform
   disables Chrome's pixel snapping and resamples the photo at a subpixel
   offset (see the ornament note below), and it would be motion rather than
   feedback. The shadow falls on bare paper beside and below the white mat,
   never under text, so no contrast figure moves. */
.ledger-row--plate:hover .ledger-plate-caption { color: var(--cinnabar); }
.ledger-row--plate:hover .ledger-plate-lead,
.ledger-row--plate:hover .ledger-plate-strip img,
.ledger-row--video:hover .ledger-video-frame { box-shadow: 0 3px 6px rgba(42,34,24,.22); }

/* Ask → one-line marginalia, a reader's letter column inside the ledger.
   Column, not a wrapping row: gives the 2-line clamps below a stable width
   to measure against, so long questions/answers cut at a real line break
   instead of wherever the Tera-side character count happened to land. */
.ledger-row--ask {
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.ledger-ask-q {
  font-family: var(--font-prose);
  font-style: italic;
  font-size: .9rem;
  font-weight: 400;   /* an <h3>: neutralise the UA bold */
  color: var(--ink);
  /* Matches .ledger-excerpt: same face, same italic, same two-line clamped
     role in the same list. It was on the UA's `normal`, which for Georgia
     italic is 1.11, the tightest text on the site and 26% under its own
     sibling. */
  line-height: 1.4;
  transition: color var(--transition-fast);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.ledger-ask-glyph {
  color: var(--cinnabar);
  font-size: 1.1em;
}
.ledger-ask-q .ledger-ask-glyph:first-child { margin-right: .1em; }
.ledger-ask-q .ledger-ask-glyph:last-child { margin-left: .1em; }
.ledger-ask-a {
  font-family: var(--font-doc);
  font-size: .72rem;
  /* The mono sentence register, as declared on .site-footer-colophon. This
     was on `normal` (1.22). */
  line-height: 1.5;
  color: var(--ink-soft);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

@media (max-width: 600px) {
  /* No day-gutter override here, deliberately. It used to narrow the track
     to 2.2rem, which was less than the longest code ("D.19–21", 52.6px at
     .78rem), so the code overran both track and gap and touched the title by
     1.4px on every phone. Widening it to 3.4rem fixed that but then gave
     mobile 17.8px of clearance against the desktop's 11.4px, so the gutter
     read wider on a phone than on a laptop. Inheriting the default 3rem plus
     1rem gap gives one behaviour at every width: the code overflows 4.6px
     into the gap and clears the title by 11.4px, and .ledger-row--indented
     keeps its single 4.2rem value. */
  .ledger-plate-body { flex-direction: column; }
  .ledger-plate-lead { width: 100%; height: auto; aspect-ratio: 4 / 3; }
  .ledger-plate-strip { width: 100%; }
  .ledger-plate-strip img { width: 92px; height: 70px; }
}

/* Video → same media-row idiom as the gallery plate: one framed still
   instead of a strip, no card shell. Never a lead (video posts aren't
   "Den N" titled), always indented like galleries/asks/tips. A doc-font
   "Video" kicker (matching the plate's "Galerie · N fotografií" caption)
   ties it to the same family — without it, a hatched box + bold title
   could be misread as a tip row with a failed image. */
.ledger-row--video {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.ledger-video-caption {
  font-family: var(--font-doc);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color var(--transition-fast);
}
.ledger-video-body {
  display: flex;
  align-items: center;
  gap: .9rem;
}
/* Matches the gallery strip tile exactly (100×76, 3px mat) — a video row
   is never a lead, so it takes the tile rung, not the lead's 160×120. Its
   own former 120×84 was a third, unaffiliated size; the "VIDEO" kicker,
   ink-hatch treatment and play glyph already signal the genre, so the
   frame doesn't need a wider aspect on top of that to read as video. */
.ledger-video-frame {
  flex-shrink: 0;
  width: 100px;
  height: 76px;
  background: #fff;
  padding: 3px;
  box-shadow: 0 1px 2px rgba(42,34,24,.18);
  transition: box-shadow var(--transition-fast);
}
.ledger-video-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Lives in the caption line, on paper — see the comment in index.html's video
   branch for why it isn't overlaid on the thumbnail. */
.ledger-play {
  color: var(--cinnabar);
  font-size: .8em;   /* of the .68rem caption — a mark, not a headline glyph */
  /* ▶ (U+25B6) sits low in its em box relative to Latin caps, so on a baseline
     it lands ~1.7px below the cap-height centre of "VIDEO" (measured at 8x).
     Raised by .2em of its own size to optically centre it. vertical-align, not
     transform: transform doesn't apply to non-replaced inline elements. */
  vertical-align: .2em;
}
.ledger-video-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;   /* matches the indented/tip title scale */
  line-height: 1.3;
}
.ledger-row--video:hover .ledger-video-caption { color: var(--cinnabar); }
@media (max-width: 600px) {
  .ledger-video-frame { width: 92px; height: 70px; }   /* matches the strip tile's own mobile size */
}

/* ── Page masthead (detail pages) ────────────────── */
/* The way home, doubling as brand identity — not a separate utility link.
   Same lockup as the homepage opening (.pc-opening-id), same column
   .site-footer already matches (this sits outside <main>, a sibling, same
   as the footer, so it needs its own copy of that column geometry). Fixed
   size, no clamp: a running header shouldn't breathe with the viewport the
   way the homepage's one-time opening does. */
.page-masthead {
  max-width: 810px;
  margin: 0 auto 0;
  padding: 1.5rem 1.75rem 0;
}
@media (min-width: 810px) {
  .page-masthead {
    margin: 0 auto 0 var(--column-left);
    padding-top: 2rem;
  }
}
.page-masthead a {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  text-decoration: none;
  color: var(--ink);
  transition: color var(--transition-fast);
}
.page-masthead a:hover { color: var(--cinnabar); }
.page-masthead-en {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.page-masthead-cn {
  font-family: var(--font-cn-display);
  font-weight: 700;
  font-size: .95rem;
}

/* ── Single post (detail) — "one entry of the same book": no card shell,
   same paper as the ledger, same column main/.site-footer already use.
   Structurally an entry-head (echoing the chapter-opener's rule + kicker +
   name) followed by prose capped to a real reading measure. ── */
/* The top padding is the running head's breathing room. At .6rem the entry
   rule sat 10px under the wordmark, so a 1px --ink rule (the same weight as
   .chapter-rule, which gets --gap * 5 above it on the homepage) read as an
   underline to the masthead rather than as the entry's own opening rule, and
   rule + kicker + title hung off the wordmark as one dense stack. --gap * 2
   puts ~38px between glyphs and rule, against ~37px above the wordmark, so
   the masthead sits centred in its own band. --gap * 3 overshoots: the head
   would then out-breathe the 24px title-to-prose gap below it. */
.post-wrap {
  padding: calc(var(--gap) * 2) 1.75rem 3rem;
}
.entry-head {
  position: relative;
  margin-bottom: 1.25rem;
}
/* Seal's rotated footprint (see .entry-seal): only reserved when a seal is
   actually rendered — an unmapped city has no seal and shouldn't leave a
   dead gap on the right of the kicker/title. */
.entry-head--sealed {
  padding-right: 4rem;
  /* Title-less heads (galleries) are otherwise only as tall as one kicker
     line — too short for the seal's rotated footprint to center into
     without poking past the rule above or the prose below. Diary/ask/video
     heads already clear this via their title line and are unaffected. */
  min-height: 4.6rem;
}
/* padding-right clips the rule 4rem short of the column on sealed pages —
   every other rule/photo/prose line on the page runs full width, so this
   restores that without touching the padding text-clearance relies on. */
.entry-head--sealed .entry-rule {
  margin-right: -4rem;
}
.entry-seal {
  position: absolute;
  /* Centered across the kicker+title band, not the whole entry-head: offset
     down by half the rule's own footprint (.85rem margin + 1px border) so
     the rule above isn't counted into the centering. */
  top: calc(50% + .43rem);
  right: 1.1rem;
  transform: translateY(-50%) rotate(-6deg);
  width: 2.2rem; height: 2.2rem;
  border: 1.5px solid var(--cinnabar);
  border-radius: 3px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-cn-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--cinnabar);
}
/* Same fix as the chapter chop above: the seal gets its own column instead
   of a guessed padding-right, so a seal and a title cannot collide however
   long the title runs. min-height goes because the seal's own row is the
   floor now, which also means a title-less gallery head is exactly as tall
   as it needs to be. */
@media (max-width: 600px) {
  .entry-head--sealed {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 2.2rem;
    column-gap: .9rem;
    padding-right: 0;
    min-height: 0;
  }
  .entry-head--sealed .entry-rule { grid-column: 1 / -1; grid-row: 1; margin-right: 0; }
  .entry-head--sealed .entry-kicker { grid-column: 1; grid-row: 2; }
  .entry-head--sealed .entry-title,
  .entry-head--sealed .entry-question { grid-column: 1; grid-row: 3; }
  .entry-seal {
    position: static;
    grid-column: 2;
    grid-row: 2 / span 2;
    align-self: center;
    transform: rotate(-6deg);
  }
}
.entry-rule {
  border-top: 1px solid var(--ink);
  height: 1px;
  margin-bottom: .85rem;
}
.entry-kicker {
  font-family: var(--font-doc);
  font-size: .7rem;
  letter-spacing: .06em;
  /* It was on the UA's `normal`, which for this stack is 1.16, the tightest
     leading on the site. One line at desktop, so it never showed there, but
     the type-and-tags string wraps to three lines by 414px and four by 320.
     1.4 matches .entry-nav-kicker. */
  line-height: 1.4;
  color: var(--ink-soft);
  margin-bottom: .5rem;
}
.entry-kicker-type { color: var(--cinnabar); text-transform: uppercase; }
.entry-tags { margin-left: .1em; color: var(--ink-soft); }
.entry-title {
  position: relative;
  font-size: clamp(1.5rem, 3.5vw, 2.2rem);
  line-height: 1.25;
  letter-spacing: .01em;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
}
/* Ask detail — same idiom as the ledger's ask row, at page scale. Sized to
   actually take the title slot (per the comment where it's built in
   page.html), not just be a slightly-large paragraph. */
.entry-question {
  font-family: var(--font-prose);
  font-style: italic;
  font-size: clamp(1.35rem, 2.8vw, 1.8rem);
  line-height: 1.4;
  color: var(--ink);
  /* This is an <h1> (the question is the page's title), so font-size above and
     weight here both have to be stated to override the UA's h1 defaults —
     margins are already zeroed by the global reset. */
  font-weight: 400;
}
.entry-ask-glyph { color: var(--cinnabar); font-size: 1.1em; }
.entry-question .entry-ask-glyph:first-child { margin-right: .1em; }
.entry-question .entry-ask-glyph:last-child { margin-left: .1em; }
.entry-answer { position: relative; }
.entry-answer p:first-of-type::before {
  content: "↳ ";
  color: var(--cinnabar);
  font-family: var(--font-doc);
}

.post-content {
  margin-top: 1.5rem;
  line-height: 1.75;
  font-size: 1.0625rem;
}
/* Diary-only drop cap — modeled on .pc-opening-dropcap, a size grade
   smaller. Scoped via this modifier (set in the template, which can see
   post_type) rather than in raw CSS, which can't. Safe no-op when the first
   paragraph is image-only: ::first-letter has no text to grab. */
.post-content--diary > p:first-child::first-letter {
  float: left;
  font-family: var(--font-prose);
  font-size: 3.2em;
  line-height: .8;
  font-weight: 700;
  color: var(--cinnabar);
  padding-right: .12em;
}
.post-content p { margin-bottom: 1.1rem; }
.post-content ul, .post-content ol { margin: 0 0 1.1rem 1.3rem; }
.post-content figure { margin: 0; }
/* Same "a pasted print casts a shadow" diet as the ledger, one grade
   heavier — a full-width photo is ~5× a ledger tile's area, so the
   ledger's shadow alone reads as nothing under it; the extra soft/ambient
   term is proportional to the bigger sheet of paper. */
.post-content img,
.post-content video {
  width: 100%;
  /* Required now that the images carry real width/height attributes: without
     it the height attribute is honoured literally against a 100% width and
     every photo is stretched. The attributes are what let the browser reserve
     the right box before the image loads, so they earn their keep. */
  height: auto;
  background: #fff;
  padding: 4px;
  box-shadow: 0 1px 2px rgba(42,34,24,.18), 0 2px 8px rgba(42,34,24,.08);
  margin: 1.5rem 0;
  display: block;
}
.post-content a { color: var(--cinnabar); }

/* Prev/next — the book's own continuity, not a diary-only "next entry":
   every post type can sit on either side, so this reads as one running
   sequence rather than a sub-index. Doc-font register like .entry-kicker
   (own class, not shared — kicker is uppercased metadata, this carries a
   real mixed-case title and must not be). A lone side (first/last post in
   the whole site) just omits the other <a>; margin-left:auto on the next
   link is what pins it to the right whether or not a prev link exists. */
.entry-nav {
  display: flex;
  /* Default stretch makes each link fill the row's height, then the link's
     own align-items:center re-centers within that — so two sides with
     different text heights (a 2-line title vs. a 1-line one) don't share a
     kicker baseline. flex-start fixes both kickers to one shared top line;
     the thumbnail gets its own align-self below to stay centered on its
     text without needing the row-level centering. */
  align-items: flex-start;
  gap: 1.5rem;
  margin-top: calc(var(--gap) * 3);
  padding-top: .85rem;
  /* 2px, diverging from .entry-rule's 1px on purpose: this rule carries 2px
     ornaments (the chevron caps, the trigram's bars), which cannot center
     on an odd-width line at 1x DPR — a 2px mark straddling a 1px line lands
     asymmetrically depending on the page's fractional scroll offset, seen
     as a visible blob/step at the arrow tips. Still the deliberate bookend
     to .entry-rule in spirit (this rule opens the entry, this one closes
     it) — just a heavier foot rule under a lighter head rule, legitimate
     hierarchy since the two are never in view together.
     Color is --hairline-opaque, not --ink: at 2px, full ink read as heavier
     than the page's own masthead band (measured ~2x the masthead's own
     1px .entry-rule, worse on short posts where both sit close together).
     --ink-soft alone wasn't enough (still ~1.4x); the hairline weight is
     what actually reads calmer than the header. Cinnabar on hover (below)
     and the trigram's permanent cinnabar are the intended accents — this
     rest state is deliberately quiet so those pop instead. */
  border-top: 2px solid var(--hairline-opaque);
  position: relative;
}
/* Hovering one side reddens only that half of the shared closing rule (plus
   its own arrowhead via currentColor on .entry-nav-link:hover) — a half-red
   line pointing toward where you're going, rather than the whole rule (which
   read as a generic "active" flash, or wrong-headed if only one arrowhead
   changed with it). Overlays, not a border split: the rule stays one real
   border so the fused arrowheads' math (measured off .entry-nav's own
   padding/border) doesn't need to change. */
.entry-nav::before,
.entry-nav::after {
  content: "";
  position: absolute;
  top: -2px;
  height: 2px;
  background: var(--cinnabar);
  opacity: 0;
  transition: opacity var(--transition-fast);
}
/* Stop short of 50%, not flush with it — .entry-nav-mid's paper-masked box
   (16px trigram + 9px padding each side, 17px from center) sits exactly
   there, and a real DOM child painting after ::before but before ::after
   means a flush-to-center ::after would paint OVER the ornament on hover
   (::after is generated content, painted last regardless of source order).
   Leaving a gap avoids relying on stacking order at all. */
.entry-nav::before { left: 0; width: calc(50% - 17px); }
.entry-nav::after { right: 0; width: calc(50% - 17px); }
.entry-nav:has(.entry-nav-link--prev:hover)::before { opacity: 1; }
.entry-nav:has(.entry-nav-link--next:hover)::after { opacity: 1; }
.entry-nav-link {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  max-width: 48%;
  color: var(--ink);
  text-decoration: none;
  position: relative;
  transition: color var(--transition-fast);
}
.entry-nav-link:hover { color: var(--cinnabar); }
.entry-nav-link:hover .entry-nav-kicker,
.entry-nav-link:hover .entry-nav-title,
.entry-nav-link:hover .entry-nav-arrow { color: var(--cinnabar); }
.entry-nav-link--next { margin-left: auto; }
/* Rides .entry-nav's own border-top rather than sitting inside the tile:
   a flex child here would steal width from the thumbnail/text, indenting
   them off the column edge every other element on the page uses (measured
   ~21px off at 1400px). The rule itself is the arrow's shaft; only the
   head is drawn — as an SVG mask dart, not the &larr;/&rarr; text glyph
   still in the markup (silenced via font-size:0, kept as an aria-hidden/
   no-CSS fallback) and not a `clip-path` (see below). background:
   currentColor keeps the existing :hover → cinnabar rule working as-is;
   color is --hairline-opaque at rest for the same reason as .entry-nav's
   own border-top, see that rule's comment. */
.entry-nav-arrow {
  font-size: 0;
  color: var(--hairline-opaque);
  background: currentColor;
  width: 6px;
  height: 12px;
  position: absolute;
  top: calc(-.85rem - 7px);
  transition: color var(--transition-fast);
}
/* Open chevron at exactly 45°, integer coordinates, drawn as an SVG mask
   rather than `clip-path`. Both encode the identical polygon, but Chrome
   pixel-snaps border/background/mask paint rects to the device grid — the
   same mechanism that keeps the rule and the trigram's gradient bars crisp
   — while `clip-path` geometry is NEVER snapped, it rasterizes at the
   element's raw fractional position. That position is `.entry-nav`'s
   border-box top minus a fixed offset, and border-box top is fractional
   for an ordinary reason (whatever content happens to sit above the nav on
   a given page) — so the shape's mirror-symmetry axis lands at a different
   sub-pixel phase per page, and its two 45° arms (though genuinely mirror-
   symmetric in the coordinates) pick up systematically different AA
   fractions: measured 26|99|74 vs 50|99|50 on one page, reversed on
   another. A mask rasterizes into the snapped paint rect instead, so both
   arms measure identically (50|99|50) regardless of page content. left/
   right are -1px, not 0: at 0 the snapped 2px rule painted directly over
   the tip's antialiased vertex, fusing it into a blunt end with no visible
   point; 1px clear of the rule the tip renders as its own clean partial-
   coverage column, mirror-identical on both sides. */
.entry-nav-link--prev .entry-nav-arrow {
  left: -1px;
  -webkit-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="12"><path d="M6 0v2L2 6l4 4v2L0 6z"/></svg>') 0 0 / 6px 12px no-repeat;
  mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="12"><path d="M6 0v2L2 6l4 4v2L0 6z"/></svg>') 0 0 / 6px 12px no-repeat;
}
.entry-nav-link--next .entry-nav-arrow {
  right: -1px;
  -webkit-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="12"><path d="M0 0v2l4 4-4 4v2l6-6z"/></svg>') 0 0 / 6px 12px no-repeat;
  mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="12"><path d="M0 0v2l4 4-4 4v2l6-6z"/></svg>') 0 0 / 6px 12px no-repeat;
}
.entry-nav-text {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  min-width: 0;
  /* .entry-nav-thumb already centers on whichever side is taller; without
     this, the text (the other child of the same flex row) stayed pinned to
     the row's align-items:flex-start instead — invisible when text is the
     taller side (a 2-line title), but visible on gallery/ask fallback text
     ("N fotografie", one short line, shorter than the 64x48 thumbnail),
     where the text sat flush at the top instead of centered against the
     image. Both children now center symmetrically, regardless of which is
     taller. */
  align-self: center;
}
.entry-nav-link--next .entry-nav-text { text-align: right; }
.entry-nav-kicker {
  font-family: var(--font-doc);
  font-size: .68rem;
  letter-spacing: .06em;
  /* It was on the UA's `normal`, which only showed once the side-by-side nav
     made it wrap to two lines. */
  line-height: 1.4;
  color: var(--ink-soft);
  transition: color var(--transition-fast);
}
/* Keep the date whole: without this the kicker broke inside it
   ("GALERIE · 25." / "srpna 2016") rather than after the label. */
.entry-nav-date { white-space: nowrap; }
.entry-nav-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .95rem;
  color: var(--ink);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  transition: color var(--transition-fast);
}
/* Same "pasted print" idiom as the ledger plates — .ledger-plate-strip img
   uses the same padding + shadow at this scale. */
.entry-nav-thumb {
  width: 64px;
  height: 48px;
  object-fit: cover;
  background: #fff;
  padding: 3px;
  box-shadow: 0 1px 2px rgba(42,34,24,.18);
  flex-shrink: 0;
  align-self: center;
}
/* Center ornament — punches the rule into "line … ☵ … line," a printer's
   divider marking the gap between entries: ☵ Kǎn (Water) from the I Ching's
   eight trigrams — chosen over a generic shape (a diamond was tried and
   rejected for its Czech connotation) for being an actual Chinese symbol,
   and over the other seven trigrams for two reasons: it's the only pattern
   symmetric on both axes, and its solid middle bar rides exactly on the
   rule's own line, so the rule visibly threads through the ornament rather
   than breaking at it (confirmed sharpest on hover, where the reddened
   half-rule flows straight into that middle bar). Drawn as 3 stacked
   horizontal bars (broken/solid/broken), not a font glyph — the trigram
   Unicode block (U+2630-2637) is in neither subsetted webfont, and an
   unsubsetted system fallback would carry different stroke weight/hinting
   from everything else on the page. Pure axis-aligned bars are also why
   this is the first center-ornament design across many rounds to render
   with zero anti-aliased pixels at 1x DPR — no diagonal or curved edge
   anywhere for the rasterizer to blend. transform:none + integer margin-
   left is deliberate, not incidental: a transform-based center (like the
   rotated-diamond predecessor used) disables Chrome's pixel snapping and
   smears straight 1px edges at 1x — this box is centered by geometry
   instead. Always rendered (not conditional on page.higher/page.lower
   existing) since it belongs to the rule itself, which always spans the
   full width. */
.entry-nav-mid {
  position: absolute;
  left: 50%;
  margin-left: -17px;   /* half of 34px box: 16px trigram + 9px paper padding each side */
  top: -7px;            /* rule center = border-box top + 1px (now a 2px rule);
                            middle bar center = element top + 6px, so top = -7px
                            puts both centers on the same row */
  transform: none;
  background: var(--paper);
  padding: 0 9px;
}
.entry-nav-mid::before {
  content: "";
  display: block;
  width: 16px;
  height: 12px;
  /* 2px lines with 3px gaps (gap = 1.5x line weight, not the previous 2x-
     scaled 4px) — tighter rhythm reads as one mark instead of three bars
     drifting apart, and it makes the trigram exactly 12px tall: the same
     vertical extent as the arrow's own 12px box, so both ornaments span an
     identical band centered on the same rule. Every coordinate stays an
     integer — still exact axis-aligned bars, zero anti-aliasing risk. */
  background:
    linear-gradient(var(--cinnabar), var(--cinnabar)) 0 0 / 6px 2px no-repeat,
    linear-gradient(var(--cinnabar), var(--cinnabar)) 10px 0 / 6px 2px no-repeat,
    linear-gradient(var(--cinnabar), var(--cinnabar)) 0 5px / 16px 2px no-repeat,
    linear-gradient(var(--cinnabar), var(--cinnabar)) 0 10px / 6px 2px no-repeat,
    linear-gradient(var(--cinnabar), var(--cinnabar)) 10px 10px / 6px 2px no-repeat;
}
/* Side by side, not stacked. Stacked, the two links sized to their content
   rather than to the column, so prev and next had different widths and sat on
   different rows: the pair stopped reading as one "back / forward" control and
   just looked like two loose tiles. `flex: 1 1 0` gives each exactly half
   regardless of title length, and min-width: 0 lets them shrink (a flex item's
   automatic minimum is min-content, which a long title would otherwise hold
   open). The links keep their default position: relative, so each arrowhead
   anchors to its own half and needs no repositioning.

   The thumbnail goes, and that is what makes the halves work: at 375px each
   column is 152px, and 64px of thumbnail plus its .7rem gap left 77px for
   text, which broke the kicker into four lines ("GALERIE" / "· 25." /
   "srpna" / "2016"). Without it both kickers set in two lines at every width
   down to 320 and the two sides share a top line. Simplification, not a
   different design: the title and date still say where you are going, and the
   preview is the one thing a 152px column cannot afford. */
@media (max-width: 600px) {
  .entry-nav { gap: .9rem; }
  .entry-nav-link { flex: 1 1 0; max-width: none; min-width: 0; }
  /* The text box has to fill its half. Content-sized it sat at flex-start, so
     `text-align: right` had nothing to align against: a lone next (the first
     post, no prev) rendered hard left, and a short next title left a gap at
     the right edge. Above 600px the link is content-sized and pinned by
     margin-left: auto, so this does not arise there. */
  .entry-nav-link--next { margin-left: 0; }
  .entry-nav-link--next .entry-nav-text { flex: 1; }
  .entry-nav-thumb { display: none; }
}

/* ── Footer ─────────────────────────────────────── */
/* Same column as `main` (max-width + the same left gutter above 810px) —
   the footer is centered *within* that column, like a colophon centered on
   a page, not across the full viewport, which fell out of sync once the
   page itself stopped being centered. */
.site-footer {
  max-width: 810px;
  margin: 0 auto;
  text-align: center;
  padding: 2rem 1rem 3rem;
  color: var(--ink-soft);
  /* Hold the footer at the bottom of short pages. Nine pages are shorter than
     a real viewport (all six asks at 487-661px, par-cisel and one gallery at
     ~1060px, plus the 404), and without this the footer sat mid-screen above a
     screenful of empty paper. `top: 100svh` works against `body`'s existing
     `min-height: 100svh`: the footer cannot rise above one viewport from the
     top, so on a short page it drops to the bottom, and on a long one sticky
     has no free space to act in and it stays exactly where normal flow puts
     it (verified at 0 differing pixels on the homepage and a diary page).

     Deliberately not the usual `body { display: flex; flex-direction: column }`
     with `margin-top: auto`: making body a flex container turns the auto
     horizontal margins on `main`, `.page-masthead` and `.site-footer` into
     free-space absorbers instead of stretch, collapsing every column to
     fit-content (measured: 143,003 differing pixels, entry rules shortened,
     chop seals slid left, nav dates wrapped). Adding `width: 100%` to all
     three fixes that but still perturbs layout rounding, and costs five
     declarations and a global layout-mode change to undo a trap it created. */
  position: sticky;
  top: 100vh;
  top: 100svh;   /* see body: vh is the toolbar-hidden height on iOS */
}
/* Below 1200px the plate is printed after the colophon, so the footer is no
   longer the last element and sticky would slide it down over the drawing.
   It is also not needed there: the plate guarantees the page exceeds one
   viewport, which is the only thing sticky was solving. This has to sit
   after the block above, not with the other narrow-viewport rules: same
   specificity, so source order decides. */
@media (max-width: 1199px) {
  .site-footer { position: static; }
}
@media (min-width: 810px) {
  .site-footer { margin: 0 auto 0 var(--column-left); }
}
/* Shared by the two places this sentence appears: the deck under the title
   lockup on the homepage, and the footer of every other page. Named for the
   site rather than the footer because half its uses are not in one.
   One margin-bottom for both. It used to be .75rem here and 1.25rem in the
   footer, while .pc-opening-subtitle declared calc(var(--gap) * 2) for the
   deck and silently lost the cascade to this rule (same specificity, later in
   source), so the deck rendered 12px where it claimed 28px. Nothing depended
   on the difference: below the deck sit .feed's 14px padding and
   .chapter-opener's 70px margin, which cannot collapse through that padding,
   so the deck's own margin is a small part of a 96px gap. */
.site-tagline {
  font-family: var(--font-prose);
  font-style: italic;
  font-size: .82rem;
  color: var(--ink-soft);
  line-height: 1.5;
}
/* Sibling-site pointer: back matter, printed only where the trip ends (the
   foot of the homepage ledger and the last entry). Set exactly like
   .pc-opening-attribution at the top of the homepage, so the two ends of the
   book share one note-under-the-text voice.

   The mono has two registers here. .68rem is the *label* one, always tracked
   .06em or uppercase: .ledger-date, .ledger-plate-caption,
   .ledger-video-caption, .entry-nav-kicker. .72rem is the *sentence* one:
   .pc-opening-attribution and .ledger-ask-a. This line is a sentence with a
   verb, so it belongs in the second. line-height 1.5 so its wrap below
   roughly 470px leads like every other footer line, not at `normal`. */
.site-footer-colophon {
  font-family: var(--font-doc);
  font-size: .72rem;
  letter-spacing: .04em;
  line-height: 1.5;
  color: var(--ink-soft);
}
.site-footer-colophon a { color: var(--cinnabar); }
.site-footer-home {
  font-family: var(--font-cn-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color var(--transition-fast);
  display: inline-block;
  /* The glyph leads the footer and the tagline or colophon follows it, so
     this is the footer's only spacing rule: the text line is last and the
     footer's own bottom padding carries it. Kept as a margin rather than a
     flex gap because flex would stretch the glyph to the full column width
     and take its hover and hit area with it. */
  margin-bottom: 1.25rem;
  position: relative;   /* anchors the ::after gloss; no offsets, so nothing moves */
}
.site-footer-home:hover { color: var(--cinnabar); }
/* Sighted-desktop gloss for a glyph a Czech reader cannot read. It reads the
   aria-label rather than a second data- copy, so there is one string per glyph
   and no chance of the two drifting apart; the accessible name comes from
   aria-label ahead of generated content, so this is not announced and no ARIA
   is added. Absolutely positioned up into the footer's own 2rem top padding,
   which is empty paper on every page, so it adds no height: the footer is the
   last thing on the page and is sticky on the nine short ones, where extra
   height would reintroduce the overscroll svh just fixed. pointer-events:none
   keeps the link's hit area exactly its own box.
   Touch devices get nothing from this, which is why aria-label carries the
   meaning and this is only a gloss. */
.site-footer-home::after {
  content: attr(aria-label);
  position: absolute;
  left: 50%;
  bottom: calc(100% + .5rem);   /* clears the 4px focus ring by 4px */
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: var(--font-doc);
  font-size: .68rem;            /* label register, like .ledger-date */
  font-weight: 400;             /* the glyph is 700; its caption is not */
  letter-spacing: .06em;
  line-height: 1;
  color: var(--ink-soft);       /* stays soft while the glyph turns cinnabar */
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast);
}
.site-footer-home:hover::after,
.site-footer-home:focus-visible::after { opacity: 1; }

/* ── Focus ring ─────────────────────────────────── */
/* The site's default link, stated rather than inherited from the browser.
   Every structural link context (.ledger-row, .pc-opening, .entry-nav-link,
   .site-footer-home, .page-masthead a) already declares its own color and
   text-decoration: none, so this overrides nothing that exists. It exists to
   catch anything new, which would otherwise fall through to UA blue, and to
   own the underline: prose links were previously underlined by the UA
   stylesheet at thickness/offset auto, which is browser-determined. .15em was
   chosen against Georgia's descenders at 4x zoom; auto sits tight on the
   baseline and .2em reads detached. */
a {
  color: var(--cinnabar);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .15em;
}
a:focus-visible {
  outline: 2px solid var(--cinnabar);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ── Reduced motion — genuine movement only. The hover color/background
   fades above (ledger rows, captions, nav links, footer/masthead links)
   stay unconditional on purpose — they're feedback, not motion,
   and are confirmed correct as-is. ── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
