/* ---- from build/book.src.html ---- */
/* ==========================================================================
   Book detail page, /books/<slug>/

   Section order is the layering rule from CLAUDE.md, and it resolves to one
   principle: short and persuasive before long and reference, so a reader can
   stop where their need is met and never wades through someone else's answer.

     head, description, topics, pull quote, excerpts, endorsements,
     contents, contributors, publisher's note, author, more by this author

   The lay reader leaves after the description. The buyer reads the
   endorsements. The academic scans the contents. Only the last two sections are
   long, and the contributor list is collapsed, so the page reads short until
   somebody asks it to read long.
   ========================================================================== */

/* ---- breadcrumb ---- */
.crumb{padding:22px 0 0}
.crumb ol{display:flex; flex-wrap:wrap; gap:8px; list-style:none; margin:0; padding:0;
  font-family:var(--display); font-size:13px; letter-spacing:.06em; color:var(--muted)}
.crumb a{color:var(--link); text-decoration:none; border-bottom:1px solid var(--rule)}
.crumb a:hover{border-bottom-color:var(--brand)}
.crumb li+li::before{content:"/"; margin-right:8px; color:var(--rule)}
.crumb [aria-current]{color:var(--text-2)}

/* ---- head: cover beside the identifying facts ---- */
.book-head{display:grid; grid-template-columns:300px minmax(0,1fr);
  gap:clamp(26px,5vw,60px); align-items:start; padding:clamp(26px,4vw,44px) 0 clamp(34px,5vw,56px)}
.book-head .cover img{box-shadow:0 2px 6px rgba(28,26,23,.10), 0 14px 34px rgba(28,26,23,.13)}
.book-head h1{font-family:var(--book); font-weight:400; font-size:clamp(30px,4.4vw,48px);
  line-height:1.08; letter-spacing:-.012em; color:var(--heading); margin:0; text-wrap:balance}
.book-sub{font-family:var(--book); font-size:clamp(19px,2.2vw,24px); line-height:1.25;
  color:var(--text-2); margin:10px 0 0; font-style:italic; text-wrap:balance}
.book-by{font-family:var(--display); font-size:14px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:18px 0 0}
/* The standfirst is ours, one line, and it is the only sentence some readers will
   take from the page. Sized to be read first. */
.standfirst{font-size:clamp(21px,2.3vw,25px); line-height:1.45; color:var(--text);
  margin:20px 0 0; max-width:42ch}
.credits{list-style:none; margin:24px 0 0; padding:0; display:flex; flex-direction:column; gap:5px}
.credits li{font-family:var(--display); font-size:15px; color:var(--text-2)}
.book-head .cta-row{margin-top:28px}
.affiliate{font-family:var(--display); font-size:12.5px; line-height:1.5;
  color:var(--muted); margin:12px 0 0; max-width:44ch}
.ids{margin:24px 0 0; padding:16px 0 0; border-top:1px solid var(--rule);
  display:flex; flex-wrap:wrap; gap:6px 28px}
.ids div{font-family:var(--display); font-size:13px; color:var(--muted)}
.ids b{display:block; font-weight:500; font-size:11.5px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted); margin-bottom:2px}
.ids span{color:var(--text-2); font-variant-numeric:tabular-nums}

/* ---- catalogue index head ---- */
.page-head{padding:clamp(28px,4vw,48px) 0 clamp(24px,3vw,36px)}
.page-head h1{font-family:var(--book); font-weight:400; font-size:clamp(34px,5vw,54px);
  line-height:1.06; letter-spacing:-.014em; color:var(--heading); margin:0}
.page-head .standfirst{margin-top:14px; max-width:46ch}

/* ---- section furniture ---- */
.sec{padding:clamp(34px,5vw,60px) 0; border-top:1px solid var(--rule)}
.sec > .wrap > h2{font-family:var(--display); font-weight:500; font-size:12.5px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--muted); margin:0 0 22px}
.measure{max-width:68ch}

/* ---- description ---- */
.prose p{margin:0 0 1.05em; font-size:21px; line-height:1.62; color:var(--text)}
.prose p:last-child{margin-bottom:0}
/* A standalone question, set as its own line because in the source it is the hinge
   between the setup and the answer. Guideposts turns on one; so does the Pursuit
   publisher's note. */
