/* Silver Mountain Press generated bundle. Do not edit.
 * Source: src/styles/, order declared in src/styles/manifest.json.
 * Modules: 16
 */
/* ===== base/tokens.css ===== */
/* Silver Mountain Press - draft whiteboard
 *
 * DESIGN NOTE FOR WHOEVER PICKS THIS UP:
 * Every colour and typeface is a custom property in :root. The client's real palette,
 * typography and logo could not be extracted (handoff 6.8) and must be pulled by hand.
 * When they arrive, swap the tokens - do not touch the rules underneath.
 *
 * TYPOGRAPHIC SOURCE: the interior typesetting of North of Nelson Vol. III - old-style
 * book serif, justified with hyphenation at a ~40 character measure, drop cap with the
 * opening quotation mark hung outside the text block. The .excerpt component below is a
 * direct translation of that to the web. It is the one place this design spends boldness.
 *
 * MOBILE FIRST. Base rules are the phone. min-width queries add, never subtract.
 * Whitespace is earned: the scale is tight by default and opens up only where a real
 * structural break needs marking.
 *
 * --draft is the draft apparatus colour, used NOWHERE else. Deleting that token and the
 * .draft-* rules removes every provisional marker from the site.
 */

:root {
  /* ---- SYSTEM LAYER -----------------------------------------------------
   * Shared across both of the author's properties. Neutrals, type scale and
   * spacing are what make silvermountainpress.com and writerinthewilderness.com
   * read as one world. Do not fork these per property. */

  --ink:    #16181b;
  /* Warm grey, not cool. A blue-leaning grey turns visibly green against linen paper,
     and the previous value also sat at 4.61:1 on --sink, too close to the 4.5 line. */
  --stone:  #5e5c58;
  /* Paper is an antique linen wash rather than white. Warm, roughly 7% off, so it
     reads as book stock under text rather than as a screen. --sink and --rule carry
     the same warmth or the greys go green against it. One line to tune. */
  --rule:   #ded7c9;
  --paper:  #f7f2e8;
  --sink:   #efe8da;
  /* Kept, and renamed in intent rather than deleted: nothing sets white on a trim colour
     today, but the moment anything does (a print band, a reversed label) it must clear 4.5:1
     against both --draft and --spruce, and tools/contrast.js is where that is proved. */
  --banner-text: #ffffff;
  /* Draft apparatus ONLY. This is the Volume III "burned barn red" direction, parked
   * here until the book is printed - so the colour is already established in the system
   * when Volume III arrives and claims it. When that happens the draft apparatus is
   * being deleted anyway, so nothing has to move.
   *
   * It is NOT distinguished from the brand by hue any more, so it must stay
   * distinguished by structure: draft blocks always carry a left border, a tinted
   * ground and an uppercase label. Do not reduce a draft marker to coloured text. */
  /* WRITER IN THE WILDERNESS TRIM. Deliberately NOT --cover-ii.
   *
   * Volume II's jacket green (#6b9463) belongs to a book, and using it as a property colour
   * would say the wilderness site is somehow Volume II's. This is a darker conifer green,
   * chosen so the two properties can be told apart at a glance in a stack of printed paper:
   * 6.50:1 on paper against the rust's 5.31:1, so the two trims carry similar visual weight.
   * Clears 4.5:1, so it can take text if the wilderness side ever wants its own link colour. */
  --spruce: #35603f;

  /* Site-band colour for Writer in the Wilderness (client request, 2026-09-22): a header/
   * footer colour block, uniform in structure with Silver Mountain Press's but a different,
   * crisp colour - same reasoning as --spruce above (not Volume II's green, so the wilderness
   * site is never mistaken for being about one book), pushed to the same "crisp"/well-
   * saturated quality as SMP's --cover-iii (S=64%) rather than --spruce's own S=29%. Same
   * hue as --spruce (134°), not a new one, so the boosted colour still reads as the same
   * brand, just louder. Dark enough (L=20%) that --paper clears 4.5:1 here for EVERY text
   * size, not just large/bold - unlike --cover-ii, this needs no display-only carve-out.
   * Verify with node tools/contrast.js. */
  --witw-crisp: #0a5c1d;

  --draft:  #af3e2b;

  /* ---- BRAND LAYER ------------------------------------------------------
   * What differs per property. Swap these and the same system renders as the
   * other site. See docs/architecture.md. */

  /* PROVENANCE: this began as the Volume III cover direction - "burned barn red",
   * intended to pair with a second colour, "birch buds". Volume III is not printed, so
   * the red is not attributed to it and serves as the house accent instead.
   *
   * Named --iron because rust is iron oxide and the Upper Peninsula is iron country.
   * That is why it is not called --barn: the name should survive the colour being
   * retuned, and it earns its place against the subject rather than the swatch.
   *
   * The companion "birch buds" tone has not been supplied. When it arrives it is the
   * strongest candidate to replace --sink, which is a neutral placeholder doing a job
   * that a warm pale green-gold would do far better. */
  --iron:   #445069;  /* house accent: links, status, labels. Vol I's slate. 7.7:1. */

  /* ---- COVER COLOURS ----------------------------------------------------
   * Taken from the printed covers themselves, which are authoritative over the
   * loose swatches - two earlier assignments were wrong because they trusted a
   * swatch over the artifact. Check the cover before changing these.
   *
   * The house cover system: a flat colour field, an elegant letterspaced serif
   * in caps, a framed black-and-white engraving, an italic subtitle.
   *
   * DISPLAY SIZES ONLY. --cover-ii is 3.3:1 on paper and does not clear 4.5:1.
   * The rule is uniform so there is no per-volume exception to remember - links
   * and small text always use --iron.
   * Verify with: node tools/contrast.js */

  --cover-i:   var(--iron);  /* Vol I - slate blue, same colour as the house accent */
  --cover-ii:  #6b9463;  /* Vol II - green */
  /* Vol III - set 2026-09-22, sampled from the client's own print promotional artwork
   * (a letter-size flyer for the paperback/audiobook release). Real jacket red, not a
   * guess: #ab2f25, close to but distinct from --draft's placeholder "burned barn red"
   * direction (#af3e2b) - --draft stays as-is; it is a draft-apparatus colour with its
   * own job, not this book's colour, even though they were always expected to converge.
   * See docs/decisions.md 2026-09-22. */
  --cover-iii: #ab2f25;

  /* Type - PROVISIONAL. Old-style book serifs, chosen to sit near the Vol. III interior. */
  --face-text: "Iowan Old Style", "Palatino", "Palatino Linotype", "Book Antiqua", Georgia, serif;
  /* Headings (H1 and H2 titles): the owner's type treatment is capital letters in a high-contrast Garamond-style serif, semibold,
     tightly leaded. No webfont ships (CSP allows none), so a Garamond installed on the visitor's device is used when present and
     everything else falls through to the body serif; the capitals, weight and leading carry the look either way. */
  --face-display: "Cormorant Garamond", "EB Garamond", Garamond, "Iowan Old Style", "Palatino", "Palatino Linotype", "Book Antiqua", Georgia, serif;
  --face-util: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --t-xs:   0.72rem;
  --t-sm:   0.82rem;
  --t-base: 1rem;
  --t-lg:   1.1rem;
  --t-xl:   1.28rem;
  --t-2xl:  1.5rem;    /* page titles - deliberately close to the masthead, see below */
  --t-3xl:  2.15rem;   /* hero only */

  --measure: 34rem;
  --frame: 66rem;

  --gap-xs: 0.35rem;
  --gap-sm: 0.7rem;
  --gap-md: 1.15rem;
  --gap-lg: 1.75rem;
  --gap-xl: 2.75rem;

  --pad: 1.15rem;
}