.prose .turn{font-family:var(--book); font-size:clamp(22px,2.6vw,28px); line-height:1.3;
  color:var(--heading); margin:1.1em 0; max-width:30ch}
/* Lists inside a description were never styled, so they fell back to the inherited
   body size while the paragraphs around them ran at 21px, and took default list
   spacing with it. Matched to the paragraph, with the same hairline marker the
   topics list uses. */
.prose ul{margin:0 0 1.05em; padding:0; list-style:none}
.prose li{position:relative; padding-left:22px; font-size:21px; line-height:1.62;
  color:var(--text); margin-bottom:.45em}
.prose li::before{content:""; position:absolute; left:0; top:.72em; width:9px; height:1px;
  background:var(--brand)}

.topics{margin:26px 0 0; padding:0; list-style:none; display:grid; gap:10px;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.topics li{position:relative; padding-left:22px; color:var(--text-2); font-size:19.5px; line-height:1.5}
.topics li::before{content:""; position:absolute; left:0; top:.62em; width:9px; height:1px;
  background:var(--brand)}

/* ---- bibliographic notes ---- */
.bibnote{margin:28px 0 0; padding:16px 0 0; border-top:1px solid var(--rule);
  list-style:none; display:flex; flex-direction:column; gap:7px}
.bibnote li{font-family:var(--display); font-size:14.5px; line-height:1.5; color:var(--muted)}

/* ---- pull quote ---- */
/* No borders of its own. The section above and below already rule off with
   .sec{border-top}, so adding a pair here drew four hairlines around one quote. */
.pullq{margin:0; padding:clamp(4px,1vw,12px) 0}
/* Inline, following the closing quotation mark. Floated it would align to the top of
   a 38px line box and read as a superscript; as a block it sat at the 26ch boundary,
   stranded mid-page. Inline it takes the baseline and costs no vertical space. */
.pullq cite{font-family:var(--display); font-style:normal; font-size:12.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--muted);
  font-variant-numeric:tabular-nums; white-space:nowrap; margin-left:.6em}
.pullq p{font-family:var(--book); font-size:clamp(24px,3.4vw,38px); line-height:1.22;
  color:var(--heading); margin:0; max-width:26ch; text-wrap:balance}

/* ---- excerpts ---- */
.excerpts{display:flex; flex-direction:column; gap:clamp(26px,3.4vw,38px)}
.excerpt{margin:0; border-left:2px solid var(--brand); padding-left:clamp(18px,2.4vw,26px)}
/* Sentence case, not a label. Several of these are full sentences setting up the
   passage, and uppercase letterspaced type is unreadable across a line of prose. */
.excerpt .intro{font-family:var(--display); font-size:16.5px; letter-spacing:.01em;
  line-height:1.5; color:var(--text-2); margin:0 0 14px; max-width:58ch}
/* A gloss after the passage, not before it. Same face as the lead-in, but it needs
   air above rather than below, and it has to clear the floated cite or its first
   line sets in short beside the folio. */
.excerpt .intro.after{margin:16px 0 0; clear:both}
.excerpt p{font-size:20.5px; line-height:1.6; color:var(--text); margin:0 0 .85em; max-width:64ch}
.excerpt p:last-of-type{margin-bottom:0}
.excerpt ul{margin:0; padding:0; list-style:none; counter-reset:q}
.excerpt li{position:relative; counter-increment:q; padding-left:34px; font-size:20.5px;
  line-height:1.5; color:var(--text); margin-bottom:9px}
.excerpt li::before{content:counter(q); position:absolute; left:0; top:0;
  font-family:var(--display); font-size:13px; color:var(--brand);
  font-variant-numeric:tabular-nums}
/* Floated so it finishes the closing line where there is room, and drops to the
   right margin below where there is not.
   line-height is the fix for the folio sitting high, 2026-08-23. A float aligns to
   the TOP of the line box it sits in, so with the inherited 1.6 the folio's own box
   was 12.5 x 1.6 = 20px inside a 20.5 x 1.6 = 32.8px line, and its baseline landed
   roughly 8px above the prose baseline. 36px puts the two baselines together:
   half-leading of (36 - 12.5) / 2 = 11.75 plus the ascender matches 6.15 plus the
   ascender on the 20.5px text. Set in pixels because it is a match to one specific
   line, not a ratio that should scale with the folio's own size. */
.excerpt cite{float:right; margin:0 0 0 1.6em; font-family:var(--display); font-style:normal;
  font-size:12.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted);
  font-variant-numeric:tabular-nums; line-height:36px}
.excerpt::after{content:""; display:block; clear:both}

/* ---- endorsements ---- */
.quotes{display:grid; gap:clamp(26px,3.4vw,40px); grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
.quotes blockquote{margin:0}
.quotes p{font-size:20px; line-height:1.52; color:var(--text); margin:0 0 12px; max-width:52ch}
.quotes cite{font-style:normal; display:block; font-family:var(--display); font-size:12.5px;
  letter-spacing:.05em; color:var(--muted); line-height:1.6}
.quotes cite b, .press-list cite b{display:block; color:var(--text); font-weight:500; font-size:14.5px;
  letter-spacing:.03em; text-transform:none}
/* An endorsement of the author rather than of this book carries a marker, because the
   distinction is real: one can run on any of their titles, the other cannot. */
/* block, not inline-block: as an inline-block it ran straight onto the end of the
   affiliation with no separation, giving "for MeaningOn the author". */
.quotes .of-author{display:block; margin-top:6px; font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--brand)}
.press{margin:clamp(30px,4vw,44px) 0 0; padding-top:clamp(26px,3vw,34px); border-top:1px solid var(--rule)}
.press h3{font-family:var(--display); font-weight:500; font-size:12.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); margin:0 0 20px}
.press-list{display:grid; gap:20px clamp(24px,3vw,36px);
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.press-list blockquote{margin:0}
.press-list p{font-size:18.5px; line-height:1.5; color:var(--text-2); margin:0 0 7px; font-style:italic}
.press-list cite{font-style:normal; font-family:var(--display); font-size:12.5px;
  letter-spacing:.06em; color:var(--muted)}

/* ---- contents ---- */
/* For an edited collection this is the description: article titles with their authors
   tell a specialist more than any prose summary. It sits late because it is long, not
   because it is secondary. */
.toc{margin:0; max-width:74ch}
.toc-part{font-family:var(--display); font-size:12px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--brand); margin:26px 0 12px; font-weight:500}
.toc-part:first-child{margin-top:0}
.toc ol{list-style:none; margin:0; padding:0}
.toc li{display:grid; grid-template-columns:2.4em minmax(0,1fr) auto; gap:4px 10px;
  padding:9px 0; border-top:1px solid var(--rule)}
.toc li:first-child{border-top:0}
.toc .n{font-family:var(--display); font-size:13px; color:var(--muted);
  font-variant-numeric:tabular-nums; padding-top:3px}
.toc .t{font-size:19.5px; line-height:1.38; color:var(--text)}
.toc .pg{font-family:var(--display); font-size:13px; color:var(--muted);
  font-variant-numeric:tabular-nums; text-align:right; padding-top:3px}
.toc .req{grid-column:2; justify-self:start; margin-top:7px}
.toc .req a{display:inline-block; font-family:var(--display); font-size:12.5px; letter-spacing:.05em;
  color:var(--brand); text-decoration:none; border:1px solid var(--brand); border-radius:3px;
  padding:4px 11px; line-height:1.3}
.toc .req a:hover{background:var(--brand); color:var(--on-brand)}
.toc .a{grid-column:2; font-family:var(--display); font-size:14px; color:var(--text-2)}
.toc .front{font-family:var(--display); font-size:13.5px; color:var(--muted); margin:0 0 22px}

/* ---- people, collapsed by default ---- */
/* <details> rather than script: keyboard accessible for free, and the whole list stays
   in the document for search engines while the page still reads short. */
.people{border-top:1px solid var(--rule); margin-top:8px}
.people:last-of-type{border-bottom:1px solid var(--rule)}
.people summary{display:flex; align-items:center; gap:10px; cursor:pointer; padding:18px 0;
  font-family:var(--display); font-size:15px; color:var(--link); list-style:none}
.people summary::-webkit-details-marker{display:none}
.people summary::before{content:""; flex:none; width:9px; height:9px; border-right:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor; transform:rotate(-45deg); transition:transform .15s ease}
.people[open] summary::before{transform:rotate(45deg)}
.people summary:hover{color:var(--brand)}
.people summary:focus-visible{outline:2px solid var(--brand); outline-offset:3px}
.people summary .count{font-size:12.5px; letter-spacing:.09em; text-transform:uppercase; color:var(--muted)}
.people-list{margin:0 0 26px; padding:0; list-style:none; display:flex; flex-direction:column;
  gap:18px; max-width:70ch}