/* ===== base/reset.css ===== */
/* Reset, viewport scale, motion */
*, *::before, *::after { box-sizing: border-box; }

html {
  font-size: 18px;              /* phone first; opens up on larger viewports */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--face-text);
  font-size: var(--t-base);
  line-height: 1.48;
  font-synthesis-weight: none;
  overflow-wrap: break-word;
}
@media (min-width: 34rem) {
  html { font-size: 19px; }
  :root { --pad: 1.75rem; }
}

@media (min-width: 48rem) {
  html { font-size: 20px; }
  :root { --pad: 2.25rem; }
}

/* ===== base/typography.css ===== */
.page-title {
  font-family: var(--face-display);
  font-size: var(--t-2xl);
  font-weight: 600;
  text-transform: uppercase;      /* the owner's heading treatment: capitals, semibold, tight leading */
  line-height: 1.04;
  letter-spacing: 0.01em;
  margin: 0 0 var(--gap-sm);
  max-width: 30ch;
}

.section-title {
  font-family: var(--face-display);
  font-size: var(--t-xl);
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.08;
  letter-spacing: 0.01em;
  margin: var(--gap-lg) 0 var(--gap-xs);
}

/* First section heading on a page follows the lede directly - no double gap. */
.section-title:first-child { margin-top: 0; }

.body-link { color: var(--iron); text-decoration: underline; text-underline-offset: 0.15em; }
.lede { font-size: var(--t-lg); line-height: 1.42; }

/* A lede is a short opening at display scale. Anything longer than about two sentences
   is prose and must not carry it, or a paragraph eats the viewport. */
.lede { max-width: var(--measure); }



/* Applied to <p> where it is a kicker, and to <h2> where it labels a section.
   Same treatment either way; the element carries the semantics. */
h2.eyebrow, h3.eyebrow { font-weight: 600; }

.eyebrow {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--stone);
  margin: 0 0 var(--gap-sm);
}

/* A hairline already marks the break. Paying full padding on both sides of it is
   paying twice, and on a phone it pushed section headings a full thumb apart. */
.band { padding-block: var(--gap-md); }
.rule-top { border-top: 1px solid var(--rule); padding-top: var(--gap-md); }

/* A ruled section pays for the rule, not for the rule AND a full band above it. The
   previous value stacked both and left a visible sag between short sections. */
.band.rule-top { padding-top: var(--gap-sm); }
.band + .band { padding-top: 0; }

/* A heading immediately after a rule does not need its own top margin as well. */
.rule-top > .section-title:first-child,
.band > .section-title:first-child { margin-top: 0; }

/* A colophon: two sentences of publishing fact, not prose to be read for pleasure.
   Setting it at narrative scale made it shout over the page it was appended to. */
.colophon {
  font-size: var(--t-sm);
  line-height: 1.5;
  color: var(--stone);
}

.colophon em { font-style: italic; }

/* Works cited. Italic in the house accent is how a book title is set on a page, so the
   line reads as a bibliography rather than a row of links, and carries the weight of
   something owned rather than something clicked. */
.works {
  margin: var(--gap-xs) 0 0;
  font-family: var(--face-text);
  font-style: italic;
  font-size: var(--t-lg);
  line-height: 1.4;
}

.works a {
  color: var(--iron);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.works a:hover { border-bottom-color: var(--iron); }

.works-sep {
  color: var(--rule);
  padding: 0 0.45rem;
  font-style: normal;
}

.works-list { list-style: none; margin: var(--gap-xs) 0 0; padding: 0; max-width: var(--measure); }

.works-item { border-top: 1px solid var(--rule); }
.works-item:first-child { border-top: 0; }

.works-link {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  padding-block: var(--gap-xs);
  text-decoration: none;
  color: inherit;
}

/* Sized against the text it sits beside rather than in pixels, so the jacket stays
 * glyph-scale at every step of the type scale. */
.works-thumb {
  flex: none;
  width: 2.4rem;
  height: auto;
  aspect-ratio: 5 / 8;
  object-fit: cover;
  object-position: left center;
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.14);
}

/* The spine edge is the colour attribution. Vol III used --stone (neutral) until 2026-09-22,
 * back when --cover-iii was an unset placeholder; missed when --cover-iii was set for real
 * that same day (found in a live post-cutover review). Now consistent with Vol I/II. */
.spine-i   { border-left: 3px solid var(--cover-i); }
.spine-ii  { border-left: 3px solid var(--cover-ii); }
.spine-iii { border-left: 3px solid var(--cover-iii); }

.works-thumb-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--sink);
  border-left: 3px solid var(--stone);
  font-family: var(--face-text);
  font-size: var(--t-sm);
  color: var(--stone);
}

.works-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }

/* The lead placement: the same component the wilderness bibliography and the set listing use,
   given a larger jacket and room for the description. One treatment for a list of volumes
   everywhere on both sites, instead of the three that had grown up separately. */
.works-list-lead .works-thumb { width: 3.4rem; }

.works-list-lead .works-link { align-items: flex-start; gap: var(--gap-sm); }

.works-list-lead .works-item { padding-block: var(--gap-xs); }

.works-blurb {
  margin-top: 0.15rem;
  font-family: var(--face-text);
  font-size: var(--t-base);
  line-height: 1.4;
  color: var(--ink);
}

.works-list-lead .works-status { margin-top: 0.25rem; }

.works-title {
  font-family: var(--face-text);
  font-style: italic;
  font-size: var(--t-lg);
  line-height: 1.25;
  color: var(--iron);
  border-bottom: 1px solid transparent;
}

.works-link:hover .works-title { border-bottom-color: var(--iron); }

.works-status {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.04em;
  color: var(--stone);
}

/* THE ONE VOICE. Set flush left as a statement, not indented as a nested aside: it is the
 * only endorsement on the page and the reader should meet it head on. */
.pull { margin: 0; max-width: var(--measure); }

.pull-quote {
  /* Quoted matter, set the way .endorser-quote is set: italic, below body size, tight
     leading, so it reads as something lifted from elsewhere rather than the page talking.
     This had drifted back to --t-lg roman at 1.44 - the exact setting the endorsement rule
     records as having filled a phone viewport on its own. A quote should not be the largest
     text on a page whose subject is the books. */
  margin: 0;
  font-family: var(--face-text);
  font-size: 0.96rem;
  font-style: italic;
  line-height: 1.4;
  text-indent: -0.4em;
  quotes: "\201C" "\201D";
}

.pull-quote::before { content: open-quote; }
.pull-quote::after  { content: close-quote; }

.pull-quote + .endmark { margin-top: var(--gap-xs); }

.pull-attrib {
  margin-top: var(--gap-xs);
  font-family: var(--face-util);
  font-size: var(--t-sm);
  line-height: 1.4;
  color: var(--ink);
}