.people-list li{font-size:19px; line-height:1.55; color:var(--text-2)}
.people-list b{color:var(--text); font-weight:600}

/* ---- publisher's note ---- */
/* Dateline before the first line as well as the signature after the last: it was
   written in 2013 and must not read as current. */
.pubnote{background:var(--surface); padding:clamp(28px,4vw,44px); max-width:78ch}
.pubnote .dateline{font-family:var(--display); font-size:12.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); margin:0 0 20px}
.pubnote h3{font-family:var(--book); font-weight:400; font-size:clamp(23px,2.8vw,30px);
  color:var(--heading); margin:0 0 6px}
.pubnote p{font-size:20px; line-height:1.6; color:var(--text); margin:0 0 1.05em; max-width:64ch}
.pubnote ul{margin:0 0 1.05em; padding:0; list-style:none}
.pubnote li{position:relative; padding-left:22px; font-size:19.5px; line-height:1.55;
  color:var(--text-2); margin-bottom:7px}
.pubnote li::before{content:""; position:absolute; left:0; top:.66em; width:9px; height:1px;
  background:var(--brand)}
.pubnote .turn{font-family:var(--book); font-size:clamp(21px,2.4vw,26px); color:var(--heading);
  margin:1.05em 0; line-height:1.3}
.pubnote .sig{font-family:var(--display); font-size:14px; color:var(--text-2); margin:24px 0 0;
  padding-top:16px; border-top:1px solid var(--rule)}
.pubnote .sig span{display:block; color:var(--muted); font-size:13px; margin-top:3px}

/* ---- organisation note ---- */
.orgnote{max-width:68ch}
.orgnote h3{font-family:var(--book); font-weight:400; font-size:clamp(21px,2.4vw,26px);
  color:var(--heading); margin:0 0 10px}
.orgnote p{font-size:19.5px; line-height:1.6; color:var(--text-2); margin:0}

/* ---- author ---- */
.author-bio{max-width:68ch}
.author-bio h2{font-family:var(--book); font-weight:400; font-size:clamp(23px,2.8vw,30px);
  color:var(--heading); margin:0 0 14px; text-transform:none; letter-spacing:normal}
.author-bio p{font-size:20px; line-height:1.6; color:var(--text-2); margin:0 0 1em}
.author-bio p:last-child{margin-bottom:0}

/* ---- more by this author ---- */
/* Renders through the shared .grid and .item, so these covers cannot end up a
   different size from the same covers on the homepage or on /books/. */
.more .grid{grid-template-columns:repeat(auto-fit,minmax(150px,190px))}

@media (max-width:820px){
  .book-head{grid-template-columns:1fr; gap:30px}
  .book-head .cover{max-width:230px}
  .toc li{grid-template-columns:2em minmax(0,1fr)}
}

/* ---- from build/home.src.html ---- */
/* ---- hero ---- */
.hero{padding:clamp(44px,7vw,84px) 0 clamp(48px,7vw,88px)}
.hero-in{display:grid; grid-template-columns:1.15fr .85fr; gap:clamp(28px,6vw,72px); align-items:center}
.hero h1{font-family:var(--book); font-weight:400; font-size:clamp(34px,5vw,60px); line-height:1.07;
  letter-spacing:-0.012em; color:var(--heading); margin:0 0 22px; text-wrap:balance}
/* Three lines, landing the block on "to purpose", which is also the name. Spans
   rather than <br> so the middle line can be positioned independently. Inline below
   760px, where forced breaks would orphan words, so the headline flows normally. */
.hero h1 span{display:inline}
@media (min-width:760px){
  .hero h1 span{display:block}
  .hero h1{text-wrap:initial}
}
.hero p{font-size:21px; line-height:1.55; color:var(--text-2); max-width:44ch; margin:0 0 30px}
/* The hero quote. Set roman so the italics on "why" and "how" carry the emphasis
   Frankl put there; italicising the whole line would flatten it. */
.hero .lede{font-family:var(--book); font-size:clamp(20px,2.3vw,25px); line-height:1.4;
  color:var(--text); max-width:34ch; margin:0 0 10px}
.hero .lede i{font-style:italic}
/* Break after "to live for", so the two halves of Frankl's sentence sit on their
   own lines, and offset them so they stagger rather than stacking on one edge,
   the same staircase idea as the headline.

   The offset is an em, not literal spaces. A space is a font metric: its width
   moves with the face, with the fallback if the face fails to load, and with the
   engine, so the same four spaces open differently on a phone than on a desktop.
   An em is a fixed fraction of the type size, which is already fluid via clamp(),
   so the stagger holds its proportion at every width. 2.25em is deliberately
   wider than an em dash, which is 1em by definition and too slight to read as
   deliberate rather than as an accident of wrapping.

   Two rules because the hero flips alignment at 900px, and each is inert in the
   other regime, so the same shape survives both: above 900px the copy is flush
   right, line two sits on the margin and the padding pulls line one in from it;
   below 900px the copy is flush left, line one sits on the margin and the padding
   pushes line two in. Either way line two is the outer line.

   The break holds down to phone widths. It was previously suppressed below 760px
   on the theory that a forced break there would orphan words, but the quote is
   set to a 34ch measure, and at 390px both halves still fit their line with room
   over. The offset drops to 1.25em below 700px so the indent stays a gesture
   rather than eating the measure. */
.hero .lede span{display:block}
.hero .lede span:first-child{padding-right:1.25em}
.hero .lede span:last-child{padding-left:1.25em}
@media (min-width:700px){
  .hero .lede span:first-child{padding-right:2.25em}
  .hero .lede span:last-child{padding-left:2.25em}
}
.hero .lede-src{font-family:var(--display); font-size:13px; letter-spacing:.11em;
  text-transform:uppercase; color:var(--muted); margin:0 0 30px}
.hero-art{justify-self:center; width:100%; max-width:330px}
.hero-art .cover img{box-shadow:0 2px 6px rgba(28,26,23,.10), 0 14px 34px rgba(28,26,23,.13)}

/* Right alignment lives AFTER the .hero rules on purpose. `.hero-copy p` and
   `.hero p` have identical specificity, so whichever comes last wins; when this
   block sat earlier, `.hero p{margin:0 0 30px}` reset margin-left and the subline's
   box stayed pinned left while its text aligned right, landing short of the
   headline's edge. Flush right is the whole point, so it has to come last. */
@media (min-width:900px){
  .hero-copy{text-align:right}
  .hero-copy p{margin-left:auto; margin-right:0}
  .hero-copy .cta-row{justify-content:flex-end}
  /* The same trap one level down, and it caught the quote. `.hero .lede` and
     `.hero .lede-src` set the `margin` shorthand at specificity (0,2,0), which
     outranks `.hero-copy p` at (0,1,1), so the shorthand's implied margin-left:0
     won and both boxes stayed pinned to the left edge. Their text aligned right
     inside a 34ch box, landing 164px short of the headline's margin, which is why
     the second line of the quote never reached it. Matching the specificity here
     pushes the boxes right; source order settles the tie. */
  .hero .lede, .hero .lede-src{margin-left:auto; margin-right:0}
}
/* The staircase. Right alignment alone does not make one: "is the path" and
   "to purpose" are nearly the same width, so their left edges land together and the
   block reads as a slab. Centring the middle line fixes it without a magic number:
   line one nearly fills the column and line three occupies its right half, so a
   centred middle line lands its left edge midway between the two. Self-correcting if
   the type size or the wording changes. Previous approach was padding-right:1.8em,
   which worked but had to be re-tuned by eye. */
@media (min-width:900px){
  .hero h1 .mid{text-align:center}
}

/* ---- motion --------------------------------------------------------------
   Two kinds, and the difference is deliberate.

   The hero animates on load, on a clock. Safe everywhere: if the animation does
   not run, including under reduce-motion where the global rule kills it, the
   element renders in its natural state, which is the finished one.

   Everything below the fold reveals on scroll, driven by view() with no script,
   because inline JS does not execute in every embedding context. The catch is
   recorded in CLAUDE.md: Firefox parses animation-timeline and reports support
   without implementing it, so an @supports guard cannot be trusted. That is why
   the reveal moves the element and never fades it. Where the timeline resolves,
   content rises into place; where it does not, the worst case is content sitting
   16px low, which nobody will ever notice. A fade would have left the page blank
   in that browser, which is exactly the failure the earlier parallax attempts
   hit. */