.pull-affil { color: var(--stone); }

.credits {
  margin: var(--gap-sm) 0 0;
  max-width: var(--measure);
  font-family: var(--face-util);
  font-size: var(--t-xs);
  line-height: 1.5;
  color: var(--stone);
}

/* ===== base/layout.css ===== */
.frame {
  width: 100%;
  max-width: var(--frame);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.prose { max-width: var(--measure); }

.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap-xs) var(--gap-sm);
  padding-block: var(--gap-md);
  border-bottom: 1px solid var(--rule);
}

/* The imprint name must not be dwarfed by the title of a utility page. It sits at the
   same size as a page title; only the hero is allowed to be bigger than the brand. */
.masthead-name {
  font-family: var(--face-text);
  font-size: var(--t-2xl);
  line-height: 1.1;
  text-decoration: none;
  color: var(--ink);
}

.masthead-place {
  display: block;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--stone);
  margin-top: 0.1rem;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-sm);
  font-family: var(--face-util);
  font-size: var(--t-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.nav a { color: var(--stone); text-decoration: none; }
.nav a:hover { color: var(--iron); }
.nav a[aria-current="page"] { color: var(--ink); }

/* ---- header/footer colour blocks ---------------------------------------- *
 *
 * Client request 2026-09-22: a colour block on the masthead and the footer of both
 * properties - same structure on each site, a different, crisp colour per site, so the
 * two are distinguishable at a glance and not only by their copy (helps a reader who
 * lands on one mid-scroll know immediately which site they're on; helps search engines
 * treat them as visibly, not just textually, distinct entities). SMP uses --cover-iii,
 * the client's own flyer red; Writer in the Wilderness uses --witw-crisp (see its
 * provenance comment in tokens.css - deliberately not Volume II's cover colour).
 *
 * ALL text inside either block is --paper. Both background colours were chosen so paper
 * clears 4.5:1 against them at EVERY text size in this block, not just large/bold text -
 * unlike --cover-ii, neither needs a display-only exception. That is also why hierarchy
 * inside the block (hover, the current-page nav link) is carried by underline, never by a
 * second text colour: a colour picked to work on one background is not guaranteed to work
 * on the other, and underline sidesteps the question entirely. Verify with
 * node tools/contrast.js. */

.prop-press .masthead,
.prop-press .foot {
  background: var(--cover-iii);
  border-color: transparent;
}
.prop-wilderness .masthead,
.prop-wilderness .foot {
  background: var(--witw-crisp);
  border-color: transparent;
}

/* Cancels .frame's own inline padding for just this child, then re-applies it, so the
 * colour reaches the frame's full width while the text inside still lines up with every
 * other line on the page. Not a full viewport bleed - stays within the frame's max-width,
 * same as everything else on the site. */
.prop-press .masthead, .prop-wilderness .masthead,
.prop-press .foot, .prop-wilderness .foot {
  padding-inline: var(--pad);
  margin-inline: calc(var(--pad) * -1);
}

.prop-press .masthead-name, .prop-wilderness .masthead-name,
.prop-press .masthead-place, .prop-wilderness .masthead-place,
.prop-press .nav a, .prop-wilderness .nav a,
.prop-press .foot, .prop-wilderness .foot,
.prop-press .foot-nav a, .prop-wilderness .foot-nav a,
.prop-press .foot-build, .prop-wilderness .foot-build {
  color: var(--paper);
}

.prop-press .nav a:hover, .prop-wilderness .nav a:hover,
.prop-press .foot-nav a:hover, .prop-wilderness .foot-nav a:hover {
  color: var(--paper);
  text-decoration: underline;
}

.prop-press .nav a[aria-current="page"], .prop-wilderness .nav a[aria-current="page"] {
  color: var(--paper);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}


.hero { padding-block: var(--gap-lg) var(--gap-md); }

.hero-line {
  font-size: var(--t-3xl);
  line-height: 1.1;
  font-weight: 400;
  letter-spacing: -0.012em;
  margin: 0;
  max-width: 17ch;
}

.hero-sub {
  font-size: var(--t-lg);
  color: var(--stone);
  max-width: var(--measure);
  margin: var(--gap-sm) 0 0;
}



.foot {
  border-top: 1px solid var(--rule);
  margin-top: var(--gap-md);
  padding-block: var(--gap-sm);
  font-family: var(--face-util);
  font-size: var(--t-xs);
  line-height: 1.4;
  color: var(--stone);
}

/* Two facts on one line where there is room: who published this, and which build
   you are looking at. The build stamp is what makes review feedback reproducible. */
.foot-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--gap-xs) var(--gap-md);
}

.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-xs) var(--gap-md);
  margin: 0 0 var(--gap-xs);
}

.foot-nav a { color: var(--stone); text-decoration: none; }
.foot-nav a:hover { color: var(--iron); }

.foot-imprint,
.foot-build { margin: 0; }

.foot-build {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: var(--rule);
}
@media (min-width: 48rem) {
  .hero { padding-block: var(--gap-xl) var(--gap-lg); }
  .hero-line { font-size: 3rem; max-width: 15ch; }
}

/* ---- cross-property card ---------------------------------------------- */
/* The route between the two sites, and the way out of a page that is mostly
   specifications. Needs to read as one object, not three stray paragraphs. */

/* Typographic, not a widget. A grey fill with a 1px border is the shape of a 1997
   related-links module, and it competed with the prose above it for attention it does
   not deserve. A rule and a hierarchy do the same job and read as editorial. */
.crosslink {
  margin-top: var(--gap-lg);
  padding-top: var(--gap-sm);
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
}

.crosslink-kicker {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--stone);
  margin: 0 0 0.1rem;
}

.crosslink-name {
  font-size: var(--t-lg);
  line-height: 1.2;
  margin: 0;
}

.crosslink-name a {
  color: var(--iron);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

.crosslink-name a:hover { border-bottom-color: var(--iron); }

.crosslink-name a { border-bottom-width: 2px; }

.crosslink-line {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  color: var(--stone);
  margin: 0;
}

/* ===== components/breadcrumb.css ===== */
/* Breadcrumb. Quiet by design: it is orientation, not navigation furniture.
   The apex crumb is present only in prototype mode; see lib/components/breadcrumb.js. */

.breadcrumb { padding-block: var(--gap-sm) 0; }

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--gap-xs);
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--stone);
}

.crumb + .crumb::before {
  content: "/";
  margin-right: var(--gap-xs);
  color: var(--rule);
}

.crumb a { color: var(--stone); text-decoration: none; }
.crumb a:hover { color: var(--iron); }
.crumb [aria-current="page"] { color: var(--ink); }

/* The root of the trail is a mark, not a name. Same nib that closes a cited block, so
   the house glyph means the same thing in both places. */
.crumb-mark a { display: block; line-height: 0; }

.crumb-glyph {
  display: block;
  width: 0.72rem;
  height: 0.72rem;
  background-color: var(--stone);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%2023%20L5.6%208.6%20C5.6%204.6%208.5%201.6%2012%201.6%20C15.5%201.6%2018.4%204.6%2018.4%208.6%20Z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%228.4%22%20r%3D%221.9%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M12%2022.2%20L12%2011.2%22%20stroke%3D%22%23fff%22%20stroke-width%3D%221.1%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%2023%20L5.6%208.6%20C5.6%204.6%208.5%201.6%2012%201.6%20C15.5%201.6%2018.4%204.6%2018.4%208.6%20Z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%228.4%22%20r%3D%221.9%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M12%2022.2%20L12%2011.2%22%20stroke%3D%22%23fff%22%20stroke-width%3D%221.1%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
}