@keyframes enter{from{opacity:0; transform:translateY(16px)} to{opacity:1; transform:none}}
@keyframes lift{from{transform:translateY(16px)} to{transform:none}}
.hero-copy h1,.hero-copy .lede,.hero-copy .lede-src,.hero-copy .cta-row,.hero-art{
  animation:enter .75s cubic-bezier(.22,.61,.36,1) both}
.hero-copy .lede{animation-delay:.10s}
.hero-copy .lede-src{animation-delay:.16s}
.hero-copy .cta-row{animation-delay:.22s}
.hero-art{animation-delay:.14s; animation-duration:.9s}
@supports (animation-timeline:view()){
  .reveal{animation:lift .01s linear both; animation-timeline:view();
    animation-range:entry 4% cover 22%}
  /* Each tile carries its own timeline, so the mosaic staggers itself as it
     scrolls in without a single hand-set delay. */
  .mosaic .tile{animation:lift .01s linear both; animation-timeline:view();
    animation-range:entry 0% entry 90%}
}
/* Pointer motion, which is the half that works in every browser and needs no
   timeline at all. */
.btn{transition:background .18s ease, transform .18s ease}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(1px)}
.go{display:inline-block; transition:transform .18s ease}
.pick:hover .go,.pick:focus-visible .go{transform:translateX(5px)}

/* ---- the catalogue contact sheet ---------------------------------------- */
/* Fourteen covers, one JPEG. Each tile is a window onto it: --bs sizes the sheet
   against that cover and --bp slides the right one into view, both as
   percentages, so the whole mosaic scales fluidly and nothing is pinned to a
   fixed pixel size. Built by build/make_sheet.py, which also writes the
   rectangles. Declared once here and shared by both bands, so the Gerowise
   titles keep their own heading and imprint line at no extra cost.

   Two rules from CLAUDE.md survive the merge. The box is still never painted:
   the sheet's gutters are cropped out, so a cover with a white ground shows its
   own edge and no band. And the hairline is still on the image rather than baked
   into the sheet, which keeps it 1px crisp at any size. */
:root{--sheet:url("../img/covers-sheet.jpg")}
/* Narrower than the wrap, because the point of the sheet is small covers. At the
   full 1180 the cells land near 250px, which is a catalogue; here they land near
   176px, which is a shelf you scan. The section head sits inside the same column
   so the band reads as one block rather than a wide heading over a short grid. */
.cat{max-width:800px}
.mosaic{display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(18px,2.4vw,26px) clamp(14px,1.9vw,20px)}
.tile{display:block; text-decoration:none; color:inherit}
/* The shelf holds the 2:3 cell and the common bottom line. Mixed trims sit on it
   at their true proportions; nothing is cropped to tidy the row. */
.tile .shelf{position:relative; aspect-ratio:2/3; display:flex; align-items:flex-end;
  justify-content:center}
.tile .art{width:var(--fw); aspect-ratio:var(--ar); box-sizing:content-box;
  background-image:var(--sheet); background-repeat:no-repeat;
  background-size:var(--bs); background-position:var(--bp);
  border:1px solid var(--rule); box-shadow:var(--cover-shadow);
  transition:box-shadow .18s ease, transform .18s ease}
.tile:hover .art,.tile:focus-visible .art{box-shadow:var(--cover-shadow-hover);
  transform:translateY(-3px)}
.tile:focus-visible{outline:2px solid var(--brand); outline-offset:4px}
.tile .art.empty{width:100%; aspect-ratio:2/3; background:var(--surface); display:flex;
  align-items:center; justify-content:center; text-align:center; padding:14px;
  font-family:var(--display); font-size:11px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted)}
/* The caption is the title, which is not printed under the cover any more: that
   is what buys the smaller grid. It is real text in the markup, so it is the
   link's accessible name whether or not anyone can hover, and it is revealed by
   keyboard focus as well as by pointer. Width is the cover's, not the cell's, so
   it lands on the artwork rather than in the gap beside it. */
.tile .cap{position:absolute; bottom:0; left:50%; transform:translateX(-50%);
  width:var(--fw); box-sizing:border-box; padding:9px 10px 10px;
  background:rgba(20,18,16,.90); opacity:0; pointer-events:none;
  transition:opacity .16s ease}