.crumb-mark a:hover .crumb-glyph { background-color: var(--iron); }

/* ===== components/draft.css ===== */
/* Scrolls away. Read once, then out of the way. */
/* Does not scroll. Three pixels of proof-mat around the viewport, present in every
   screenshot at every scroll position. Costs six pixels of width and height and is the
   only thing keeping the draft state visible once the banner has scrolled off. */
.draft-frame {
  position: fixed;
  inset: 0;
  z-index: 30;
  border: 3px solid var(--draft);
  pointer-events: none;
}

/* The frame now carries TWO signals at once, and it is worth being clear about which is
   which. The colour says WHICH PROPERTY you are looking at. The banner, which stays rust on
   both sides and states the words, says it is a draft, together with the [DRAFT] title
   suffix, the noindex meta, robots.txt and the gate. Turning this green on one side does not
   weaken the draft state, because the frame was never the only thing carrying it. */
.prop-wilderness .draft-frame { border-color: var(--spruce); }

.draft-note {
  border-left: 3px solid var(--draft);
  background: color-mix(in srgb, var(--draft) 6%, transparent);
  color: var(--draft);
  font-family: var(--face-util);
  font-size: var(--t-sm);
  line-height: 1.45;
  padding: 0.6rem 0.8rem;
  margin: var(--gap-sm) 0;
  max-width: var(--measure);
}

.draft-note-label {
  display: block;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: var(--t-xs);
  margin-bottom: 0.15rem;
}

.draft-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  background: var(--sink);
  border: 1px dashed var(--rule);
  color: var(--stone);
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  padding: var(--gap-md);
  min-height: 7rem;
}

/* A placeholder names what is missing and what would fill it, so the client reads it as
   something waiting on them rather than as work we have not done. */
.placeholder-label {
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--stone);
}

.placeholder-needed {
  font-size: var(--t-xs);
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--stone);
  opacity: 0.85;
  max-width: 22ch;
  line-height: 1.35;
}

/* Client-facing, ships in every build. Says what is missing without editorialising.
   Distinct from .draft-note, which is studio analysis and is stripped for the client. */
.awaiting {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
  font-family: var(--face-util);
  font-size: var(--t-sm);
  line-height: 1.4;
  color: var(--stone);
  margin: var(--gap-sm) 0;
  max-width: var(--measure);
}

.awaiting-mark {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--draft);
  border: 1px solid var(--draft);
  padding: 0.05rem 0.4rem;
}

/* ---- print ------------------------------------------------------------- *
 *
 * These pages get printed for the author to mark up, so the trim has to survive a printer,
 * and browsers drop background and border colour by default. print-color-adjust forces it.
 *
 * A colour trim is also useless on a monochrome printer, so each page carries its property
 * name in the footer of the frame as well. Colour to sort a stack quickly, words in case the
 * printer had one cartridge. */

@media print {
  .draft-frame {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  .draft-frame::after {
    position: fixed;
    right: 0.5rem;
    bottom: 0.2rem;
    font-family: var(--face-util);
    font-size: 8pt;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .prop-press .draft-frame::after {
    content: "Silver Mountain Press · draft";
    color: var(--draft);
  }

  .prop-wilderness .draft-frame::after {
    content: "Writer in the Wilderness · draft";
    color: var(--spruce);
  }

  .prop-apex .draft-frame::after {
    content: "Draft whiteboard";
    color: var(--draft);
  }

  /* Nothing on these pages is clickable on paper, and a disclosure that prints closed hides
     the thing he is being asked to read. Open every fold for print.

     A closed <details> is not hidden with `display` in current Chrome, it is hidden with
     content-visibility on the shadow slot, so overriding display alone did nothing and the
     folded paragraphs stayed off the page while the "Read the rest" control printed. The
     ::details-content pseudo-element is the handle that actually works; the display rules
     stay for engines that predate it. */
  details { display: block; }
  details > summary { display: none !important; }
  details::details-content { content-visibility: visible !important; }
  details > *:not(summary) { display: block !important; }
}

/* ===== components/excerpt.css ===== */
/* This is the signature. Hanging opening quote, drop cap, justified at reading
 * widths. Ragged-right on phones, where justification only makes rivers. */

/* The sample passage is a framed panel, in the style the owner supplied: a white page with a cream band and a thin
 * white line outside it, a large red opening quote, and a large red drop cap. The red is the crisp jacket red the
 * masthead uses (--cover-iii, 5.95:1 on paper; on white it is stronger still), so it stays the one loud thing here. */
.excerpt {
  max-width: var(--measure);
  margin-block: var(--gap-md);
  font-size: var(--t-base);
  line-height: 1.4;
  background: #fff;
  border: 0.5rem solid var(--sink);
  border-radius: 0.9rem;
  box-shadow: 0 0 0 0.2rem #fff;   /* the thin white line outside the cream band */
  padding: 1rem 1.15rem 1.1rem;
}
@media (min-width: 34rem) { .excerpt { padding: 1.25rem 1.6rem 1.35rem; } }

.excerpt-open {
  float: left;
  font-size: 4.4em;
  line-height: 0.82;
  margin: 0.02em 0.04em 0 -0.02em;
  color: var(--cover-iii);
  font-family: var(--face-text);
  font-weight: 700;
}

.excerpt-body { margin: 0; }

/* The drop cap opens the passage, once. It was set on .excerpt-body, so every paragraph
   after the first got one too, which is not how a book sets a continued page. Continuation
   paragraphs take a first-line indent instead, the way his interiors do. */
.excerpt-body-cont {
  text-indent: 1.4em;
  margin-top: 0;
}

.excerpt-body-lead::first-letter {
  float: left;
  font-size: 5.1em;
  line-height: 0.74;
  padding: 0.02em 0.09em 0 0.02em;
  font-family: var(--face-text);
  font-weight: 700;
  color: var(--cover-iii);
}

.excerpt-cite {
  display: block;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone);
  margin-top: var(--gap-sm);
  clear: both;
}
@media (min-width: 34rem) {
  .excerpt-body {
    text-align: justify;
    hyphens: auto;              /* his interiors are justified and hyphenated */
    text-wrap: pretty;
  }
}

/* The fold, styled as the jacket fold is, so the two disclosures on a product page read as
   one device rather than two. */
.excerpt-more { margin: 0; }

.excerpt-summary {
  display: inline-block;
  font-family: var(--face-util);
  font-size: var(--t-sm);
  color: var(--iron);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.15rem;
  margin-top: var(--gap-xs);
  cursor: pointer;
  list-style: none;
}

.excerpt-summary::-webkit-details-marker { display: none; }
.excerpt-summary::after { content: " \2193"; }
.excerpt-more[open] .excerpt-summary::after { content: " \2191"; }
.excerpt-summary:hover { border-bottom-color: var(--iron); }
.excerpt-more[open] .excerpt-summary { margin-bottom: var(--gap-sm); }

/* Where the sample lets out. */
.excerpt-next {
  margin: var(--gap-sm) 0 0;
  padding-top: var(--gap-xs);
  border-top: 1px solid var(--rule);
  font-family: var(--face-text);
  font-style: italic;
  font-size: var(--t-base);
  text-indent: 0;
}

.excerpt-next a { color: var(--iron); text-decoration: none; border-bottom: 1px solid var(--rule); }
.excerpt-next a:hover { border-bottom-color: var(--iron); }
.excerpt-next-soon { color: var(--stone); }

/* The reveal. Says what it is doing rather than pretending the passage stopped there. */
.excerpt-cut {
  margin: 0;
  font-family: var(--face-text);
  font-size: var(--t-base);
  line-height: 1.4;
  color: var(--stone);
  text-indent: 0;
  text-align: left;
}

/* ===== components/volume.css ===== */
.volume-title {
  font-size: var(--t-xl);
  font-weight: 400;
  line-height: 1.22;
  margin: 0 0 0.2rem;
}

.volume-title a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--rule); }
.volume-title a:hover { border-bottom-color: var(--iron); color: var(--iron); }

.volume-series {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone);
  margin: 0 0 var(--gap-sm);
  line-height: 1.4;
}

.volume-status-soon { color: var(--iron); }

/* Applied as classes, never as inline style attributes: a style="" attribute
 * would require 'unsafe-inline' in style-src, widening the CSP for decoration.
 * Display-size elements only. */

.accent-i   { color: var(--cover-i); }
.accent-ii  { color: var(--cover-ii); }
.accent-iii { color: var(--cover-iii); }

/* ---- volume bar ---------------------------------------------------------- *
 *
 * Bold colour-block status banner, one per volume. Sourced 2026-09-22 from the client's
 * own print promotional artwork: a letter-size flyer using saturated colour bands with
 * cream text to announce a book's status. This is that treatment, carrying the volume's
 * real distribution status (distributionState() in lib/components/book.js) - never
 * invented copy. Replaces the old plain-text .volume-status line on the product page.
 *
 * TEXT IS ALWAYS BOLD, UPPERCASE, AND AT LEAST --t-xl - THAT IS WHAT KEEPS THE GREEN
 * VARIANT LEGAL. --cover-ii is 3.12:1 against --paper: fails WCAG AA for normal text
 * (4.5:1), clears AA-large (3:1). "Large text" at bold weight means 14pt/18.66px or
 * above (WCAG 2.x) - --t-lg (1.1rem = 17.6px) is JUST under that, so this uses --t-xl
 * (1.28rem = 20.48px), comfortably clear. Do not shrink this text below --t-xl or drop
 * the weight; either one puts the green bar back in violation.
 * Verify with node tools/contrast.js. */

.volume-bar {
  display: inline-block;
  font-family: var(--face-util);
  font-weight: 700;
  font-size: var(--t-xl);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--paper);
  padding: 0.3rem 0.75rem;
  margin: 0 0 var(--gap-sm);
}

.volume-bar-i          { background: var(--cover-i); }
.volume-bar-ii         { background: var(--cover-ii); }
.volume-bar-iii        { background: var(--cover-iii); }
/* For pages not about one specific title (the homepage, the catalog index, the trilogy
 * set, anything else that spans or precedes a single volume): the house accent, not a
 * volume's own colour, so as not to falsely attribute the page to one book. */
.volume-bar-compatible { background: var(--iron); }

/* Full-width variant, for a tagline rather than a one-word status - block-level,
 * centred, wraps across lines the way the client's own flyer band does. Text size and
 * weight rules above still apply; do not use the pill (.volume-bar alone) for a full
 * sentence, and do not use this for a one-word status - the pill reads as a status,
 * this reads as a banner, and swapping them swaps the meaning. */
.volume-bar-full {
  display: block;
  text-align: center;
  line-height: 1.35;
  padding: var(--gap-md) var(--pad);
  margin: 0 0 var(--gap-lg);
}

/* Product tags (catalog `tags`): plain facts about the whole product, such as Illustrated, that apply to every format. */
.tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.6rem 0 0; padding: 0; list-style: none; }
.tag { padding: 0.15rem 0.6rem; border: 1px solid var(--rule); border-radius: 999px; font-family: var(--face-util); font-size: var(--t-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--stone); }

/* ===== components/detail.css ===== */
.detail {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gap-md);
  align-items: start;
  padding-block: var(--gap-lg);
}

.spec {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
  font-family: var(--face-util);
  margin-block: var(--gap-sm);
  max-width: var(--measure);
}

.spec th,
.spec td {
  text-align: left;
  vertical-align: top;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
}

.spec th {
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stone);
  font-size: var(--t-xs);
  width: 42%;
  padding-right: var(--gap-sm);
}

.spec-unset { color: var(--draft); font-style: italic; }



/* A real disabled button, not an anchor with href="#". A dead anchor sends focus to
   the top of the page on activation; a disabled button is inert and announces as such. */
.buy {
  display: inline-block;
  appearance: none;
  font: inherit;
  font-family: var(--face-util);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stone);
  background: none;
  border: 0;
  border-bottom: 2px solid var(--rule);
  padding: 0.2rem 0 0.35rem;
  text-decoration: none;
  cursor: not-allowed;
}

/* Live, it earns the accent and a solid rule. Inert, it is a quiet label with a grey
   underline. Neither is a grey box with a border, which is what it was. */
.buy-live {
  color: var(--iron);
  border-bottom-color: var(--iron);
  cursor: pointer;
}

.buy-caption {
  display: block;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  color: var(--draft);
  margin-top: 0.4rem;
  letter-spacing: 0.04em;
}



.contents { list-style: none; margin: 0 0 var(--gap-sm); padding: 0; max-width: var(--measure); }

.contents-item {
  font-size: var(--t-lg);
  padding-block: 0.4rem;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 48rem) {
  .detail {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
    gap: var(--gap-xl);
  }
}

/* Contents list. Numbered because the running order is the book's own. */
.contents { counter-reset: story; }

.contents-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  counter-increment: story;
}

.contents-title::before {
  content: counter(story, upper-roman) ". ";
  color: var(--stone);
  font-variant-numeric: tabular-nums;
}

.contents-note {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  line-height: 1.4;
  color: var(--stone);
}

/* ---- cover ------------------------------------------------------------- */
/* A real jacket, sized by its own intrinsic dimensions so a replacement file
   cannot introduce layout shift. Shadow is minimal: the artwork carries itself. */

.cover { margin: 0 0 var(--gap-sm); max-width: 18rem; }

@media (max-width: 47.999rem) {
  .detail { display: block; }

  .detail-cover { float: right; width: 42%; max-width: 9.5rem; margin: 0.3rem 0 var(--gap-sm) var(--gap-sm); }

  .detail-cover .cover { max-width: 100%; margin: 0; }
}

.cover img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--sink);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14);
}

.catalog-item .cover { max-width: 100%; margin-bottom: var(--gap-xs); }

/* ---- stand-in jacket --------------------------------------------------- */
/* Volume III has no cover. A sibling jacket stands in, obscured past recognition:
   blurred, desaturated, dimmed and tinted. It must read as "artwork pending" and
   never as "this is what the book looks like", which is why the treatment is heavy
   rather than tasteful, and why it carries a visible caption. */