.tile:hover .cap,.tile:focus-visible .cap{opacity:1}
.tile .cap b{display:block; font-family:var(--book); font-weight:400; font-size:13.5px;
  line-height:1.22; color:#FAF8F4; text-wrap:balance}
.tile .cap i{display:block; font-style:normal; font-family:var(--display); font-size:10.5px;
  letter-spacing:.09em; text-transform:uppercase; color:#C6C1B8; margin-top:5px}
/* The way out of the mosaic. Covers alone do not tell a reader that titles,
   descriptions and excerpts exist one click away, so the button says it. */
.see-all{display:flex; flex-wrap:wrap; align-items:center; gap:14px 20px;
  margin:clamp(26px,3.4vw,38px) 0 0}
.see-all span{font-size:16px; color:var(--muted); max-width:40ch}
/* The Gerowise pair, under the catalogue rather than in a band of its own. It is
   a credit, not a second catalogue, so it gets a rule and small type instead of a
   heading the same size as the one above. The covers still render in the same
   .mosaic definition, so the two groups cannot drift to different sizes, and the
   line says who published them. */
.also{margin:clamp(30px,4vw,46px) 0 0; padding:clamp(24px,3vw,32px) 0 0; border-top:1px solid var(--rule)}
.also-head{font-family:var(--display); font-size:13px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0 0 8px}
.also-line{font-size:16.5px; color:var(--text-2); max-width:52ch; margin:0 0 22px}
.also .mosaic{grid-template-columns:repeat(4,minmax(0,1fr))}

/* ---- the articles door ---- */
/* Two entries, not a list: the Articles page is the list. Cards rather than
   citations, because a citation is what a reader wants once they have decided,
   and this is the deciding. */
/* Three cards, so the column count is derived rather than declared: auto-fit fits
   as many 250px tracks as the wrap allows and stretches them to fill, which lands
   three across on a desktop, two on a tablet and one on a phone, with no
   breakpoint to keep in step with the number of picks. A fourth pick would strand
   itself on its own row here, so if one is ever added this becomes two by two. */
.picks{display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:clamp(20px,3vw,32px)}
.pick{display:block; text-decoration:none; background:var(--surface); border:1px solid var(--rule);
  padding:clamp(22px,2.6vw,30px); transition:border-color .18s ease, transform .18s ease,
  box-shadow .18s ease}
.pick:hover{border-color:var(--brand); transform:translateY(-3px); box-shadow:var(--cover-shadow)}
.pick-src{display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  font-family:var(--display); font-size:12px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0 0 12px}
.pick-src .yr{flex:none; font-variant-numeric:tabular-nums}
.pick h3{font-family:var(--book); font-weight:400; font-size:clamp(21px,2.3vw,25px); line-height:1.2;
  color:var(--heading); margin:0 0 6px; text-wrap:balance}
.pick-sub{font-family:var(--book); font-size:18px; line-height:1.3; color:var(--text-2); margin:0 0 14px}
.pick-note{font-size:16px; color:var(--muted); margin:0 0 18px; max-width:34ch}
.pick .go{font-family:var(--display); font-size:13.5px; letter-spacing:.06em; color:var(--link)}
.pick .go::after{content:" \2192"}

@media (max-width:620px){
  .mosaic{grid-template-columns:repeat(3,minmax(0,1fr))}
  .also .mosaic{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* ---- vista: the one parallax band, between the catalogue and the publisher ---- */
/* Pure CSS. background-attachment:fixed sizes the image to the viewport rather than
   the band, so the photograph holds still while the band travels over it. No script,
   which matters because inline JS does not execute in every embedding context.
   iOS ignores fixed attachment and renders it as a normal background: no parallax,
   but nothing breaks. */
.vista{position:relative; overflow:hidden; min-height:clamp(300px,48vh,470px);
  display:flex; align-items:center; background-color:var(--text);
  background-image:url("../img/w720/vista.jpg");
  background-size:cover; background-position:center 42%;
  background-repeat:no-repeat; background-attachment:fixed}
/* Scrim tuned to the worst case, not the average. The text zone's p99 luminance is
   227 after the 2026-08-23 recrop, the far end of the arcade; it was 244 before,
   because the bottom 15% was lit floor. Composited against the gradient the quote
   holds a median 12.1:1 and a p1 of 5.0:1, the citation 9.4:1 and 3.4:1. That p1 on
   the citation is under AA and is the one number here worth revisiting: it is small
   uppercase type over the brightest pixels in the arcade. Falls to .12 on the right,
   where no text sits, so the colonnade reads as a photograph. */
.vista-scrim{position:absolute; inset:0;
  background:linear-gradient(90deg, rgba(20,18,16,.66) 0%, rgba(20,18,16,.50) 42%, rgba(20,18,16,.12) 100%)}
/* width:100% because the band is a flex container and this is its only item:
   without it the wrap shrinks to the quote's 24ch and the auto margins centre
   it, which lands the text over the middle of the photograph. The scrim is
   graded dark on the left and nearly clear on the right precisely because the
   text sits left, so centring it also walks the quote off its own contrast. */
.vista-in{position:relative; width:100%; padding:clamp(38px,6vw,64px) 0}
.vista blockquote{margin:0; max-width:24ch}
.vista blockquote p{font-family:var(--book); font-size:clamp(25px,3.4vw,40px); line-height:1.22;
  color:#FAF8F4; margin:0 0 18px; text-wrap:balance}
.vista cite{font-family:var(--display); font-style:normal; font-size:14px; letter-spacing:.1em;
  text-transform:uppercase; color:#EDE8E0; display:block; line-height:1.6}
.vista cite b{display:block; color:#FAF8F4; font-weight:500; letter-spacing:.09em}
@media (prefers-reduced-motion:reduce){
  .vista{background-attachment:scroll}
}

/* ---- endorsements ------------------------------------------------------- */
/* Asymmetric on purpose: one lead quote against two supporting ones, so this
   section does not repeat the three-column rhythm of the writing section below.
   Three different people on three different books, which shows the catalogue's
   range better than three quotes about one title would. */
.endorse{display:grid; grid-template-columns:1.25fr 1fr; gap:clamp(30px,5vw,64px); align-items:start}
.endorse blockquote{margin:0}
.endorse p{font-family:var(--book); color:var(--text); margin:0 0 14px}
.endorse-lead p{font-size:clamp(21px,2.5vw,27px); line-height:1.34; max-width:30ch}
.endorse-side{display:flex; flex-direction:column; gap:clamp(24px,3vw,34px)}
.endorse-side p{font-size:18px; line-height:1.5; color:var(--text-2); max-width:44ch}
.endorse cite{font-style:normal; display:block; font-family:var(--display); font-size:12.5px;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted); line-height:1.65}
.endorse cite b{display:block; color:var(--text); font-weight:500; font-size:14px; letter-spacing:.07em}
/* Not link-coloured, because it is not a link. It becomes one once the book pages
   exist, and then the colour is earned rather than borrowed. */
.endorse cite .on{display:block; color:var(--text-2); text-transform:none; letter-spacing:.01em;
  font-family:var(--book); font-size:15.5px; font-style:italic; margin-top:3px}
.endorse-side blockquote + blockquote{border-top:1px solid var(--rule); padding-top:clamp(24px,3vw,34px)}
@media (max-width:820px){ .endorse{grid-template-columns:1fr} }

/* ---- writing ---- */
.posts{display:grid; grid-template-columns:repeat(auto-fit,minmax(270px,1fr)); gap:clamp(26px,4vw,44px)}
.post h3{font-family:var(--book); font-weight:400; font-size:23px; line-height:1.22; color:var(--heading); margin:0 0 9px;
  text-wrap:balance}
.post h3 a{color:inherit; text-decoration:none}
.post h3 a:hover{border-bottom:1px solid var(--brand)}
.post p{font-size:18px; color:var(--text-2); margin:0}
.post .when{font-family:var(--display); font-size:12.5px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0 0 9px; font-variant-numeric:tabular-nums}
.correction{border-left:2px solid var(--brand); padding:4px 0 4px 16px; margin:16px 0 0}
.correction p{font-family:var(--display); font-size:14.5px; line-height:1.5; color:var(--link); margin:0}

@media (max-width:900px){
  .hero-in{grid-template-columns:1fr; gap:38px}
  .hero-art{max-width:250px; justify-self:start}
  .pub{grid-template-columns:1fr}
  .portrait{max-width:200px}
}