.cover-standin { position: relative; }

.cover-standin img {
  filter: grayscale(1) blur(7px) contrast(0.55) brightness(1.12);
  opacity: 0.5;
  transform: scale(1.04);          /* hide the blur feathering at the edges */
}

.cover-standin::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg,
              color-mix(in srgb, var(--sink) 70%, transparent),
              color-mix(in srgb, var(--stone) 30%, transparent));
}

.cover-standin-note {
  position: absolute;
  inset-inline: 0;
  bottom: 0.6rem;
  z-index: 1;
  text-align: center;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}

/* ---- colophon line and the offer --------------------------------------- */

/* The reference facts, set the way a book sets them: one run, small, quiet, scannable.
 * Nothing here is a decision the reader makes, so nothing here gets structure. */
.colophon-line {
  margin: var(--gap-sm) 0 var(--gap-md);
  max-width: var(--measure);
  font-family: var(--face-util);
  font-size: var(--t-xs);
  line-height: 1.7;
  color: var(--stone);
}

.colophon-sep { padding: 0 0.15em; color: var(--rule); }

/* The offer, which is the part a customer acts on, is the only thing here that gets rows. */
.offer { padding-block: var(--gap-xs); border-top: 1px solid var(--rule); }

.offer-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem var(--gap-sm);
  margin: 0;
}

.offer-binding { margin: 0 0 0.15rem; 

  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stone);
}

.offer-price {
  font-family: var(--face-text);
  font-size: var(--t-xl);
  color: var(--ink);
}

/* Five of six bindings have no price yet. An empty slot beside a Buy control reads as a
 * bug; naming the gap reads as a question he can answer, which is what it is. */
.offer-price-none {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  font-style: italic;
  color: var(--stone);
}

.offer-isbn {
  margin-left: auto;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  color: var(--stone);
}

/* Outbound retailer links (Amazon, Audible, Google eBooks) - a different thing from the Buy
 * control above: this site never processes the sale, it only points at one that does, so
 * none of the payment-provider caution applies. Live and pending share one line so the
 * pattern reads the same as the disabled Buy button: quiet grey text is "not yet", the
 * house accent is "real". See lib/components/book.js retailerLinks(). */
.offer-retailers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem var(--gap-sm);
  margin: 0.3rem 0 0;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.04em;
}

.retailer-link {
  color: var(--iron);
  text-decoration: none;
  border-bottom: 1px solid var(--iron);
}
.retailer-link:hover { color: var(--ink); border-bottom-color: var(--ink); }

.retailer-pending {
  color: var(--stone);
  font-style: italic;
}

/* The set had exactly one inbound link on the whole site, from the catalogue, which is thin
   for the highest-value thing on offer. Each volume now points at it: a cross-sell where a
   reader is already looking at one of the three, and three more internal links into the page
   that most needs them. */
.also-set {
  margin: var(--gap-sm) 0 0;
  padding-top: var(--gap-xs);
  border-top: 1px solid var(--rule);
  font-family: var(--face-text);
  font-style: italic;
  font-size: var(--t-base);
}

.also-set a { color: var(--iron); text-decoration: none; border-bottom: 1px solid var(--rule); }
.also-set a:hover { border-bottom-color: var(--iron); }

/* One listing, formats as variations (lib/components/book.js formatRows). Radios sit first so sibling selectors can drive the
 * panel; the stylesheet has one rule per position, up to MAX_VARIANTS. */
.variants { position: relative; }
.variants > input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.variant-chips { display: flex; flex-wrap: wrap; gap: var(--gap-xs); padding-block: var(--gap-xs); border-top: 1px solid var(--rule); }
.variant-chips label {
  display: inline-flex; align-items: baseline; gap: 0.5em; padding: 0.35rem 0.8rem; cursor: pointer;
  border: 1px solid var(--rule); border-radius: 999px;
  font-family: var(--face-util); font-size: var(--t-sm); color: var(--iron);
}
.variant-price { font-size: var(--t-xs); color: var(--stone); }
.variant-panel { display: none; border-top: 0; }
.variant-panel .offer-binding { display: none; } /* the chosen chip already names it */
.variants > input:nth-of-type(1):checked ~ .variant-panels > .variant-panel:nth-of-type(1) { display: block; }
.variants > input:nth-of-type(1):checked ~ .variant-chips > label:nth-of-type(1) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(1):checked ~ .variant-chips > label:nth-of-type(1) .variant-price { color: inherit; }
.variants > input:nth-of-type(1):focus-visible ~ .variant-chips > label:nth-of-type(1) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(2):checked ~ .variant-panels > .variant-panel:nth-of-type(2) { display: block; }
.variants > input:nth-of-type(2):checked ~ .variant-chips > label:nth-of-type(2) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(2):checked ~ .variant-chips > label:nth-of-type(2) .variant-price { color: inherit; }
.variants > input:nth-of-type(2):focus-visible ~ .variant-chips > label:nth-of-type(2) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(3):checked ~ .variant-panels > .variant-panel:nth-of-type(3) { display: block; }
.variants > input:nth-of-type(3):checked ~ .variant-chips > label:nth-of-type(3) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(3):checked ~ .variant-chips > label:nth-of-type(3) .variant-price { color: inherit; }
.variants > input:nth-of-type(3):focus-visible ~ .variant-chips > label:nth-of-type(3) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(4):checked ~ .variant-panels > .variant-panel:nth-of-type(4) { display: block; }
.variants > input:nth-of-type(4):checked ~ .variant-chips > label:nth-of-type(4) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(4):checked ~ .variant-chips > label:nth-of-type(4) .variant-price { color: inherit; }
.variants > input:nth-of-type(4):focus-visible ~ .variant-chips > label:nth-of-type(4) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(5):checked ~ .variant-panels > .variant-panel:nth-of-type(5) { display: block; }
.variants > input:nth-of-type(5):checked ~ .variant-chips > label:nth-of-type(5) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(5):checked ~ .variant-chips > label:nth-of-type(5) .variant-price { color: inherit; }
.variants > input:nth-of-type(5):focus-visible ~ .variant-chips > label:nth-of-type(5) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(6):checked ~ .variant-panels > .variant-panel:nth-of-type(6) { display: block; }
.variants > input:nth-of-type(6):checked ~ .variant-chips > label:nth-of-type(6) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(6):checked ~ .variant-chips > label:nth-of-type(6) .variant-price { color: inherit; }
.variants > input:nth-of-type(6):focus-visible ~ .variant-chips > label:nth-of-type(6) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(7):checked ~ .variant-panels > .variant-panel:nth-of-type(7) { display: block; }
.variants > input:nth-of-type(7):checked ~ .variant-chips > label:nth-of-type(7) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(7):checked ~ .variant-chips > label:nth-of-type(7) .variant-price { color: inherit; }
.variants > input:nth-of-type(7):focus-visible ~ .variant-chips > label:nth-of-type(7) { outline: 2px solid var(--iron); outline-offset: 2px; }
.variants > input:nth-of-type(8):checked ~ .variant-panels > .variant-panel:nth-of-type(8) { display: block; }
.variants > input:nth-of-type(8):checked ~ .variant-chips > label:nth-of-type(8) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.variants > input:nth-of-type(8):checked ~ .variant-chips > label:nth-of-type(8) .variant-price { color: inherit; }
.variants > input:nth-of-type(8):focus-visible ~ .variant-chips > label:nth-of-type(8) { outline: 2px solid var(--iron); outline-offset: 2px; }
@media print { .variant-chips { display: none; } .variant-panel { display: block; } .variant-panel .offer-binding { display: block; } }

/* Bookshelf Partners page (lib/components/partners.js): a plain list of stores that carry the books. */
.partners { list-style: none; margin: 0 0 var(--gap-md); padding: 0; }
.partner { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem var(--gap-sm); padding-block: var(--gap-xs); border-top: 1px solid var(--rule); }
.partner-place { font-family: var(--face-util); font-size: var(--t-sm); color: var(--stone); }
.partner-titles { flex-basis: 100%; font-family: var(--face-util); font-size: var(--t-xs); color: var(--stone); }

/* ===== components/jacket.css ===== */
/* The publisher's promotional voice. Set as book copy, not as UI text. */

.jacket { max-width: var(--measure); margin-block: var(--gap-md); }

.jacket-para {
  font-size: var(--t-lg);
  line-height: 1.46;
  margin: 0 0 var(--gap-sm);
  text-wrap: pretty;
}

.jacket-para:first-of-type { color: var(--ink); }

/* The fold. Styled as a control, not as a browser widget: the default triangle marker is
   removed and replaced with a rule and the house accent, so it reads like the rest of the page. */
.jacket-more { margin: 0 0 var(--gap-sm); }

.jacket-summary {
  display: inline-block;
  font-family: var(--face-util);
  font-size: var(--t-sm);
  color: var(--iron);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.15rem;
  cursor: pointer;
  list-style: none;
  margin-bottom: var(--gap-sm);
}

.jacket-summary::-webkit-details-marker { display: none; }
.jacket-summary::after { content: " \2193"; }
.jacket-more[open] .jacket-summary::after { content: " \2191"; }
.jacket-summary:hover { border-bottom-color: var(--iron); }

.jacket-cite {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone);
  margin: var(--gap-sm) 0 0;
}


/* Draft apparatus. Goes away with everything else that uses --draft. */

.corrections {
  border: 1px solid var(--draft);
  border-left-width: 3px;
  background: color-mix(in srgb, var(--draft) 5%, transparent);
  padding: var(--gap-md) var(--gap-sm);
  margin-block: var(--gap-md);
  max-width: var(--measure);
}

.corrections-head {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--draft);
  margin: 0 0 var(--gap-xs);
}

.corrections-intro {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--draft);
  margin: 0 0 var(--gap-md);
}

.correction { border-top: 1px solid color-mix(in srgb, var(--draft) 30%, transparent); padding-block: var(--gap-sm); }

.correction-was,
.correction-now {
  font-size: var(--t-sm);
  line-height: 1.5;
  margin: 0 0 var(--gap-xs);
}

.correction-was { color: var(--stone); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--draft) 50%, transparent); }
.correction-now { color: var(--ink); }

.correction-tag {
  display: block;
  font-family: var(--face-util);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--draft);
  text-decoration: none;
  margin-bottom: 0.1rem;
}

.correction-note {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  line-height: 1.5;
  color: var(--stone);
  margin: 0;
}

/* ===== components/endmark.css ===== */
/* ---- end mark ---------------------------------------------------------- */
/* Closes a cited block: jacket copy, an endorsement. A pen nib, because these are
   the words of writers and reviewers rather than the site talking.
 *
 * Drawn as a mask rather than a coloured SVG, so it takes --stone from the token
 * layer instead of hardcoding a hex that would survive a palette change.
 *
 * PLACEHOLDER. Andreea Chele illustrated both published volumes; the real mark
 * should be hers. Swapping it is one URL in this rule. */

.endmark {
  display: inline-block;
  vertical-align: -0.02em;
  width: 0.66rem;
  height: 0.66rem;
  margin-left: 0.4em;
  background-color: var(--stone);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%2023%20L5.6%208.6%20C5.6%204.6%208.5%201.6%2012%201.6%20C15.5%201.6%2018.4%204.6%2018.4%208.6%20Z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%228.4%22%20r%3D%221.9%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M12%2022.2%20L12%2011.2%22%20stroke%3D%22%23fff%22%20stroke-width%3D%221.1%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%2023%20L5.6%208.6%20C5.6%204.6%208.5%201.6%2012%201.6%20C15.5%201.6%2018.4%204.6%2018.4%208.6%20Z%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%228.4%22%20r%3D%221.9%22%20fill%3D%22%23fff%22%2F%3E%3Cpath%20d%3D%22M12%2022.2%20L12%2011.2%22%20stroke%3D%22%23fff%22%20stroke-width%3D%221.1%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
}

/* ===== components/recognition.css ===== */
.awards {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gap-xs);
  list-style: none;
  margin: 0;
  padding: 0;
}

.award-label {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--iron);
}

.award-detail {
  font-size: var(--t-sm);
  line-height: 1.4;
  color: var(--stone);
}

.endorsers { list-style: none; margin: 0; padding: 0; }

.endorser {
  padding-block: var(--gap-xs);
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
}

.endorser-by {
  margin: var(--gap-xs) 0 0;
  line-height: 1.4;
}

.endorser-name { font-size: var(--t-base); }

.endorser-affil {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  color: var(--stone);
  line-height: 1.45;
}

/* Comma set in CSS so the name and the affiliation stay separate elements for the
   structured data that goes in at launch. Scoped to the attribution line: the volume-page
   recognition list reuses .endorser-affil for award strings and was picking up a leading comma. */
.endorser-by .endorser-affil::before { content: ", "; }



.endorser-quote {
  /* Quoted matter, not prose. Set BELOW body size with tighter leading so it reads as
     something lifted from elsewhere rather than as the page talking. An earlier setting
     ran at --t-lg with 1.46 leading and filled a phone viewport on its own. */
  margin: 0 0 var(--gap-xs);
  font-size: 0.92rem;
  line-height: 1.38;
  font-style: italic;
  color: var(--ink);

  /* The opening quote hangs into the margin, echoing the book interiors rather than
     reaching for the conventional left rule. */
  text-indent: -0.42em;
  quotes: "\201C" "\201D";
}

.endorser-quote::before { content: open-quote; }
.endorser-quote::after  { content: close-quote; }

.endorser-source {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stone);
  margin: 0.15rem 0 0;
}
@media (min-width: 34rem) {
  .awards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 64rem) {
  .awards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.award {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.5ch;
  padding-block: var(--gap-xs);
  border-top: 1px solid var(--rule);
}

.award:first-child { border-top: 0; }

/* ===== components/catalog.css ===== */
/* ---- the set ----------------------------------------------------------- */
/* Three books, three jackets, slightly overlapped so they read as a set rather
   than as three unrelated items. Used on the set's own product page.

   The catalogue grid that used to live here is gone: the catalogue is a list of
   volumes, so it now uses the same works list as every other list of volumes.
   With it went .catalog-grid, .catalog-item, .catalog-numeral, and the
   .pill-available / .pill-soon pair that rendered "Available" with a shopping-cart
   emoji instead of reading distributionState() like everywhere else. */

.cover-set {
  display: flex;
  align-items: flex-end;
  gap: 0;
  margin-bottom: var(--gap-sm);
}

.cover-set .cover {
  max-width: 42%;
  margin: 0 0 0 -6%;
  transition: none;
}

.cover-set .cover:first-child { margin-left: 0; }
.cover-set .cover img { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.22); }

/* ===== components/portrait.css ===== */
/* Capped at the supplied file's native width so the photograph never upscales.
   Raise this once a higher-resolution original arrives. */
.portrait { margin: 0 0 var(--gap-sm); max-width: 18rem; }

.portrait img {
  display: block;
  width: 100%;
  height: auto;              /* never distort a photograph of a person */
  background: var(--sink);
}

.portrait-caption {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone);
  margin-top: var(--gap-xs);
}

/* ---- the author page, as the book sets it ------------------------------ */
/* The printed author page in Volume II puts the photograph top-left with the
   biography wrapping around it. That segments ~900 characters of prose without
   editing a word of it, and it is his own layout rather than one we invented.
   An earlier version set the same text at lede size in its own block and it
   filled a phone viewport by itself. */

.bio { max-width: var(--measure); }

/* Right edge, so the reader's eye starts on text at the left margin rather than
   stepping around a picture to reach the first word. */
.portrait-inline {
  container-type: inline-size;   /* the cutline sizes itself against this */
  float: right;
  width: 38%;
  max-width: 10rem;
  margin: 0.2rem 0 var(--gap-xs) var(--gap-sm);
  shape-margin: var(--gap-sm);
}

/* Cutline, set the way a book sets an illustration caption: text face, italic, small,
   sitting tight under the image rather than floating away from it. */
/* One line, always. Sized in container units against the figure rather than in rem,
   so it fits the picture at any width instead of wrapping to two lines on a phone and
   stealing the space the picture was buying. */
.cutline {
  margin-top: 0.25rem;
  font-family: var(--face-text);
  font-style: italic;
  line-height: 1.2;
  color: var(--stone);
  white-space: nowrap;
  font-size: clamp(0.58rem, 7.4cqw, 0.82rem);
}

.bio-text {
  margin: 0;
  text-wrap: pretty;
  /* Defensive, 2026-09-28 (see .portrait-lead's note below): body's global overflow-wrap:
     break-word (reset.css) would otherwise let the browser break "Hilton Everett Moore" itself
     mid-word to fit a squeezed column - its non-breaking spaces only stop breaks BETWEEN the
     three words, not within one. The float-vs-stack breakpoint fix is the real fix; this is the
     backstop for any narrower or zoomed viewport that still squeezes this column. */
  overflow-wrap: normal;
}

/* Multiple bio-text paragraphs (the paragraphed WITW bio, 2026-09-28) need real space between
   them - zero margin was correct when this was always exactly one paragraph, but with several
   adjacent .bio-text elements it read as one run-on block with odd, uneven wraps rather than
   deliberate paragraphs, worse beside the floated portrait where line lengths already vary.
   Scoped to the sibling case only, so a single paragraph (press's about page) is unaffected. */
.bio-text + .bio-text { margin-top: 1em; }

.bio::after { content: ""; display: block; clear: both; }

@media (min-width: 34rem) {
  .portrait-inline { width: 34%; max-width: 12rem; margin-left: var(--gap-md); }
}

/* ---- lead photo, news-article style (WITW homepage, 2026-09-28) -------- */
/* Owner asked for the author photo at the top, the way a news article leads with its
   photo - refined same day to top-right of the About section specifically (the section's
   own <h2> is a11y-only/visually hidden, so "top right of ~h2" means the top of that
   section, not beside visible heading text). Floated right so the paragraphed bio text
   wraps beside and below it, same wrapping mechanic as the book's own .portrait-inline
   (which stays untouched for the press about page - this is additive, not a replacement),
   just larger and top-of-section rather than mid-paragraph. The source file is 384x512
   (native), so this stays under that rather than upscale it - a larger cap would look soft.
   *
   * NOT floated below 34rem (2026-09-28, real bug found live on a phone screenshot): floating
   * at 45% width on a narrow phone leaves too little room beside it for "Hilton Everett Moore"
   * to fit as the single unbreakable unit its non-breaking spaces make it - `body`'s global
   * `overflow-wrap: break-word` (reset.css) then breaks it MID-WORD ("Hilton Everett Moo" /
   * "re is...") rather than between the joined words, which the non-breaking spaces alone don't
   * prevent. Stacking full-width below this breakpoint removes the squeeze entirely, the same
   * way most news sites don't float a lead image beside body text on a phone either - float
   * only becomes the top-right, wrap-around treatment once there is a wide enough column left
   * over to actually hold the name. `.bio-text` also gets a defensive `overflow-wrap: normal`
   * below, belt and suspenders, in case a narrower or zoomed viewport squeezes it regardless. */
.portrait-lead { float: none; width: 100%; max-width: 20rem; margin: 0 auto var(--gap-md); }
.portrait-lead .cutline { white-space: normal; font-size: var(--t-xs); }

@media (min-width: 34rem) {
  .portrait-lead { float: right; width: 38%; max-width: 16rem; margin: 0 0 var(--gap-md) var(--gap-md); }
}

/* ===== components/apex.css ===== */
.doors { display: grid; grid-template-columns: 1fr; gap: var(--gap-lg); }

.door { max-width: var(--measure); }

.door-line {
  font-family: var(--face-util);
  font-size: var(--t-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--stone);
  margin: 0 0 var(--gap-sm);
}

.door-role {
  font-family: var(--face-util);
  font-size: var(--t-sm);
  color: var(--iron);
  margin: var(--gap-xs) 0 0;
}

.crosslink {
  margin: 0 0 var(--gap-sm);
  padding-bottom: var(--gap-sm);
  border-bottom: 1px solid var(--rule);
}

.crosslink a { color: var(--iron); }

/* Separation between the properties is structural, not a second invented palette -
   we have no basis for one.
   
   The wilderness side used to drop the cover colours entirely on the grounds that they
   belong to the books. That still holds for its own furniture, but the works list carries
   each jacket's colour on the spine deliberately: there it IS the book being pointed at,
   and the colour is what makes the link read as a product rather than a footnote. */

@media (min-width: 48rem) {
  .doors { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-xl); }
}

/* ===== base/a11y.css ===== */
a:focus-visible,
.buy:focus-visible {
  outline: 2px solid var(--iron);
  outline-offset: 3px;
}

/* ======================================================================= *
 * Larger viewports. Additive only.
 * ======================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Skip link. First focusable element on the page; visible only when focused. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  padding: 0.6rem 1rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--face-util);
  font-size: var(--t-sm);
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

/* A heading that is read but not seen.
 *
 * The landing pages carry sections with no visible heading on purpose - an eyebrow over a
 * three-item list is tooling, not an instrument. But a section with no heading is a section a
 * screen-reader user cannot jump to, and a document outline with one h1 and nothing else gives
 * a search engine no structure to read. The heading exists; it is simply not drawn.
 *
 * This is NOT for stuffing keywords into invisible text. Each one names a section that is
 * genuinely there and visibly obvious to someone who can see it. */
.a11y-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
