/*
  Support Human — base design system.
  Palette, type scale and motifs from design/00-master-brief.md §2, amended by the link-color
  correction in design/09-site-decisions.md (chat 6, turn 17) and the contrast floors in CLAUDE.md.
  This file carries chrome (site-header, site-footer) plus the shared reset and type primitives
  every later template builds on. Section-specific styling (strips, cards, post layout) belongs
  in its own template pass, not here.
*/

:root {
  /* Core */
  --sh-ink: #030203;
  --sh-paper: #fdfdfd;
  --sh-hairline: #d8d5d0;

  /* Small-text color floor (CLAUDE.md) */
  --sh-grey-on-paper: #6b6b6b;
  --sh-grey-on-tint: #3a3a3a;
  --sh-grey-on-ink: #b8b6b4;

  /* Core accents */
  --sh-coral: #ee897c;
  --sh-peach: #fed5b7;
  --sh-blue: #69a3ff;
  --sh-purple-display: #a957b0;
  /* The third purple, display-only (41h, 14 Aug 2026). It exists for one situation:
     display type sitting on a ground made of the accent itself, where hue can no longer
     separate the two and value has to. 7.85:1 on paper against #a957b0's 4.41:1, so the
     page headline stops being a barely-large-text pass. Never below 15px — #8f3f96 is
     still the floor there — and never a fourth value. */
  --sh-purple-header: #7a3480;
  --sh-hot-pink: #fa5791;
  --sh-light-pink: #eda7e3;
  --sh-grey: #9c9c9c;
  --sh-green-bjb-only: #7fd6a2;
  --sh-career-suite-green: #c8e0b4;

  /* THE MARKER HIGHLIGHT (turn 38) — one device, one set of values, defined once.

     It had drifted into four different paints doing the same job: post.css's opaque #ee897c,
     the social cards' #f7cfc8, the authoring guide's #f7cac3 with a broken stop, and
     .wp-why__marked's #f7cec7. The handoff collapses the first three and says a fourth is
     drift; these tokens are what stops a fifth. post.css consumes them for pull quotes and
     body marks, main.css for the /who-pays-for-this/ and /bad-job-bingo/ lines.

     --sh-mark-ink is here so the alphas are readable and stay in one place, NOT as a hue knob:
     a custom property substitutes at computed-value time on the element that DEFINES it, so a
     child overriding --sh-mark-ink cannot re-tint a gradient declared up here on :root. The one
     variant carries its own pass below and says so. (Verified in the browser — the blue line on
     /bad-job-bingo/ rendered coral until this was understood.)

     The numbers are the adopted spec exactly. The tilt is the effect: DO NOT round
     179.1deg/180.9deg to 180, and do not widen the lower pass — both passes ending at the
     same point is `37b`/`37d`, rejected for reading as one printed bar. */
  --sh-mark-ink: 238, 137, 124;
  --sh-mark-two-pass:
    linear-gradient(179.1deg, rgba(var(--sh-mark-ink), 0) 14%, rgba(var(--sh-mark-ink), 0.4) 14%,
                              rgba(var(--sh-mark-ink), 0.4) 72%, rgba(var(--sh-mark-ink), 0) 72%),
    linear-gradient(180.9deg, rgba(var(--sh-mark-ink), 0) 34%, rgba(var(--sh-mark-ink), 0.42) 34%,
                              rgba(var(--sh-mark-ink), 0.42) 99%, rgba(var(--sh-mark-ink), 0) 99%);
  --sh-mark-two-pass-size: 100% 100%, calc(100% - 0.55em) 100%;
  --sh-mark-two-pass-pos: 0 0, 0.34em 0;
  --sh-mark-one-pass:
    linear-gradient(to bottom, rgba(var(--sh-mark-ink), 0) 18%, rgba(var(--sh-mark-ink), 0.55) 18%,
                               rgba(var(--sh-mark-ink), 0.55) 99%, rgba(var(--sh-mark-ink), 0) 99%);

  /* Links — purple is the signature color (09 turn 17), retired #0b6aff site-wide */
  --sh-link: #8f3f96;
  --sh-link-hover: #ee897c;
  --sh-link-on-ink: #c9a0d1;

  /* Footer / near-black ground */
  --sh-footer-bg: #030203;
  --sh-footer-tagline: #c084c8;
  --sh-footer-meta: #b8b6b4;
  /* Both footer greys sit on the near-black ground, where the floor is a minimum LIGHTNESS:
     never darker than #b8b6b4 (CLAUDE.md). The label was #9c9c9c at 10px — 7.5:1, under the
     floor's 10.3:1 — and is the same slip Clign caught in the canvases. */
  --sh-footer-label: #b8b6b4;
  --sh-footer-rule: #3a3a3a;

  /* Section strip tints (pale) — 00 §"Shared chrome" + 09 §4 for Career Suite */
  --sh-tint-newsletter: #fbe3de;
  --sh-tint-jobs: #cfe1ff;
  --sh-tint-resources: #fbe6d4;
  --sh-tint-footnotes: #fdd9e6;
  --sh-tint-career-suite: #c8e0b4;
  --sh-tint-portfolio: #f0e4f5;
  --sh-tint-closed: #e6e4e2;

  /* Darkened nav-active-rule tints (09 turn 14, all four record-carried since the
     10 Aug 2026 amendment): Jobs and Resources from the canvas; Newsletter and Footnotes
     derived by the same lightness/saturation reduction and confirmed by delegation.
     Career Suite is the fifth, ruled 13 Aug 2026 — turn 14 left it off because an active
     state would need a value nothing documented, and because the entry used to leave the
     site. It no longer does (the nav points at /career-suite/, Steph's 9 Aug ruling), so the
     one thing standing in the way was the value. Derived from #c8e0b4 by the same reduction
     as the other four. */
  --sh-active-newsletter: #eb9c8c;
  --sh-active-jobs: #6ea8f5;
  --sh-active-resources: #f0b98a;
  --sh-active-footnotes: #f282ab;
  --sh-active-career-suite: #8fbf6b;

  /* Type */
  --sh-font-display: 'Instrument Serif', Georgia, serif;
  --sh-font-body: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --sh-font-mono: 'Space Mono', monospace;

  --sh-gutter: 44px;
}

/* Reset */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* The column layout is the sticky-footer fix (critique, 13 Aug 2026): on a short page the footer
   used to stop wherever the content did, leaving bare paper under the heaviest object in the design
   — measured 68px on /account/ at a 900px viewport, and it grows with the screen (~370px at 1200).
   main takes the slack. Every template renders header → main → footer as siblings, so this needs no
   template change; the `> main` selector also covers the templates that wrap main in nothing else. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.5;
}
body > main {
  flex: 1 0 auto;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote { margin: 0; }

/* `height: auto` belongs with `max-width` and was the missing half of the pair. Ghost
   writes width= and height= on the images it has processed into srcset variants, and
   those attributes act as low-priority CSS: max-width squeezed the width while the
   height stayed pinned at the attribute, so the image rendered at the wrong shape —
   the Fin issue's closing meme came out 420×973 instead of 420×310, over three times
   too tall. Nothing on the site loses layout stability by this: with both dimensions
   auto AND both attributes present, browsers derive `aspect-ratio` from the attributes
   themselves, so the space is still reserved during load. Every element that wants a
   fixed image height sets it from a class, which outranks this. */
img { max-width: 100%; height: auto; display: block; }

button { font: inherit; }

/* Placeholder = the house small-text grey, not the UA default #757575 (which sat at
   4.53:1 — technically passing, but the floor value is the system's own answer).
   Every input in this theme sits on the paper ground, where the floor is #6b6b6b. */
input::placeholder,
textarea::placeholder {
  color: var(--sh-grey-on-paper);
  opacity: 1; /* Firefox dims placeholders by default */
}

/* Links — purple, hover coral (paper); on the footer's near-black ground, light purple */
a {
  color: var(--sh-link);
}
a:hover {
  color: var(--sh-link-hover);
}

/* On any tinted or near-black surface, links go back to ink + underline — the tint/ground itself
   carries the affordance instead of color (00 §2, "the contrast rule"). Apply this class to any
   wrapper sitting on a section tint. */
.sh-on-tint a {
  color: var(--sh-ink);
  text-decoration: underline;
}

/* Baseline keyboard focus — the ruled 3px device (shelf search, contact form, services topics)
   extended to everything that lacks its own treatment; controls with their own focus rules
   override by specificity.

   THE TWO-VALUE RULE APPLIES TO THE FOCUS RING TOO (critique, 13 Aug 2026). The original rule
   was a single blue value checked against the near-black grounds, where it clears 8.17:1 — but
   the site is overwhelmingly paper, and there blue #69a3ff measures 2.49:1 (1.92:1 on the jobs
   tint) against WCAG 2.2 SC 1.4.11's 3:1 floor for a focus indicator. So the ring takes its two
   values like every other accent: ink on paper and on every tint (20.36:1), blue on the
   near-black grounds where ink would be invisible (8.17:1).

   --sh-focus is flipped by the ink-ground CONTAINERS listed below, not by ink-filled controls:
   the ring sits 2px OUTSIDE its element, so what it needs to clear is the parent's ground. An
   ink button on paper keeps the ink ring (the 2px gap shows paper through). The hairline grids
   (home chips, contact cards, error doors) are included because their cells are tinted but the
   gap the ring lands in is the grid's own ink. */
:root {
  --sh-focus: var(--sh-ink);
}
:focus-visible {
  outline: 3px solid var(--sh-focus);
  outline-offset: 2px;
}
.site-footer,
.funding-band,
.ask-band,
.error-hero,
.error-doors,
.legal-close,
.contact-cards,
.contact-elsewhere,
.home-chips,
.home-suite__tools,
.news-picks__grid,
.wp-refusals,
.wp-means,
.bjb-hero,
.bjb-samples,
.bjb-shelves,
.cs-hero,
.fr-cells,
.about-places {
  --sh-focus: var(--sh-blue);
}

/* --------------------------------------------------------------------------
   Selection, and arrival at a shared passage.

   Highlighting was the one moment on the site still painted by the browser —
   default blue, a color that appears nowhere in the palette, at exactly the
   point a reader is engaging hardest with the writing. Coral with ink on top
   is the house rule for an accent (a surface, never type), and it makes the
   reader's highlighting the same gesture as `25d`'s marked pull quote: coral
   swiped under the line that matters. Steph picks one per issue; the reader
   picks their own, in the same color.

   ::target-text is the same paint for a passage someone was SENT to — a
   shared link carrying a #:~:text= fragment. The browser applies it natively,
   so arriving at a quoted passage lands in the site's own color rather than
   the browser's yellow. The fragment itself is deliberately unreadable from
   JavaScript, so this pseudo-element is the only way to dress that arrival —
   which is why it is CSS here and not a class in post.js.
   -------------------------------------------------------------------------- */
::selection {
  background: var(--sh-coral);
  color: var(--sh-ink);
}
::target-text {
  background: var(--sh-coral);
  color: var(--sh-ink);
}

/* Coral on coral is no selection at all. The few coral surfaces carrying real
   copy take the active-chip inversion instead — ink ground, paper text. */
.services-joke ::selection,
.funding-stamp ::selection,
.cs-stamp ::selection,
.wp-stamp ::selection {
  background: var(--sh-ink);
  color: var(--sh-paper);
}

/* Nothing in this system listens for transition/animation end, so the guard can be a blanket. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Decorative twinkle — aria-hidden at the call site, never text content */
.sh-twinkle {
  font-family: var(--sh-font-display);
  color: var(--sh-coral);
  font-style: normal;
}

/* The home page winks once on arrival (Steph's ruling, 12 Aug 2026, 12 §8): each eyebrow
   twinkle glints in reading order shortly after load. Home only — navigating anywhere
   else stays still. The success-state twinkle glints when its message reveals instead:
   animations don't run while the parent is display:none, which is exactly the timing
   we want. Transform-only; the reduced-motion blanket zeroes it. */
@keyframes sh-twinkle-glint {
  0%, 100% { transform: scale(1) rotate(0deg); }
  50% { transform: scale(1.3) rotate(18deg); }
}
.home .sh-twinkle {
  display: inline-block;
  animation: sh-twinkle-glint 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.6s 1 both;
}
.home .home-latest__eyebrow .sh-twinkle { animation-delay: 0.78s; }
.home .home-more__eyebrow .sh-twinkle { animation-delay: 0.96s; }
/* The success-state twinkle glints on EVERY page's subscribe card, not just home — it
   fires at the reveal (the parent is display:none until Ghost's .success lands), so it
   is a success celebration, not an arrival wink; the home-only ruling governs arrival
   (12 §8, extended for the newsletter pass). */
.sh-form-state .sh-twinkle {
  display: inline-block;
  animation: sh-twinkle-glint 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.15s 1 both;
}

/* ---------------------------------------------------------------------------
   THE PAGE HEADER'S DOT FIELD (09, 14 Aug 2026 — frames 41a/41b/41c), and the two twinkles
   that ride with it. Defined once here for every band that takes it, because eight copies of
   the same nine declarations is the duplication that drifts.

   It began as the /newsletter/ hero's device and generalised to every page header: they were
   flat white slabs sitting between a tinted strip and a colored band, and they read as the
   emptiest thing on their own pages.

   THE RULE FOR WHETHER A HEADER IS ON THIS LIST: every page header carries the field, except
   one that already carries a screen of its own — .wp-hero, .bjb-hero, .cs-hero, .error-hero
   and .events-header all have one, and two screens on one band is two. The other exception is
   a header that is not a full-bleed band at all: .page-header is a max-width block inside the
   page's own padding, so a field on it would be a floating rectangle rather than a band.

   Purple, not the section accent: 41g built one-color-per-section and it fails as a set —
   peach needs roughly 0.85 opacity to register at all, so the value becomes a per-section
   number tuned by eye, and portfolio's accent IS the headline purple, so that page would have
   to drop its headline to near-black. The section signal is the tinted strip above; the band
   is house furniture, and purple is the house's own signature (links, footer tagline,
   masthead italic).
   --------------------------------------------------------------------------- */
.board-header,
.home-hero,
.news-hero,
.about-hero,
.tag-header,
.legal-hero,
.contact-hero,
.browse-header { position: relative; overflow: clip; }

.board-header::before,
.home-hero::before,
.news-hero::before,
.about-hero::before,
.tag-header::before,
.legal-hero::before,
.contact-hero::before,
.browse-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-purple-display) 0.9px, transparent 1px);
  background-size: 6px 6px;
  opacity: 0.22;
  pointer-events: none;
}

.board-header > *:not(.sh-sparks),
.home-hero > *:not(.sh-sparks),
.news-hero > *:not(.sh-sparks),
.about-hero > *:not(.sh-sparks),
.tag-header > *:not(.sh-sparks),
.legal-hero > *:not(.sh-sparks),
.contact-hero > *:not(.sh-sparks),
.browse-header > *:not(.sh-sparks) { position: relative; }

/* Header sparks — the dot field's companions (41a–41c, 14 Aug 2026). Two coral twinkles,
   pulsing out of phase, one at each end of the band's COLUMN GUTTER.

   The canvas put them at hard pixel offsets on the right, because a single-column stack left
   a dead zone across the middle-right of the band that something had to occupy. Live's
   headers fill both columns, so there is no dead zone to fill and those coordinates would
   drop a glyph on top of the copy. Measured instead: the gutter is the one strip of all four
   bands that is empty at every viewport whatever the copy does, so they run down the fold
   between the columns — which is where a broadsheet would put an ornament anyway.

   --sh-sparks-x is the x of that gutter's centre, per band, because the two heroes do not
   split 1fr 1fr. If a band's column width or gap changes, this changes with it.

   Glyphs are pseudo content so no band needs two more spans; the host carries aria-hidden.
   Animating `scale`/`opacity` rather than `transform` leaves `translate` free to do the
   centering — a transform keyframe would clobber it. They rest at full opacity, so the
   reduced-motion blanket (~232) leaves a visible static twinkle rather than a faded one. */
@keyframes sh-sparkle-pulse {
  0%, 100% { opacity: 0.35; scale: 0.85; }
  50%      { opacity: 1;    scale: 1.1; }
}
.sh-sparks { position: absolute; inset: 0; pointer-events: none; }
.sh-sparks::before,
.sh-sparks::after {
  position: absolute;
  left: var(--sh-sparks-x);
  font-family: var(--sh-font-display);
  font-style: normal;
  line-height: 1;
  color: var(--sh-coral);
  animation: sh-sparkle-pulse 3.4s ease-in-out infinite;
}
.sh-sparks::before {
  content: "✦";
  font-size: 20px;
  top: 30px;
  translate: -50% 0;
}
/* Below and right of the first, so the two read as one small constellation rather than two
   lone marks. Both anchored to the TOP of the band, not one to each end: the bottom of every
   one of these bands is where both columns finish, so a glyph there lands beside the margin
   note's rule and reads as a stray dot next to it. */
.sh-sparks::after {
  /* ✦, not the canvas's ✴ — 00 §2 retired ✴ site-wide in chat 2 and the record beats the
     frame. The pair separates by size and phase instead of by glyph. */
  content: "✦";
  font-size: 13px;
  top: 68px;
  translate: 10% 0;
  animation-duration: 4.1s;
  animation-delay: -1.4s;
}

.sh-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.sh-skip-link {
  position: absolute;
  left: 12px;
  top: -48px;
  z-index: 100;
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 12px 16px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  transition: top 0.15s ease;
}
.sh-skip-link:focus {
  top: 12px;
}

/* Members subscribe form states (home + /newsletter/ cards). Ghost's portal script toggles
   .loading/.success/.error on [data-members-form]; the .sh-form-state line under the form is
   CSS-revealed from those classes so a submit always answers. The container stays rendered
   (aria-live needs it in the tree); only the messages toggle. Mono meta voice, ink on the
   tint (the on-tint floor is #3a3a3a); state is told by the words, never by color alone. */
form[data-members-form].loading button {
  pointer-events: none;
  opacity: 0.55;
  cursor: wait;
}
.sh-form-state__msg {
  display: none;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.55;
  color: var(--sh-ink);
}
form[data-members-form].success + .sh-form-state .sh-form-state__msg--success { display: block; }
form[data-members-form].error + .sh-form-state .sh-form-state__msg--error { display: block; }
/* Ghost fills [data-members-error] with a reason when it has one; this is the fallback. */
.sh-form-state__msg--error:empty::before {
  content: "That didn't send. Give it a minute and try again.";
}

/* THE HOUSE ARROW (delight passes, 12–14 Aug 2026 — resources `Open it ↗`, the chrome's
   `WHO PAYS FOR THIS →`, the portfolio's doors). An arrow points at something, so it leans
   toward what it points at when its link is pointed at or keyboard-entered. Always its own
   aria-hidden span: it moves without dragging the words, and it is never spoken.
   Descendant, not child — several call sites wrap the label in a state span. */
.sh-arrow {
  display: inline-block;
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
a:hover .sh-arrow,
a:focus-visible .sh-arrow {
  transform: translateX(3px);
}
/* The one arrow that points home. Source order carries it — same specificity as the rule above. */
a:hover .sh-arrow--back,
a:focus-visible .sh-arrow--back {
  transform: translateX(-3px);
}
/* The arrow that points OFF THE SITE leans diagonally, because that is where ↗ points.
   Extracted 16 Aug 2026 on the same three-instance threshold as .sh-arrow itself: the
   footnotes entry title (04a §12) and the library entry's `Open it ↗` (02a §12) had each
   hand-rolled this lean, and /about/'s Elsewhere rail would have been the third. Both
   bespoke rules were deleted in favour of this one; the call sites keep their own classes
   for size and color and add these two for the motion. 2px on each axis, not 3 — the
   diagonal's magnitude is 2.83, which matches the straight arrow's step. */
a:hover .sh-arrow--out,
a:focus-visible .sh-arrow--out {
  transform: translate(2px, -2px);
}

/* Hit-area floor (WCAG 2.5.8): the short inline links grow their tap height to ≥24px
   without moving a pixel — padding-block matched by an equal negative margin, so layout,
   baselines and rules stay exactly where they are. Visual values untouched. */
.home-hero__links a,
.home-subscribe__rss a,
.home-latest__all,
.funding-band__link,
.news-subscribe__rss,
.site-footer__who-pays,
.site-footer__utility-links a,
/* Three more found by the 13 Aug 2026 critique sweep, measured against the 24px floor:
   the specimen read CTA (17px — the primary action on /portfolio/), the search box's own
   Clear (19px, the recovery control on the site's main input), and the section strip's
   right-hand action (18px, present on every section index). */
.specimen__read,
.search-bar__clear,
.section-strip__action {
  padding-block: 6px;
  margin-block: -6px;
}
.site-footer__group-link {
  padding-block: 4px;
  margin-block: -4px;
}

/* ==========================================================================
   Koenig card widths — Ghost requires these to exist (gscan GS050).
   Base definitions only. design/09-site-decisions.md turn 35 maps them onto the post grid:
   Regular = the 562px measure, Wide = spans the notes margin and contents rail, and
   Full is deliberately NOT used on posts (a viewport-bleeding image fights the three-column
   grid). The post template pass sets the real values against that grid; these keep the
   classes defined everywhere else content can render.
   ========================================================================== */

.kg-width-wide {
  width: 100%;
}

.kg-width-full {
  width: 100%;
}

/* ==========================================================================
   Site header — masthead + nav (design 14a) and the mobile overlay (14b)
   ========================================================================== */

.site-header {
  border-bottom: 1px solid var(--sh-ink);
  background: var(--sh-paper);
}

.site-header__row {
  padding: 22px var(--sh-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
}

.site-header__brand {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
  text-decoration: none;
}
.site-header__brand:hover { color: var(--sh-ink); }

.site-header__avatar {
  width: 72px;
  height: auto;
  display: block;
  flex: none;
}

/* min-width: max-content, NOT 0 (critique, 13 Aug 2026). With min-width: 0 the flex row was free
   to crush this group, and the global `img { max-width: 100% }` reset then overrode the wordmark's
   explicit width: measured 63px at 920px viewport and 103px at 960px against a designed 256px, with
   the nowrap tagline overflowing toward the nav. `flex: none` does not protect against this — it
   governs the column's own main axis, not the parent's horizontal shrink. See the wordmark rule
   below for the second half of the fix. */
.site-header__wordmark-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: max-content;
}

/* max-width: none is load-bearing — it is what stops the img reset at the top of this file from
   scaling the mark down when space gets tight. CLAUDE.md's "always an explicit width and height
   plus flex: none" holds; this is the third guard the same rule needed. */
.site-header__wordmark {
  height: 24px;
  width: 256px;
  max-width: none;
  flex: none;
  display: block;
}

.site-header__tagline {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 18px;
  line-height: 1;
  color: var(--sh-ink);
  white-space: nowrap;
}

/* Desktop nav */
.site-nav {
  display: flex;
  align-items: center;
  gap: 24px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* nowrap: a two-word nav item ("Career Suite") breaking across two lines took the whole row
   ragged and 6px taller — measured wrapping from 1160px down. The nav row is a fixed set of
   short labels; if they cannot sit on one line the overlay is the right answer, not a fold. */
.site-nav__link {
  position: relative;
  color: var(--sh-ink);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  padding-bottom: 3px;
  white-space: nowrap;
}
.site-nav__link[aria-current="page"] {
  font-weight: 700;
  border-bottom-color: var(--sh-nav-active-tint, var(--sh-ink));
}

/* THE NAV WIPES IN THE COLOR OF WHERE YOU'D LAND (delight pass, 14 Aug 2026).
   The hover mark used to be a grey hairline, which said "this is a link" — something a nav
   row does not need to say. It now paints the section's own darkened tint left-to-right, the
   same value turn 14 settled for that section's active rule, so the reader sees the color of
   the page before committing to it. Color still says where you are; this says where you'd be.

   A wiped ::after rather than the border-bottom, for two reasons: a border color cannot
   animate directionally, and keeping the two devices separate keeps the two states separate —
   the page you are ON has its rule painted already and never rehearses (the wipe is suppressed
   on [aria-current]), so a moving mark always means "not here yet" and the static one always
   means "here". Left-to-right because a hand draws that way; same gesture as the post's
   highlighter swipe (09, post delight pass §3). Reduced motion → the blanket zeroes the
   duration and the mark simply appears, which is still the right answer. */
.site-nav__link::after,
.site-nav__search::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--sh-nav-hover-tint, var(--sh-ink));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.site-nav__link:hover::after,
.site-nav__link:focus-visible::after,
.site-nav__search:hover::after,
.site-nav__search:focus-visible::after {
  transform: scaleX(1);
}
.site-nav__link[aria-current="page"]::after {
  content: none;
}
.site-nav__link[data-section="newsletter"] { --sh-nav-hover-tint: var(--sh-active-newsletter); }
.site-nav__link[data-section="jobs"] { --sh-nav-hover-tint: var(--sh-active-jobs); }
.site-nav__link[data-section="resources"] { --sh-nav-hover-tint: var(--sh-active-resources); }
.site-nav__link[data-section="footnotes"] { --sh-nav-hover-tint: var(--sh-active-footnotes); }
.site-nav__link[data-section="career-suite"] { --sh-nav-hover-tint: var(--sh-active-career-suite); }

/* Search entry (18 §A masthead placement; icon form ruled 8 Aug 2026). Takes the same wipe as
   the text links so the row still moves as one; ink, because search is not a section and has
   no tint of its own. */
.site-nav__search {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: var(--sh-ink);
  border-bottom: 2px solid transparent;
  padding-bottom: 3px;
}
.site-nav__search svg { display: block; }

.site-nav__subscribe {
  font-weight: 700;
  color: var(--sh-paper);
  background: var(--sh-ink);
  text-decoration: none;
  padding: 9px 16px;
}
.site-nav__subscribe:hover {
  color: var(--sh-paper);
  background: var(--sh-grey-on-paper);
}

/* Per-section active-tint hook: each template that includes this partial with active="jobs"
   etc. gets a body/header modifier class that sets --sh-nav-active-tint. */
.site-header--active-newsletter { --sh-nav-active-tint: var(--sh-active-newsletter); }
.site-header--active-jobs { --sh-nav-active-tint: var(--sh-active-jobs); }
.site-header--active-resources { --sh-nav-active-tint: var(--sh-active-resources); }
.site-header--active-footnotes { --sh-nav-active-tint: var(--sh-active-footnotes); }
.site-header--active-career-suite { --sh-nav-active-tint: var(--sh-active-career-suite); }

.site-header__menu-toggle {
  display: none;
}

/* Mobile overlay menu (14b) */
.site-header__overlay {
  display: none;
}

/* 1120px, not 900 (critique, 13 Aug 2026). The desktop row needs brand (~350) + gap (40) +
   nav (639, now that the links are nowrap) + gutters (88) = ~1129px to sit on one line, so 1140
   with a little air. Below that the old 900px breakpoint kept the desktop nav and paid for it
   twice: "Career Suite" wrapped to two lines (measured up to 1160px before the nowrap rule), and
   the brand was squeezed to a quarter width (see the wordmark rules above). The overlay is the
   better answer for the whole band — it was already the answer 240px lower. */
@media (max-width: 1140px) {
  .site-nav { display: none; }

  .site-header__menu-toggle {
    display: inline-flex;
    align-items: center;
    font-family: var(--sh-font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sh-paper);
    background: var(--sh-ink);
    border: none;
    text-decoration: none;
    padding: 11px 14px;
    cursor: pointer;
  }

  .site-header__row {
    padding: 14px 18px;
  }
  .site-header__avatar { width: 44px; }
  .site-header__wordmark { height: 17px; width: 181.33px; }
  .site-header__tagline { display: none; }

  .site-header__overlay {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 90;
    background: var(--sh-paper);
    overflow-y: auto;
    transform: translateY(-100%);
    transition: transform 0.18s ease;
  }
  .site-header__overlay[data-open="true"] {
    transform: translateY(0);
  }

  .site-header__overlay-top {
    padding: 14px 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    border-bottom: 1px solid var(--sh-ink);
  }

  .site-header__overlay-close {
    font-family: var(--sh-font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sh-ink);
    background: var(--sh-paper);
    border: 1px solid var(--sh-ink);
    text-decoration: none;
    padding: 10px 14px;
    cursor: pointer;
  }

  .site-header__overlay-nav {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .site-header__overlay-link {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 17px 18px;
    border-bottom: 1px solid var(--sh-ink);
    color: var(--sh-ink);
    text-decoration: none;
  }
  .site-header__overlay-link--newsletter { background: var(--sh-tint-newsletter); }
  .site-header__overlay-link--jobs { background: var(--sh-tint-jobs); }
  .site-header__overlay-link--resources { background: var(--sh-tint-resources); }
  .site-header__overlay-link--footnotes { background: var(--sh-tint-footnotes); }
  .site-header__overlay-link--career-suite { background: var(--sh-tint-career-suite); }

  /* THE OVERLAY DEALS ITS SECTIONS (delight pass, 14 Aug 2026). The panel slid in as one
     rectangle and the five tinted rows — the best thing in this theme — arrived as wallpaper.
     They now land in reading order behind the panel's own 180ms slide, 40ms apart, which is
     the odometer's cadence (visitor-counter.js steps its cells by 45ms) applied to the other
     mechanical object in the chrome.

     An animation, not a transition, and scoped to [data-open="true"]: the resting state is a
     fully visible row, so a headless render, a hidden tab or a browser that never runs the
     keyframes still gets the whole menu. Nothing here gates content on a class.

     The row you are already on does NOT deal — it is already placed. See the aria-current
     block below. */
  @keyframes sh-overlay-deal {
    from { opacity: 0; transform: translateY(-10px); }
    to { opacity: 1; transform: translateY(0); }
  }
  .site-header__overlay[data-open="true"] .site-header__overlay-link {
    animation: sh-overlay-deal 0.24s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  .site-header__overlay-nav li:nth-child(1) .site-header__overlay-link { animation-delay: 0.14s; }
  .site-header__overlay-nav li:nth-child(2) .site-header__overlay-link { animation-delay: 0.18s; }
  .site-header__overlay-nav li:nth-child(3) .site-header__overlay-link { animation-delay: 0.22s; }
  .site-header__overlay-nav li:nth-child(4) .site-header__overlay-link { animation-delay: 0.26s; }
  .site-header__overlay-nav li:nth-child(5) .site-header__overlay-link { animation-delay: 0.30s; }

  /* THE OVERLAY SAYS WHICH ROW YOU ARE STANDING ON (delight pass, 14 Aug 2026). The masthead
     has carried an active state since turn 14, and the overlay — the only navigation that
     exists below 1140px — carried none at all: the 13 Aug critique measured no aria-current
     anywhere on mobile. The row now takes the house's own selected grammar on its count slot
     (chip-active: ink ground, paper text, 20.4:1) rather than a sixth color, and the link
     carries aria-current="page" for the readers who cannot see either.

     It is also the one row that does not deal in — the deal is the menu arriving, and this
     row is where the reader already is. */
  .site-header__overlay-link[aria-current="page"] .site-header__overlay-link-count {
    background: var(--sh-ink);
    color: var(--sh-paper);
    padding: 3px 7px;
    font-weight: 700;
  }
  .site-header__overlay[data-open="true"] .site-header__overlay-link[aria-current="page"] {
    animation: none;
  }

  .site-header__overlay-link-label {
    font-family: var(--sh-font-display);
    font-size: 30px;
    line-height: 1;
  }
  /* uppercase here, not in the copy (critique, 13 Aug 2026): four of these rows are server-rendered
     mono caps ("58 ISSUES", "38 OPEN", "240 LISTED", "4 TOOLS") and the fifth is written by
     footnotes.js, which owes the home chip its sentence-case "46 entries" per 09 §2. Casing the
     slot rather than the string keeps both records true and the row voice consistent. */
  .site-header__overlay-link-count {
    font-family: var(--sh-font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .site-header__overlay-foot {
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .site-header__overlay-subscribe {
    display: block;
    text-align: center;
    background: var(--sh-ink);
    color: var(--sh-paper);
    text-decoration: none;
    padding: 15px;
    font-family: var(--sh-font-body);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .site-header__overlay-utility {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 18px;
    font-family: var(--sh-font-mono);
    font-size: 11px;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .site-header__overlay-utility a { color: var(--sh-ink); }
}

/* ==========================================================================
   Site footer (design 14d — the adopted "medium" option)
   ========================================================================== */

.site-footer {
  background: var(--sh-footer-bg);
  color: var(--sh-paper);
}

.site-footer__columns {
  padding: 36px var(--sh-gutter) 30px;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 44px;
}

.site-footer__brand-col {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.site-footer__wordmark {
  height: 22px;
  width: 234.66px;
  flex: none;
  display: block;
  align-self: flex-start;
}
.site-footer__tagline {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 24px;
  line-height: 1.15;
  color: var(--sh-footer-tagline);
}
.site-footer__policy {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.5;
  color: #e6e4e2;
  max-width: 34ch;
}
.site-footer__who-pays {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--sh-link-on-ink);
}
/* Its arrow rides the shared .sh-arrow device (defined above the hit-area block). */
.site-footer__joke {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--sh-footer-meta);
  max-width: 36ch;
  margin-top: 2px;
}

.site-footer__group {
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.site-footer__group-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--sh-footer-label);
}
.site-footer__group-link {
  font-family: var(--sh-font-display);
  font-size: 20px;
  color: var(--sh-paper);
  text-decoration: none;
}
/* Declare-on-hover, the house vocabulary (the ramps, the library card's `More →`): color
   alone was doing the work in a column of twenty 20px serif links, where the color shift is
   the hardest thing on the page to notice. Underline + color, with focus parity. */
.site-footer__group-link:hover,
.site-footer__group-link:focus-visible {
  color: var(--sh-link-on-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.site-footer__utility-row {
  border-top: 1px solid var(--sh-footer-rule);
  padding: 18px var(--sh-gutter) 22px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  flex-wrap: wrap;
}

.site-footer__utility-links {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
}
.site-footer__utility-links a { color: var(--sh-link-on-ink); }

.site-footer__copyright {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-footer-meta);
}

/* Visitor counter — live, backed by Supabase. See assets/js/visitor-counter.js.
   The [hidden] rule needs to be explicit: a bare `hidden` attribute loses to the class's own
   `display: flex`, so without it the empty counter would flash before JS fills it. */
.site-footer__counter {
  display: flex;
  flex-direction: column;
  gap: 7px;
  align-items: flex-end;
}
.site-footer__counter[hidden] {
  display: none;
}
.site-footer__counter-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--sh-footer-meta);
  text-transform: uppercase;
}
.site-footer__counter-digits {
  display: flex;
  gap: 3px;
}
.site-footer__counter-digit {
  width: 24px;
  height: 30px;
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 17px;
  overflow: hidden;
}
/* The odometer roll: each cell holds a strip of 0–9 and rolls to its digit on hydrate,
   because a mechanical counter should behave like one. Percent transform = strip-relative,
   so -10% per digit regardless of cell size. Leading zeros genuinely don't move. The
   reduced-motion blanket zeroes the duration, so the count simply appears. */
.site-footer__counter-strip {
  display: block;
  transform: translateY(0);
  transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}
.site-footer__counter-strip span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 30px;
}

@media (max-width: 900px) {
  .site-footer__columns {
    grid-template-columns: 1fr 1fr;
    gap: 32px 24px;
  }
  .site-footer__brand-col {
    grid-column: 1 / -1;
  }
  .site-footer__utility-row {
    flex-direction: column;
    align-items: flex-start;
  }
  .site-footer__counter {
    align-items: flex-start;
  }
}


/* ==========================================================================
   /newsletter/ (index-newsletter.hbs) and shared section components.
   The section strip, the chip and the funding band are shared: the funding band appears on
   the home page too, and the strip belongs to every section template still to be built.
   ========================================================================== */

/*
  /newsletter/ — frame 11d. See index.hbs for why this page introduces before it archives.
  Shared components that later index-*.hbs templates will reuse (the section strip, the chip,
  the funding band) live here for now and should move into main.css the moment a second
  section template needs them, rather than being copied.
*/

/* --------------------------------------------------------------------------
   Section strip — shared chrome. A full-bleed bordered band under the masthead, tinted per
   section, carrying exactly three things: section identity, the live count, and the one
   action that section wants.
   -------------------------------------------------------------------------- */

.section-strip {
  border-bottom: 1px solid var(--sh-ink);
  padding: 9px var(--sh-gutter);
  display: flex;
  gap: 9px;
  align-items: center;
  flex-wrap: wrap;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.section-strip--newsletter { background: var(--sh-tint-newsletter); }
.section-strip--jobs { background: var(--sh-tint-jobs); }
.section-strip--resources { background: var(--sh-tint-resources); }
.section-strip--footnotes { background: var(--sh-tint-footnotes); }

.section-strip__name { font-weight: 700; }
.section-strip__count { white-space: nowrap; }

/* Separators are generated by the segment that follows them, never typed into the markup.
   That is what makes the zero rule work: a recency count renders as an empty span when its
   number is zero, `:empty` removes it, and its "·" goes with it rather than stranding itself
   against the next segment. `0 NEW THIS WEEK` would announce a quiet stretch across the top
   of the page, which is the same objection that ruled out the fundraiser thermometer.
   Separators are decoration, so they are hidden from assistive tech. */
/* The name→detail separator is the coral ✦ (01a §2.2 / 00 §2: "coral ✦ as the opening
   mark and as separators" — the copy is verbatim "✦ THE JOB BOARD ✦ HOME OF…").
   Counts keep the grey middle dot, matching the same copy's "· 39 OPEN · …". */
.section-strip__detail::before {
  content: "✦";
  padding-right: 9px;
  color: var(--sh-coral);
}
.section-strip__count::before {
  content: "·";
  padding-right: 9px;
  color: var(--sh-grey-on-tint);
}
.section-strip__count:empty { display: none; }

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.news-hero {
  border-bottom: 1px solid var(--sh-ink);
  padding: 52px var(--sh-gutter) 46px;
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 56px;
  align-items: center;
  /* Right column (400) + half the gap (28), measured in from the band's right edge. */
  --sh-sparks-x: calc(100% - var(--sh-gutter) - 428px);
}
/* The dot field, at the settled values (41h, 14 Aug 2026). This band is where the device
   started, in coral at 0.4; it was recolored when the field went to every section front
   door, so that all five carry one field rather than this one being the odd warm one.
   The headline here stays ink — it is the marketing statement at full volume, and the
   purple headline belongs to the .board-header pages. */

.news-hero__pitch,
.news-subscribe { position: relative; }

.news-hero__pitch { display: flex; flex-direction: column; gap: 18px; }

/* Uncensored, deliberately — the archive below runs "assholes" and "goddamn" at full size, so
   starring the marketing copy was the only inconsistent option.

   The header purple, like every other page headline (14 Aug 2026) — which also makes this
   band the matched pair the other five are: display type in #7a3480 over a field made of
   #a957b0, where value separates type from ground because hue no longer can.

   The breaks are hand-placed, not balanced — four lines, one beat each (Steph, 14 Aug 2026),
   the same four-line stack the home hero runs. `balance` optimised for even line length and
   split the clauses in the wrong places; a single break after the second sentence then
   orphaned one word at every width below 1440 ("tech." alone at 1360, "bullshit." and
   "and tech." both at 1280).

   The size is derived, not guessed. Measured in Instrument Serif at this tracking, the four
   lines need 4.149 / 5.826 / 6.571 / 4.943 px of width per 1px of font-size, so the third one
   governs and the column is the viewport less the gutters, the gap and the card. Dividing by
   6.7 with 560px off keeps headroom for the scrollbar.

   The 80px cap is a HEIGHT decision, not a width one — width alone would allow 136px. Sizing
   it to stand exactly level with the 390px subscribe card put it at 92px and that was too
   loud (Steph, 14 Aug 2026); 80 leaves the pitch column ~40px shorter than the card, which
   `align-items: center` absorbs, and still reads bigger than the 76px this carried when it
   was two lines. The 54px floor is what the band just above the 900px breakpoint needs.

   IF THE COPY OR THE BREAKS CHANGE, RE-MEASURE: a longer line needs a bigger divisor, and a
   different line count changes what fills the card's height. */
.news-hero__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: clamp(54px, calc((100vw - 560px) / 6.7), 80px);
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--sh-purple-header);
}
.news-hero__sub {
  font-family: var(--sh-font-body);
  font-size: 18px;
  line-height: 1.55;
  max-width: 58ch;
}

.news-subscribe {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.news-subscribe__heading {
  font-family: var(--sh-font-display);
  font-size: 28px;
  font-weight: 400; /* explicit: the element is an h2, which would otherwise bold */
  line-height: 1.06;
}
.news-subscribe__sub {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.5;
}
.news-subscribe__form { display: flex; flex-direction: column; gap: 12px; }
.news-subscribe__form input {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 12px;
  font-family: var(--sh-font-mono);
  font-size: 14px;
  width: 100%;
}
.news-subscribe__form button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 13px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  width: 100%;
}
.news-subscribe__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.55;
}
.news-subscribe__rss {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-ink);
  border-top: 1px solid var(--sh-hairline);
  padding-top: 10px;
}

/* --------------------------------------------------------------------------
   The three series panels — hairline grid made from a black background showing through gaps.
   -------------------------------------------------------------------------- */

.news-series {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.news-series__panel {
  padding: 26px 28px 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.news-series__panel--bjb { background: #fcbcd2; }
.news-series__panel--roundup { background: #cfe1ff; }
.news-series__panel--deep { background: #e5cde8; }

.news-series__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.news-series__headline {
  font-family: var(--sh-font-display);
  font-size: 32px;
  line-height: 1.04;
}
.news-series__body {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.5;
}
/* Steph's own line about the series — pushed to the foot so the three panels' asides align
   regardless of how long the body copy above them runs. */
.news-series__aside {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 15px;
  line-height: 1.35;
  margin-top: auto;
  padding-top: 14px;
}

/* --------------------------------------------------------------------------
   Hand-picked issues
   -------------------------------------------------------------------------- */

.news-picks {
  padding: 34px var(--sh-gutter) 36px;
  border-bottom: 1px solid var(--sh-ink);
}
.news-picks__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 42px;
  margin-bottom: 6px;
}
.news-picks__sub {
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.5;
  margin-bottom: 20px;
}
.news-picks__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border: 1px solid var(--sh-ink);
}

/* The imageless card IS the treatment for issues, not a fallback — Steph dropped cover art to
   cut the work of publishing one. It fills its height with type. Never a grey box, never
   stock, never a shorter card that breaks the grid. */
.issue-card {
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 22px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.issue-card:hover { color: var(--sh-ink); }
/* The card declares its action on hover — same device as the home chips (12 §8). */
.issue-card:hover .issue-card__cta,
.issue-card:focus-visible .issue-card__cta { text-decoration: underline; text-underline-offset: 2px; }
.issue-card__top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 2px solid var(--sh-hairline);
  padding-bottom: 10px;
}
.issue-card--roundup .issue-card__top { border-bottom-color: #cfe1ff; }
.issue-card--bad-job-bingo .issue-card__top { border-bottom-color: #fcbcd2; }
.issue-card--deep-dives .issue-card__top { border-bottom-color: #e5cde8; }

/* Oversized numeral — the ISSUE NUMBER at 11d's 44px serif, digits riding the #issue-NNN
   tag description (09 turn 17 RESOLVED; drift item 72 — the bare day-of-month it used to
   print read as a false issue number). Same prefix-reveal device as .issue-row__cell-no;
   the day/month stack stays as the no-number fallback. Real content either way, so no
   aria-hidden. */
.issue-card__numeral {
  font-family: var(--sh-font-display);
  font-size: 44px;
  line-height: 0.82;
}
.issue-card__no { display: none; }
.issue-card__no[data-slug^="hash-issue-"]:not(:empty) { display: block; }
.issue-card__day { display: block; }
.issue-card__month {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
  margin-top: 3px;
}
.issue-card__numeral:has(.issue-card__no[data-slug^="hash-issue-"]:not(:empty)) .issue-card__day,
.issue-card__numeral:has(.issue-card__no[data-slug^="hash-issue-"]:not(:empty)) .issue-card__month {
  display: none;
}
.issue-card__series {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-align: right;
  line-height: 1.35;
  text-transform: uppercase;
}
.issue-card__title {
  font-family: var(--sh-font-display);
  font-size: 28px;
  line-height: 1.06;
}
.issue-card__dek {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.45;
}
.issue-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: auto;
  padding-top: 12px;
  color: var(--sh-grey-on-tint);
}
.issue-card__cta { color: var(--sh-link); }

/* --------------------------------------------------------------------------
   The archive
   -------------------------------------------------------------------------- */

.news-archive {
  padding: 30px var(--sh-gutter) 0;
  border-bottom: 1px solid var(--sh-ink);
}
.news-archive__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 4px;
}
.news-archive__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 42px;
}
.news-archive__range {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.news-archive__browse {
  margin-left: 14px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #8f3f96; /* link purple, small-size value */
}
.news-archive__sub {
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.5;
  margin-bottom: 18px;
}
.news-archive__filters {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

/* One chip system, everywhere. */
.chip {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  padding: 5px 11px;
}
.chip:hover { color: var(--sh-ink); }
.chip--active { background: var(--sh-ink); color: var(--sh-paper); }
.chip--active:hover { color: var(--sh-paper); }
/* Never a series tint on a chip (00 §Color, 07 §20): chips carry axis values elsewhere
   on the same page. Series color lives on the issue-number cell only. */

.issue-row {
  display: flex;
  gap: 20px;
  align-items: baseline;
  padding: 15px 0;
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
  margin: 0 calc(var(--sh-gutter) * -1);
  padding-left: var(--sh-gutter);
  padding-right: var(--sh-gutter);
}
.issue-row:hover,
.issue-row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.issue-row:hover .issue-row__meta,
.issue-row:focus-visible .issue-row__meta { color: var(--sh-grey-on-tint); }

/* The numeral cell. Shows the real issue number — the sequence in content/issue-numbers.md
   ("Steph's call: number them all"), backfilled as #issue-NNN internal tags 8 Aug 2026,
   resolving 09 turn 17's open question in favour of numbering. The digits are the tag's
   DESCRIPTION (a template cannot substring the name), prefix-revealed like every other
   tag-driven fact; the day/month stack remains as the fallback for any unnumbered post —
   which is exactly a future issue published before its tag is added. */
.issue-row__cell {
  width: 46px;
  flex: none;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  text-align: center;
  font-family: var(--sh-font-mono);
  padding: 3px 0 4px;
  display: flex;
  flex-direction: column;
  line-height: 1.1;
  align-self: center;
}
.issue-row--roundup .issue-row__cell { background: #cfe1ff; }
.issue-row--bad-job-bingo .issue-row__cell { background: #fcbcd2; }
.issue-row--deep-dives .issue-row__cell { background: #e5cde8; }

.issue-row__cell-day { font-size: 13px; font-weight: 700; }
.issue-row__cell-month {
  font-size: 10px; /* was 9px — below the 10px floor (CLAUDE.md); raised 8 Aug 2026 */
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.issue-row__cell-no { display: none; }
.issue-row__cell-no[data-slug^="hash-issue-"]:not(:empty) {
  display: block;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.5; /* matches the two-line day/month stack's height, so rows stay even */
}
.issue-row__cell:has(.issue-row__cell-no[data-slug^="hash-issue-"]:not(:empty)) .issue-row__cell-day,
.issue-row__cell:has(.issue-row__cell-no[data-slug^="hash-issue-"]:not(:empty)) .issue-row__cell-month {
  display: none;
}

/* The dek beneath this is capped at 567px (~76ch) and the headline above it was not, so a long
   Roundup title set as one unbroken 102-character line across a 1332px row while its own summary
   stayed measured (critique, 13 Aug 2026). Titles are scanned rather than read, which buys some
   latitude — 46em at 26px is ~46 words of headline, generous for a broadsheet and still short of
   the point where the eye loses the line. */
.issue-row__title {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.1;
  max-width: 46em;
}
.issue-row__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-left: auto;
  white-space: nowrap;
}

.news-pagination {
  padding: 18px 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  font-family: var(--sh-font-mono);
  font-size: 11px;
}
.news-pagination__link {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 6px 13px;
}
/* A spent pagination arrow is still text, not a disabled form control, so it takes the paper
   floor: #6b6b6b at 11px (5.2:1). It was --sh-grey #9c9c9c, which measures 2.7:1. */
.news-pagination__link--off {
  border-color: var(--sh-hairline);
  color: var(--sh-grey-on-paper);
}
.news-pagination__position {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sh-grey-on-tint);
}

/* --------------------------------------------------------------------------
   Quotes wall
   -------------------------------------------------------------------------- */

.news-quotes {
  border-bottom: 1px solid var(--sh-ink);
  padding: 34px var(--sh-gutter) 38px;
}
.news-quotes::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.3;
  pointer-events: none;
}
.news-quotes__head,
.news-quotes__grid { position: relative; }

.news-quotes__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 20px;
}
.news-quotes__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 42px;
}
.news-quotes__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sh-grey-on-tint);
}
.news-quotes__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  align-items: start;
}
.news-quotes__col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.news-quote {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Three accent cards, one per column (07-quotes-wall.md). These are the drawn
   values as quote-card grounds — not the chip/cell/strip tint scopes. */
.news-quote--blue { background: #cfe1ff; }
.news-quote--blush { background: #fbe3de; }
.news-quote--pink { background: #fcbcd2; }
/* A reader's words, so Instrument Serif italic — their words, not Steph's.
   Longer quote = smaller type; line-height eases as size drops so the columns
   sit roughly level (the spec's own table). */
.news-quote blockquote {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 19px;
  line-height: 1.28;
}
.news-quote--s17 blockquote { font-size: 17px; line-height: 1.32; }
.news-quote--s18 blockquote { font-size: 18px; line-height: 1.3; }
.news-quote--s19 blockquote { font-size: 19px; line-height: 1.28; }
.news-quote--s21 blockquote { font-size: 21px; line-height: 1.24; }
.news-quote--s24 blockquote { font-size: 24px; line-height: 1.22; }
.news-quote--s26 blockquote { font-size: 26px; line-height: 1.2; }
.news-quote figcaption {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.04em; /* the spec's tracking */
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}

/* --------------------------------------------------------------------------
   Funding band. The footer deliberately does NOT absorb this (14e was the version that did) —
   pages keep their own funding band as a designed moment and the footer stays furniture.
   -------------------------------------------------------------------------- */

/* The compact byline (09 turn 12 item 5, drawn in 11d): 62px headshot, one line,
   MORE ABOUT ME →. Sits between the quotes wall and the funding band. */
.news-byline {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 22px var(--sh-gutter) 24px;
  border-bottom: 1px solid var(--sh-ink);
}
.news-byline__headshot {
  width: 62px;
  height: 62px;
  flex: none;
  object-fit: cover;
  border: 1px solid var(--sh-ink);
}
.news-byline__line { font-size: 15px; line-height: 1.55; max-width: 72ch; }
.news-byline__more {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  white-space: nowrap;
}

.funding-band {
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 34px var(--sh-gutter) 38px;
  display: grid;
  grid-template-columns: 1fr 420px;
  gap: 56px;
  align-items: center;
}
.funding-band__pitch { display: flex; flex-direction: column; gap: 12px; }
.funding-band__heading {
  font-family: var(--sh-font-display);
  font-size: 40px;
  font-weight: 400; /* explicit: the element is an h2, which would otherwise bold */
  line-height: 1.04;
}
.funding-band__body {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.55;
  color: #e6e4e2;
  max-width: 44ch;
}
.funding-band__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-link-on-ink);
}

.funding-band__actions { display: flex; flex-direction: column; gap: 9px; }

/* The buttons name actions and are visually flat against each other on purpose: hedging one
   of them ranks the options, which policy forbids. The closing line removes the obligation
   for all three at once. */
.funding-band__button {
  border: 1px solid var(--sh-grey-on-paper);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 13px 18px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  font-family: var(--sh-font-body);
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* Delight (17 Aug 2026): the ask is the only thing this site asks for, and policy forbids
   every device that would push it — no ranking, no counts, no urgency, no advance thanks.
   What is left to earn a click is craft, and these were the least-made buttons in the theme.
   The outline pair twitched a border color, and the PRIMARY'S ONLY HOVER STATE WAS AN UNDO:
   `:hover { color: var(--sh-ink) }`, which exists solely to cancel the paper text the shared
   rule below sets. Restoring a resting value is not a response, so the loudest of the three
   answered the pointer with nothing at all.

   The outline pair now takes the house near-black button fill (`.legal-close__button`'s
   12% paper), and the arrows do the rest — see .sh-arrow at the top of this file. The three
   stay flat against each other: same gesture, same weight, differing only in where they go. */
.funding-band__button:hover,
.funding-band__button:focus-visible {
  color: var(--sh-paper);
  border-color: var(--sh-paper);
  background: rgba(253, 253, 253, 0.12);
}
.funding-band__button--primary {
  background: var(--sh-paper);
  color: var(--sh-ink);
  border-color: var(--sh-paper);
  font-weight: 700;
}
/* The primary is already at the filled end, so it sharpens instead: the house paper-ground
   hover (`.faq-jump__chip`'s inset ink rule). It still has to carry the three undos — same
   specificity as the shared rule, so every value that rule sets must be named again here or
   the button hovers to paper-on-paper. Hover only: on :focus-visible the global 3px ring is
   the stronger signal, and an element gets one outline, so the ring wins by design. */
.funding-band__button--primary:hover {
  color: var(--sh-ink);
  background: var(--sh-paper);
  border-color: var(--sh-paper);
  outline: 2px solid var(--sh-ink);
  outline-offset: -2px;
}

/* The close line carries the page's most important promise, so it no longer whispers:
   12px/700 at the band's own body-grey (Steph's ruling, 12 Aug 2026 — recorded in
   design/12-funding-decisions.md; caps-mono grammar of 09 §5 kept). */
.funding-band__close {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #e6e4e2; /* the funding-band__body grey on this same ground */
  margin-top: 2px;
}

/* --------------------------------------------------------------------------
   390px
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .section-strip,
  .news-hero,
  .news-picks,
  .news-archive,
  .news-quotes,
  .news-byline,
  .funding-band {
    padding-left: 18px;
    padding-right: 18px;
  }

  .news-byline { flex-wrap: wrap; }
  .news-byline__more { margin-left: 82px; }

  .news-hero {
    grid-template-columns: 1fr;
    gap: 28px;
    padding-top: 32px;
    padding-bottom: 32px;
  }
  .news-hero__heading { font-size: 40px; }

  .news-series { grid-template-columns: 1fr; }
  .news-series__headline { font-size: 26px; }

  .news-picks__grid { grid-template-columns: 1fr; }
  .news-picks__heading,
  .news-archive__heading,
  .news-quotes__heading { font-size: 30px; }

  .issue-row {
    flex-wrap: wrap;
    gap: 10px 14px;
    margin-left: -18px;
    margin-right: -18px;
    padding-left: 18px;
    padding-right: 18px;
  }
  .issue-row__title { font-size: 21px; flex: 1 1 60%; }
  .issue-row__meta { margin-left: 0; flex-basis: 100%; }

  .news-quotes__grid { grid-template-columns: 1fr; }
  .news-quotes__head { flex-direction: column; gap: 8px; }

  .funding-band {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .funding-band__heading { font-size: 30px; }
}


/* ==========================================================================
   The home page (index.hbs) — frame 13b.
   Type and color fields only: no photographic or graphic objects except the stamp in the
   funding band. No section strip — "/" is not a section.
   ========================================================================== */

/* THE HOME HERO — frame `42f`, adopted 14 Aug 2026. Two cells, NO GAP. The dot field covers
   the whole band and the right panel paints paper over it, so the field visibly STOPS on the
   panel's left rule rather than fading or being masked. That hard stop is the design: the field
   belongs to the claim, and the person stands on plain paper that bleeds to the edge.

   THE LEFT CELL TAKES A MEASURE, which the canvas does not specify because it is drawn at a
   fixed 1180px. Without one the 1fr grows without limit and at 1920 the claim sits in a 1376px
   cell it fills less than half of — the exact "basic and empty" the melded hero was fixing. The
   claim caps at 900px of content and stays on the gutter; the field keeps running to the panel
   rule, which is what that space is for. RESPONSIVE BELOW 900px IS NOT IN THE CANVAS — the
   stacked behavior further down is the obvious reading of it and still wants Steph's eyes. */
.home-hero {
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: minmax(0, 1fr) 452px;
  position: relative;
  overflow: clip;
}
/* This band has no column gutter — the cells butt on a rule — so the shared --sh-sparks-x
   mechanism has nothing to aim at. 42f places them in the field instead: one against the panel
   rule at the top, one in the far corner at the bottom, so they bracket the field they belong
   to. Both ✦: 00 §2 retired ✴ site-wide in chat 2 and the record beats the frame. */
.home-hero .sh-sparks::before {
  left: auto;
  right: calc(452px + 42px);
  top: 26px;
  translate: 0 0;
}
.home-hero .sh-sparks::after {
  left: 34px;
  top: auto;
  bottom: 30px;
  translate: 0 0;
}
/* Purple at display size is the sanctioned decorative use — this is a headline, not body copy.
   The hand-placed <br>s are the design: four sentences, one per line, three "I" clauses as
   anaphora and the payoff closing as its own sentence rather than trailing off the third on a
   comma (Steph's ruling, 14 Aug 2026 — rhythm and symmetry; it amends copy pass item 1, which
   had approved the comma-and-lowercase version). Do NOT add text-wrap: balance, and do not
   "fix" the four sentences back to the comma.

   LEFT: the claim. RIGHT: the person. */
.home-hero__lead {
  padding: 52px 48px 50px var(--sh-gutter);
  display: flex;
  flex-direction: column;
  gap: 26px;
  justify-content: center;
  align-items: flex-start;
}
.home-hero__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  /* 62px is the canvas value and the ceiling. Fluid below it because the canvas is one width:
     the left cell is the viewport less the 452 panel and its own padding, and the longest of
     the four lines needs 7.55px of width per 1px of font-size. Without this the headline
     overflows its cell between 900 and 1180. The 44px floor is set by the narrowest desktop
     width: at 901 the left cell offers 357px and the longest line needs 332, which leaves real
     margin — 46px left only 10px and one metric change away from a five-line headline. */
  font-size: clamp(44px, calc((100vw - 560px) / 8.2), 62px);
  line-height: 1.03;
  letter-spacing: -0.015em;
  color: var(--sh-purple-header);
  max-width: 900px;
}
.home-hero__body {
  font-family: var(--sh-font-body);
  font-size: 16.5px;
  line-height: 1.55;
  text-wrap: pretty;
  max-width: 48ch;
}

.home-hero__panel {
  background: var(--sh-paper);
  border-left: 1px solid var(--sh-ink);
  display: flex;
  flex-direction: column;
}
/* The plate is the panel's masthead: full width, closed by the same 1px rule the panel is.

   THE RATIO IS THE SPEC, NOT THE HEIGHT. 42f says `height: 244px` because the canvas is one
   frame at one width, where the panel is exactly 452 — and 452 × 244 is this ratio. A fixed
   height does not survive a width change: `cover` scales the square source to fill the width,
   so at 768 the same 244px shows only 32% of the image instead of 54% and the crop takes the
   head off at the chin. Measured, not guessed. As a ratio the visible slice is the same 54% at
   every width, so the face is framed exactly as drawn — at 452 this still computes to 244. */
.home-hero__plate {
  width: 100%;
  height: auto;
  aspect-ratio: 452 / 244;
  object-fit: cover;
  object-position: center 14%;
  display: block;
  border-bottom: 1px solid var(--sh-ink);
}
.home-hero__panel-body {
  padding: 26px 44px 28px;
  display: flex;
  flex-direction: column;
  gap: 13px;
  justify-content: center;
  flex: 1;
}
.home-hero__kicker {
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
/* Near-black, NOT purple: one purple display voice per band, and it belongs to the claim. */
.home-hero__why {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1.04;
  max-width: 18ch;
}
.home-hero__origin {
  font-family: var(--sh-font-body);
  font-size: 15.5px;
  line-height: 1.55;
  text-wrap: pretty;
}
.home-hero__links {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  border-top: 1px solid var(--sh-hairline);
  margin-top: 3px;
}
.home-hero__links a {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-ink);
  padding-top: 12px;
}

.home-eyebrow {
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.home-eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }

/* The four properties. Hairline grid from a black ground showing through 1px gaps. */
.home-chips {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.home-chip {
  color: var(--sh-ink);
  text-decoration: none;
  padding: 24px 24px 26px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.home-chip:hover { color: var(--sh-ink); }
/* On tint, underline IS the link affordance (00 §2) — the chip declares its action on hover. */
.home-chip:hover .home-chip__cta,
.home-chip:focus-visible .home-chip__cta { text-decoration: underline; text-underline-offset: 2px; }
.home-chip--newsletter { background: var(--sh-tint-newsletter); }
.home-chip--jobs { background: var(--sh-tint-jobs); }
.home-chip--resources { background: var(--sh-tint-resources); }
.home-chip--footnotes { background: var(--sh-tint-footnotes); }

.home-chip__label {
  font-family: var(--sh-font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.home-chip__count {
  font-family: var(--sh-font-display);
  font-size: 42px;
  line-height: 0.98;
}
.home-chip__body {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.45;
}
/* The CTA is an action, never a count — nothing on a link that has to be counted by hand. */
.home-chip__cta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-top: auto;
  padding-top: 14px;
}

/* Career Suite — leaf green, halftone. Halftone appears exactly twice on this page (here and
   the subscribe card) so it stays an event rather than a texture. */
.home-suite {
  background: var(--sh-career-suite-green);
  border-bottom: 1px solid var(--sh-ink);
  padding: 30px var(--sh-gutter) 32px;
  position: relative;
  overflow: clip;
}
.home-suite::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 6px 6px;
  opacity: 0.13;
  pointer-events: none;
}
.home-suite__head,
.home-suite__tools { position: relative; }

.home-suite__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  margin-bottom: 20px;
}
.home-suite__intro { display: flex; align-items: center; gap: 20px; }
.home-suite__avatar { width: 76px; height: auto; flex: none; }
.home-suite__label {
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 6px;
}
.home-suite__heading {
  font-family: var(--sh-font-display);
  font-size: 40px;
  font-weight: 400; /* explicit: the element is an h2, which would otherwise bold */
  line-height: 1.04;
}
.home-suite__cta {
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-paper);
  background: var(--sh-ink);
  text-decoration: none;
  padding: 12px 17px;
  white-space: nowrap;
  flex: none;
}
.home-suite__cta:hover { color: var(--sh-paper); }

.home-suite__tools {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border: 1px solid var(--sh-ink);
}
.home-tool {
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.home-tool:hover { color: var(--sh-ink); }
.home-tool__kind {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.home-tool__name {
  font-family: var(--sh-font-display);
  font-size: 24px;
  line-height: 1.05;
}
.home-tool__body {
  font-family: var(--sh-font-body);
  font-size: 13px;
  line-height: 1.4;
}

/* Bio */

/* The teaser and "Last few issues" share this 1fr 340px grid on purpose — the aligned divider
   is what makes them read as one newsletter zone. Don't "fix" the uniformity. */
.home-newsletter,
.home-latest {
  display: grid;
  grid-template-columns: 1fr 340px;
  border-bottom: 1px solid var(--sh-ink);
}

.home-teaser {
  padding: 30px var(--sh-gutter) 32px;
  border-right: 1px solid var(--sh-ink);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.home-teaser__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 42px;
  line-height: 1.02;
  margin-bottom: 12px;
}
.home-teaser__row {
  display: flex;
  gap: 14px;
  align-items: baseline;
  padding: 11px 0;
  border-top: 1px solid var(--sh-hairline);
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.45;
}
.home-teaser__rows .home-teaser__row:last-child { border-bottom: 1px solid var(--sh-hairline); }
.home-teaser__series {
  flex: none;
  width: 132px;
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  padding: 3px 0;
}
.home-teaser__series--roundup { background: #cfe1ff; }
.home-teaser__series--bjb { background: #fcbcd2; }
.home-teaser__series--deep { background: #e5cde8; }
.home-teaser__cta {
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: none;
  border-bottom: 2px solid var(--sh-ink);
  padding-bottom: 2px;
  align-self: flex-start;
  /* Hit-area floor: 5px of the 22px gap becomes transparent padding (22 = 17 + 5), so the
     visual position holds while the tap height clears 24px. The bottom edge keeps its
     2px-rule underline untouched. */
  margin-top: 17px;
  padding-top: 5px;
}

.home-subscribe {
  background: var(--sh-tint-newsletter);
  padding: 32px 30px;
  display: flex;
  flex-direction: column;
  gap: 13px;
  justify-content: center;
  position: relative;
  overflow: clip;
}
.home-subscribe::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 5px 5px;
  opacity: 0.16;
  pointer-events: none;
}
.home-subscribe > * { position: relative; }
.home-subscribe__heading {
  font-family: var(--sh-font-display);
  font-size: 30px;
  font-weight: 400; /* explicit: the element is an h2, which would otherwise bold */
  line-height: 1.06;
}
.home-subscribe__sub {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.5;
}
.home-subscribe__form { display: flex; flex-direction: column; gap: 8px; }
.home-subscribe__form input {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 11px 12px;
  font-family: var(--sh-font-mono);
  font-size: 14px;
  width: 100%;
}
.home-subscribe__form button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 12px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  width: 100%;
}
.home-subscribe__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.55;
}
/* RSS is offered as an equal alternative to email, not a consolation prize. */
.home-subscribe__rss {
  border-top: 1px solid var(--sh-ink);
  padding-top: 11px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.home-subscribe__rss-heading {
  font-family: var(--sh-font-display);
  font-size: 19px;
  font-weight: 400; /* explicit: the element is an h3, which would otherwise bold */
  line-height: 1.15;
}
/* On a tint, links take ink + underline. */
.home-subscribe__rss a {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--sh-ink);
}

.home-latest__main { border-right: 1px solid var(--sh-ink); }
.home-latest__head {
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
}
.home-latest__eyebrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.home-latest__eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }
.home-latest__all {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-ink);
}

.home-issue {
  display: flex;
  gap: 22px;
  align-items: center;
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
}
.home-issue:last-child { border-bottom: none; }
.home-issue:hover,
.home-issue:focus-visible { color: var(--sh-ink); background: #fff6ef; }
/* On the hover tint the ≤13px floor is #3a3a3a (CLAUDE.md; 18 §F's exact pair). */
.home-issue:hover .home-issue__meta,
.home-issue:focus-visible .home-issue__meta { color: var(--sh-grey-on-tint); }

.home-issue__cell {
  width: 74px;
  flex: none;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 7px 9px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.home-issue--roundup .home-issue__cell { background: #cfe1ff; }
.home-issue--bad-job-bingo .home-issue__cell { background: #fcbcd2; }
.home-issue--deep-dives .home-issue__cell { background: #e5cde8; }
.home-issue__cell-day {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 0.85;
}
/* The issue numeral (13b): same prefix-reveal device as .issue-row__cell-no — digits ride
   the #issue-NNN tag description; the day stays as the no-number fallback. Mono: numbers
   are data, matching the /newsletter/ cell. */
.home-issue__cell-no { display: none; }
.home-issue__cell-no[data-slug^="hash-issue-"]:not(:empty) {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1;
}
.home-issue__cell:has(.home-issue__cell-no[data-slug^="hash-issue-"]:not(:empty)) .home-issue__cell-day {
  display: none;
}
.home-issue__cell-series {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.2;
  text-transform: uppercase;
}
.home-issue__title {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.08;
}
.home-issue__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-left: auto;
  white-space: nowrap;
}

.home-more {
  padding: 22px 30px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.home-more__eyebrow {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.home-more__eyebrow .sh-twinkle { font-size: 20px; line-height: 1; }
.home-more__links { display: flex; flex-direction: column; }
.home-more__links a {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.1;
}
.home-more__links a:last-child { border-bottom: 1px solid var(--sh-hairline); }
.home-more__links a span:last-child {
  font-family: var(--sh-font-mono);
  font-size: 15px;
  /* The link value, not the display one: 15px is the two-value rule's boundary, and
     #a957b0 only measures 4.41:1 on paper. #8f3f96 is 6.22:1. */
  color: var(--sh-link);
  /* The arrow leans into the hover — transform only, the one motion this system permits. */
  display: inline-block;
  transition: transform 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
.home-more__links a:hover span:last-child,
.home-more__links a:focus-visible span:last-child { transform: translateX(3px); }
/* Steph's aside — coral bar, the marginalia device. */
.home-more__note {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 15px;
  line-height: 1.35;
  padding-left: 12px;
  border-left: 2px solid var(--sh-coral);
  margin-top: 4px;
}

/* The press stamp — one editorial aside per page maximum, and this page's is here. */
/* Re-stamp on hover (Steph's ruling, 12 Aug 2026, 12 §8): a quick press-in that always
   returns to the ruled −8° rest — 09 §6's resting angle is untouched. A discovery
   reward for the pointer that wanders over it; the stamp stays non-interactive. */
@keyframes sh-restamp {
  0% { transform: rotate(-8deg); }
  40% { transform: rotate(-6.5deg) translateY(2px); }
  100% { transform: rotate(-8deg); }
}
.funding-stamp:hover { animation: sh-restamp 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
.funding-stamp {
  /* −8° per 09 §6 (the money-side record wins over 00's −7 and the canvas's −6). */
  transform: rotate(-8deg);
  flex: none;
  border: 3px double var(--sh-paper);
  background: var(--sh-coral);
  padding: 5px;
  align-self: center;
}
.funding-stamp__inner {
  border: 1px solid var(--sh-ink);
  padding: 12px 16px 11px;
  text-align: center;
  font-family: var(--sh-font-mono);
  color: var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.funding-stamp__stars {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.34em;
}
.funding-stamp__text {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.09em;
  line-height: 1.34;
  text-transform: uppercase;
}

/* The home page's funding band carries the stamp beside the copy. */
.home .funding-band__pitch {
  flex-direction: row;
  align-items: flex-start;
  gap: 22px;
}
.home .funding-band__copy {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

@media (max-width: 900px) {
  /* THE HERO AT 900 AND BELOW IS NOT IN THE 42f CANVAS, which is drawn at one desktop width.
     This is the behavior its spec describes as the obvious reading — panel drops below the
     claim, plate goes full width, field runs the whole band — built so the page is not broken
     while it waits, and flagged for Steph rather than treated as settled.

     The cells carry their own padding now, so the band takes none: an 18px band padding would
     inset the plate and stop it going full width, which is the one thing the spec does name. */
  .home-hero {
    grid-template-columns: 1fr;
    padding: 0;
  }
  .home-hero__lead {
    padding: 30px 18px 28px;
    gap: 20px;
  }
  .home-hero__heading { font-size: 38px; }
  /* The rule moves from the side to the top, because the panel is now below the claim rather
     than beside it. It still paints paper over the field, so the field still stops on a rule —
     the device survives the stack. */
  .home-hero__panel {
    border-left: 0;
    border-top: 1px solid var(--sh-ink);
  }
  .home-hero__panel-body { padding: 22px 18px 26px; }
  .home-hero__why { font-size: 28px; }
}

/* TABLET — the panel goes side by side (Steph, 14 Aug 2026). Stacked, the plate is as wide as
   the band, and the ratio that makes a 210px plate at 390 makes a 415px one at 768: correctly
   cropped but far too much photograph. Turning the panel into two cells fixes it by making the
   plate narrow rather than by re-cropping — which §4 forbids doing by eye.

   The plate takes the cell's height instead of a ratio here, so it always finishes level with
   the text beside it. `object-fit: cover` with the same `object-position` keeps the framing:
   the window changes, the face stays centered and in the same place in it. The rule that closed
   the plate turns ninety degrees with the layout — bottom edge when it sits above the text,
   right edge when it sits beside it.

   Only above 600px. Narrower than that, two cells give a cramped plate next to a 200px measure,
   and the stacked version is better. */
@media (min-width: 601px) and (max-width: 900px) {
  .home-hero__panel {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    align-items: stretch;
  }
  .home-hero__plate {
    aspect-ratio: auto;
    height: 100%;
    border-bottom: 0;
    border-right: 1px solid var(--sh-ink);
  }
  .home-hero__panel-body { padding: 24px 24px 26px; }
}

/* Back to the ≤900 block: everything below is the mobile layout for the rest of the page and
   must NOT be scoped to the tablet range — the chip grid collapses here. */
@media (max-width: 900px) {
  .home-eyebrow,
  .home-suite,
  .home-teaser,
  .home-latest__head,
  .home-issue {
    padding-left: 18px;
    padding-right: 18px;
  }

  .home-chips,
  .home-suite__tools { grid-template-columns: 1fr; }

  .home-suite__head { flex-direction: column; align-items: flex-start; gap: 18px; }
  .home-suite__heading { font-size: 28px; white-space: normal; }

  .home-newsletter,
  .home-latest { grid-template-columns: 1fr; }
  .home-teaser,
  .home-latest__main { border-right: none; border-bottom: 1px solid var(--sh-ink); }
  .home-teaser__heading { font-size: 30px; }
  .home-teaser__row { flex-direction: column; gap: 6px; }
  .home-teaser__series { width: auto; align-self: flex-start; padding: 3px 10px; }

  .home-issue { flex-wrap: wrap; gap: 12px 16px; }
  .home-issue__title { font-size: 21px; flex: 1 1 60%; }
  .home-issue__meta { margin-left: 0; flex-basis: 100%; }

  .home .funding-band__pitch { flex-direction: column; }
}


/* ==========================================================================
   /t/{slug}/ — the shared tag archive (tag.hbs), plus the row and card vocabulary the
   section indexes inherit unchanged: the job row, the resource card, the chip system.
   Record: design/05a-tag-template-decisions.md.
   ========================================================================== */

/* Chrome accent by tag family. Ghost puts `tag-{slug}` on <body>, so the slug-prefix branching
   the record describes is done here with attribute-prefix selectors rather than in Handlebars,
   which has no prefix match. Order matters: first match in the record wins, so the more
   specific families are declared after the general ones. */
/* The per-family accent (05a §1's branch table), off Ghost's tag-{slug} body class.
   Coral is the bare-tag fallback — "never wrong for the tags that matter, only plain".
   bjb-* takes the RATING'S OWN pale tint, not a blanket pink (the §1 row says "rating
   tint"); bjb-by-the-audience sits outside the ramp and falls through to coral.
   Rendered as flat blocks with ink on top (the eyebrow chip, the mixed-group spines) —
   no accent in the palette is legible as text on the page ground. */
.tag-header { --tag-accent: var(--sh-coral); }
body[class*="tag-job-"] .tag-header { --tag-accent: var(--sh-blue); }
body[class*="tag-res-"] .tag-header { --tag-accent: var(--sh-peach); }
body[class*="tag-job-status-"] .tag-header { --tag-accent: var(--sh-grey); }
body[class*="tag-hash-portfolio"] .tag-header { --tag-accent: var(--sh-purple-display); }
body[class*="tag-bjb-green-means-go"] .tag-header { --tag-accent: #c9ead6; }
body[class*="tag-bjb-probably-fine"] .tag-header { --tag-accent: #fdeadb; }
body[class*="tag-bjb-tread-carefully"] .tag-header { --tag-accent: #f7cac3; }
body[class*="tag-bjb-bingo"] .tag-header { --tag-accent: #fcbcd2; }
body[class*="tag-bjb-maybe-dont"] .tag-header { --tag-accent: #d6d4d6; }

/* Section chrome (05a §1's Chrome column; drift item 89). tag.hbs renders all four
   strips; the owning family's shows here off the same body-class prefix branch as
   the accents, with the Issues strip as §1's bare-slug fallback — shown only when
   no family owns the page, via :not() rather than a show-then-unset dance so the
   base strip styles stay untouched. */
.tag-strip { display: none; }
body[class*="tag-job-"] .tag-strip--jobs,
body[class*="tag-bjb-"] .tag-strip--jobs { display: flex; }
body[class*="tag-res-"] .tag-strip--resources { display: flex; }
body.tag-hash-portfolio .tag-strip--portfolio { display: flex; }
body.tag-template:not([class*="tag-job-"]):not([class*="tag-bjb-"]):not([class*="tag-res-"]):not(.tag-hash-portfolio) .tag-strip--newsletter { display: flex; }

/* The nav's active state, same branch, off the links' data-section hooks. This is
   the visual half only — aria-current stays off deliberately (tag.hbs's header
   comment says why) — so it re-states the [aria-current] rule's two declarations
   rather than reusing the modifier-class hook, which site-header.hbs cannot set
   without a prefix match. Portfolio has no masthead item (09 turn 14), so
   hash-portfolio pages mark nothing. */
body[class*="tag-job-"] .site-nav__link[data-section="jobs"],
body[class*="tag-bjb-"] .site-nav__link[data-section="jobs"] {
  font-weight: 700;
  border-bottom-color: var(--sh-active-jobs);
}
body[class*="tag-res-"] .site-nav__link[data-section="resources"] {
  font-weight: 700;
  border-bottom-color: var(--sh-active-resources);
}
body.tag-template:not([class*="tag-job-"]):not([class*="tag-bjb-"]):not([class*="tag-res-"]):not(.tag-hash-portfolio) .site-nav__link[data-section="newsletter"] {
  font-weight: 700;
  border-bottom-color: var(--sh-active-newsletter);
}

.tag-header {
  padding: 44px var(--sh-gutter) 40px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
  /* Symmetric 1fr 1fr — the gap's centre is exactly 50%. */
  --sh-sparks-x: 50%;
}
.tag-header--compressed {
  grid-template-columns: 1fr auto;
  padding-top: 30px;
  padding-bottom: 28px;
  align-items: baseline;
}
/* The field yes, the sparks no. This variant is `1fr auto` — the second track is the count,
   so the name column runs to within a chip's width of the right edge and there is no gutter
   to stand in; at 50% both glyphs land on the company name. Measured, not guessed. It is also
   the most compact band in the system (30/28 padding, ~150 of these pages), which is the same
   reason stated twice. */
.tag-header--compressed .sh-sparks { display: none; }

/* The "Tagged" eyebrow above the tag-page h1 was removed 12 Aug 2026 (00 §2's
   No-Eyebrow rule, the 01a §13.1 precedent; recorded 02a §11). The family accent it
   carried still shows in the section strip and the axis chips. */
/* Purple at display size is the sanctioned decorative use of accent color. */
.tag-header__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 82px;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--sh-purple-header);
  text-wrap: pretty;
}
.tag-header--compressed .tag-header__title { font-size: 48px; }
.tag-header__description {
  font-family: var(--sh-font-body);
  font-size: 17px;
  line-height: 1.55;
}
.tag-header__count {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  margin-top: 14px;
}
.tag-header--compressed .tag-header__count { margin-top: 0; white-space: nowrap; }

/* Company furniture on the compressed header (05a §5; drift item 85): the mark and
   the verdict count row, gated to tag-job-company- pages — Salary and Location share
   the compressed variant but get neither. The mark is the job row's device at header
   scale: frame 2e draws it name-height (34px mark beside the 34px name), so it takes
   the compressed title's 48px; the initial keeps the row mark's ~0.63 face-to-box
   ratio (19px in a 30px tile). monogram.js fills the initial and the name-indexed
   tint, same as everywhere. */
.tag-header__name-row { display: flex; align-items: center; gap: 16px; }
/* Paper ground lives on the BASE class at single-class specificity so monogram.js's
   later job-row__mark--tint-N wins on source order; on the higher-specificity
   body-class rule it would silently beat the tint. */
.tag-header__mark { display: none; background: var(--sh-paper); }
body[class*="tag-job-company-"] .tag-header__mark {
  display: flex;
  width: 48px;
  height: 48px;
  flex: none;
  border: 1px solid var(--sh-ink);
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.tag-header__mark img { width: 100%; height: 100%; object-fit: contain; }
.tag-header__mark--monogram {
  font-family: var(--sh-font-display);
  font-size: 30px;
  line-height: 1;
}

/* The verdict count row (05a §5, amended 9 Sep 2026 — replaced the 2e rating-spread
   bar on Steph's ruling that an unlabelled bar reads as nothing). Five rating chips,
   the same construction as the job rows', worst-last, each carrying its count. Gated to
   company pages like the bar was. A zero chip is the plain outlined chip on paper: no
   icon, so no pale ground (the tint exists to seat the icon), and the name plus a bold
   0 says "never rated BINGO" in words instead of a black sliver. */
.tag-verdicts {
  grid-column: 1 / -1;
  display: none;
}
body[class*="tag-job-company-"] .tag-verdicts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.tag-verdicts__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.tag-verdicts__count {
  font-weight: 700;
}
.tag-verdicts__item--zero {
  background: var(--sh-paper);
}

/* The sibling-axis rail (05a §1's job-* branch; drift item 90). partials/tag-siblings.hbs
   renders one rail per axis; the page's own axis shows off its slug prefix — the shelf's
   family-gating architecture again. Chips are frame 2b's: bordered mono at the 10px
   floor, board-wide counts (each chip is a link to another tag page, so the
   destination's own total is the honest number), closing on the all-axes exit. An
   axis whose every sibling is empty hides whole rather than stranding its label
   against the lone exit (18 §H's defined zero). */
.tag-siblings {
  grid-column: 1 / -1;
  display: none;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
}
body[class*="tag-job-discipline-"] .tag-siblings--discipline { display: flex; }
body[class*="tag-job-level-"] .tag-siblings--level { display: flex; }
body[class*="tag-job-type-"] .tag-siblings--type { display: flex; }
body[class*="tag-job-arrangement-"] .tag-siblings--arrangement { display: flex; }
body[class*="tag-job-salary-"] .tag-siblings--salary { display: flex; }
body[class*="tag-job-location-"] .tag-siblings--location { display: flex; }
body[class*="tag-res-collection-"] .tag-siblings--res-collection { display: flex; }
.tag-siblings:not(:has(.tag-siblings__chip:not(.tag-siblings__chip--all))) { display: none; }

.tag-siblings__label {
  font-family: var(--sh-font-mono);
  font-size: 10px; /* drawn 9px — below the floor; it is a semantic label */
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-right: 4px;
}
.tag-siblings__chip {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  padding: 4px 9px;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.tag-siblings__chip:hover { color: var(--sh-ink); outline: 2px solid var(--sh-ink); outline-offset: -2px; }

/* --------------------------------------------------------------------------
   Chips. Color marks the AXIS, not the value — per-value color would need 14+ hues and the
   palette has seven, with green and grey already committed.
   One chip system, used everywhere on the site.
   -------------------------------------------------------------------------- */

.tag-rows .chip,
.job-row__chips a,
.jobrail__tags a,
.resource-card__chips a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.4;
  padding: 3px 8px;
  white-space: nowrap;
}

/* Rating chips are TINTED rather than full strength, because the icon sits bare on the chip
   with no containing box and needs a pale ground to read. */
.chip--rating img {
  width: 15px;
  height: 15px;
  display: block;
  flex: none;
}
/* The warning glyph is too light against a pale tint without this — it is carried inline in
   every design frame for the same reason. */
.chip__icon--outlined {
  filter: drop-shadow(0 0 .6px #030203) drop-shadow(0 0 .6px #030203);
}
.chip--rating-green { background: #c9ead6; }
.chip--rating-fine { background: #fdeadb; }
.chip--rating-tread { background: #f7cac3; }
.chip--rating-bingo { background: #fcbcd2; }
.chip--rating-dont { background: #d6d4d6; }

/* Live status is full strength — it is the one thing on the row that must not read as a
   category. */
.chip--open { background: var(--sh-blue); }
.chip--closed { background: var(--sh-grey); }
/* Suspected ghost job (01a §5/§8): grey tint, uppercase per the drawn 1b row. */
.chip--ghost { background: var(--sh-tint-closed); text-transform: uppercase; letter-spacing: 0.04em; }

/* --------------------------------------------------------------------------
   Job row (2a / 2b)
   -------------------------------------------------------------------------- */

/* The row is a div carrying a stretched title link, because it contains tag links and an
   <a> cannot nest inside another <a>. position: relative scopes the stretch. */
.job-row {
  position: relative;
  display: grid;
  grid-template-columns: 56px 1fr 150px;
  gap: 20px;
  align-items: start;
  padding: 18px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
}
/* :focus-within, not :focus-visible — the row is an <article> full of links, so the
   keyboard's hover is "something inside me holds focus" (the library card's device). */
.job-row:hover,
.job-row:focus-within { background: #fff6ef; }
/* ≤13px grey text on the hover tint floors at #3a3a3a (CLAUDE.md); company/foot are
   the mobile board's 10px lines, display:none at desktop. */
.job-row:hover .job-row__fact-label,
.job-row:focus-within .job-row__fact-label,
.job-row--board:hover .job-row__company,
.job-row--board:focus-within .job-row__company,
.job-row--board:hover .job-row__foot,
.job-row--board:focus-within .job-row__foot { color: var(--sh-grey-on-tint); }

.job-row__title {
  color: var(--sh-ink);
  text-decoration: none;
}
/* Stretches the title's hit area over the whole row so the row still behaves like one target. */
.job-row__title::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* The chips sit above the stretched link so they stay independently clickable. */
.job-row__chips { position: relative; z-index: 1; }

/* Closed listings stay inline chronologically with a grey spine. Not bucketed — the archive
   is the point, and 408 of 447 listings are closed. */
.job-row--closed {
  border-left: 3px solid var(--sh-grey);
  padding-left: calc(var(--sh-gutter) - 3px);
}

.job-row__mark {
  width: 56px;
  height: 56px;
  background: var(--sh-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: clip;
  flex: none;
}
.job-row__mark img { width: 100%; height: 100%; object-fit: contain; }

/* The monogram fallback. Tints assigned by assets/js/monogram.js from the company name.
   Only the monogram cell is bordered (18 §H.3) — company logos carry no border (01a §2.6). */
.job-row__mark--monogram {
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1;
}
/* Rotation per 01a §12.2 (Steph, 10 Aug 2026): the fourth value is teal — the canvas's
   #c9ead6 was Green Means Go's pale ground, and ramp tints are ratings only (01a §8). */
.job-row__mark--tint-0 { background: #cfe1ff; }
.job-row__mark--tint-1 { background: #fbe6d4; }
.job-row__mark--tint-2 { background: #e5cde8; }
.job-row__mark--tint-3 { background: #c6e6e3; }

.job-row__main {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.job-row__title-line {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.job-row__title {
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.04;
}
.job-row__commentary {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.5;
  color: var(--sh-grey-on-tint);
}
.job-row__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

/* All three facts in Instrument Serif so they read as one set against the mono chips. Never
   mono: an early mock set location and dates in mono and it made the row feel like a
   spreadsheet rather than a broadsheet listing. */
.job-row__facts {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: right;
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.14;
}
.job-row__date { color: var(--sh-grey-on-paper); }
/* 05a §2's tag-page Location cell: arrangement stacked over country (drift item 83) —
   the block display makes the stack; the meta line's ", " join has no place here. */
.job-row__facts .jobpost__arrangement { display: block; }
.job-row__facts .jobpost__arrangement::after { content: none; }

/* --------------------------------------------------------------------------
   Resource card (2c)
   -------------------------------------------------------------------------- */

.resource-card {
  position: relative;
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 20px;
  align-items: start;
  padding: 20px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
}
.resource-card:hover,
.resource-card:focus-within { background: #fff6ef; }
/* Drops the art column rather than leaving a 120px hole when an entry has no cover. */
.resource-card--no-art { grid-template-columns: 1fr; }

/* 2c's kind strip with the coral dog-eared corner on the tag-page card (drift item 86):
   the library card's own band device, spanning the row's grid. Hidden when the entry
   carries no directory tag, so the coral corner never dangles on an unfiled entry. */
.resource-card__band { grid-column: 1 / -1; border: 1px solid var(--sh-ink); }
.resource-card__band:not(:has(.fact-tag[data-slug^="res-directory-"])) { display: none; }

.resource-card__title {
  color: var(--sh-ink);
  text-decoration: none;
}
.resource-card__title::after {
  content: "";
  position: absolute;
  inset: 0;
}
.resource-card__chips { position: relative; z-index: 1; }
.resource-card__art {
  border: 1px solid var(--sh-ink);
  overflow: clip;
  display: block;
}
.resource-card__art img { width: 100%; height: auto; display: block; }
.resource-card__main {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}
.resource-card__title {
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.04;
}
/* Neutral, and NOT italic. Most descriptions are the source's own words and they run long —
   italics would be a punishing read and a promise every future entry has to honor (chat 10). */
.resource-card__description {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.55;
}
.resource-card__chips { display: flex; flex-wrap: wrap; gap: 5px; }
.resource-card__more {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-link);
}

/* --------------------------------------------------------------------------
   Portfolio card — a clip file of published articles, not case studies (03a).
   -------------------------------------------------------------------------- */

.portfolio-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 18px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
}
.portfolio-card:hover,
.portfolio-card:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.portfolio-card:hover .portfolio-card__meta,
.portfolio-card:focus-visible .portfolio-card__meta { color: var(--sh-grey-on-tint); }
.portfolio-card__title {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.06;
}
.portfolio-card__dek {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.5;
  color: var(--sh-grey-on-tint);
}
.portfolio-card__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

/* --------------------------------------------------------------------------
   The tag-page shelf's family gating (05a §4, ruled 10 Aug 2026): both family
   group sets are server-rendered — Handlebars cannot prefix-match the tag slug —
   and CSS shows the right one off the tag-{slug} body class. Bare, newsletter
   and portfolio tags get no panel at all: search + sort only. The page's own
   axis is suppressed (a Company filter on a company page is clutter); those
   rules sit LAST so source order beats the family rules at equal specificity.
   -------------------------------------------------------------------------- */

.tag-shelf .shelf__group { display: none; }
.tag-shelf [data-shelf-toggle] { display: none; }

body[class*="tag-job-"] .tag-shelf [data-shelf-toggle],
body[class*="tag-bjb-"] .tag-shelf [data-shelf-toggle],
body[class*="tag-res-"] .tag-shelf [data-shelf-toggle] { display: inline-flex; }

body[class*="tag-job-"] .tag-shelf .shelf__group--fam-jobs,
body[class*="tag-bjb-"] .tag-shelf .shelf__group--fam-jobs { display: block; }
body[class*="tag-res-"] .tag-shelf .shelf__group--fam-res { display: block; }

/* Self-axis suppression, one rule per axis family. Type covers both merged axes. */
body[class*="tag-bjb-"] .tag-shelf .shelf__group[data-shelf-group="Rating"],
body[class*="tag-job-discipline-"] .tag-shelf .shelf__group[data-shelf-group="Discipline"],
body[class*="tag-job-level-"] .tag-shelf .shelf__group[data-shelf-group="Role level"],
body[class*="tag-job-type-"] .tag-shelf .shelf__group[data-shelf-group="Type"],
body[class*="tag-job-arrangement-"] .tag-shelf .shelf__group[data-shelf-group="Type"],
body[class*="tag-job-location-"] .tag-shelf .shelf__group[data-shelf-group="Location"],
body[class*="tag-job-salary-"] .tag-shelf .shelf__group[data-shelf-group="Salary"],
body[class*="tag-job-company-"] .tag-shelf .shelf__group[data-shelf-group="Company"],
body[class*="tag-job-status-"] .tag-shelf .shelf__group[data-shelf-group="Status"],
body[class*="tag-res-directory-"] .tag-shelf .shelf__group[data-shelf-group="Directory"],
body[class*="tag-res-collection-"] .tag-shelf .shelf__group[data-shelf-group="Collection"],
body[class*="tag-res-publisher-"] .tag-shelf .shelf__group[data-shelf-group="Publisher"] { display: none; }

/* A group whose every option counts zero on this page hides whole (script-set). */
.shelf__group--empty { display: none !important; }
.shelf__option--zero { display: none; }

/* The sort menu (05a §4: Newest · Oldest · Salary high→low · BJB rating best→worst). */
.shelf__sort-wrap { position: relative; }
.shelf__sort-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 30;
  min-width: 230px;
  background: var(--sh-paper);
  border: 1px solid var(--sh-ink);
}
.shelf__sort-option {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--sh-hairline);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 9px 12px;
  cursor: pointer;
}
.shelf__sort-option:last-child { border-bottom: 0; }
.shelf__sort-option[aria-pressed="true"] { background: var(--sh-ink); color: var(--sh-paper); }

/* Sorting by salary collects no-comp listings at the bottom under their own divider (05a §4). */
.shelf-sort-divider {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  border-top: 1px solid var(--sh-ink);
  padding: 12px var(--sh-gutter) 4px;
}

/* --------------------------------------------------------------------------
   Kind groups (05a §5). Each group keeps its own row type and a color spine in
   its family accent. An empty group vanishes whole; the labels render only when
   the tag is genuinely mixed (two or more kinds present), so a single-family
   archive stays one plain list.
   -------------------------------------------------------------------------- */

.tag-group:not(:has(.tag-group__rows > *)) { display: none; }

.tag-group__label {
  display: none;
  align-items: center;
  gap: 10px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 26px 0 10px;
}
.tag-rows:has(.tag-group--jobs .tag-group__rows > *):has(.tag-group--resources .tag-group__rows > *) .tag-group__label,
.tag-rows:has(.tag-group--jobs .tag-group__rows > *):has(.tag-group--portfolio .tag-group__rows > *) .tag-group__label,
.tag-rows:has(.tag-group--jobs .tag-group__rows > *):has(.tag-group--issues .tag-group__rows > *) .tag-group__label,
.tag-rows:has(.tag-group--resources .tag-group__rows > *):has(.tag-group--portfolio .tag-group__rows > *) .tag-group__label,
.tag-rows:has(.tag-group--resources .tag-group__rows > *):has(.tag-group--issues .tag-group__rows > *) .tag-group__label,
.tag-rows:has(.tag-group--portfolio .tag-group__rows > *):has(.tag-group--issues .tag-group__rows > *) .tag-group__label {
  display: flex;
}

.tag-group__spine {
  width: 10px;
  height: 22px;
  border: 1px solid var(--sh-ink);
  flex: none;
}
.tag-group--jobs .tag-group__spine { background: var(--sh-blue); }
.tag-group--resources .tag-group__spine { background: var(--sh-peach); }
.tag-group--portfolio .tag-group__spine { background: var(--sh-purple-display); }
.tag-group--issues .tag-group__spine { background: var(--sh-coral); }

/* --------------------------------------------------------------------------
   Issue rows on /t/ — the LABELED numeral cell (07 decision 20 settled 6b; 00's
   numeral-cell motif: serif numeral over a 10px Space Mono series label, 88px
   desktop / 62px at 390; drift item 88), plus the 2d dek with the meta line under
   it. Scoped to the tag archive: /newsletter/'s 46px compact cell is the sanctioned
   dense-list variant and keeps the shared base rules untouched. The numbered case
   follows the home cell exactly (13b: mono 22px bold — numbers are data); the
   day/month stack stays as the no-number fallback.
   -------------------------------------------------------------------------- */

.tag-archive .issue-row { align-items: flex-start; }
.tag-archive .issue-row__cell {
  width: 88px;
  align-self: flex-start;
  text-align: left;
  padding: 8px 10px 9px;
  gap: 3px;
  line-height: normal;
}
.tag-archive .issue-row__cell-day {
  font-family: var(--sh-font-display);
  font-size: 26px;
  font-weight: 400;
  line-height: 0.85;
}
.tag-archive .issue-row__cell-no[data-slug^="hash-issue-"]:not(:empty) {
  font-size: 22px;
  line-height: 0.9;
}
/* The base rules already swap day/month out when the numeral is present; the full
   date lives in the meta line under the dek (decision 20), so the cell never
   carries both. */
.tag-archive .issue-row__cell-series {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.2;
  text-transform: uppercase;
  margin-top: 1px;
}
.tag-archive .issue-row__main {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
/* 2d's dek values: 15px/1.55 body at 68ch. */
.tag-archive .issue-row__dek {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.55;
  max-width: 68ch;
}
/* The base meta rides the title line and never wraps; under the dek it is a normal
   text line and must wrap at 390 rather than clip. */
.tag-archive .issue-row__meta { margin-left: 0; white-space: normal; }

/* --------------------------------------------------------------------------
   Empty tag
   -------------------------------------------------------------------------- */

.tag-empty {
  padding: 48px var(--sh-gutter) 56px;
  border-bottom: 1px solid var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 62ch;
}
.tag-empty__heading {
  font-family: var(--sh-font-display);
  font-size: 34px;
  line-height: 1.06;
}
.tag-empty__body {
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.55;
}
.tag-empty__exits {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 6px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media (max-width: 900px) {
  .tag-header,
  .tag-header--compressed {
    grid-template-columns: 1fr;
    gap: 18px;
    padding: 26px 18px 24px;
  }
  .tag-header__title { font-size: 40px; }
  .tag-header--compressed .tag-header__title { font-size: 32px; }

  /* Rows restack: title first, then meta, then chips wrapped. The desktop grid collapses
     entirely — the job board in particular gets read on a phone by people who are at work. */
  .job-row {
    grid-template-columns: 44px 1fr;
    gap: 14px;
    padding: 16px 18px;
  }
  .job-row--closed { padding-left: 15px; }
  .job-row__mark { width: 44px; height: 44px; }
  .job-row__title { font-size: 21px; }
  .job-row__facts {
    grid-column: 1 / -1;
    flex-direction: row;
    gap: 14px;
    text-align: left;
    font-size: 17px;
  }

  .resource-card {
    grid-template-columns: 84px 1fr;
    gap: 14px;
    padding: 16px 18px;
  }
  .resource-card__title { font-size: 21px; }

  .portfolio-card { padding: 16px 18px; }
  .tag-empty { padding: 32px 18px 36px; }

  /* The motif's 390 cell: 62px, label at 0.03em (00 §Numeral cell). */
  .tag-archive .issue-row__cell { width: 62px; padding: 7px 8px 8px; }
  .tag-archive .issue-row__cell-series { letter-spacing: 0.03em; }

  /* Compressed-header mark at the job row's own mobile size (44px), initial scaled
     with it. */
  body[class*="tag-job-company-"] .tag-header__mark { width: 44px; height: 44px; }
  .tag-header__mark--monogram { font-size: 27px; }
  .tag-header__name-row { gap: 12px; }
}


/* ==========================================================================
   page.hbs and the error pages
   ========================================================================== */

.page {
  padding: 44px var(--sh-gutter) 56px;
}
.page-header {
  max-width: 680px;
  margin-bottom: 28px;
}
/* The purple header is the sectionless page's one distinguishing mark — its substitute
   for a section strip (Page canvas 1a/1b, adopted 18 §E; drift item 50): #a957b0 at
   76px desktop / 48px at 390. Display type, so the display purple holds. */
.page-header__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 76px;
  line-height: 0.96;
  letter-spacing: -0.02em;
  color: var(--sh-purple-header);
  max-width: 20ch;
  text-wrap: balance;
}
.page-header__dek {
  font-family: var(--sh-font-body);
  font-size: 20px;
  line-height: 1.5;
  color: var(--sh-grey-on-tint);
  margin-top: 16px;
}
/* 11px sits at the ≤13px floor, and #6b6b6b is exactly the paper floor — compliant. */
.page-header__updated {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-top: 10px;
}

/* The ON THIS PAGE rail (Page canvas 1a; drift item 98) — page.js gates it on >2 H2s
   and flips the layout to the drawn two-column grid. Mobile (frame 1b) has no rail. */
.page-layout--toc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 64px;
  align-items: start;
}
.page-toc[hidden] { display: none; }
.page-toc {
  border: 1px solid var(--sh-ink);
  padding: 20px 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.page-toc__label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0;
}
.page-toc__nav { display: flex; flex-direction: column; gap: 9px; }
.page-toc__link {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.4;
  color: var(--sh-ink);
  text-decoration: none;
  border-top: 1px solid var(--sh-hairline);
  padding-top: 9px;
}
.page-feature {
  max-width: 680px;
  margin-bottom: 28px;
}
.page-feature figcaption {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  color: var(--sh-grey-on-paper);
  margin-top: 8px;
}

/* Error pages — the 404's frame-1a chrome and error.hbs's 1c (drift items 53/54).
   The hero halftone is the drawn coral dot grid, the same pattern device the site's
   other stamped bands use; on the near-black ground the ≤13px floor is #b8b6b4,
   which is exactly what the frame's small mono runs carry. */

.error-hero {
  position: relative;
  overflow: clip;
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 54px var(--sh-gutter) 50px;
  display: grid;
  grid-template-columns: 1fr 420px;
  gap: 56px;
  align-items: center;
}
.error-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.16;
}
.error-hero > * { position: relative; }
/* error.hbs's 1c band: one column, no search slot. */
.error-hero--plain {
  grid-template-columns: 1fr;
  padding: 44px var(--sh-gutter);
}
/* The canvas pulses this; the built site ships every ✦ static, so this one is too. */
.error-hero__sparkle {
  position: absolute;
  top: 44px;
  right: 300px;
  font-size: 15px;
}
.error-hero__main {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.error-hero__eyebrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
}
.error-hero__eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }
.error-hero__eyebrow-text {
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
/* 1c's eyebrow is the coral mono form at every width (1b uses the same at 390). */
.error-hero__eyebrow--mono {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sh-coral);
}
.error-hero__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 74px;
  line-height: 0.96;
  letter-spacing: -0.02em;
  margin: 0;
}
.error-hero__heading--balance {
  font-size: 56px;
  line-height: 0.98;
  text-wrap: balance;
}
/* Coral at display size on the near-black ground — the drawn two-tone device; the
   accent never reaches body text (00 §2). */
.error-hero__accent { color: var(--sh-coral); }
.error-hero__body {
  font-family: var(--sh-font-body);
  font-size: 17px;
  line-height: 1.55;
  margin: 0;
  max-width: 58ch;
  color: #e6e4e2;
}
.error-hero--plain .error-hero__body { max-width: 56ch; }

/* The hero's search slot — 1a's right column. The 8 Aug 2026 amendment ruled the
   ENTRY plaintext, so the drawn box is a plain link in the drawn slot. */
.error-hero__search {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.error-hero__search-label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #b8b6b4;
  margin: 0;
}
.error-hero__search-link {
  font-family: var(--sh-font-body);
  font-size: 16px;
  color: var(--sh-paper);
  text-decoration: underline;
  text-underline-offset: 3px;
  align-self: flex-start;
}
/* Delight (18 Aug 2026): this rule's whole content was an undo — it stops the global
   `a:hover` shifting the link off paper on a near-black ground, and did nothing else, so the
   hero's one exit answered nothing. The undo stays, and the underline doubles under the hand:
   the house declare-on-hover, and the same move the footer group links took in the chrome
   pass for the same reason (color alone cannot carry a link on near-black). */
.error-hero__search-link:hover,
.error-hero__search-link:focus-visible {
  color: var(--sh-paper);
  text-decoration-thickness: 2px;
}
.error-hero__search-note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: #b8b6b4;
  margin: 0;
}

/* error.hbs's minimal chrome (1c): wordmark + status code, no site header or footer —
   the shared header runs three {{#get}} queries, a lot to ask of a server mid-500. */
.err-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
}
.err-head__wordmark {
  display: block;
  height: 20px;
  width: 213.33px; /* wordmark ratio 10.6665 — explicit both ways + flex none, always */
  flex: none;
}
.err-head__code {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

/* 1c's exits: filled Try again, outline homepage, the report link in link purple. */
.error-actions {
  padding: 24px var(--sh-gutter) 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.error-actions__buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.error-actions__button {
  border: 1px solid var(--sh-ink);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 12px 18px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.error-actions__button:hover { color: var(--sh-ink); box-shadow: inset 0 0 0 1px var(--sh-ink); }
.error-actions__button--primary {
  background: var(--sh-ink);
  color: var(--sh-paper);
  font-weight: 700;
}
.error-actions__button--primary:hover { color: var(--sh-paper); }
.error-actions__report {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
}

.error-moves {
  padding: 30px var(--sh-gutter) 32px;
  border-bottom: 1px solid var(--sh-ink);
}
.error-moves__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  margin-bottom: 14px;
}
.error-moves__list { list-style: none; padding: 0; }
.error-move {
  display: grid;
  grid-template-columns: 220px 260px 1fr;
  gap: 20px;
  align-items: baseline;
  padding: 12px 0;
  border-top: 1px solid var(--sh-hairline);
}
.error-move__old {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  color: var(--sh-grey-on-paper);
  word-break: break-all;
}
.error-move__new {
  font-family: var(--sh-font-display);
  font-size: 24px;
  line-height: 1.1;
}
/* A reader who followed a dead link is owed the reason, not just a destination. */
.error-move__why {
  font-family: var(--sh-font-body);
  font-size: 15px;
  line-height: 1.5;
  color: var(--sh-grey-on-tint);
}

.error-doors {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.error-door {
  color: var(--sh-ink);
  text-decoration: none;
  padding: 22px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* Delight (18 Aug 2026): the four doors are the 404's main exits and the biggest targets on
   the page, and this rule was an undo and nothing more — it holds the link at ink against the
   global `a:hover`, which is necessary and invisible. They now declare on the name, which is
   the house on-tint affordance (`00` §2, the same device the home chips take): the cells are
   already tinted, so a paper wash is the one thing that cannot say "this one". */
.error-door:hover,
.error-door:focus-visible {
  color: var(--sh-ink);
}
.error-door:hover .error-door__name,
.error-door:focus-visible .error-door__name {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.error-door--newsletter { background: var(--sh-tint-newsletter); }
.error-door--jobs { background: var(--sh-tint-jobs); }
.error-door--resources { background: var(--sh-tint-resources); }
.error-door--footnotes { background: var(--sh-tint-footnotes); }
.error-door__chip {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.error-door__name {
  font-family: var(--sh-font-display);
  font-size: 30px;
  line-height: 1.04;
}
.error-door__body {
  font-family: var(--sh-font-body);
  font-size: 14px;
  line-height: 1.45;
}

/* The 404's closing report band, per the adopted frame 1a (drift item 96): STILL NOTHING
   eyebrow over the 34px serif heading at the left, body + bordered button at the right. */
.error-still {
  padding: 30px var(--sh-gutter) 34px;
  border-top: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 56px;
  align-items: center;
}
.error-still__head { display: flex; flex-direction: column; gap: 10px; }
.error-still__eyebrow {
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: 0;
}
.error-still__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.04;
  letter-spacing: -0.015em;
  margin: 0;
}
.error-still__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 58ch;
}
.error-still__body p { font-size: 17px; line-height: 1.55; margin: 0; }
.error-still__button {
  align-self: flex-start;
  border: 1px solid var(--sh-ink);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 12px 18px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media (max-width: 900px) {
  .page { padding: 26px 18px 36px; }
  .page-header__title { font-size: 48px; } /* 1b's named mobile size (drift item 50) */
  /* No rail on the mobile frame (1b): the box comes off rather than trailing the body. */
  .page-layout--toc { grid-template-columns: 1fr; gap: 0; }
  .page-toc { display: none; }

  .error-moves,
  .error-still { padding-left: 18px; padding-right: 18px; }
  .error-still { grid-template-columns: 1fr; gap: 18px; }
  .error-move { grid-template-columns: 1fr; gap: 4px; }
  .error-doors { grid-template-columns: 1fr; }

  /* Frame 1b: no strip, no sparkle, one column; the eyebrow becomes the coral mono
     form and the heading balances at 44 instead of breaking at the drawn <br>. */
  .error-strip { display: none; }
  .error-hero,
  .error-hero--plain {
    grid-template-columns: 1fr;
    gap: 26px;
    padding: 30px 18px;
  }
  .error-hero__sparkle { display: none; }
  .error-hero__eyebrow .sh-twinkle { display: none; }
  .error-hero__eyebrow-text {
    font-family: var(--sh-font-mono);
    font-size: 11px;
    letter-spacing: 0.16em;
    color: var(--sh-coral);
  }
  .error-hero__heading,
  .error-hero__heading--balance {
    font-size: 44px;
    line-height: 0.98;
    text-wrap: balance;
  }
  .error-hero__heading br { display: none; }
  .error-hero__body { font-size: 16px; line-height: 1.5; }
  .err-head,
  .error-actions { padding-left: 18px; padding-right: 18px; }
}

/* ==========================================================================
   Section index pages — /jobs/ (index-jobs.hbs), /resources/ (index-resources.hbs),
   /portfolio/ (index-portfolio.hbs), /footnotes/ (index-footnotes.hbs).
   Records: design/01a, 02a, 03a, 04a. The job row, resource-card and chip vocabulary above
   is inherited; what follows is the index-only furniture: the house page header, the
   rating ramp, the filter shelf, the library card grid, the specimen and the reading list.
   ========================================================================== */

.section-strip--portfolio { background: var(--sh-tint-portfolio); }

/* Strip action: the one action the section wants, underlined like the canvas. */
.section-strip__action {
  margin-left: auto;
  white-space: nowrap;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   House page header (01a §3): near-white ground, 82px Instrument Serif tagline in the
   display purple, body copy in a second column, vertically centered. The marginalia note
   takes a 2px rule in the section's accent.
   -------------------------------------------------------------------------- */

.board-header {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 44px;
  /* Centered, not end-aligned. The 41 canvas bottom-aligns its two columns and that was
     adopted in the first pass; on live it made the headline sit low in its own half while the
     taller copy column filled the band, which reads as the type sagging rather than as a firm
     bottom edge (Steph, 14 Aug 2026). Reverted. */
  align-items: center;
  padding: 44px var(--sh-gutter) 40px;
  border-bottom: 2px solid var(--sh-ink);
  /* 1fr 1fr with a symmetric gutter puts the gap's centre at exactly 50%. */
  --sh-sparks-x: 50%;
}
.board-header__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 82px;
  line-height: 0.94;
  letter-spacing: -0.025em;
  color: var(--sh-purple-header);
  text-wrap: balance;
}

.board-header__copy p { font-size: 17px; line-height: 1.55; }
.board-header__note {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 18px;
  line-height: 1.45;
  margin-top: 14px;
  padding-left: 14px;
  border-left: 2px solid var(--sh-blue);
}
.board-header__note--coral { border-left-color: var(--sh-coral); }
/* The channel vendor explainer is Steph's own disclosure copy, not a quoted voice —
   body sans, roman, and no quote bar (her rulings, 12 Aug 2026, 02a §11): the left
   rule is the pull-quote/marginalia device, and this is neither. The their-words
   italic and its bar stay on true marginalia like the index margin note. */
.board-header__note--plain {
  font-family: var(--sh-font-body);
  font-style: normal;
  border-left: 0;
  padding-left: 0;
  /* Size and leading come from .board-header__copy p (17px/1.55), same as the
     description above it. */
}
/* Directory channel header (02a frame 3a): back link over the directory name. */
.board-header__lead { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.board-header__back {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  text-decoration: none;
}
.board-header__note--purple { border-left-color: var(--sh-purple-display); }
.board-header__note--pink { border-left-color: var(--sh-hot-pink); }
/* The Footnotes header note wears the dagger, not the quote bar (Steph, 19 Aug 2026):
   down in the entries the pink LEFT BAR marks the source's words and the pink † marks
   Steph's, so the line announcing her footnotes previews the sword — same glyph, same
   geometry as .fn-entry__dagger/.fn-entry__note, so the header teaches the entry. */
.board-header__note--dagger {
  border-left: 0;
  padding-left: 0;
  display: flex;
  align-items: flex-start;
  gap: 11px;
}
.board-header__dagger {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 46px;
  line-height: 0.62;
  color: var(--sh-hot-pink);
  flex: none;
}

.board-header--footnotes .board-header__title-col {
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: flex-start;
}
.fn-free-badge {
  border: 1px solid var(--sh-ink);
  background: var(--sh-peach);
  padding: 5px 11px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   The rating ramp (Jobs 5a): five cells in the verdict tints, icon + serif name +
   mono count + one-line description. On a rating channel the current cell gets the
   inset ink keyline. Suppressed entirely when nothing is open.
   -------------------------------------------------------------------------- */

.rating-ramp {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--sh-ink);
}
.rating-ramp__cell {
  flex: 1 1 auto;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 11px 14px;
  color: var(--sh-ink);
  text-decoration: none;
  border-right: 1px solid var(--sh-ink);
}
.rating-ramp__cell:last-child { border-right: 0; }
.rating-ramp__cell:hover { color: var(--sh-ink); }
.rating-ramp__cell[aria-current="page"] { box-shadow: inset 0 0 0 3px var(--sh-ink); }
.rating-ramp__cell--green { background: #c9ead6; }
.rating-ramp__cell--fine { background: #fdeadb; }
.rating-ramp__cell--tread { background: #f7cac3; }
.rating-ramp__cell--bingo { background: #fcbcd2; }
.rating-ramp__cell--dont { background: #d6d4d6; }
.rating-ramp__cell > img { width: 19px; height: 19px; flex: none; margin-top: 2px; }

/* The ramp answers the cursor (delight pass, 12 Aug 2026): the icon nudges and the name
   takes the house declare-on-hover underline, on both ramps (board + /bad-job-bingo/).
   Keyboard focus gets the identical treatment; the blanket reduced-motion guard makes
   the nudge instant. */
.rating-ramp__cell > img,
.bjb-ramp__cell > img { transition: transform 0.15s cubic-bezier(0.25, 1, 0.5, 1); }
.rating-ramp__cell:hover > img,
.rating-ramp__cell:focus-visible > img,
.bjb-ramp__cell:hover > img,
.bjb-ramp__cell:focus-visible > img { transform: translateY(-2px) rotate(-6deg); }
.rating-ramp__cell:hover .rating-ramp__name,
.rating-ramp__cell:focus-visible .rating-ramp__name,
.bjb-ramp__cell:hover .bjb-ramp__name,
.bjb-ramp__cell:focus-visible .bjb-ramp__name { text-decoration: underline; text-underline-offset: 3px; }
.rating-ramp__body { display: block; flex: 1; min-width: 0; }
.rating-ramp__name-line { display: flex; align-items: center; gap: 14px; }
.rating-ramp__name {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.05;
  white-space: nowrap;
}
.rating-ramp__count {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  margin-left: auto;
}
.rating-ramp__desc {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.5;
  margin-top: 5px;
  color: var(--sh-grey-on-tint);
}

/* The board with nothing open (18 §H frame 1a). */
.board-dry {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 44px;
  padding: 36px var(--sh-gutter) 40px;
  border-bottom: 1px solid var(--sh-ink);
}
.board-dry__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: 1.02;
  margin-bottom: 14px;
}
.board-dry__copy p { font-size: 16px; line-height: 1.55; max-width: 58ch; margin-bottom: 10px; }
.board-dry__stat {
  border: 1px solid var(--sh-ink);
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-self: start;
}
.board-dry__stat-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.board-dry__stat-count {
  font-family: var(--sh-font-display);
  font-size: 64px;
  line-height: 1;
}
.board-dry__stat-note { font-family: var(--sh-font-mono); font-size: 11px; line-height: 1.6; color: var(--sh-grey-on-tint); }
.board-dry__prompt {
  grid-column: 1 / -1;
  font-size: 15px;
  line-height: 1.55;
  border-top: 1px solid var(--sh-hairline);
  padding-top: 16px;
}

/* --------------------------------------------------------------------------
   Filter shelf — shared by /jobs/ and /resources/ (frames 6a → 1b, 02a §4).
   One bar: black FILTERS button, mono search, sort. The whole section carries `hidden`
   in the markup and is revealed by filter-shelf.js, so a no-JS page never shows dead
   controls. Under 900px the open panel becomes the full-height filter sheet (1e / 7b).
   -------------------------------------------------------------------------- */

.shelf[hidden] { display: none; }
.shelf { border-bottom: 1px solid var(--sh-ink); }

/* Filtered-out and past-per-page rows. filter-shelf.js hides with the bare `hidden`
   attribute, and every row kind sets its own display (grid row, flex card), which beats
   the UA's [hidden] rule — the footer-counter trap again. One attribute-pair rule
   (0-2-0) outranks any single row class on every shelf surface. */
[data-shelf-item][hidden] { display: none; }

.shelf__bar {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--sh-ink);
}
.shelf__filters-toggle {
  border: 0;
  border-right: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 15px 22px;
  cursor: pointer;
}
.shelf__search {
  flex: 1;
  min-width: 0;
  border: 0;
  border-right: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 12px;
  padding: 15px 16px;
}
.shelf__search:focus-visible { outline: 3px solid var(--sh-focus); outline-offset: -3px; }
/* The bar's browse-directory exit (copy pass item 17) — dir-browse__all's treatment,
   sat in the bar beside the sort. */
.shelf__browse {
  display: flex;
  align-items: center;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-ink);
  padding: 0 16px;
  white-space: nowrap;
  border-left: 1px solid var(--sh-ink);
}
.shelf__sort {
  border: 0;
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 12px;
  padding: 15px 20px;
  cursor: pointer;
  white-space: nowrap;
}

/* Under 560px the one-row bar broke ragged: the sort button wrapped onto its own orphan
   row and the search squeezed to placeholder width (critique, 12 Aug 2026). Two deliberate
   rows instead — FILTERS + search, then the browse exit and sort sharing the second. The
   visually-hidden search label is position:absolute, so the grid ignores it. */
@media (max-width: 560px) {
  .shelf__bar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "toggle search search"
      "browse browse sort";
  }
  .shelf__filters-toggle { grid-area: toggle; }
  .shelf__search { grid-area: search; border-right: 0; }
  .shelf__browse {
    grid-area: browse;
    border-left: 0;
    border-top: 1px solid var(--sh-ink);
    padding: 13px 16px;
  }
  .shelf__sort-wrap {
    grid-area: sort;
    border-top: 1px solid var(--sh-ink);
    border-left: 1px solid var(--sh-ink);
  }
  .shelf__sort-wrap .shelf__sort { width: 100%; height: 100%; }
}

/* The panel. Desktop: drops below the bar. Mobile: becomes the sheet. */
.shelf__panel { border-bottom: 1px solid var(--sh-ink); background: var(--sh-paper); }
.shelf__panel-head {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 14px var(--sh-gutter) 12px;
  border-bottom: 1px solid var(--sh-ink);
}
.shelf__panel-title { font-family: var(--sh-font-display); font-size: 28px; line-height: 1; }
.shelf__panel-hint { font-family: var(--sh-font-mono); font-size: 10px; color: var(--sh-grey-on-paper); }
.shelf__panel-close {
  margin-left: auto;
  border: 0;
  background: none;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.shelf__groups {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 0 32px;
  padding: 8px var(--sh-gutter) 14px;
}
.shelf__group { border: 0; margin: 0; padding: 0; min-width: 0; }
.shelf__group-head { display: block; width: 100%; padding: 0; }
.shelf__group-head button {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  min-height: 46px;
  border: 0;
  border-bottom: 1px solid var(--sh-hairline);
  background: none;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}
.shelf__group-meta { font-family: var(--sh-font-mono); font-size: 12px; font-weight: 400; color: var(--sh-grey-on-paper); text-transform: none; }
.shelf__group-body { border-bottom: 1px solid var(--sh-hairline); }
.shelf__group--tall .shelf__group-body { max-height: 320px; overflow-y: auto; }
.shelf__option {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 2px;
  border-bottom: 1px solid #e6e4e2;
  cursor: pointer;
}
.shelf__option:last-of-type { border-bottom: 0; }
/* Selected value: pale wash + 3px blue left edge (01a §8); Footnotes swaps the accent. */
.shelf__option:has(input:checked) { background: #fff6ef; box-shadow: inset 3px 0 0 var(--sh-blue); }
.shelf__option input {
  width: 12px;
  height: 12px;
  flex: none;
  accent-color: var(--sh-ink);
}
.shelf__option .chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 2px 6px;
}
.shelf__option .chip img { width: 14px; height: 14px; }
.shelf__option-count { font-family: var(--sh-font-mono); font-size: 10px; color: var(--sh-grey-on-paper); margin-left: auto; }
.shelf__group-note {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.7;
  color: var(--sh-grey-on-tint);
  background: #f2f0ee;
  padding: 9px 12px;
  margin: 8px 0;
}
/* Collection sub-headings written in by the script (By Discipline / Topic / Theme). */
.shelf__subhead {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  padding: 11px 2px 3px;
}

.shelf__panel-actions {
  display: flex;
  gap: 12px;
  padding: 14px var(--sh-gutter) 18px;
}
.shelf__clear,
.shelf__apply {
  border: 1px solid var(--sh-ink);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 15px 0;
  cursor: pointer;
}
.shelf__clear { flex: 1; background: var(--sh-paper); color: var(--sh-ink); }
.shelf__apply { flex: 2; background: var(--sh-ink); color: var(--sh-paper); }

/* Active pills. Tints are painted by the script from the value's axis. */
.shelf__pills {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 11px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  background: #fff6ef;
}
.shelf__pills-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-right: 4px;
}
.shelf__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  text-transform: uppercase;
  padding: 3px 7px;
  cursor: pointer;
}
.shelf__pill strong { font-weight: 700; }
.shelf__pills-clear {
  border: 0;
  background: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.shelf__result-line {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-grey-on-tint);
  padding: 9px var(--sh-gutter);
}

/* Over-filtered empty state (1b): a bordered panel, never a bare nothing. */
.shelf__empty { margin: 20px var(--sh-gutter) 28px; border: 1px solid var(--sh-ink); }
.shelf__empty-band {
  background: var(--sh-grey);
  padding: 13px 22px;
  border-bottom: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.shelf__empty-body { padding: 24px 22px 26px; }
.shelf__empty-heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 34px; line-height: 1.04; }
.shelf__empty-copy { font-size: 15px; line-height: 1.58; max-width: 58ch; margin-top: 12px; }
.shelf__empty-exits { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.shelf__empty-exits button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  padding: 7px 10px;
  cursor: pointer;
}
.shelf__empty-exits button[data-clear-all] { background: var(--sh-ink); color: var(--sh-paper); }

/* The honest empty shelf — an empty-but-real directory channel (Steph's ruling,
   12 Aug 2026, 02a §11; the 05a §5 empty-tag shape: grey band, honest explanation,
   two exits). Same band/body/exits anatomy as the over-filtered state above, but
   server-rendered and the exits are links. */
.channel-empty { margin: 26px var(--sh-gutter) 34px; border: 1px solid var(--sh-ink); }
.channel-empty__band {
  background: var(--sh-grey);
  padding: 13px 22px;
  border-bottom: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.channel-empty__body { padding: 24px 22px 26px; }
.channel-empty__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.04;
  max-width: 26ch;
  text-wrap: balance;
}
.channel-empty__copy { font-size: 15px; line-height: 1.58; max-width: 58ch; margin-top: 12px; }
.channel-empty__exits { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.channel-empty__exits a {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 7px 10px;
  text-decoration: none;
}
.channel-empty__exits a:hover { outline: 2px solid var(--sh-ink); outline-offset: -2px; }

/* --------------------------------------------------------------------------
   The board row — job-row extended for /jobs/ (frame 1a): per-row labeled facts on
   desktop, the 1d card on mobile. No column header row; each row labels its own values.
   -------------------------------------------------------------------------- */

.job-row--board {
  grid-template-columns: 40px minmax(0, 1fr) 132px 148px 112px;
  align-items: start;
  padding: 22px var(--sh-gutter);
}
.job-row--board .job-row__mark { width: 40px; height: 40px; }
.job-row--board .job-row__title { font-size: 27px; }

/* Desktop hides the mobile-card furniture. */
.job-row__band,
.job-row__foot,
.job-row--board .job-row__company { display: none; }

.job-row__fact { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.job-row__fact-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.job-row__fact-value,
.job-row__fact-arrangement {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.14;
}
.job-row__fact--posted { text-align: right; }
/* Similar-jobs rows: salary right-aligned in its column (01a §4; frame 1c). */
.job-row--similar .job-row__fact--salary { text-align: right; }
/* 07 decision 18: closed rows grey their TEXT (#3a3a3a), not just spine and chip — the
   title included, and the tag-page facts (job-row__salary/__date, which don't carry the
   board's fact-value token) alike. Applies on /jobs/ and every /t/ page. */
.job-row--closed .job-row__title { color: var(--sh-grey-on-tint); }
.job-row--closed .job-row__fact-value,
.job-row--closed .job-row__fact-arrangement,
.job-row--closed .job-row__salary,
.job-row--closed .job-row__date,
.job-row--closed .job-row__commentary { color: var(--sh-grey-on-tint); }

/* Tag-sourced fact values: every tag is rendered, CSS reveals the family the cell is
   about. Handlebars has no prefix match — this is the same substitution tag.hbs makes
   for chrome accents, applied to row data. */
.fact-tag { display: none; }
.job-row__fact-value--salary .fact-tag[data-slug^="job-salary-"] { display: block; }
.job-row__fact-value--location { font-size: 18px; color: var(--sh-grey-on-paper); }
.job-row__fact-value--location .fact-tag[data-slug^="job-location-"] { display: inline; }
.job-row__fact-value--location .fact-tag[data-slug^="job-location-"] ~ .fact-tag[data-slug^="job-location-"]::before { content: " · "; }
/* "See listing" appears only when no salary band tag exists on the row. Browsers without
   :has() show a blank cell instead — quieter than a wrong value. */
.fact-fallback { display: none; }
.job-row__fact-value--salary:not(:has([data-slug^="job-salary-"])) .fact-fallback { display: block; }

/* --------------------------------------------------------------------------
   Chip axis tints. Color marks the AXIS, not the value (00 §2); {{tags}} outputs plain
   links, so the axis is read off the /t/{slug}/ href prefix. Job and resource tints per
   01a §8 / 02a; portfolio per 03a §2 (publication only). The rating and status tags render
   as designed chips in the markup itself, so their raw {{tags}} duplicates are dropped.
   -------------------------------------------------------------------------- */

.job-row__chips a[href*="/t/bjb-"],
.job-row__chips a[href*="/t/job-status-"],
.jobrail__tags a[href*="/t/bjb-"],
.resource-card__chips a[href*="/t/bjb-"],
.library-card__chips a[href*="/t/bjb-"] { display: none; }

/* The bad-job-bingo SERIES tag is chrome (breadcrumbs, series surfaces), not a row axis —
   as a raw {{tags}} chip it masqueraded as a label beside the real facts (critique,
   12 Aug 2026). Scoped to job surfaces only: on newsletter surfaces the series chip is
   designed and stays. */
.job-row__chips a[href*="/t/bad-job-bingo"],
.jobrail__tags a[href*="/t/bad-job-bingo"] { display: none; }

.job-row__chips a[href*="/t/job-discipline-"],
.jobrail__tags a[href*="/t/job-discipline-"],
.resource-card__chips a[href*="/t/job-discipline-"] { background: var(--sh-tint-jobs); }
.job-row__chips a[href*="/t/job-level-"],
.jobrail__tags a[href*="/t/job-level-"],
.resource-card__chips a[href*="/t/job-level-"] { background: #e5cde8; }
.job-row__chips a[href*="/t/job-type-"],
.job-row__chips a[href*="/t/job-arrangement-"],
.jobrail__tags a[href*="/t/job-type-"],
.jobrail__tags a[href*="/t/job-arrangement-"],
.resource-card__chips a[href*="/t/job-type-"],
.resource-card__chips a[href*="/t/job-arrangement-"] { background: #e6e4e2; }
.job-row__chips a[href*="/t/job-salary-"],
.jobrail__tags a[href*="/t/job-salary-"],
.resource-card__chips a[href*="/t/job-salary-"] { background: var(--sh-tint-resources); }
/* The no-comp family is the loudest chip on the board on purpose — full-strength pink,
   because missing pay is the thing a job seeker most often can't find out any other way. */
.job-row__chips a[href*="/t/job-salary-no-comp"],
.job-row__chips a[href*="/t/job-salary-competitive"],
.job-row__chips a[href*="/t/job-salary-i-dont"],
.jobrail__tags a[href*="/t/job-salary-no-comp"],
.jobrail__tags a[href*="/t/job-salary-competitive"],
.jobrail__tags a[href*="/t/job-salary-i-dont"] { background: var(--sh-hot-pink); }

/* The rail's Tags cell keeps the status tags the rows drop — rows hand-render their
   designed Open/Closed chips, but the rail chips ARE the raw {{tags}} output (01a §4–5).
   1c draws Open at full blue, 7a draws §5's grey Closed, and the ghost flag takes §8's
   grey tint like its shelf group. bjb-* stays hidden here: the rating's designed treatment
   is the meta-line block, and no frame draws it as a rail chip. */
.jobrail__tags a[href*="/t/job-status-open"] { background: var(--sh-blue); }
.jobrail__tags a[href*="/t/job-status-closed"] { background: var(--sh-grey); }
.jobrail__tags a[href*="/t/job-status-ghost-job"] { background: #e6e4e2; }

.library-card__chips a,
.respost__chips a {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.4;
  padding: 3px 8px;
  white-space: nowrap;
}
.library-card__chips a[href*="/t/res-directory-"],
.resource-card__chips a[href*="/t/res-directory-"],
.respost__chips a[href*="/t/res-directory-"] { background: var(--sh-tint-resources); }
.library-card__chips a[href*="/t/res-collection-"],
.resource-card__chips a[href*="/t/res-collection-"],
.respost__chips a[href*="/t/res-collection-"] { background: #f5d9f1; }
.library-card__chips a[href*="/t/res-publisher-"],
.resource-card__chips a[href*="/t/res-publisher-"],
.respost__chips a[href*="/t/res-publisher-"] { background: #f7cec7; }

.specimen__chips a,
.portpost__chips a,
.chip--plain {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 3px 7px;
  white-space: nowrap;
}
.specimen__chips a[href*="/t/port-pub-"],
.portpost__chips a[href*="/t/port-pub-"] { background: var(--sh-tint-portfolio); }
.specimen__chips a[href*="/t/port-format-"],
.portpost__chips a[href*="/t/port-format-"] { background: #e6e4e2; }

/* --------------------------------------------------------------------------
   Library cards — /resources/ (frame 1a): kind band with coral corner, cover thumb,
   serif title, neutral description, chips, ADDED/MORE foot.
   -------------------------------------------------------------------------- */

.library-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  padding: 24px var(--sh-gutter) 28px;
}
.library-card {
  position: relative;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  display: flex;
  flex-direction: column;
}
.library-card:hover,
.library-card:focus-within { background: #fff6ef; }
.library-card__band {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--sh-ink);
}
.library-card__kind {
  flex: 1;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 8px 11px;
}
.library-card__kind .fact-tag[data-slug^="res-directory-"] { display: inline; }
.library-card__kind .fact-tag[data-slug^="res-directory-"] ~ .fact-tag[data-slug^="res-directory-"]::before { content: " · "; }
/* The dog-ear folds (delight pass, 12 Aug 2026, 02a §12): picking the card up folds
   the corner a little further. Width, not transform — the fold IS the band geometry,
   the reflow is contained to the card's own kind row. Rides the blanket
   reduced-motion guard. :focus-within is the keyboard's hover. */
.library-card__corner {
  width: 26px;
  background: var(--sh-coral);
  border-left: 1px solid var(--sh-ink);
  transition: width 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
.library-card:hover .library-card__corner,
.library-card:focus-within .library-card__corner { width: 36px; }
.library-card__head {
  padding: 16px 14px 0;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.library-card__art {
  width: 52px;
  height: 52px;
  flex: none;
  border: 1px solid var(--sh-ink);
  overflow: clip;
}
.library-card__art img { width: 100%; height: 100%; object-fit: cover; }
.library-card__title {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.04;
  color: var(--sh-ink);
  text-decoration: none;
}
.library-card__title::after { content: ""; position: absolute; inset: 0; }
.library-card__when {
  margin: 12px 14px 0;
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-resources);
  padding: 7px 10px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.library-card__desc { font-size: 14px; line-height: 1.55; margin: 12px 14px 0; }
/* The event card's description is body markup ({{content words}} — drift item 117):
   flatten it to card-desc text. Inner links sit under the stretched title link and are
   not clickable here, so they must not dress as links. */
.library-card__desc--body p { margin: 0; font: inherit; display: inline; }
.library-card__desc--body p + p::before { content: " "; }
.library-card__desc--body a { color: inherit; text-decoration: none; }
.library-card__chips {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 14px 0;
}
.library-card__foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: auto;
  padding: 16px 14px 12px;
}
.library-card__added {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.library-card__more {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  transition: transform 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
/* Declare-on-hover + nudge — the jobs ramps' vocabulary (01a §14), same guard. */
.library-card:hover .library-card__more,
.library-card:focus-within .library-card__more {
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  transform: translateX(3px);
}

/* Directory browse row (frame 1a; 7d for the mobile disclosure). */
.dir-browse { border-bottom: 2px solid var(--sh-ink); }
.dir-browse__bar {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--sh-ink);
}
.dir-browse__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 12px 14px;
  border-right: 1px solid var(--sh-ink);
  white-space: nowrap;
  display: flex;
  align-items: center;
}
/* The mobile disclosure's Collections door (02a §8 / frame 7d); desktop uses the bar link. */
.dir-browse__sheet-all { display: none; }
.dir-browse__all {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 12px 14px;
}
.dir-browse__disclosure { display: none; }
.dir-browse__grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}
.dir-browse__cell {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--sh-ink);
  text-decoration: none;
  background: var(--sh-tint-resources);
  padding: 11px 14px;
  border-right: 1px solid var(--sh-ink);
}
.dir-browse__cell:nth-child(5n) { border-right: 0; }
.dir-browse__cell:nth-child(-n+5) { border-bottom: 1px solid var(--sh-ink); }
.dir-browse__cell:hover,
.dir-browse__cell:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.dir-browse__name { font-family: var(--sh-font-display); font-size: 19px; }
.dir-browse__count { font-family: var(--sh-font-mono); font-size: 10px; margin-left: auto; color: var(--sh-grey-on-tint); }
/* Honest zero (02a §11): an empty directory's cell is a span, not a link — Ghost 404s
   a channel whose tag has no posts — so it drops the hover affordance and greys down.
   #3a3a3a on the peach tint holds the small-text floor. */
.dir-browse__cell--empty:hover { background: var(--sh-tint-resources); }
.dir-browse__cell--empty .dir-browse__name { color: var(--sh-grey-on-tint); }
/* Live shelves declare on hover (delight pass, 02a §12) — inert zeros stay inert. */
.dir-browse__cell:not(.dir-browse__cell--empty):hover .dir-browse__name,
.dir-browse__cell:not(.dir-browse__cell--empty):focus-visible .dir-browse__name {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* What's new — the changelog's home (02a §7). */
.whats-new { padding: 30px var(--sh-gutter) 34px; border-bottom: 1px solid var(--sh-ink); }
.whats-new__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  border-bottom: 2px solid var(--sh-ink);
  padding-bottom: 10px;
}
.whats-new__twinkle { font-size: 26px; line-height: 1; }
.whats-new__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.015em;
}
.whats-new__all {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-underline-offset: 3px;
}
.whats-new__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--sh-ink);
  border-top: 0;
  margin-top: 18px;
}
.whats-new__entry {
  padding: 16px 18px;
  border-right: 1px solid var(--sh-ink);
  color: var(--sh-ink);
  text-decoration: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.whats-new__entry:last-child { border-right: 0; }
.whats-new__entry:hover,
.whats-new__entry:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.whats-new__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.whats-new__title { font-family: var(--sh-font-display); font-size: 24px; line-height: 1.06; }
.whats-new__dek { font-size: 14px; line-height: 1.5; }

/* --------------------------------------------------------------------------
   Section CTA band — the hiring CTA on /jobs/, the suggest CTA on /resources/, the
   availability band on /portfolio/. Peach halftone; the dot grid is decoration.
   -------------------------------------------------------------------------- */

.hiring-band {
  position: relative;
  overflow: hidden;
  background: var(--sh-peach);
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 44px;
  align-items: center;
  padding: 34px var(--sh-gutter);
}
.hiring-band::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 6px 6px;
  opacity: 0.14;
  pointer-events: none;
}
.hiring-band__copy,
.hiring-band__button { position: relative; }
.hiring-band__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 38px;
  line-height: 1.04;
  letter-spacing: -0.015em;
}
.hiring-band__heading .sh-twinkle { font-size: 26px; vertical-align: 0.18em; }
.hiring-band__copy p { font-size: 15px; line-height: 1.58; max-width: 56ch; margin-top: 14px; }
.hiring-band__button {
  display: block;
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-align: center;
  padding: 16px 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
}
/* The hire-me door had no hover state at all — this rule only held the color against the
   global a:hover. It now takes the house primary-button hover (#6b6b6b), the same one the
   nav's Subscribe and the resources pass's `Open it ↗` use. Delight pass, 14 Aug 2026. */
.hiring-band__button:hover,
.hiring-band__button:focus-visible {
  color: var(--sh-paper);
  background: var(--sh-grey-on-paper);
}
.hiring-band__button { transition: background-color 0.18s cubic-bezier(0.22, 1, 0.36, 1); }

/* Paging row shared by the boards. */
.board-paging {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  padding: 0 var(--sh-gutter);
}
.board-paging:empty { display: none; }
.board-paging .news-pagination { border-bottom: 0; flex: 1; }
.board-paging__perpage {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  padding: 18px 0;
}
.board-paging__perpage button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  padding: 4px 9px;
  cursor: pointer;
}
.board-paging__perpage button[aria-pressed="true"] { background: var(--sh-ink); color: var(--sh-paper); }

/* --------------------------------------------------------------------------
   The Specimen — /portfolio/ (03a §3, frames 1b / 5a). Panels alternate pale purple
   and peach. The pulled paragraph is their published work: serif, 27px, upright.
   -------------------------------------------------------------------------- */

/* 420px, not 330 (critique, 13 Aug 2026). Measured at 1440: the panel gave the TITLE — the name
   of the work, on the page whose whole job is showing the work — a 269px column, where "Why Great
   Customer Service Isn't Just Important, It's a Necessity" set as four lines of 34px serif, while
   the quote column next to it ran 1110px wide around a 546px quote and left 564px of nothing. The
   space was taken from the one element that needed it. The panel takes 90px back and the quote
   measure opens up; what remains empty is margin rather than a hole. */
.specimen {
  display: grid;
  grid-template-columns: 420px minmax(0, 1fr);
  align-items: stretch;
  border-bottom: 1px solid var(--sh-ink);
}
.specimen__panel {
  border-right: 1px solid var(--sh-ink);
  background: var(--sh-tint-portfolio);
  padding: 28px 30px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 18px;
}
.specimen:nth-of-type(even) .specimen__panel { background: var(--sh-tint-resources); }
.specimen__pub {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.specimen__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.02;
  margin-top: 10px;
}
.specimen__panel-foot { display: flex; flex-direction: column; gap: 10px; }
.specimen__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.specimen__read {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  align-self: flex-start;
}
/* Format-aware CTA (drift item 111): the generic "Read it →" yields when a format label
   rendered. Without :has() both show — visibly wrong, never silently empty (§11's rule). */
.specimen__read:has(.specimen__read-label) .specimen__read-fallback { display: none; }

/* THE DOOR ANSWERS THE WHOLE CUTTING (delight pass, 14 Aug 2026). A specimen is one clipping
   mounted across two cells — a tinted panel and the pulled paragraph — and its single action
   sits in the bottom corner of the left one. Pointing anywhere in the row, or tabbing into it,
   declares that action: the underline doubles and the arrow leans toward the piece. The reader's
   pointer is usually on the quote, which is the half that makes them want the door. */
.specimen__read {
  transition: text-decoration-thickness 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.specimen:hover .specimen__read,
.specimen:focus-within .specimen__read {
  text-decoration-thickness: 2px;
}
.specimen:hover .specimen__read .sh-arrow,
.specimen:focus-within .specimen__read .sh-arrow {
  transform: translateX(3px);
}
.specimen__quote-col {
  padding: 30px 40px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  justify-content: center;
}
.specimen__quote {
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.24;
  max-width: 52ch;
}
.specimen__attrib {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

/* Everything else — the clip-file list. */
.clip-file { padding: 26px var(--sh-gutter) 30px; }
.clip-file__head { display: flex; align-items: baseline; gap: 12px; }
.clip-file__twinkle { font-size: 22px; line-height: 1; }
.clip-file__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 36px; line-height: 1; }
.clip-file__count {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.clip-file__list {
  border-top: 2px solid var(--sh-ink);
  margin-top: 12px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 40px;
}
.clip-file__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 13px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
/* The wash arrived without the title declaring, on the one list where every row is a door
   (delight pass, 14 Aug 2026). The rail's related rows a few hundred lines down have done
   exactly this since they were built; the clip file now matches, with focus parity. */
.clip-file__row:hover,
.clip-file__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.clip-file__row:hover .clip-file__credit,
.clip-file__row:focus-visible .clip-file__credit { color: var(--sh-grey-on-tint); }
.clip-file__row:hover .clip-file__title,
.clip-file__row:focus-visible .clip-file__title {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.clip-file__title { font-family: var(--sh-font-display); font-size: 21px; line-height: 1.14; }
.clip-file__credit {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Footnotes — /footnotes/ (04a §7 anatomy). Number and title serif, meta Space Mono,
   quote serif italic with the pink rule, footnote body sans opened by the dagger.
   -------------------------------------------------------------------------- */

.fn-controls { padding: 26px var(--sh-gutter) 0; }
.fn-controls[hidden] { display: none; }
.fn-controls__bar { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; }
.fn-controls__search {
  flex: 1;
  min-width: 200px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 11px 14px;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--sh-ink);
}
.fn-controls__sort,
.fn-controls__clear,
.fn-controls__rss {
  border: 1px solid var(--sh-ink);
  padding: 11px 16px;
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
.fn-controls__sort { background: var(--sh-paper); color: var(--sh-ink); }
.fn-controls__clear { background: var(--sh-ink); color: var(--sh-paper); }
.fn-controls__rss { background: var(--sh-peach); color: var(--sh-ink); }
/* The template holds the feed link hidden until the feed URL exists; without this guard
   the inline-flex above beats the UA's [hidden] rule and a 404 button ships. */
.fn-controls__rss[hidden] { display: none; }

.fn-tags { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin-top: 16px; }
.fn-tag {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 4px 10px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--sh-ink);
  cursor: pointer;
}
.fn-tag[aria-pressed="true"] {
  background: #fff6ef;
  border-left: 3px solid var(--sh-hot-pink);
}
.fn-tag__count { color: var(--sh-grey-on-paper); margin-left: 4px; }
/* Selected chip ground is the #fff6ef tint — the ≤13px floor there is #3a3a3a (CLAUDE.md). */
.fn-tag[aria-pressed="true"] .fn-tag__count { color: var(--sh-grey-on-tint); }
.fn-tags__more {
  border: 0;
  background: none;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--sh-link);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  padding: 4px 6px;
}

.fn-result-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.fn-result-line__hint {
  text-transform: none;
  letter-spacing: 0.04em;
  color: var(--sh-grey-on-paper);
}

.fn-entries { padding: 0 var(--sh-gutter); }
.fn-entry {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 28px;
  padding: 34px 0 32px;
  border-bottom: 1px solid var(--sh-hairline);
}
.fn-entry__rail { display: flex; flex-direction: column; gap: 8px; }
.fn-entry__number { font-family: var(--sh-font-display); font-size: 46px; line-height: 0.9; }
.fn-entry__media {
  font-family: var(--sh-font-mono);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.fn-entry__main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.fn-entry__title-line { display: flex; align-items: baseline; gap: 12px; }
/* The h2 is structural — 46 entries need headings to navigate by; type lives on the link
   so the 900px override keeps working. */
.fn-entry__title-wrap { flex: 1; margin: 0; font-size: inherit; font-weight: inherit; line-height: inherit; }
.fn-entry__title {
  font-family: var(--sh-font-display);
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--sh-ink);
  text-decoration: none;
}
.fn-entry__title:hover,
.fn-entry__title:focus-visible { color: var(--sh-link); }
/* Delight (13 Aug 2026, 04a §12 — the marginalia lean in): the way out declares. The lean
   itself now rides .sh-arrow--out (extracted 16 Aug 2026); this rule keeps only the size. */
.fn-entry__out { font-size: 24px; }
.fn-entry__anchor {
  border: 0;
  background: none;
  padding: 2px 4px;
  font-family: var(--sh-font-mono);
  font-size: 14px;
  color: var(--sh-grey-on-paper);
  cursor: pointer;
  transition: color 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
/* The # is an invitation once the hand is near — grey is its rest state, never gone. */
.fn-entry:hover .fn-entry__anchor,
.fn-entry:focus-within .fn-entry__anchor { color: var(--sh-ink); }
/* The ✓ lands like a stamp (the jobs dauber's -5deg, one beat). */
.fn-entry__anchor.is-copied { animation: fn-stamp 0.18s cubic-bezier(0.25, 1, 0.5, 1); }
/* THE HOUSE STAMP. Named for where it was first written; used in three places now — this ✓,
   the FAQ question anchor's ✓, and the ✦ landing on a picked contact reason. Transform-only,
   so the reduced-motion blanket zeroes it. */
@keyframes fn-stamp { from { transform: scale(1.5) rotate(-5deg); } }
/* Arriving on a saved anchor lands on the house selected grammar — wash + pink edge,
   fading in from paper so the entry you asked for says "here". State marker, not a
   card accent (the ignore.md side-tab exemption family). The class twin exists because
   :target can't see ids that render after navigation (footnotes.js hash-honor). */
.fn-entry:target,
.fn-entry--here {
  background: #fff6ef;
  border-left: 3px solid var(--sh-hot-pink);
  padding-left: 16px;
  padding-right: 16px;
  animation: fn-arrive 0.5s cubic-bezier(0.25, 1, 0.5, 1);
}
.fn-entry { scroll-margin-top: 24px; }
@keyframes fn-arrive { from { background: var(--sh-paper); } }
.fn-entry__byline {
  font-family: var(--sh-font-mono);
  font-size: 14px;
  line-height: 1.5;
}
.fn-entry__byline a {
  font-weight: 700;
  color: var(--sh-ink);
  text-decoration: underline;
  text-decoration-color: var(--sh-hot-pink);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
/* 04a §7: the name pops at 700 whether or not it links; the underline stays link-only. */
.fn-entry__byline-name { font-weight: 700; }
.fn-entry__byline .fn-entry__in { color: var(--sh-grey-on-paper); }
.fn-entry__dates {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--sh-grey-on-paper);
}
/* Verb purple is the consolidated small-text value #8f3f96 (18 chat-12 second pass:
   04a §7's old #8a3f91 was consolidated to the site-wide value, 09 turn 17). */
.fn-entry__verb { font-weight: 700; color: #8f3f96; text-transform: uppercase; }
.fn-entry__quote {
  margin-top: 6px;
  border-left: 2px solid var(--sh-hot-pink);
  padding-left: 14px;
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 21px;
  line-height: 1.34;
  /* No measure cap — Steph, twice on 19 Aug 2026: 66ch wrapped at half the column, the
     75ch bump was still "half a page" on wide screens. The quote and note now fill the
     entry's main column like every other full-bleed row device on this site (the job
     rows stretch the same way); the ch caps were the anomaly, not the rule. */
  text-wrap: pretty;
}
.fn-entry__note { display: flex; align-items: flex-start; gap: 11px; margin-top: 4px; }
.fn-entry__dagger {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 46px;
  line-height: 0.62;
  color: var(--sh-hot-pink);
  flex: none;
}
.fn-entry__note p { font-size: 17px; line-height: 1.56; text-wrap: pretty; }
.fn-entry__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.fn-entry__tag {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 3px 8px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  /* A chip is one unit — "customer trust & loyalty" was breaking mid-label (found 19 Aug
     2026 while measuring the page). The tags row is flex-wrap, so whole chips still wrap. */
  white-space: nowrap;
  color: var(--sh-ink);
  cursor: pointer;
}
.fn-entry__tag[aria-pressed="true"] { background: #fff6ef; border-left: 3px solid var(--sh-hot-pink); }

.fn-state {
  margin: 28px var(--sh-gutter);
  border: 1px solid var(--sh-ink);
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
.fn-state[hidden] { display: none; }
.fn-state__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.fn-state__dagger {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 54px;
  line-height: 1;
  color: var(--sh-hot-pink);
}
/* The dagger breathes while the list is on its way — waiting, not stuck. Rides the
   blanket reduced-motion guard like every animation here. */
.fn-state--loading .fn-state__dagger { animation: fn-breathe 1.6s ease-in-out infinite; }
@keyframes fn-breathe { 50% { opacity: 0.55; } }
.fn-state__heading { font-family: var(--sh-font-display); font-size: 34px; line-height: 1.05; }
.fn-state--loading .fn-state__heading { font-size: 28px; line-height: 1.1; }
.fn-state__copy { font-size: 15px; line-height: 1.55; max-width: 56ch; }
.fn-state__button {
  margin-top: 4px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}

.fn-paging {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  padding: 26px var(--sh-gutter) 30px;
  font-family: var(--sh-font-mono);
  font-size: 12px;
}
.fn-paging[hidden] { display: none; }
.fn-paging__pages { display: flex; gap: 6px; align-items: center; }
.fn-paging button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 12px;
  padding: 6px 11px;
  cursor: pointer;
}
.fn-paging button[aria-current="page"],
.fn-paging button[aria-pressed="true"] { background: var(--sh-ink); color: var(--sh-paper); }
.fn-paging__range { margin-left: 12px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
.fn-paging__perpage { display: flex; gap: 6px; align-items: center; }
.fn-paging__perpage-label { font-size: 11px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--sh-grey-on-paper); }

.fn-send {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  background: var(--sh-peach);
  border-top: 1px solid var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
  padding: 30px var(--sh-gutter);
}
.fn-send__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 34px; line-height: 1.04; letter-spacing: -0.015em; }
/* On /newsletter/browse/ the band is the newsletter's own blush at 16a's 30px —
   never another section's peach (00 §strip scope). */
.fn-send--newsletter { background: var(--sh-tint-newsletter); }
.fn-send--newsletter .fn-send__heading { font-size: 30px; }
.fn-send__copy p { font-size: 15px; line-height: 1.55; margin-top: 8px; max-width: 62ch; }
.fn-send__button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 13px 22px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: none;
  white-space: nowrap;
}
.fn-send__button:hover { color: var(--sh-ink); }

.fn-support {
  position: relative;
  overflow: hidden;
  background: var(--sh-hot-pink);
  border-bottom: 1px solid var(--sh-ink);
}
.fn-support::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 6px 6px;
  opacity: 0.14;
  pointer-events: none;
}
.fn-support__inner {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 56px;
  padding: 40px var(--sh-gutter);
}
.fn-support__pitch { display: flex; flex-direction: column; gap: 18px; max-width: 620px; }
.fn-support__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 46px;
  line-height: 1.02;
  letter-spacing: -0.015em;
}
.fn-support__pitch p { font-size: 16px; line-height: 1.55; max-width: 56ch; text-wrap: pretty; }
.fn-support__card {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 22px;
  width: 340px;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.fn-support__card-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.fn-support__action {
  display: block;
  text-align: center;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 14px 18px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: none;
}
.fn-support__action:hover { color: var(--sh-ink); }
.fn-support__action--primary { background: var(--sh-ink); color: var(--sh-paper); }
.fn-support__action--primary:hover { color: var(--sh-paper); }
.fn-support__action--member { background: var(--sh-peach); }
.fn-support__aside,
.fn-support__close {
  font-family: var(--sh-font-mono);
  font-size: 12px; /* close-line lift, with its siblings (12 Aug 2026 ruling, 12 §amend) */
  line-height: 1.7;
  letter-spacing: 0.04em;
}
/* The closing line is small-caps mono (09 §5), like every other support block's close. */
.fn-support__close { font-weight: 700; text-transform: uppercase; }

/* --------------------------------------------------------------------------
   Mobile — 900px and down. The shelf panel becomes the full-height filter sheet
   (Jobs 1e / Resources 7b), the job row becomes the 1d card, the library goes to one
   column behind the directory disclosure (7a/7d), the specimen stacks (5a).
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .board-header,
  .board-header--footnotes {
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 24px 18px 26px;
  }
  /* One column, so there is no gutter to stand in and nowhere on a 390px band that is
     reliably clear of the copy. The dot field carries the treatment alone here. */
  .sh-sparks { display: none; }
  .board-header__title { font-size: 46px; line-height: 0.96; }

  .rating-ramp { flex-direction: column; }
  .rating-ramp__cell { border-right: 0; border-bottom: 1px solid var(--sh-ink); }
  .rating-ramp__cell:last-child { border-bottom: 0; }
  .rating-ramp__name { font-size: 21px; white-space: normal; }

  .board-dry { grid-template-columns: 1fr; gap: 20px; padding: 26px 18px; }

  /* The filter sheet: the open panel takes the viewport. */
  .shelf__panel {
    position: fixed;
    inset: 0;
    z-index: 60;
    overflow-y: auto;
    border-bottom: 0;
  }
  .shelf__panel-head {
    position: sticky;
    top: 0;
    background: var(--sh-paper);
    padding: 18px 18px 16px;
    z-index: 1;
  }
  .shelf__panel-title { font-size: 32px; }
  .shelf__panel-hint { display: none; }
  .shelf__groups { grid-template-columns: 1fr; padding: 0 18px; gap: 0; }
  .shelf__group-head button { min-height: 46px; }
  .shelf__option { padding: 12px 2px; }
  .shelf__panel-actions {
    position: sticky;
    bottom: 0;
    background: var(--sh-paper);
    border-top: 1px solid var(--sh-ink);
    padding: 16px 18px 20px;
  }
  /* 02a §8 (and 00): "Filter bar sticks to the top on scroll" — drift item 80. Sticky
     on .shelf, not the bar: sticky is bounded by its parent, and the bar's parent is the
     short shelf itself — the shelf's parent contains the board, which is the scroll the
     bar must survive. The open panel is the fixed full-height sheet (z 60), so it never
     rides along; pills and the result line do, which keeps the active-filter context in
     view. Paper ground so rows never show through. */
  .shelf {
    position: sticky;
    top: 0;
    z-index: 6;
    background: var(--sh-paper);
  }
  .shelf__bar { flex-wrap: wrap; }
  .shelf__pills { padding: 11px 18px; }
  .shelf__result-line { padding: 8px 18px; }
  .shelf__empty { margin: 16px 18px 22px; }
  .channel-empty { margin: 16px 18px 22px; }
  .channel-empty__heading { font-size: 28px; }

  /* Job row → the 1d card. */
  .job-row--board {
    display: flex;
    flex-direction: column;
    gap: 0;
    border: 1px solid var(--sh-ink);
    border-left-width: 1px;
    margin: 14px 14px 0;
    padding: 0;
  }
  .job-row--board.job-row--closed { border-left: 4px solid var(--sh-grey); padding: 0; }
  .job-row--board .job-row__band {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    border-bottom: 1px solid var(--sh-ink);
    padding: 8px 12px;
    font-family: var(--sh-font-mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .job-row__band-rating { display: inline-flex; align-items: center; gap: 7px; }
  .job-row__band-rating img { width: 16px; height: 16px; }
  .job-row__band-status { font-weight: 400; }
  /* Band takes the row's rating tint. */
  .job-row--board:has(.chip--rating-green) .job-row__band { background: #c9ead6; }
  .job-row--board:has(.chip--rating-fine) .job-row__band { background: #fdeadb; }
  .job-row--board:has(.chip--rating-tread) .job-row__band { background: #f7cac3; }
  .job-row--board:has(.chip--rating-bingo) .job-row__band { background: #fcbcd2; }
  .job-row--board:has(.chip--rating-dont) .job-row__band { background: #d6d4d6; }
  /* No closed override on the band: the rating keeps its tint on close (01a §5), and the
     ramp tints are ratings only (01a §8) — #d6d4d6 here read as "closed", which it never means.
     Closed is signaled by the grey spine, greyed commentary and the status chip (07 d.18). */

  .job-row--board .job-row__mark {
    width: 26px;
    height: 26px;
    border: 0;
    position: absolute;
  }
  .job-row--board { position: relative; }
  .job-row--board .job-row__mark { margin: 14px 0 0 14px; }
  .job-row--board .job-row__company {
    display: block;
    font-family: var(--sh-font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sh-grey-on-paper);
    padding: 20px 14px 0 50px;
  }
  .job-row--board .job-row__main { padding: 0 14px; }
  .job-row--board .job-row__title { font-size: 28px; line-height: 1.06; }
  .job-row--board .job-row__title-line { margin-top: 8px; }
  .job-row--board .job-row__title-line .chip--open,
  .job-row--board .job-row__title-line .chip--closed { display: none; }
  .job-row--board .job-row__commentary { color: var(--sh-ink); }
  .job-row--closed .job-row__commentary { color: var(--sh-grey-on-tint); }
  .job-row--board .job-row__chips {
    border-top: 1px solid var(--sh-hairline);
    margin-top: 12px;
    padding-top: 12px;
  }
  .job-row--board .job-row__fact {
    padding: 0 14px;
    border-top: 1px solid var(--sh-hairline);
    margin-top: 12px;
    padding-top: 12px;
  }
  .job-row--board .job-row__fact--posted { display: none; }
  .job-row--board .job-row__fact-value { font-size: 21px; }
  .job-row--board .job-row__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* The desktop row's `align-items: start` carries into this flex column, shrinking
       the foot to content width — date and CTA collided with space-between doing
       nothing (critique, 12 Aug 2026). Stretch keeps the margins honest. */
    align-self: stretch;
    border-top: 1px solid var(--sh-hairline);
    margin: 12px 14px 0;
    padding: 12px 0 14px;
    font-family: var(--sh-font-mono);
    font-size: 10px;
    color: var(--sh-grey-on-paper);
  }
  .job-row--board .job-row__foot-cta { font-size: 11px; color: var(--sh-link); }
  .board-rows { padding-bottom: 14px; }

  .library-grid { grid-template-columns: 1fr; padding: 16px; gap: 14px; }

  /* Directory row → disclosure (7d): collapsed by default so the first card sits high. */
  .dir-browse__bar { border-bottom: 0; }
  .dir-browse__label,
  .dir-browse__all { display: none; }
  .dir-browse__disclosure {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    min-height: 46px;
    padding: 0 16px;
    border: 0;
    border-bottom: 1px solid var(--sh-ink);
    background: var(--sh-tint-resources);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    cursor: pointer;
  }
  .dir-browse__disclosure-count { font-family: var(--sh-font-mono); font-size: 12px; color: var(--sh-grey-on-tint); }
  .dir-browse__grid { display: none; grid-template-columns: 1fr 1fr; }
  .dir-browse--open .dir-browse__grid { display: grid; }
  /* The link out to /resources/browse/ closes the open grid (7d's 44px row). */
  .dir-browse--open .dir-browse__sheet-all {
    display: flex;
    align-items: center;
    grid-column: 1 / -1;
    min-height: 44px;
    padding: 0 16px;
    border-bottom: 1px solid var(--sh-ink);
    font-family: var(--sh-font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sh-link);
    text-decoration: none;
  }
  .dir-browse__cell,
  .dir-browse__cell:nth-child(5n) {
    min-height: 46px;
    align-items: center;
    border-right: 1px solid var(--sh-ink);
    border-bottom: 1px solid var(--sh-ink);
  }
  .dir-browse__cell:nth-child(2n) { border-right: 0; }
  .dir-browse--open .dir-browse__bar::after { content: none; }

  .whats-new { padding: 24px 18px 28px; }
  .whats-new__grid { grid-template-columns: 1fr; }
  .whats-new__entry { border-right: 0; border-bottom: 1px solid var(--sh-ink); }
  .whats-new__entry:last-child { border-bottom: 0; }

  .hiring-band { grid-template-columns: 1fr; gap: 18px; padding: 24px 18px; }
  .hiring-band__heading { font-size: 32px; }

  /* Specimen stacks: the tinted panel announces the lead before you read a word (5a).
     Every lead gets a bordered read button — the underline is not a 44px target. */
  .specimen { grid-template-columns: 1fr; }
  .specimen__panel { border-right: 0; border-bottom: 1px solid var(--sh-hairline); padding: 18px; }
  .specimen__title { font-size: 30px; }
  .specimen__quote-col { padding: 18px; }
  .specimen__quote { font-size: 21px; line-height: 1.26; }
  .specimen__read {
    align-self: stretch;
    border: 1px solid var(--sh-ink);
    padding: 12px;
    text-align: center;
    text-decoration: none;
  }
  .clip-file { padding: 22px 18px; }
  .clip-file__list { grid-template-columns: 1fr; }
  .clip-file__row { grid-template-columns: 1fr; gap: 4px; }

  .fn-controls { padding: 12px 18px 0; }
  .fn-entries { padding: 0 18px; }
  .fn-entry { grid-template-columns: 1fr; gap: 9px; padding: 22px 0 20px; }
  .fn-entry__rail { flex-direction: row; align-items: baseline; gap: 10px; }
  .fn-entry__number { font-size: 34px; }
  .fn-entry__media { font-size: 12px; }
  .fn-entry__title { font-size: 26px; }
  .fn-entry__dagger { font-size: 40px; line-height: 0.66; }
  .fn-state { margin: 20px 18px; }
  .fn-paging { padding: 20px 18px 24px; }
  .fn-send { flex-direction: column; align-items: flex-start; gap: 14px; padding: 22px 18px; }
  .fn-support__inner { flex-direction: column; gap: 20px; padding: 24px 18px; }
  .fn-support__card { width: 100%; }
  .fn-support__heading { font-size: 32px; }
  .board-paging { padding: 0 18px; }
}

/* Base chip visuals for the chips the board rows declare directly (rating, Open/Closed) —
   the original rule up in the tag-template section is scoped to .tag-rows, and the boards
   render outside it. Same values; do not fork them. */
.job-row .chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.4;
  padding: 3px 8px;
  white-space: nowrap;
}
.job-row .chip--open { background: var(--sh-blue); }
.job-row .chip--closed { background: var(--sh-grey); }

/* ==========================================================================
   /resources/events/ (index-events.hbs, frame 4a/7c) and the two browse pages
   (browse-jobs.hbs frame 10a, browse-resources.hbs frame 2a).
   ========================================================================== */

/* Events header — peach halftone band with the NEXT ONE card. */
.events-header {
  position: relative;
  overflow: hidden;
  background: var(--sh-peach);
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 44px;
  align-items: start;
  padding: 34px var(--sh-gutter) 32px;
}
.events-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 6px 6px;
  opacity: 0.14;
  pointer-events: none;
}
.events-header__copy,
.events-next { position: relative; }
.events-header__crumb {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.events-header__crumb a { color: var(--sh-ink); text-underline-offset: 3px; }
.events-header__path { color: var(--sh-grey-on-tint); }
.events-header__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 60px;
  line-height: 1;
  letter-spacing: -0.02em;
}
.events-header__intro { font-size: 16px; line-height: 1.6; max-width: 52ch; margin-top: 14px; }
.events-header__note {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 17px;
  line-height: 1.45;
  margin-top: 14px;
  padding-left: 14px;
  border-left: 2px solid var(--sh-coral);
  max-width: 56ch;
}
.events-next { border: 1px solid var(--sh-ink); background: var(--sh-paper); }
.events-next[hidden] { display: none; }
.events-next__body { padding: 16px 14px 14px; border-bottom: 1px solid var(--sh-ink); }
.events-next__label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.events-next__soon {
  display: block;
  font-family: var(--sh-font-display);
  font-size: 44px;
  line-height: 1.02;
  margin-top: 4px;
}
.events-next__split {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.7;
  color: var(--sh-grey-on-tint);
  margin-top: 6px;
}
.events-next__asof {
  padding: 11px 14px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sh-grey-on-tint);
}

.events-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  background: #fff6ef;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-grey-on-tint);
}

/* The event row: date cell (script-revealed) · body · WHERE column. */
.event-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px;
  gap: 24px;
  align-items: start;
  padding: 20px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
}
.event-row--dated { grid-template-columns: 132px minmax(0, 1fr) 220px; }
.event-row:hover,
.event-row:focus-within { background: #fff6ef; }
.event-row:hover .event-row__where-label,
.event-row:focus-within .event-row__where-label { color: var(--sh-grey-on-tint); }
.event-row__cell {
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-resources);
  padding: 9px 10px;
  display: flex;
  flex-direction: column;
}
.event-row__cell[hidden] { display: none; }
.event-row__cell-month {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--sh-grey-on-tint);
}
.event-row__cell-day {
  font-family: var(--sh-font-display);
  font-size: 30px;
  line-height: 1;
  margin-top: 2px;
}
.event-row__cell-mode {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--sh-grey-on-tint);
  margin-top: 4px;
}
.event-row__main { min-width: 0; }
.event-row__title {
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.04;
  color: var(--sh-ink);
  text-decoration: none;
}
.event-row__title::after { content: ""; position: absolute; inset: 0; }
.event-row__when {
  display: block;
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.2;
  color: var(--sh-grey-on-tint);
  margin-top: 4px;
}
.event-row__desc { display: block; font-size: 14px; line-height: 1.55; max-width: 66ch; margin-top: 9px; }
/* The desc is {{content words}} now (drift item 117 — {{excerpt}} echoed the dateline),
   so it arrives as paragraphs: inline them, same treatment as .library-card__desc--body. */
.event-row__desc p { margin: 0; font: inherit; display: inline; }
.event-row__desc p + p::before { content: " "; }
.event-row__desc a { color: inherit; text-decoration: none; }
/* Live (pre-migration) event bodies open with headings inside the 30-word window —
   a heading element inside a list-row teaser is noise to screen readers and renders
   bold mid-desc. Drop them; the desc is the body's prose, not its structure. */
.event-row__desc :is(h1, h2, h3, h4, h5, h6),
.library-card__desc--body :is(h1, h2, h3, h4, h5, h6) { display: none; }
.event-row__chips {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 11px;
}
.event-row__chips a {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 3px 7px;
  white-space: nowrap;
}
.event-row__chips a[href*="/t/res-directory-"] { display: none; } /* the page IS the directory */
.event-row__chips a[href*="/t/res-collection-"] { background: #f5d9f1; }
.event-row__where { text-align: right; }
.event-row__where-label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.event-row__where-label[hidden] { display: none; }
.event-row__where-place {
  display: block;
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.2;
  margin-top: 4px;
}
.event-row__more {
  display: inline-block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  margin-top: 10px;
}

/* Already happened — the grey ledger. */
.events-past[hidden] { display: none; }
.events-past__band {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--sh-ink);
  background: #e6e4e2;
  padding: 14px var(--sh-gutter);
  font-family: var(--sh-font-mono);
  text-align: left;
  cursor: pointer;
}
.events-past__band-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.events-past__band-note { font-size: 11px; color: var(--sh-grey-on-tint); }
.events-past__list[hidden] { display: none; }
.events-past__row {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr) 220px;
  gap: 24px;
  align-items: baseline;
  padding: 13px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.events-past__row:hover,
.events-past__row:focus-visible { background: #fff6ef; }
.events-past__chip {
  justify-self: start;
  border: 1px solid var(--sh-ink);
  background: #e6e4e2;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 7px;
  white-space: nowrap;
  /* The hand-stamped ledger (delight pass, 02a §12): rotated stamps are a named
     Broadsheet motif (00 §Design language) that resources never used. Alternating
     small angles read as stamped by hand, not templated. Static — no motion. */
  transform: rotate(-2deg);
}
.events-past__row:nth-child(even) .events-past__chip { transform: rotate(1.25deg); }
.events-past__title {
  font-family: var(--sh-font-display);
  font-size: 22px;
  line-height: 1.1;
  color: var(--sh-grey-on-tint);
}
.events-past__place {
  font-family: var(--sh-font-display);
  font-size: 18px;
  color: var(--sh-grey-on-paper);
  text-align: right;
}
.events-past__rule {
  padding: 16px var(--sh-gutter) 20px;
  border-bottom: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.8;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--sh-grey-on-tint);
  /* Unbounded it ran the full viewport — ~240 characters a line at 1200px
     (critique, 12 Aug 2026). 72ch of 10px mono is a readable footnote block. */
  max-width: 72ch;
}

/* --------------------------------------------------------------------------
   Browse pages — shared header, categories box, sections, counted chips.
   -------------------------------------------------------------------------- */

.section-strip__name--link { font-weight: 700; color: var(--sh-ink); }

.browse-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 44px;
  align-items: start;
  padding: 34px var(--sh-gutter) 30px;
  border-bottom: 2px solid var(--sh-ink);
  /* Right column (360) + half the gap (22), in from the band's right edge. */
  --sh-sparks-x: calc(100% - var(--sh-gutter) - 382px);
}
.browse-header__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 64px; /* 01a §6's named size for /jobs/browse/; /resources/browse/ mirrors it */
  line-height: 0.98;
  letter-spacing: -0.02em;
  /* The header purple, but no dot field — 41e's ruling. The color and the field are
     separable: the field is the section front door's mark, the deeper purple is just the
     better headline value (7.85:1 against 4.41:1). */
  color: var(--sh-purple-header);
}
/* /newsletter/browse/ takes the 01a §3 house header per turn 16 — 82px, 44px at 390px. */
.browse-header__title--house { font-size: 82px; letter-spacing: -0.015em; }
.browse-header__intro { font-size: 17px; line-height: 1.6; max-width: 56ch; margin-top: 18px; }
.browse-header__links {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  margin-top: 20px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.browse-header__links a { text-underline-offset: 3px; }

.browse-doors { display: flex; flex-direction: column; margin-top: 26px; border-top: 1px solid var(--sh-ink); }
.browse-doors__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.browse-doors__row:hover,
.browse-doors__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.browse-doors__name { font-family: var(--sh-font-display); font-size: 23px; line-height: 1.1; }
.browse-doors__cta {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  white-space: nowrap;
}

.browse-cats { border: 1px solid var(--sh-ink); padding: 14px 16px 12px; }
.browse-cats__label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--sh-ink);
}
.browse-cats__sub {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.6;
  color: var(--sh-grey-on-tint);
  margin-top: 6px;
}
.browse-cats__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.browse-cats__row:last-of-type { border-bottom: 0; }
.browse-cats__row:hover,
.browse-cats__row:focus-visible { color: var(--sh-link); }
.browse-cats__name {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.browse-cats__value {
  font-family: var(--sh-font-display);
  font-size: 19px;
  line-height: 1;
  color: var(--sh-grey-on-paper);
}
.browse-cats__note {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.7;
  color: var(--sh-grey-on-tint);
  background: #f2f0ee;
  padding: 9px 12px;
  margin-top: 8px;
}

.browse-section { padding: 30px var(--sh-gutter) 0; }
.browse-section--last,
.browse-page .browse-section:last-of-type { padding-bottom: 34px; }
.browse-section__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  justify-content: space-between;
  padding-bottom: 11px;
  border-bottom: 2px solid var(--sh-ink);
}
.browse-section__twinkle { font-size: 26px; line-height: 1; }
.browse-section__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin-right: auto;
}
.browse-section__anchor {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--sh-grey-on-paper);
}
.browse-section__intro {
  font-size: 16px;
  line-height: 1.58;
  max-width: 96ch; /* reference measure, not reading measure (01a §6) */
  margin-top: 14px;
  color: var(--sh-grey-on-tint);
}
.browse-section__intro code { font-family: var(--sh-font-mono); font-size: 13px; }

.browse-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; }
.browse-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 5px 9px;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
}
.browse-chip:hover { color: var(--sh-ink); outline: 2px solid var(--sh-ink); outline-offset: -2px; }
.browse-chip__count { font-size: 11px; color: var(--sh-grey-on-tint); }
/* Axis tints; rating chips take their own verdict tint per value (no icons here). */
.browse-chips--discipline .browse-chip { background: var(--sh-tint-jobs); }
.browse-chips--level .browse-chip { background: #e5cde8; }
.browse-chips--type .browse-chip { background: #e6e4e2; }
.browse-chips--salary .browse-chip { background: var(--sh-tint-resources); }
.browse-chips--salary .browse-chip[href*="no-comp"],
.browse-chips--salary .browse-chip[href*="competitive"],
.browse-chips--salary .browse-chip[href*="i-dont"] { background: var(--sh-hot-pink); }
.browse-chips--status .browse-chip[href*="job-status-open"] { background: var(--sh-blue); }
.browse-chips--status .browse-chip[href*="job-status-closed"] { background: var(--sh-grey); }
.browse-chips--other .browse-chip { background: #e6e4e2; }
.browse-chips--rating .browse-chip[href*="/t/bjb-green-means-go"] { background: #c9ead6; }
.browse-chips--rating .browse-chip[href*="/t/bjb-probably-fine"] { background: #fdeadb; }
.browse-chips--rating .browse-chip[href*="/t/bjb-tread-carefully"] { background: #f7cac3; }
.browse-chips--rating .browse-chip[href*="/t/bjb-bingo"] { background: #fcbcd2; }
.browse-chips--rating .browse-chip[href*="/t/bjb-maybe-dont"] { background: #d6d4d6; }

/* Directory rows (browse-resources): two-column bordered grid, blurb from the tag
   description. */
.browse-dir {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--sh-ink);
  margin-top: 16px;
}
.browse-dir__row {
  display: block;
  padding: 14px 16px;
  text-decoration: none;
  color: var(--sh-ink);
  border-bottom: 1px solid var(--sh-hairline);
}
.browse-dir__row:nth-child(odd) { border-right: 1px solid var(--sh-hairline); }
.browse-dir__row:hover,
.browse-dir__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.browse-dir__name-line { display: flex; align-items: baseline; gap: 10px; }
.browse-dir__name { font-family: var(--sh-font-display); font-size: 24px; }
.browse-dir__count {
  margin-left: auto;
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-resources);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 2px 6px;
}
.browse-dir__blurb {
  display: block;
  font-size: 14px;
  line-height: 1.5;
  margin-top: 6px;
  color: var(--sh-grey-on-tint);
  text-wrap: pretty;
}
/* Honest zero (02a §11): an empty directory stays visible but INERT — a span, not a
   link, because Ghost 404s a channel whose tag has no posts. The count chip goes to
   the closed/grey vocabulary and the row drops its hover affordance. */
.browse-dir__row--empty .browse-dir__count { background: var(--sh-tint-closed); color: var(--sh-grey-on-tint); }
.browse-dir__row--empty .browse-dir__name { color: var(--sh-grey-on-tint); }
.browse-dir__row--empty:hover { background: transparent; }
/* Live shelves declare on hover (delight pass, 02a §12) — inert zeros stay inert. */
.browse-dir__row:not(.browse-dir__row--empty):hover .browse-dir__name,
.browse-dir__row:not(.browse-dir__row--empty):focus-visible .browse-dir__name {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Collection / publisher groups: chip + blurb + count rows. */
.browse-group { border: 1px solid var(--sh-ink); margin-top: 16px; }
.browse-group__label {
  display: block;
  padding: 9px 14px;
  border-bottom: 1px solid var(--sh-ink);
  background: #f2f0ee;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.browse-group__row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.browse-group__row:last-child { border-bottom: 0; }
.browse-group__row:hover,
.browse-group__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.browse-group__row:hover .browse-group__count,
.browse-group__row:focus-visible .browse-group__count { color: var(--sh-grey-on-tint); }
.browse-group__chip {
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 3px 7px;
  white-space: nowrap;
  min-width: 190px;
}
.browse-group__chip--collection { background: #f5d9f1; }
.browse-group__chip--publisher { background: #f7cec7; }
.browse-group__blurb { font-size: 14px; line-height: 1.5; color: var(--sh-grey-on-tint); }
.browse-group__count {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  color: var(--sh-grey-on-paper);
}

@media (max-width: 900px) {
  .events-header { grid-template-columns: 1fr; gap: 20px; padding: 24px 18px; }
  .events-header__title { font-size: 44px; }
  .events-bar { padding: 9px 18px; }
  .event-row,
  .event-row--dated { grid-template-columns: 1fr; gap: 12px; padding: 18px; }
  .event-row__cell { flex-direction: row; align-items: baseline; gap: 10px; align-self: start; }
  .event-row__cell-day { margin-top: 0; }
  .event-row__where { text-align: left; }
  .events-past__band { padding: 12px 18px; flex-direction: column; gap: 4px; }
  .events-past__row { grid-template-columns: 1fr; gap: 6px; padding: 12px 18px; }
  .events-past__place { text-align: left; }
  .events-past__rule { padding: 14px 18px 18px; }

  .browse-header { grid-template-columns: 1fr; gap: 22px; padding: 24px 18px; }
  .browse-header__title { font-size: 40px; }
  .browse-header__title--house { font-size: 44px; }
  .browse-section { padding: 24px 18px 0; }
  .browse-section--last,
  .browse-page .browse-section:last-of-type { padding-bottom: 26px; }
  .browse-dir { grid-template-columns: 1fr; }
  .browse-dir__row:nth-child(odd) { border-right: 0; }
  .browse-group__row { flex-wrap: wrap; }
  .browse-group__chip { min-width: 0; }
}

/* ==========================================================================
   /who-pays-for-this/ (who-pays-for-this.hbs, 12 §1: this page owns the near-black
   ground and full-strength coral), /contact/ (contact.hbs, 13) and /services/
   (services.hbs, 03a §5). The ask-band is the shared money closer for the page set.
   ========================================================================== */

.section-strip--plain { background: var(--sh-paper); }
.section-strip--plain .section-strip__count { color: var(--sh-grey-on-paper); text-transform: uppercase; }

.wp-eyebrow {
  font-family: var(--sh-font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* Full-width ruled band label — the 13px size of the two-size eyebrow system (12 §4). */
.wp-band {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
}
.wp-band__twinkle { font-size: 22px; line-height: 1; }
.wp-band__label {
  font-family: var(--sh-font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* Hero — near-black, coral halftone at 0.16. */
.wp-hero {
  position: relative;
  overflow: clip;
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 60px var(--sh-gutter) 56px;
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 56px;
  align-items: center;
}
.wp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.16;
  pointer-events: none;
}
.wp-hero__copy, .wp-stamp { position: relative; }
.wp-hero__copy { display: flex; flex-direction: column; gap: 20px; }
.wp-hero__eyebrow { display: flex; align-items: baseline; gap: 10px; font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; }
.wp-hero__eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }
.wp-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 78px;
  line-height: 0.96;
  letter-spacing: -0.02em;
}
.wp-hero__title-accent { color: var(--sh-coral); }
.wp-hero__sub { font-size: 17px; line-height: 1.55; max-width: 58ch; color: #e6e4e2; }

/* The re-stamp Steph ruled for (12 §8) reached `.funding-stamp` and stopped there — and this
   is the SAME OBJECT: same copy, same double-ruled box, same coral, same −8°, on the page the
   stamp is actually about. Found 17 Aug 2026 by hovering it. `aria-hidden`, non-interactive,
   pointer-only by design; the keyframe and its reasoning live at .funding-stamp. */
.wp-stamp:hover { animation: sh-restamp 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
.wp-stamp {
  transform: rotate(-8deg);
  justify-self: center;
  border: 3px double var(--sh-paper);
  background: var(--sh-coral);
  padding: 5px;
}
.wp-stamp__inner {
  border: 1px solid var(--sh-ink);
  padding: 14px 18px 13px;
  text-align: center;
  font-family: var(--sh-font-mono);
  color: var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.wp-stamp__stars { font-size: 10px; font-weight: 700; letter-spacing: 0.34em; }
.wp-stamp__text { font-size: 14px; font-weight: 700; letter-spacing: 0.09em; line-height: 1.34; text-transform: uppercase; }

/* Refusals — 3×2 hairline grid, centered cells. */
.wp-refusals {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.wp-refusal {
  background: var(--sh-paper);
  padding: 24px 24px 26px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 7px;
  min-height: 96px;
}
.wp-refusal__name { font-family: var(--sh-font-display); font-size: 34px; line-height: 1.02; }
.wp-refusal__note { font-family: var(--sh-font-mono); font-size: 11px; line-height: 1.55; color: var(--sh-grey-on-paper); }

.wp-just-no { padding: 30px var(--sh-gutter) 34px; border-bottom: 1px solid var(--sh-ink); }
.wp-just-no p {
  font-size: 27px;
  font-weight: 700;
  line-height: 1.25;
  max-width: 40ch;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.wp-just-no .sh-twinkle { font-size: 22px; line-height: 1; flex: none; }
.wp-just-no em { font-family: var(--sh-font-display); font-weight: 400; font-size: 30px; }

/* Their words take the serif; the highlighter mark is the body's own device. */
.wp-their-words { font-family: var(--sh-font-display); font-size: 19px; }

.wp-why,
.wp-payers {
  padding: 46px var(--sh-gutter) 48px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 372px 1fr;
  gap: 56px;
  align-items: start;
}
.wp-why__head { display: flex; flex-direction: column; gap: 11px; position: sticky; top: 20px; }
.wp-why__heading,
.wp-payers__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 42px;
  line-height: 1.02;
  text-wrap: balance;
}
.wp-why__heading { color: var(--sh-purple-header); }
.wp-why__body { display: flex; flex-direction: column; gap: 18px; max-width: 62ch; }
.wp-why__body p { font-size: 17px; line-height: 1.55; }
/* Rides a <span> inside the paragraph — as a flex item this was blockified and the stroke
   painted one band across the whole block instead of hugging the words. The parent p carries the
   size so the line box is right; the span keeps the paint.

   Takes the adopted marker values (turn 38) rather than its own #f7cec7 band, which was the
   fourth paint of this one device. It runs at 27px, so it gets the two-pass treatment. */
p:has(> .wp-why__marked) {
  font-size: 27px !important;
  line-height: 1.3 !important;
}
.wp-why__marked {
  font-weight: 700;
  background-color: transparent;
  color: inherit;
  background-image: var(--sh-mark-two-pass);
  background-size: var(--sh-mark-two-pass-size);
  background-position: var(--sh-mark-two-pass-pos);
  background-repeat: no-repeat;
  display: inline;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  padding: 0.02em 0.24em 0.05em 0.14em;
  margin: 0 -0.14em;
}

.wp-means {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.wp-means__cell {
  background: var(--sh-paper);
  padding: 30px var(--sh-gutter) 34px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.wp-means__label { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.wp-means__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 32px; line-height: 1.04; max-width: 34ch; text-wrap: balance; }
.wp-means__cell p { font-size: 16px; line-height: 1.5; }

.wp-cost {
  padding: 44px var(--sh-gutter) 46px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 440px 1fr;
  gap: 56px;
  align-items: center;
}
.wp-cost__figure { display: flex; flex-direction: column; gap: 10px; }
.wp-cost__number { display: flex; align-items: baseline; gap: 14px; }
.wp-cost__amount { font-family: var(--sh-font-display); font-size: 104px; line-height: 0.86; color: var(--sh-coral); }
.wp-cost__unit { font-family: var(--sh-font-mono); font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase; }
.wp-cost__unit-sub { color: var(--sh-grey-on-paper); }
.wp-cost__what { font-family: var(--sh-font-mono); font-size: 12px; line-height: 1.6; color: var(--sh-grey-on-paper); max-width: 40ch; }
.wp-cost__copy { display: flex; flex-direction: column; gap: 16px; max-width: 52ch; }
.wp-cost__copy p { font-size: 17px; line-height: 1.55; }

.wp-payers__head { display: flex; flex-direction: column; gap: 11px; }
.wp-payers__list { display: flex; flex-direction: column; gap: 20px; max-width: 60ch; }
.wp-payers__list p { display: flex; align-items: baseline; gap: 12px; font-size: 17px; line-height: 1.55; }
.wp-payers__n { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; color: var(--sh-link); width: 18px; flex: none; }
.wp-payers__close { font-size: 21px !important; font-weight: 700; line-height: 1.4 !important; margin-top: 6px; gap: 10px !important; }
.wp-payers__close .sh-twinkle { font-size: 17px; line-height: 1; flex: none; }

/* The tier — near-black again. */
.wp-tier {
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 54px var(--sh-gutter) 56px;
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 56px;
  align-items: start;
}
.wp-tier__copy { display: flex; flex-direction: column; gap: 15px; }
.wp-tier__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 62px;
  line-height: 0.98;
  max-width: 18ch;
  margin-bottom: 3px;
}
.wp-tier__copy p { font-size: 17px; line-height: 1.55; max-width: 60ch; color: #e6e4e2; }
.wp-tier__dont { color: var(--sh-coral); }
.wp-tier__panel {
  border: 1px solid var(--sh-grey-on-paper);
  padding: 26px 24px 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.wp-tier__panel-label { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sh-grey-on-ink); }
.wp-tier__panel-answer { font-family: var(--sh-font-display); font-size: 56px; line-height: 0.9; color: var(--sh-coral); }
.wp-tier__free-list {
  list-style: none;
  margin: 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--sh-footer-rule);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.wp-tier__free-list li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 15px; }
.wp-tier__free-tag { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--sh-grey-on-ink); }

/* Broke help — halftone on paper at 0.3. */
.wp-broke {
  position: relative;
  overflow: clip;
  border-bottom: 1px solid var(--sh-ink);
  padding: 40px var(--sh-gutter) 44px;
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 56px;
  align-items: center;
}
.wp-broke::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.3;
  pointer-events: none;
}
.wp-broke__head, .wp-broke__list { position: relative; }
.wp-broke__head { display: flex; flex-direction: column; gap: 10px; }
.wp-broke__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 40px; line-height: 1.02; }
.wp-broke__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.wp-broke__list li { display: flex; align-items: baseline; gap: 9px; font-size: 17px; line-height: 1.5; }
.wp-broke__list .sh-twinkle { font-size: 15px; line-height: 1; flex: none; }

.wp-disclaimer {
  padding: 30px var(--sh-gutter) 32px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 56px;
  align-items: start;
}
.wp-disclaimer__label { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.wp-disclaimer__body { display: flex; flex-direction: column; gap: 10px; max-width: 62ch; }
.wp-disclaimer__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 30px; line-height: 1.04; }
.wp-disclaimer__body p { font-size: 16px; line-height: 1.5; color: var(--sh-grey-on-tint); }
.wp-disclaimer__aside {
  font-size: 17px !important;
  font-weight: 700;
  line-height: 1.45 !important;
  color: var(--sh-ink) !important;
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-top: 4px;
}
.wp-disclaimer__aside .sh-twinkle { font-size: 15px; line-height: 1; flex: none; }

/* The ask band — shared closer for the money-adjacent pages. */
.ask-band {
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 44px var(--sh-gutter) 46px;
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 56px;
  align-items: center;
  border-bottom: 1px solid var(--sh-footer-rule);
}
.ask-band__pitch { display: flex; flex-direction: column; gap: 12px; }
.ask-band__heading { font-family: var(--sh-font-display); font-size: 44px; line-height: 1.04; }
.ask-band__body { font-size: 15px; line-height: 1.55; max-width: 46ch; color: #e6e4e2; }
.ask-band__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-link-on-ink);
  align-self: flex-start;
}
/* The fundraiser line — text, never a button; hidden until one is running. */
.ask-band__fundraiser {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: var(--sh-coral);
  margin-top: 4px;
}
.ask-band__fundraiser[hidden] { display: none; }
.ask-band__actions { display: flex; flex-direction: column; gap: 9px; }
.ask-band__action {
  border: 1px solid var(--sh-grey-on-paper);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 13px 18px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* The ask band is the funding band's twin on the pages that close on money themselves;
   both took the 17 Aug 2026 pass together, and the reasoning lives at .funding-band__button. */
.ask-band__action:hover,
.ask-band__action:focus-visible {
  color: var(--sh-paper);
  border-color: var(--sh-paper);
  background: rgba(253, 253, 253, 0.12);
}
.ask-band__action--primary {
  background: var(--sh-paper);
  color: var(--sh-ink);
  border-color: var(--sh-paper);
  font-weight: 700;
}
.ask-band__action--primary:hover {
  color: var(--sh-ink);
  background: var(--sh-paper);
  border-color: var(--sh-paper);
  outline: 2px solid var(--sh-ink);
  outline-offset: -2px;
}
/* Same close-line lift as .funding-band__close (Steph's ruling, 12 Aug 2026, 12 §amend):
   the promise reads at 12px/700, band-body grey. */
.ask-band__close {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #e6e4e2;
  margin-top: 2px;
}

/* --------------------------------------------------------------------------
   /contact/
   -------------------------------------------------------------------------- */

.contact-hero {
  padding: 52px var(--sh-gutter) 46px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 372px;
  gap: 56px;
  align-items: end;
  /* Right column (372) + half the gap (28), in from the band's right edge. */
  --sh-sparks-x: calc(100% - var(--sh-gutter) - 400px);
}
.contact-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 78px;
  line-height: 0.96;
  letter-spacing: -0.02em;
}
.contact-hero__sub { font-size: 18px; line-height: 1.55; max-width: 58ch; margin-top: 18px; }
.contact-expect {
  border: 1px solid var(--sh-ink);
  padding: 22px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.contact-expect p { font-size: 16px; line-height: 1.5; }

.contact-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.contact-card {
  background: var(--sh-paper);
  border: 0;
  margin: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: var(--sh-ink);
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-height: 104px;
}
.contact-card:hover,
.contact-card:focus-visible { background: #fff6ef; }
.contact-card--active,
.contact-card--active:hover,
.contact-card--active:focus-visible { background: var(--card-tint); }
.contact-card__name {
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.04;
}
.contact-card__mark {
  color: var(--sh-coral);
  font-family: var(--sh-font-display);
  font-size: 16px;
  line-height: 1;
  width: 12px;
  flex: none;
  visibility: hidden;
}
.contact-card--active .contact-card__mark { visibility: visible; }
/* Delight (16 Aug 2026): the mark lands on the reason you picked. The house stamp keyframe
   — the jobs dauber's -5deg, one beat — third use after the footnotes ✓ and the dauber
   itself. Gated on [data-picked], which contact.js sets on the first click only: select()
   also runs on load to honor ?reason=, and a stamp firing on arrival would be motion
   nobody asked for on every visit. The visible resting state is the CSS default, so a
   headless render or a hidden tab still shows the mark on the chosen card. */
[data-contact-cards][data-picked] .contact-card--active .contact-card__mark {
  animation: fn-stamp 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
.contact-card__blurb {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.55;
  color: var(--sh-grey-on-tint);
  padding-left: 21px;
}

.contact-panel {
  padding: 44px var(--sh-gutter) 48px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 372px 1fr;
  gap: 56px;
  align-items: start;
}
.contact-panel[hidden] { display: none; }
.contact-panel__happens { display: flex; flex-direction: column; gap: 12px; }
.contact-panel__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 38px; line-height: 1.02; }
.contact-panel__happens > p { font-size: 16px; line-height: 1.5; color: var(--sh-grey-on-tint); }
.contact-panel__aside {
  font-size: 16px !important;
  font-weight: 700;
  line-height: 1.45 !important;
  color: var(--sh-ink) !important;
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-top: 4px;
}
.contact-panel__aside .sh-twinkle { font-size: 15px; line-height: 1; flex: none; }
.contact-panel__alt {
  border-top: 1px solid var(--sh-hairline);
  padding-top: 16px;
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.contact-panel__alt p { font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); }
.contact-panel__alt a {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  align-self: flex-start;
}

.contact-form { display: flex; flex-direction: column; gap: 20px; }
.contact-form__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 22px;
}
.contact-form__field { display: flex; flex-direction: column; gap: 7px; }
.contact-form__field--wide { grid-column: 1 / -1; }
.contact-form__label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.contact-form__hint {
  font-style: normal;
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--sh-grey-on-paper);
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form input[type="url"],
.contact-form textarea {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 12px 14px;
  font-family: var(--sh-font-body);
  font-size: 16px;
  line-height: 1.5;
  color: var(--sh-ink);
  width: 100%;
}
.contact-form textarea { resize: vertical; }
.contact-form input:focus-visible,
.contact-form textarea:focus-visible {
  outline: none;
  border-color: var(--sh-link);
  box-shadow: inset 0 0 0 1px var(--sh-link);
}
.contact-form__optin { display: flex; align-items: flex-start; gap: 11px; cursor: pointer; }
.contact-form__optin input { width: 17px; height: 17px; margin-top: 2px; accent-color: var(--sh-link); flex: none; }
.contact-form__optin span { font-size: 15px; line-height: 1.45; }
.contact-form__actions { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 2px; }
.contact-form__submit {
  background: var(--sh-ink);
  color: var(--sh-paper);
  border: 0;
  cursor: pointer;
  padding: 15px 26px;
  font-family: var(--sh-font-body);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.contact-form__submit:hover { background: var(--sh-link); }
.contact-form__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--sh-grey-on-paper);
  max-width: 46ch;
}

/* Honeypot (13 §9). `left: -9999px` rather than `display: none` on purpose — a bot that
   parses CSS skips anything hidden, and this field only works if it looks reachable.
   The wrapper carries aria-hidden so nothing is announced. */
.contact-form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Submission outcome. Sits where the form's own note sits, in the same voice — success is
   a fact, not a celebration, and it never promises a reply time (13 §2). */
.contact-form__result {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  max-width: 46ch;
  padding: 12px 14px;
  border: 1px solid var(--sh-ink);
}
.contact-form__result--ok { background: var(--sh-tint-resources); }
.contact-form__result--error { background: #f7cac3; }
/* The address keeps its own case inside the uppercase result line: an email address is a string
   to read, and STEPH@SUPPORTHUMAN.CX is measurably harder to parse than the real thing. Links on
   a tinted surface are ink + underline, per the house rule. */
.contact-form__result-address {
  text-transform: lowercase;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* The result takes focus on submit (contact.js) — it is a message, not a control, so the ring is
   the only thing that should mark it. */
.contact-form__result:focus { outline: none; }
.contact-form__result:focus-visible { outline: 3px solid var(--sh-focus); outline-offset: 2px; }

/* Hidden by default and revealed two ways, so the page works with or without JS:
   :target for the no-JS POST (the Worker 303s back to #sent / #send-failed), and the
   data-shown attribute for the scripted path. Ghost cannot read a query string, which is
   why this is a fragment rather than ?sent=1. */
.contact-form__result { display: none; margin-top: 18px; }
.contact-form__result:target,
.contact-form__result[data-shown] { display: block; }
.contact-result { scroll-margin-top: 24px; }

.contact-elsewhere {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.contact-elsewhere__cell {
  background: var(--sh-paper);
  padding: 24px 24px 26px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.contact-elsewhere__label { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.contact-elsewhere__cell p { font-size: 16px; line-height: 1.5; }
.contact-elsewhere__cell a {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  align-self: flex-start;
}

/* --------------------------------------------------------------------------
   /services/
   -------------------------------------------------------------------------- */

.services-header__aside { font-size: 15px !important; color: var(--sh-grey-on-tint); margin-top: 12px; }

.offer {
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 380px 1fr;
}
.offer__intro {
  border-right: 1px solid var(--sh-ink);
  padding: 30px 34px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Oversized purple numerals: the sanctioned decorative use of accent color. */
.offer__numeral { font-family: var(--sh-font-display); font-size: 54px; line-height: 0.9; color: var(--sh-purple-display); }
.offer__name { font-family: var(--sh-font-display); font-weight: 400; font-size: 34px; line-height: 1.08; }
.offer__framing { font-size: 14px; line-height: 1.55; }
.offer__badge {
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-portfolio);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
  align-self: flex-start;
  margin-top: 4px;
}
.offer__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 4px;
  align-self: flex-start;
}
.offer__scope { padding: 26px 40px; }
.offer__scope--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px;
}
.offer__phase { display: flex; flex-direction: column; gap: 10px; }
.offer__phase-name { font-family: var(--sh-font-display); font-weight: 400; font-size: 26px; line-height: 1; }
.offer__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 14px;
  line-height: 1.5;
}
.offer__list li { border-top: 1px solid var(--sh-hairline); padding-top: 9px; }
.offer__list--pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 34px;
}
.offer__scope-label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-bottom: 14px;
}
.offer__chips { display: flex; flex-wrap: wrap; gap: 7px; }
.offer__chip {
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 10px;
}
.offer__chip--ghost { background: #e6e4e2; }
.offer__scope-note { font-size: 14px; line-height: 1.55; max-width: 62ch; margin-top: 14px; }

/* The joke band — coral halftone, kept verbatim. */
.services-joke {
  position: relative;
  overflow: hidden;
  background: var(--sh-coral);
  border-bottom: 1px solid var(--sh-ink);
  padding: 34px var(--sh-gutter);
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 44px;
  align-items: start;
}
.services-joke::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-ink) 0.6px, transparent 0.7px);
  background-size: 6px 6px;
  opacity: 0.14;
  pointer-events: none;
}
.services-joke__intro, .services-joke__list { position: relative; }
.services-joke__intro { display: flex; flex-direction: column; gap: 10px; }
.services-joke__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 40px; line-height: 1; }
.services-joke__offer { font-family: var(--sh-font-display); font-size: 26px; line-height: 1.1; }
.services-joke__framing { font-size: 14px; line-height: 1.55; }
.services-joke__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 34px;
  font-size: 15px;
  line-height: 1.5;
}
.services-joke__list li { border-top: 1px solid var(--sh-ink); padding-top: 10px; }

.services-close {
  display: grid;
  grid-template-columns: 1fr 440px;
  border-bottom: 1px solid var(--sh-ink);
}
.services-terms {
  padding: 40px;
  border-right: 1px solid var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 26px;
  justify-content: center;
}
.services-terms__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 46px; line-height: 1.02; max-width: 16ch; }
.services-terms__list { margin: 0; display: flex; flex-direction: column; gap: 13px; }
.services-terms__row { display: flex; gap: 14px; align-items: baseline; }
.services-terms__row dt {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  flex: 0 0 96px;
}
.services-terms__row dd { margin: 0; font-size: 16px; line-height: 1.5; }

.services-form { padding: 34px 40px; gap: 12px; }
.services-form__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 32px; line-height: 1.05; margin-bottom: 2px; }
.services-form__topics { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.services-form__topic-row { display: flex; flex-wrap: wrap; gap: 6px; }
.services-form__topic { cursor: pointer; }
.services-form__topic input { position: absolute; opacity: 0; pointer-events: none; }
.services-form__topic span {
  display: inline-block;
  border: 1px solid var(--sh-ink);
  padding: 6px 10px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.services-form__topic input:checked + span { background: var(--sh-ink); color: var(--sh-paper); }
.services-form__topic input:focus-visible + span { outline: 3px solid var(--sh-focus); outline-offset: 1px; }
/* Delight (17 Aug 2026): this fieldset asks the same question /contact/'s picker asks, of
   the same reason ("work"), and answered it silently while the picker stamps. It now takes
   the house stamp too.

   :focus-within is the gate, and it needs no JS: picking a topic — by pointer or by arrow
   key — focuses the radio, so the newly-checked pill starts matching and the keyframe runs.
   Nothing is focused on load, so the default AI pill never stamps on arrival, which is the
   same rule the contact card's [data-picked] flag exists to enforce. Tabbing back into the
   group re-stamps the current pill; that reads as "here is where you are" and is the one
   behavior this gate cannot separate from a fresh pick. */
.services-form__topics:focus-within input:checked + span {
  animation: fn-stamp 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
.services-form__submit { width: 100%; }

@media (max-width: 900px) {
  .wp-hero { grid-template-columns: 1fr; gap: 32px; padding: 32px 18px 36px; }
  .wp-hero__title { font-size: 44px; }
  .wp-stamp { justify-self: start; }
  .wp-band { padding: 14px 18px; }
  .wp-refusals, .wp-means { grid-template-columns: 1fr; }
  .wp-refusal, .wp-means__cell { padding: 20px 18px; }
  .wp-just-no { padding: 22px 18px 26px; }
  .wp-just-no p { font-size: 21px; flex-wrap: wrap; }
  .wp-why, .wp-payers, .wp-cost, .wp-broke, .wp-disclaimer, .wp-tier {
    grid-template-columns: 1fr;
    gap: 22px;
    padding: 28px 18px 32px;
  }
  .wp-why__head { position: static; }
  .wp-why__heading, .wp-payers__heading { font-size: 32px; }
  .wp-cost__amount { font-size: 72px; }
  .wp-tier__heading { font-size: 40px; }
  .ask-band { grid-template-columns: 1fr; gap: 24px; padding: 30px 18px 34px; }
  .ask-band__heading { font-size: 32px; }

  .contact-hero { grid-template-columns: 1fr; gap: 22px; padding: 28px 18px 30px; }
  .contact-hero__title { font-size: 46px; }
  .contact-cards { grid-template-columns: 1fr; }
  .contact-panel { grid-template-columns: 1fr; gap: 26px; padding: 28px 18px 32px; }
  .contact-form__grid { grid-template-columns: 1fr; }
  .contact-elsewhere { grid-template-columns: 1fr; }

  .offer { grid-template-columns: 1fr; }
  .offer__intro { border-right: 0; border-bottom: 1px solid var(--sh-hairline); padding: 22px 18px; }
  .offer__scope { padding: 20px 18px 24px; }
  .offer__scope--split, .offer__list--pair { grid-template-columns: 1fr; }
  .services-joke { grid-template-columns: 1fr; padding: 24px 18px; }
  .services-joke__list { grid-template-columns: 1fr; }
  .services-close { grid-template-columns: 1fr; }
  .services-terms { border-right: 0; border-bottom: 1px solid var(--sh-ink); padding: 26px 18px; }
  .services-terms__heading { font-size: 34px; }
  .services-form { padding: 24px 18px 28px; }
}

/* ==========================================================================
   Legal pages — /privacy/ (privacy.hbs, 15 §5–6) and /terms/ (terms.hbs, 16).
   One layout: white strip with the maintained date, purple hero with a two-column
   intro, ruled two-column sections (serif heading | 72ch body), near-black closer.
   ========================================================================== */

.legal-hero {
  padding: 52px var(--sh-gutter) 44px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 420px;
  gap: 56px;
  align-items: start;
  /* Right column (420) + half the gap (28), in from the band's right edge. */
  --sh-sparks-x: calc(100% - var(--sh-gutter) - 448px);
}
.legal-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 82px;
  line-height: 0.94;
  letter-spacing: -0.02em;
  color: var(--sh-purple-header);
  text-wrap: balance;
}
.legal-hero__intro {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 8px;
}
.legal-hero__intro p { font-size: 17px; line-height: 1.55; }

.legal-section {
  border-bottom: 1px solid var(--sh-hairline);
  padding: 26px var(--sh-gutter) 28px;
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 44px;
  align-items: start;
}
.legal-section__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 32px;
  line-height: 1.06;
}
.legal-section__body {
  font-size: 16px;
  line-height: 1.62;
  max-width: 72ch;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* The comment rules — same ruled vocabulary as the 21b strip above the comment box. */
.legal-rules {
  border-top: 1px solid var(--sh-ink);
  margin-top: 4px;
  display: flex;
  flex-direction: column;
}
.legal-rules__row {
  border-bottom: 1px solid var(--sh-hairline);
  padding: 12px 0;
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
  align-items: baseline;
}
.legal-rules__label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.legal-rules__text { font-size: 15px; line-height: 1.55; }

.legal-close {
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 34px var(--sh-gutter) 36px;
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 50px;
  align-items: start;
  border-bottom: 1px solid var(--sh-footer-rule);
}
.legal-close__copy { display: flex; flex-direction: column; gap: 12px; }
.legal-close__heading { font-family: var(--sh-font-display); font-size: 42px; line-height: 1.02; }
.legal-close__body { font-size: 15px; line-height: 1.55; max-width: 52ch; color: #e6e4e2; }
.legal-close__actions { display: flex; flex-direction: column; gap: 13px; }
.legal-close__button {
  border: 1px solid var(--sh-paper);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 13px 18px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* The `color` is the undo that holds the link against the global `a:hover` on this near-black
   ground; the fill is the real response. Focus parity added 18 Aug 2026 — this is the closing
   action on both legal pages and it was pointer-only. */
.legal-close__button:hover,
.legal-close__button:focus-visible { color: var(--sh-paper); background: rgba(253, 253, 253, 0.12); }
.legal-close__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-link-on-ink);
}

@media (max-width: 900px) {
  .legal-hero { grid-template-columns: 1fr; gap: 14px; padding: 26px 18px 24px; }
  .legal-hero__title { font-size: 44px; line-height: 0.98; }
  .legal-hero__intro { padding-top: 0; }
  .legal-section { grid-template-columns: 1fr; gap: 10px; padding: 20px 18px 22px; }
  .legal-section__title { font-size: 26px; }
  .legal-rules__row { grid-template-columns: 1fr; gap: 5px; }
  .legal-close { grid-template-columns: 1fr; gap: 16px; padding: 24px 18px 26px; }
  .legal-close__heading { font-size: 30px; }
}

/* ==========================================================================
   /about/ (about.hbs, 15a) and /faqs/ (faqs.hbs, 18a — shares the legal-page shell).
   ========================================================================== */

.sh-twinkle--purple { color: var(--sh-link); }

/* The dot field and its sparks, at the shared values (14 Aug 2026). /about/ is a page header
   like the six front doors and was the last 2-column one without it. */
.about-hero {
  padding: 52px var(--sh-gutter) 46px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 460px;
  gap: 56px;
  align-items: center;
  position: relative;
  overflow: clip;
  /* Right column (460) + half the gap (28), in from the band's right edge. */
  --sh-sparks-x: calc(100% - var(--sh-gutter) - 488px);
}

.about-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 76px;
  line-height: 0.96;
  letter-spacing: -0.02em;
  color: var(--sh-purple-header);
}
.about-hero__sub { font-size: 18px; line-height: 1.55; text-wrap: pretty; }

.about-places {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.about-place {
  background: var(--place-tint, var(--sh-paper));
  padding: 22px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.about-place__name {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.about-place__what { font-family: var(--sh-font-display); font-size: 26px; line-height: 1.04; }

.about-work {
  padding: 36px var(--sh-gutter) 38px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 460px;
  gap: 56px;
  align-items: center;
}
.about-work__head { display: flex; flex-direction: column; gap: 11px; }
.about-work__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 48px;
  line-height: 1;
  max-width: 22ch;
}
.about-work__body { display: flex; flex-direction: column; gap: 16px; }
.about-work__body p { font-size: 17px; line-height: 1.55; }
.about-work__links {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.about-work__links a { color: var(--sh-ink); }

.about-person {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--sh-ink);
  padding: 40px var(--sh-gutter) 42px;
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 44px;
  align-items: start;
}
.about-person::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.3;
  pointer-events: none;
}
.about-person__photo, .about-person__copy { position: relative; }
.about-person__photo { display: flex; flex-direction: column; gap: 14px; }
.about-person__photo img { width: 100%; height: auto; border: 1px solid var(--sh-ink); }
.about-person__caption { font-family: var(--sh-font-mono); font-size: 11px; line-height: 1.6; }
.about-person__copy { display: flex; flex-direction: column; gap: 16px; }
.about-person__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 48px;
  line-height: 1;
  max-width: 24ch;
}
.about-person__copy p { font-size: 17px; line-height: 1.55; }
/* Steph's asides, in the device 12 §4 reserves for them: ✦-marked bold body sans, no bar, no
   italic (ruled 13 Aug 2026). The coral-barred serif italic these used to wear is the
   their-words treatment — 10 §11 is explicit that a left bar means someone else is talking, and
   03a §69 removed a portfolio marginalia note rather than break the same rule. /contact/'s
   .contact-panel__aside is the reference; these now match it. */
.about-person__note,
.about-elsewhere__note {
  font-family: var(--sh-font-body);
  font-style: normal;
  font-weight: 700;
  color: var(--sh-ink);
  display: flex;
  align-items: baseline;
  gap: 9px;
}
.about-person__note .sh-twinkle,
.about-elsewhere__note .sh-twinkle { line-height: 1; flex: none; }

.about-person__note {
  font-size: 17px !important;
  line-height: 1.45 !important;
}
.about-person__note .sh-twinkle { font-size: 16px; }

.about-foot {
  display: grid;
  grid-template-columns: 1fr 340px;
  border-bottom: 1px solid var(--sh-ink);
}
.about-disclaimer {
  padding: 30px var(--sh-gutter) 32px;
  border-right: 1px solid var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 11px;
  justify-content: center;
}
.about-disclaimer__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: 1.02;
  max-width: 28ch;
}
.about-disclaimer p { font-size: 16px; line-height: 1.5; max-width: 58ch; }
.about-elsewhere {
  padding: 22px 30px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.about-elsewhere__label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.about-elsewhere__label .sh-twinkle { font-size: 20px; line-height: 1; }
.about-elsewhere__list { display: flex; flex-direction: column; }
.about-elsewhere__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.1;
}
.about-elsewhere__row:last-child { border-bottom: 1px solid var(--sh-hairline); }
/* Delight (16 Aug 2026): the row declares. Color alone was carrying three 20px serif rows
   that look exactly like the unlinked one above them — same finding as the portfolio clip
   file, same fix. [href] scopes it OFF the Supportlandia row, which is deliberately not a
   link yet and must not rehearse being one. */
.about-elsewhere__row[href]:hover span:first-child,
.about-elsewhere__row[href]:focus-visible span:first-child {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* The link value at 15px, the two-value rule's boundary — see .home-more__links. */
.about-elsewhere__out { font-family: var(--sh-font-mono); font-size: 15px; color: var(--sh-link); }
.about-elsewhere__note {
  font-size: 14px;
  line-height: 1.5;
  margin-top: 10px;
}
.about-elsewhere__note .sh-twinkle { font-size: 13px; }

/* FAQs — legal shell plus the jump chips and the Q/A grid. */
.legal-hero__note {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 17px !important;
  line-height: 1.4 !important;
  padding-left: 14px;
  border-left: 2px solid var(--sh-purple-display);
}
/* Sticky, because this is a 7,000px page and the jump list was a one-shot: a reader four
   thousand pixels into section three had no route back to it but the top of the document
   (critique, 13 Aug 2026). Paper ground so the rows pass under it cleanly. */
.faq-jump {
  padding: 22px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--sh-paper);
}

/* Every question is its own address now (31 stable ids in faqs.hbs). scroll-margin keeps the
   heading clear of the sticky bar when someone arrives on one. faqs.js measures that bar and
   writes --faq-bar, because it is 79px at 1440 and 111px below 900 where the chips wrap to
   two rows; the fallback is the static value this rule shipped with. */
.faq-qa__q {
  scroll-margin-top: calc(var(--faq-bar, 79px) + 11px);
}
.faq-jump__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  margin-right: 4px;
}
.faq-jump__chip {
  border: 1px solid var(--sh-ink);
  background: var(--chip-tint, var(--sh-paper));
  color: var(--sh-ink);
  text-decoration: none;
  padding: 7px 14px;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  /* The mark hands off between chips as the reader scrolls rather than jumping. */
  transition: background-color 0.18s cubic-bezier(0.22, 1, 0.36, 1),
              color 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.faq-jump__chip:hover { color: var(--sh-ink); outline: 2px solid var(--sh-ink); outline-offset: -2px; }
/* Delight (16 Aug 2026): the bar says which section you are standing in. faqs.js sets
   aria-current="location" from post.js's reading-line rule; this is the house's own
   selected grammar — ink ground, paper text, 20.4:1 — rather than a sixth color, exactly
   as the overlay's current row took it. Placed AFTER :hover on purpose: pointing at the
   chip you are already on must not repaint it back to a tint you are not standing on. */
.faq-jump__chip[aria-current] {
  background: var(--sh-ink);
  color: var(--sh-paper);
}
.faq-jump__chip[aria-current]:hover { color: var(--sh-paper); outline-color: var(--sh-paper); }

.faq-section { border-bottom: 1px solid var(--sh-ink); padding: 34px var(--sh-gutter) 14px; }
.faq-section__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 46px;
  line-height: 1;
}
.faq-section__blurb {
  font-size: 15px;
  line-height: 1.55;
  color: var(--sh-grey-on-tint);
  margin: 10px 0 22px;
  max-width: 88ch;
}
.faq-qa {
  border-top: 1px solid var(--sh-hairline);
  padding: 20px 0;
  display: grid;
  grid-template-columns: 400px 1fr;
  gap: 40px;
  align-items: start;
}
.faq-qa__q {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 27px;
  line-height: 1.1;
}
/* Delight (16 Aug 2026): every question hands over its own address. faqs.js wraps the
   heading and its # in this block; without the script the heading IS the grid's first
   column, unchanged.

   The heading goes inline inside it, which is the whole point: a flex row baselines the #
   against the heading's FIRST line, so on the eleven questions that wrap to two the mark
   fell to a third line on its own, orphaned at the left margin. Inline flow puts it after
   the last word every time. Measured: scroll-margin-top still clears the sticky bar on an
   inline box, which is what arriving at /faqs/#a-question depends on. */
.faq-qa__head { display: block; }
.faq-qa__head .faq-qa__q { display: inline; }
/* Modelled on the footnotes entry anchor, down to its ruling: grey is the # 's rest state,
   never gone — an invitation once the hand is near, and still there for a thumb, which a
   hover-only affordance would not be. 14px mono at #6b6b6b is the small-text floor. */
.faq-qa__anchor {
  border: 0;
  background: none;
  margin-left: 4px;
  padding: 2px 4px;
  font-family: var(--sh-font-mono);
  font-size: 14px;
  line-height: 1;
  color: var(--sh-grey-on-paper);
  cursor: pointer;
  transition: color 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}
.faq-qa:hover .faq-qa__anchor,
.faq-qa:focus-within .faq-qa__anchor { color: var(--sh-ink); }
.faq-qa__anchor.is-copied { animation: fn-stamp 0.18s cubic-bezier(0.25, 1, 0.5, 1); }
/* And the other end of the same gesture: someone sends you /faqs/#do-you-take-sponsors and
   you land in the middle of a 7,054px page. The row you were sent to says "here" — the
   house arrival wash, fading in from paper (`fn-arrive`, defined at the footnotes entry).
   No pink edge: footnotes needs one because its entries are cards in a stack, and these are
   rows on a hairline grid where a wash is already unambiguous.

   :has() scoped to .faq-qa, which only ever contains its own question. The rule the
   portfolio pass paid for: a :has() on a page-level wrapper reads every other post on the
   page. There is no class twin here because these ids are server-rendered, so :target sees
   them on arrival — the thing footnotes.js has to work around. */
.faq-qa:has(.faq-qa__q:target) {
  background: #fff6ef;
  animation: fn-arrive 0.5s cubic-bezier(0.25, 1, 0.5, 1);
}
.faq-qa__a {
  font-size: 16px;
  line-height: 1.62;
  max-width: 72ch;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

@media (max-width: 900px) {
  .about-hero { grid-template-columns: 1fr; gap: 16px; padding: 26px 18px 28px; }
  .about-hero__title { font-size: 42px; }
  .about-places { grid-template-columns: 1fr 1fr; }
  .about-work, .about-person { grid-template-columns: 1fr; gap: 20px; padding: 26px 18px 30px; }
  .about-work__heading, .about-person__heading { font-size: 34px; }
  .about-person__photo { max-width: 260px; }
  .about-foot { grid-template-columns: 1fr; }
  .about-disclaimer { border-right: 0; border-bottom: 1px solid var(--sh-ink); padding: 24px 18px 26px; }
  .about-disclaimer__heading { font-size: 30px; }
  .about-elsewhere { padding: 20px 18px 24px; }

  .faq-jump { padding: 16px 18px; }
  .faq-section { padding: 26px 18px 10px; }
  .faq-section__title { font-size: 34px; }
  .faq-qa { grid-template-columns: 1fr; gap: 10px; padding: 16px 0 18px; }
}

.about-elsewhere__soon {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

/* ==========================================================================
   /bad-job-bingo/ (bad-job-bingo.hbs — github-career-suite.md, frames 1a/1b).
   The game's page: near-black hero on the jobs blue, six real squares, the verdict
   ramp with live counts, and the honesty band.
   ========================================================================== */

/* Coral vanishes on the jobs tint; the blue tint takes the small-text tread rust,
   the black grounds take the board blue. Both are decorative marks. */
.sh-twinkle--rust { color: #94493a; }
.sh-twinkle--blue { color: var(--sh-blue); }

.wp-band--blue { background: var(--sh-tint-jobs); }
.wp-band__meta {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.wp-band__link {
  margin-left: auto;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-underline-offset: 3px;
}

.bjb-hero {
  position: relative;
  overflow: clip;
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 56px var(--sh-gutter) 52px;
  display: grid;
  grid-template-columns: 1fr 330px;
  gap: 56px;
  align-items: center;
}
.bjb-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-blue) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.18;
  pointer-events: none;
}
.bjb-hero__copy, .bjb-hero__panel { position: relative; }
.bjb-hero__copy { display: flex; flex-direction: column; gap: 18px; }
.bjb-hero__eyebrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.bjb-hero__eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }
.bjb-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 74px;
  line-height: 0.96;
  letter-spacing: -0.02em;
}
.bjb-hero__title-accent { color: var(--sh-blue); }
.bjb-hero__sub { font-size: 17px; line-height: 1.55; max-width: 58ch; color: #e6e4e2; }
.bjb-hero__panel {
  border: 1px solid var(--sh-grey-on-paper);
  padding: 24px 22px 26px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.bjb-hero__panel-label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sh-grey-on-ink);
}
.bjb-hero__panel-answer {
  font-family: var(--sh-font-display);
  font-size: 40px;
  line-height: 1.02;
  color: var(--sh-blue);
}
.bjb-hero__panel-note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--sh-grey-on-ink);
  border-top: 1px solid var(--sh-footer-rule);
  padding-top: 12px;
}

/* The one variant: /bad-job-bingo/ marks its line in the jobs blue rather than coral. Same two
   passes at the same alphas, tilts and offsets — only the hue differs — but it has to be spelled
   out because of the substitution rule noted at :root.

   SETTLED 16 Aug 2026 (Steph): the blue stays. Turn 38 specifies one paint and no new color,
   and no frame shows this treatment in blue — so read that rule as governing the MARKER, not
   the hue: one device, one set of alphas, tilts and offsets, which this obeys exactly. The hue
   is the section's, and /bad-job-bingo/ is the one page that belongs to jobs rather than to the
   house. Do not add a third hue on the strength of this — that would be the drift the rule is
   actually pointed at. */
.wp-why__marked--blue {
  background-image:
    linear-gradient(179.1deg, rgba(105, 163, 255, 0) 14%, rgba(105, 163, 255, 0.4) 14%,
                              rgba(105, 163, 255, 0.4) 72%, rgba(105, 163, 255, 0) 72%),
    linear-gradient(180.9deg, rgba(105, 163, 255, 0) 34%, rgba(105, 163, 255, 0.42) 34%,
                              rgba(105, 163, 255, 0.42) 99%, rgba(105, 163, 255, 0) 99%);
}
.wp-why__heading--ink { color: var(--sh-ink); }
.bjb-squares-intro { padding-bottom: 30px; }

.bjb-samples {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.bjb-sample {
  background: var(--sh-paper);
  padding: 26px 26px 28px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.bjb-sample__chip {
  align-self: flex-start;
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
}
.bjb-sample__chip--red { background: #fcbcd2; }
.bjb-sample__chip--yellow { background: #fdeadb; }
.bjb-sample__square {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 27px;
  line-height: 1.08;
  text-wrap: pretty;
}
.bjb-sample__why { font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); }

/* Mark-the-square (delight pass, 12 Aug 2026): the page is about a game, so the sampler
   is playable. The button IS the dauber — pressing it stamps the card (chip-active
   vocabulary, the brand's rotated-stamp motif) and tints the card in the page's own
   blue. Injected by the template's inline script; no JS, no button. The blanket
   reduced-motion guard neutralises the landing animation; the rotated STATE stays. */
.bjb-sample { position: relative; }
.bjb-sample__mark {
  position: absolute;
  top: 21px;
  right: 21px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 7px 11px;
  cursor: pointer;
}
.bjb-sample__mark:hover,
.bjb-sample__mark:focus-visible { background: #cfe1ff; }
.bjb-sample--marked { background: #cfe1ff; }
.bjb-sample--marked .bjb-sample__mark {
  background: var(--sh-ink);
  color: var(--sh-paper);
  transform: rotate(-5deg);
  animation: bjb-stamp-land 0.18s cubic-bezier(0.25, 1, 0.5, 1) 1;
}
@keyframes bjb-stamp-land {
  from { transform: rotate(-11deg) scale(1.22); }
  to { transform: rotate(-5deg) scale(1); }
}

/* The all-six payoff band: result-line voice, revealed by the script, aria-live at the
   call site. Explicit [hidden] because the element is display-styled (the footer-counter
   trap). */
.bjb-samples__payoff {
  margin: 0;
  padding: 14px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
}
.bjb-samples__payoff[hidden] { display: none; }

.bjb-howto {
  padding: 26px var(--sh-gutter) 30px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 400px 1fr;
  gap: 56px;
  align-items: start;
}
.bjb-howto__list { display: flex; flex-direction: column; gap: 14px; max-width: 62ch; }
.bjb-howto__list p { display: flex; align-items: baseline; gap: 12px; font-size: 16px; line-height: 1.5; }

.bjb-ramp {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-bottom: 1px solid var(--sh-ink);
}
.bjb-ramp__cell {
  display: block;
  text-decoration: none;
  color: var(--sh-ink);
  background: var(--verdict-tint);
  padding: 24px 20px;
  border-right: 1px solid var(--sh-ink);
}
.bjb-ramp__cell:last-child { border-right: 0; }
.bjb-ramp__cell:hover { color: var(--sh-ink); box-shadow: inset 0 0 0 3px var(--sh-ink); }
.bjb-ramp__cell img { width: 30px; height: 30px; display: block; }
.bjb-ramp__name {
  display: block;
  font-family: var(--sh-font-display);
  font-size: 28px;
  line-height: 1.02;
  margin-top: 16px;
}
.bjb-ramp__desc {
  display: block;
  font-size: 13px;
  line-height: 1.45;
  margin-top: 10px;
  color: var(--sh-grey-on-tint);
  text-wrap: pretty;
}
.bjb-ramp__count {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 14px;
  color: var(--sh-grey-on-tint);
}
.bjb-ramp-note {
  background: #e5cde8;
  border-bottom: 1px solid var(--sh-ink);
  padding: 13px var(--sh-gutter);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
}
.bjb-ramp-note__copy { font-family: var(--sh-font-mono); font-size: 11px; line-height: 1.7; }
.bjb-ramp-note__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  white-space: nowrap;
  color: var(--sh-ink);
  text-underline-offset: 3px;
}

.bjb-skip {
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 48px var(--sh-gutter) 50px;
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 56px;
  align-items: start;
}
.bjb-skip__copy { display: flex; flex-direction: column; gap: 15px; }
.bjb-skip__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 58px;
  line-height: 0.98;
  max-width: 20ch;
  margin-bottom: 3px;
}
.bjb-skip__copy > p { font-size: 17px; line-height: 1.55; max-width: 60ch; color: #e6e4e2; }
.bjb-skip__not-list {
  list-style: none;
  margin: 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--sh-footer-rule);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.bjb-skip__not-list li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 15px; }
.bjb-skip__no { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--sh-grey-on-ink); }

.bjb-play { background: var(--sh-tint-jobs); border-bottom: 1px solid var(--sh-ink); padding: 40px var(--sh-gutter) 48px; }
.bjb-play__head {
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 56px;
  align-items: center;
  margin-bottom: 24px;
}
.bjb-play__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 42px; line-height: 1.02; margin-top: 10px; }
/* The label and its headline are one cell. See the note in bad-job-bingo.hbs. */
.bjb-play__title { min-width: 0; }
.bjb-play__sub { font-size: 17px; line-height: 1.55; max-width: 56ch; }
.bjb-play__tools { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.bjb-tool {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  text-decoration: none;
  color: var(--sh-ink);
  padding: 26px 26px 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.bjb-tool:hover,
.bjb-tool:focus-visible { color: var(--sh-ink); box-shadow: inset 0 0 0 2px var(--sh-ink); }
.bjb-tool__kicker { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.bjb-tool__name { font-family: var(--sh-font-display); font-size: 34px; line-height: 1.02; }
.bjb-tool__body { font-size: 15px; line-height: 1.5; }
.bjb-tool__cta { font-family: var(--sh-font-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; margin-top: 6px; color: var(--sh-link); }
.bjb-tool__url { font-family: var(--sh-font-mono); font-size: 10px; color: var(--sh-grey-on-paper); }

.bjb-paper {
  border-bottom: 1px solid var(--sh-ink);
  padding: 14px var(--sh-gutter);
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.bjb-paper[hidden] { display: none; }
.bjb-paper__copy { font-family: var(--sh-font-mono); font-size: 11px; line-height: 1.7; color: var(--sh-grey-on-tint); }
.bjb-paper__links { margin-left: auto; font-family: var(--sh-font-mono); font-size: 11px; white-space: nowrap; }

.bjb-shelves {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.bjb-shelf { background: var(--sh-paper); padding: 28px 30px 30px; display: flex; flex-direction: column; gap: 14px; }
.bjb-shelf__name { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.bjb-shelf__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 0;
  border-top: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
  font-family: var(--sh-font-display);
  font-size: 21px;
  line-height: 1.1;
}
.bjb-shelf__kind { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--sh-grey-on-paper); white-space: nowrap; }

.bjb-recent { border-bottom: 1px solid var(--sh-ink); }
.bjb-recent__row {
  display: flex;
  gap: 20px;
  align-items: baseline;
  padding: 15px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  color: var(--sh-ink);
  text-decoration: none;
}
.bjb-recent__row:last-child { border-bottom: 0; }
.bjb-recent__row:hover,
.bjb-recent__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.bjb-recent__row:hover .bjb-recent__date,
.bjb-recent__row:focus-visible .bjb-recent__date { color: var(--sh-grey-on-tint); }
.bjb-recent__cell {
  flex: none;
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-jobs);
  text-align: center;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  padding: 3px 8px;
  white-space: nowrap;
}
.bjb-recent__title { font-family: var(--sh-font-display); font-size: 26px; line-height: 1.1; }
.bjb-recent__date {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-left: auto;
  white-space: nowrap;
}

.bjb-send {
  position: relative;
  overflow: clip;
  background: var(--sh-tint-jobs);
  border-bottom: 1px solid var(--sh-ink);
  padding: 40px var(--sh-gutter) 44px;
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 56px;
  align-items: center;
}
.bjb-send__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 40px; line-height: 1.02; margin-top: 10px; }
.bjb-send__body { display: flex; flex-direction: column; gap: 14px; max-width: 56ch; }
.bjb-send__body p { font-size: 17px; line-height: 1.55; }
.bjb-send__button {
  align-self: flex-start;
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 13px 20px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* `.sh-on-tint a` (0-1-1) outranks the single class above on `color`, which rendered the
   label ink-on-ink — the button must re-win at higher specificity, resting AND hover. */
.sh-on-tint a.bjb-send__button,
.sh-on-tint a.bjb-send__button:hover { color: var(--sh-paper); text-decoration: none; }

/* Same collision, and the reason the rule needs a shape test rather than a bigger hammer.
   `.sh-on-tint a` exists so a TEXT link on a tint keeps its affordance without relying on
   color. A .bjb-tool is not a text link: it is a bordered PAPER card sitting on the tint, with
   its own `Open the game ↗` and the URL printed underneath. The blanket rule was underlining the
   whole card — kicker, name, body, CTA and URL — because text-decoration paints through
   descendants and cannot be switched off from inside. The card's own ground is paper, so the
   on-tint rule should never have reached it. */
.sh-on-tint a.bjb-tool { text-decoration: none; }

@media (max-width: 900px) {
  .bjb-hero { grid-template-columns: 1fr; gap: 28px; padding: 30px 18px 34px; }
  .bjb-hero__title { font-size: 44px; }
  .bjb-samples { grid-template-columns: 1fr; }
  .bjb-howto { grid-template-columns: 1fr; gap: 16px; padding: 22px 18px 26px; }
  .bjb-ramp { grid-template-columns: 1fr; }
  .bjb-ramp__cell { border-right: 0; border-bottom: 1px solid var(--sh-ink); }
  .bjb-ramp__cell:last-child { border-bottom: 0; }
  .bjb-ramp-note { padding: 12px 18px; }
  .bjb-skip { grid-template-columns: 1fr; gap: 24px; padding: 30px 18px 34px; }
  .bjb-skip__heading { font-size: 38px; }
  .bjb-play { padding: 26px 18px 30px; }
  .bjb-play__head { grid-template-columns: 1fr; gap: 12px; margin-bottom: 18px; }
  .bjb-play__tools { grid-template-columns: 1fr; }
  .bjb-shelves { grid-template-columns: 1fr; }
  .bjb-recent__row { flex-wrap: wrap; gap: 10px; padding: 13px 18px; }
  .bjb-recent__title { font-size: 21px; }
  .bjb-send { grid-template-columns: 1fr; gap: 16px; padding: 26px 18px 30px; }
}

/* ==========================================================================
   /account/ (account.hbs, 17d/17f) and /podcast/ (podcast.hbs, 19c).
   ========================================================================== */

.account-hero { align-items: center; }
.account-signin { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 8px; }
.account-signin__button {
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 13px 26px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.account-signin__button:hover { color: var(--sh-paper); background: var(--sh-link); }
.account-signin__alt {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-underline-offset: 3px;
}

.account-acknowledged {
  background: var(--sh-tint-newsletter);
  border-bottom: 1px solid var(--sh-ink);
  padding: 30px var(--sh-gutter) 32px;
}
.account-acknowledged__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 38px;
  line-height: 1.02;
}
.account-acknowledged p { font-size: 16px; line-height: 1.55; max-width: 66ch; margin-top: 10px; }

.account-card {
  border-bottom: 1px solid var(--sh-ink);
  padding: 26px var(--sh-gutter) 30px;
  max-width: 860px;
}
.account-card__label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.account-card__body { font-size: 16px; line-height: 1.55; max-width: 62ch; margin-bottom: 14px; }
.account-card__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  padding: 12px 0;
  border-top: 1px solid var(--sh-hairline);
}
.account-card__value { font-family: var(--sh-font-display); font-size: 22px; line-height: 1.1; }
.account-card__value-group { display: flex; flex-direction: column; gap: 4px; }
.account-card__value-note {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.account-card__link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  text-underline-offset: 3px;
}
.account-card__note { font-size: 14px; color: var(--sh-grey-on-tint); margin-top: 8px; }
.account-card__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.account-card__button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-decoration: none;
  padding: 12px 20px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.account-card__button:hover { color: var(--sh-paper); background: var(--sh-link); border-color: var(--sh-link); }
.account-card__button--quiet { background: var(--sh-paper); color: var(--sh-ink); }
/* The second undo the 17 Aug pass found, and the same shape as the ask band's primary: all
   three values here cancel .account-card__button:hover's purple fill, so the quiet twin of
   "Change or cancel" answered nothing. The undos stay — they are load-bearing — and the
   house paper-ground hover goes on top. */
.account-card__button--quiet:hover {
  background: var(--sh-paper);
  color: var(--sh-ink);
  border-color: var(--sh-ink);
  outline: 2px solid var(--sh-ink);
  outline-offset: -2px;
}

.account-feeds { display: flex; flex-direction: column; }
.account-feeds__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 11px 0;
  border-top: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.account-feeds__row:hover,
.account-feeds__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.account-feeds__name {
  font-family: var(--sh-font-display);
  font-size: 21px;
  line-height: 1.1;
  padding: 2px 10px;
}
.account-feeds__name--roundup { background: var(--sh-tint-newsletter); }
.account-feeds__name--bjb { background: #fcbcd2; }
.account-feeds__name--deep { background: #e5cde8; }
.account-feeds__path {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  white-space: nowrap;
}
.ask-band__link + .ask-band__close { margin-top: 2px; }

/* Podcast */
.podcast-subscribe {
  display: flex;
  align-items: baseline;
  gap: 18px;
  flex-wrap: wrap;
  padding: 14px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  background: #fff6ef;
}
.podcast-subscribe__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.podcast-subscribe__app {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.1;
  text-underline-offset: 3px;
}
/* Delight (18 Aug 2026): all five of these leave the site and none of them answered the hand.
   They take the same declare-on-hover as the Career Suite doors — and NOT a visible `↗`.
   The glyph earns its place where a reader could plausibly think a control stays put, which
   is why the ask band's coffee button carries one; under a label reading "Subscribe in",
   nobody thinks Spotify is on this site, and four arrows would turn a clean row of app names
   into noise. The four that open a tab carry the house screen-reader string instead, which
   they had been missing entirely. */
.podcast-subscribe__app:hover,
.podcast-subscribe__app:focus-visible { text-decoration-thickness: 2px; }
.podcast-episodes__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 30px var(--sh-gutter) 8px;
}
.podcast-episodes__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 46px; line-height: 1; }
.podcast-episodes__count {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.podcast-episodes { padding: 10px var(--sh-gutter) 34px; }
/* The row plays (Steph's ruling, 18 Aug 2026 — she asked for the player in place, which
   retires 15 §2's "a row here hands off to it rather than pretending this page can play what
   it cannot reach"). That sentence rested on a premise this page turned out not to have:
   `{{html}}` IS reachable inside the episode {{#get}}, the audio card comes through it whole,
   and Ghost's cards.min.js is already loaded here — so the page could always reach it.

   The 56px purple ▶ cell is GONE, not repurposed. It was drawn as a transport control and
   navigated to the issue instead, which is the one thing the 13 Aug critique called a
   surprise; replacing it with the control it was imitating is the honest end of that. The row
   is now two columns, and the player sits under the copy where the reader's eye already is. */
.podcast-episode {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px;
  align-items: start;
  padding: 20px 0;
  border-top: 1px solid var(--sh-hairline);
}
.podcast-episode__player:not(:empty) { margin-top: 14px; max-width: 640px; }
/* The card carries the issue title and the row already says it in 27px serif — same reason
   the issue page's listen slot hides it. */
main .podcast-episode__player .kg-audio-title { display: none; }
/* The row's two links — the title and `Read the issue` — still share one destination, so
   pointing or tabbing at either declares both (18 Aug 2026). Scoped to the two links rather
   than to the row, because the row now contains a player: hovering a seek slider is not
   pointing at the issue page, and a row that underlines while you scrub is a row arguing with
   the control inside it. */
.podcast-episode__title:hover,
.podcast-episode__title:focus-visible,
.podcast-episode:has(.podcast-episode__read:hover) .podcast-episode__title,
.podcast-episode:has(.podcast-episode__read:focus-visible) .podcast-episode__title {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.podcast-episode__read:hover .sh-arrow,
.podcast-episode__read:focus-visible .sh-arrow,
.podcast-episode:has(.podcast-episode__title:hover) .podcast-episode__read .sh-arrow,
.podcast-episode:has(.podcast-episode__title:focus-visible) .podcast-episode__read .sh-arrow {
  transform: translateX(3px);
}
.podcast-episode__title {
  font-family: var(--sh-font-display);
  font-size: 27px;
  line-height: 1.08;
  color: var(--sh-ink);
  text-decoration: none;
}
.podcast-episode__title:hover { color: var(--sh-link); }
.podcast-episode__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin-top: 6px;
}
.podcast-episode__blurb { font-size: 15px; line-height: 1.5; max-width: 66ch; margin-top: 8px; }
.podcast-episode__read {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  /* Was `center`, which centered it against a 56px play cell. The row is much taller now that
     it holds a player, and centering dragged this down beside the seek bar; it belongs on the
     title's line, because the title is what it is a second route to. */
  align-self: start;
  margin-top: 7px;
  text-underline-offset: 3px;
}
.podcast-episodes__empty {
  padding: 10px var(--sh-gutter) 34px;
  font-size: 16px;
  line-height: 1.55;
  max-width: 62ch;
  color: var(--sh-grey-on-tint);
}

@media (max-width: 900px) {
  .account-card { padding: 20px 18px 24px; }
  .account-acknowledged { padding: 24px 18px 26px; }
  .account-acknowledged__heading { font-size: 30px; }
  .podcast-subscribe { padding: 12px 18px; }
  .podcast-episodes__head { padding: 24px 18px 6px; }
  .podcast-episodes__heading { font-size: 34px; }
  .podcast-episodes { padding: 8px 18px 26px; }
  /* One column below 900: the player needs the whole width for its seek bar, so the row
     stacks and `Read the issue` follows it rather than sitting in a second column. */
  .podcast-episode { grid-template-columns: 1fr; gap: 12px; }
  .podcast-episode__read { justify-self: start; }
  .podcast-episode__player:not(:empty) { max-width: none; }
}

/* ==========================================================================
   /newsletter/browse/ (browse-newsletter.hbs, Homepage turn 16; record 14).
   ========================================================================== */

.browse-header--single { grid-template-columns: minmax(0, 720px); }

/* Frame 16a's search band (drift item 109): the tint runs full-bleed and the column
   inside caps at the drawn 780px — max-width on the band itself would stop the
   ground mid-page. */
.news-search {
  padding: 24px var(--sh-gutter) 26px;
  border-bottom: 1px solid var(--sh-ink);
  background: #fff6ef;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.news-search > * { max-width: 780px; }
.news-search[hidden] { display: none; }
.news-search__label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.news-search__form { display: flex; align-items: stretch; }
.news-search__form input {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--sh-ink);
  border-right: 0;
  background: var(--sh-paper);
  padding: 13px 16px;
  font-family: var(--sh-font-mono);
  font-size: 15px; /* 16a's drawn input face (drift item 109) */
  color: var(--sh-ink);
}
.news-search__form button {
  border: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 13px 26px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.news-search__scope {
  font-family: var(--sh-font-mono);
  font-size: 11px; /* 16a's 11px; on the band's tint the <=13px floor is #3a3a3a */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}

/* Section heads on /newsletter/browse/ — frame 16a's coral-✦ serif 40px h2s with the
   right-aligned mono meta (drift item 71; the first build borrowed .wp-band, a device
   no record sanctions on browse pages, and lost the h2 semantics with it). Mobile is
   16a's own 390 variant: 30px, 18px gutters, meta wrapping under. */
.news-browse__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 34px var(--sh-gutter) 16px;
}
.news-browse__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 0;
}
.news-browse__heading .sh-twinkle { color: var(--sh-coral); }
.news-browse__meta {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
@media (max-width: 900px) {
  .news-browse__head { padding-left: 18px; padding-right: 18px; }
  .news-browse__heading { font-size: 30px; }
}

/* The three series — numeral-cell tints, motif sizes per 14 §6 (label 10px/0.06em).
   Cell 88px desktop / 62px mobile: the labeled numeral-cell motif's own widths
   (00 §Motifs; canvas 16a draws 88px) — 150px was drift. */
.series-index { border-bottom: 1px solid var(--sh-ink); }
.series-index__row {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) auto;
  gap: 24px;
  align-items: center;
  padding: 16px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.series-index__row:last-child { border-bottom: 0; }
.series-index__row:hover,
.series-index__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.series-index__cell {
  border: 1px solid var(--sh-ink);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* Roundup series blue (07 §20 SETTLED 6b), NOT the newsletter section-strip tint —
   the two tints mean different things and the strip tint is never reused (00 §Color). */
.series-index__cell--roundup { background: #cfe1ff; }
.series-index__cell--bjb { background: #fcbcd2; }
.series-index__cell--deep { background: #e5cde8; }
.series-index__count { font-family: var(--sh-font-display); font-size: 26px; line-height: 1; } /* 16a (item 109) */
.series-index__cell-name {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.series-index__name { display: block; font-family: var(--sh-font-display); font-size: 30px; line-height: 1.06; } /* 16a (item 109) */
.series-index__desc { display: block; font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); margin-top: 5px; }
.series-index__path {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  white-space: nowrap;
}

/* The A–Z: CSS columns, not a grid (14 §2) — punchline tags shouldn't shove neighbors. */
.tag-index { padding: 22px var(--sh-gutter) 34px; border-bottom: 1px solid var(--sh-ink); }
/* 62ch, matching .browse-header__intro — the 88ch cap still let lines run ~98 chars
   (critique, 12 Aug 2026). */
.tag-index__intro { font-size: 15px; line-height: 1.55; max-width: 62ch; color: var(--sh-grey-on-tint); margin-bottom: 20px; }
.tag-index__list { columns: 3; column-gap: 44px; }
.tag-index__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  padding: 8px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
  break-inside: avoid;
}
.tag-index__row:hover,
.tag-index__row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.tag-index__row:hover .tag-index__count,
.tag-index__row:focus-visible .tag-index__count { color: var(--sh-grey-on-tint); }
.tag-index__name { font-family: var(--sh-font-display); font-size: 21px; line-height: 1.15; } /* 16a (item 109) */
.tag-index__count {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-grey-on-paper);
  white-space: nowrap;
}

.fn-send__aside a { text-underline-offset: 3px; }
.fn-send__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.fn-send__button--primary { background: var(--sh-ink); color: var(--sh-paper); }
.fn-send__button--primary:hover { color: var(--sh-paper); }

@media (max-width: 900px) {
  .news-search { padding: 18px 18px 22px; }
  .series-index__row { grid-template-columns: 62px 1fr; padding: 14px 18px; }
  .series-index__path { grid-column: 2; justify-self: start; }
  .tag-index { padding: 18px 18px 26px; }
  .tag-index__list { columns: 1; }
}

/* ==========================================================================
   /search/ (search.hbs; 18 §A, frames 1a–1c). Grouped results with each type's
   native row. States rendered by assets/js/search.js.
   ========================================================================== */

.search-bar { border-bottom: 1px solid var(--sh-ink); padding: 22px var(--sh-gutter) 0; }
.search-bar__form {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 0 16px;
  max-width: 860px;
}
.search-bar__glyph { font-size: 22px; line-height: 1; }
.search-bar__form input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  padding: 15px 0;
  font-family: var(--sh-font-display);
  font-size: 30px; /* 1a's drawn query face (drift item 49); 24px at 390 per 1c */
  color: var(--sh-ink);
}
.search-bar__form input:focus-visible { outline: none; }
.search-bar__form:focus-within { outline: 3px solid var(--sh-focus); outline-offset: -3px; }
/* The matched substring in a result row. Solid coral with ink on top, the same paint as
   ::selection — NOT the marker highlight, which turn 38 made a translucent two-pass gesture.
   Two reasons it stays solid: it is the ::selection family (a utility mark the browser or the
   search made, not one Steph made), and the marker is rationed to once an issue precisely so it
   stays an event — putting it on every search match is what would make it ordinary.
   UA default for <mark> is yellow-on-black, which appears nowhere in this palette. */
.search-hit {
  background: var(--sh-coral);
  color: var(--sh-ink);
}

/* Chrome draws its own cancel button inside every input[type=search] — a blue ✕ 54px from the
   theme's own CLEAR, in a color that appears nowhere in this palette, doing the identical job
   (critique, 13 Aug 2026). type=search is kept for the semantics and the mobile keyboard's
   search key; only the UA's control goes. */
.search-bar__form input::-webkit-search-cancel-button,
.search-bar__form input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
  display: none;
}
.search-bar__clear {
  border: 0;
  background: none;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  cursor: pointer;
  white-space: nowrap;
}
/* The type row IS the filter (canvas principle 3; drift item 52): buttons in each
   type's own section tint plus the black ALL chip, counts on the on-tint grey. The
   pressed chip takes the house inset ring (the rating ramp's current-page device). */
.search-bar__types { display: flex; flex-wrap: wrap; gap: 10px; padding: 14px 0 16px; }
.search-bar__types[hidden] { display: none; }
.search-bar__type {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 11px;
  color: var(--sh-ink);
  cursor: pointer;
}
.search-bar__type:hover,
.search-bar__type:focus-visible { outline: 2px solid var(--sh-ink); outline-offset: -2px; }
.search-bar__type[aria-pressed="true"] { box-shadow: inset 0 0 0 2px var(--sh-ink); font-weight: 700; }
.search-bar__type--issues { background: var(--sh-tint-newsletter); }
.search-bar__type--jobs { background: var(--sh-tint-jobs); }
.search-bar__type--resources { background: var(--sh-tint-resources); }
.search-bar__type--portfolio { background: var(--sh-tint-portfolio); }
.search-bar__type--footnotes { background: var(--sh-tint-footnotes); }
.search-bar__type-count { color: var(--sh-grey-on-tint); }
/* The drawn ALL chip is the one dark chip; its ring and count swap to the dark
   ground's values (#b8b6b4 is the near-black floor). */
.search-bar__type--all { background: var(--sh-ink); color: var(--sh-paper); }
/* Delight (18 Aug 2026): this painted an ink outline on an ink ground — invisible, on the chip
   that is selected by default and is therefore the first one a reader points at. Paper is not a
   new value here: it is already this chip's own selected inset, one line below. */
.search-bar__type--all:hover,
.search-bar__type--all:focus-visible { outline-color: var(--sh-paper); }
.search-bar__type--all[aria-pressed="true"] { box-shadow: inset 0 0 0 2px var(--sh-paper); }
.search-bar__type--all .search-bar__type-count { color: #b8b6b4; }

.search-group { border-bottom: 1px solid var(--sh-ink); padding-bottom: 8px; }
/* Group heads are 1a's tint bands (drift item 49): each result group wears its
   section's identity — 12px sans label on the section tint, the ✦ in the drawn
   #94493a. The serif-on-paper head this replaces was carried by no record. */
.search-group__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 14px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
}
.search-group--issues .search-group__head { background: var(--sh-tint-newsletter); }
.search-group--jobs .search-group__head { background: var(--sh-tint-jobs); }
.search-group--resources .search-group__head { background: var(--sh-tint-resources); }
.search-group--portfolio .search-group__head { background: var(--sh-tint-portfolio); }
.search-group--footnotes .search-group__head { background: var(--sh-tint-footnotes); }
.search-group__head .sh-twinkle { font-size: 20px; line-height: 1; color: #94493a; }
.search-group__name {
  font-family: var(--sh-font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.2;
  margin-right: auto;
}
.search-group__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
/* The capped head's "All N →" — the one route to matches 9+ of a type (item 52). */
.search-group__all {
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
/* Delight (18 Aug 2026): this is the ONLY route to matches 9+ of a kind — the code above
   calls it machinery, not sugar — and it had no interactive state of any kind, on a tinted
   group head where a static underline reads as emphasis rather than as a control. The
   underline doubles and the arrow steps; the arrow rides .sh-arrow from search.js. */
.search-group__all:hover,
.search-group__all:focus-visible { text-decoration-thickness: 2px; }
.search-group__all:hover .sh-arrow,
.search-group__all:focus-visible .sh-arrow { transform: translateX(3px); }

.search-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 18px;
  align-items: baseline;
  padding: 13px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
/* The wash is what says "this row"; before 18 Aug 2026 it was pointer-only, on the one page
   whose entire purpose is returning rows to pick from. */
.search-row:hover,
.search-row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.search-row:hover .search-row__aside,
.search-row:focus-visible .search-row__aside { color: var(--sh-grey-on-tint); }
.search-row__lead { flex: none; }
.search-row__lead .chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 3px 8px;
  white-space: nowrap;
}
.search-row__lead .chip img { width: 15px; height: 15px; }
.search-row__lead .chip--directory { background: var(--sh-tint-resources); }
.search-row__title { display: block; font-family: var(--sh-font-display); font-size: 23px; line-height: 1.12; }
.search-row__sub {
  display: block;
  font-size: 14px;
  line-height: 1.5;
  color: var(--sh-grey-on-tint);
  margin-top: 3px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.search-row__aside {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  white-space: nowrap;
}
.search-row__cell {
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-newsletter);
  padding: 6px 9px;
  display: flex;
  flex-direction: column;
  align-items: center;
  align-self: start;
}
.search-row__cell-day { font-family: var(--sh-font-display); font-size: 21px; line-height: 1; }
/* The issue numeral (canvas 1a's "092"); mono — numbers are data, as on /newsletter/. */
.search-row__cell-no { font-family: var(--sh-font-mono); font-size: 16px; font-weight: 700; letter-spacing: 0.04em; line-height: 1.65; }
.search-row__cell-mon {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.search-row__dagger {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 30px;
  line-height: 0.8;
  color: var(--sh-hot-pink);
  align-self: start;
}

.search-empty {
  padding: 36px var(--sh-gutter) 40px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 56px;
  align-items: start;
}
.search-empty[hidden] { display: none; }
.search-empty--resting { grid-template-columns: minmax(0, 720px); }
.search-empty__heading { font-family: var(--sh-font-display); font-weight: 400; font-size: 46px; line-height: 1.02; } /* 1b (item 49) */
.search-empty__copy p { font-size: 16px; line-height: 1.55; max-width: 58ch; margin-top: 12px; }
/* The scope caveat sits under the invitation, in the meta voice — it is a fact about the
   machine, not part of the welcome. Same floor as every other small text on paper. */
.search-empty__scope {
  font-size: 14px !important;
  color: var(--sh-grey-on-paper);
  margin-top: 16px !important;
}
.search-empty__browse { border: 1px solid var(--sh-ink); padding: 14px 16px 6px; }
.search-empty__browse-label {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--sh-ink);
}
.search-empty__browse-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
  font-family: var(--sh-font-display);
  font-size: 19px;
  line-height: 1.15;
}
.search-empty__browse-row:last-child { border-bottom: 0; }
/* These four rows are the only exits from a failed search or a broken index, so they are the
   last place on the site that should be pointer-only. */
.search-empty__browse-row:hover,
.search-empty__browse-row:focus-visible { color: var(--sh-ink); background: #fff6ef; }
.search-empty__browse-row:hover span:last-child,
.search-empty__browse-row:focus-visible span:last-child { color: var(--sh-grey-on-tint); }
.search-empty__browse-row span:last-child { font-family: var(--sh-font-mono); font-size: 11px; color: var(--sh-grey-on-paper); }

.search-scope {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
  padding: 13px var(--sh-gutter);
  border-bottom: 1px solid var(--sh-ink);
  background: #fff6ef;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.7;
  color: var(--sh-grey-on-tint);
}
.search-scope[hidden] { display: none; }
.search-scope a { white-space: nowrap; text-underline-offset: 3px; }

@media (max-width: 900px) {
  .search-bar { padding: 16px 18px 0; }
  .search-bar__form input { font-size: 24px; padding: 13px 0; } /* 1c's 390 query face (item 49) */
  .search-group__head { padding: 14px 18px 9px; }
  .search-row { grid-template-columns: auto minmax(0, 1fr); padding: 12px 18px; }
  .search-row__aside { grid-column: 2; }
  .search-row__title { font-size: 20px; }
  .search-empty { grid-template-columns: 1fr; gap: 22px; padding: 26px 18px 30px; }
  .search-scope { padding: 12px 18px; }
}

/* --------------------------------------------------------------------------
   /fundraiser/ — a ledger, not a thermometer (12 §3; Who Pays frames 2a/2b).
   Shares the who-pays chrome: wp-hero (near-black + coral halftone), wp-band, ask-band.
   Only the fundraiser-specific pieces live here. No fill, no percentage, no progress
   geometry anywhere in this block — a bar is a race, a ledger is a price list.
   -------------------------------------------------------------------------- */

.fr-hero { grid-template-columns: 1fr 360px; }

/* The raised box. Hand-counted figure with its stamp — the stamp is what makes a
   week-stale number honest. #b8b6b4 is the small-text floor on the near-black ground. */
.fr-raised {
  border: 1px solid var(--sh-grey-on-paper);
  padding: 26px 24px 28px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.fr-raised__label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sh-grey-on-ink);
}
.fr-raised__amount {
  font-family: var(--sh-font-display);
  font-size: 76px;
  line-height: 0.9;
  color: var(--sh-coral);
}
.fr-raised__stamp {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--sh-grey-on-ink);
}

/* The ledger. */
.fr-ledger {
  padding: 30px var(--sh-gutter) 36px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 56px;
  align-items: start;
}
.fr-ledger__head { display: flex; flex-direction: column; gap: 12px; }
.fr-ledger__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: 1.02;
}
.fr-ledger__sub { font-size: 16px; line-height: 1.5; color: var(--sh-grey-on-tint); }

.fr-ledger__rows { display: flex; flex-direction: column; }
.fr-rung {
  display: grid;
  grid-template-columns: 96px 1fr 110px;
  gap: 20px;
  align-items: baseline;
  padding: 14px 0;
  border-top: 1px solid var(--sh-hairline);
}
.fr-rung__amount {
  font-family: var(--sh-font-mono);
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--sh-grey-on-paper);
}
.fr-rung--covered .fr-rung__amount { color: var(--sh-ink); }
.fr-rung__buys { font-size: 17px; line-height: 1.45; }
.fr-rung__status {
  justify-self: end;
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sh-ink);
}
.fr-rung__status .sh-twinkle { color: var(--sh-coral); font-size: 14px; }

.fr-ledger__over {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.4;
  margin-top: 20px;
  display: flex;
  align-items: baseline;
  gap: 9px;
}
.fr-ledger__over .sh-twinkle { color: var(--sh-coral); font-size: 15px; line-height: 1; flex: none; }

/* The two commitments, on the shared hairline grid. */
.fr-cells {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
}
.fr-cell {
  background: var(--sh-paper);
  padding: 30px var(--sh-gutter) 34px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.fr-cell__label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.fr-cell__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 32px;
  line-height: 1.04;
  max-width: 22ch;
}
.fr-cell__body { font-size: 16px; line-height: 1.5; }

@media (max-width: 900px) {
  .fr-hero { grid-template-columns: 1fr; }
  .fr-raised { padding: 18px 16px 20px; }
  .fr-raised__amount { font-size: 56px; }

  .fr-ledger {
    grid-template-columns: 1fr;
    gap: 20px;
    padding: 24px 18px 26px;
  }
  .fr-ledger__heading { font-size: 30px; }
  .fr-ledger__sub { font-size: 15px; }

  /* 2b: amount and status share the first row, what-it-buys takes the second. */
  .fr-rung {
    grid-template-columns: 1fr auto;
    gap: 3px 12px;
    padding: 11px 0;
  }
  .fr-rung__amount { font-size: 15px; }
  .fr-rung__buys { grid-column: 1 / -1; font-size: 15px; }
  .fr-rung__status { grid-row: 1; grid-column: 2; }
  .fr-ledger__over { font-size: 16px; margin-top: 8px; }

  .fr-cells { grid-template-columns: 1fr; }
  .fr-cell { padding: 20px 18px 22px; }
  .fr-cell__heading { font-size: 26px; }
}

/* --------------------------------------------------------------------------
   Comment counts on issue rows and cards (comments canvas: non-zero only, never in email).
   {{comment_count empty="" ... class="sh-comment-count"}} renders nothing at zero, so the
   separator lives here rather than dangling in the template.
   -------------------------------------------------------------------------- */
.sh-comment-count::before { content: " · "; }

/* ==========================================================================
   /jobs/{slug}/ — a rated job listing (partials/post-job.hbs, job-similar.hbs).
   Record: design/01a-index-jobs-decisions.md §4–5. Design: Jobs canvas 1c (header from
   8a), 7a closed, 7b ghost job, 9a reader-submitted, 12a at 390px.

   The body is the bjb-job-tool's HTML, so almost everything below styles {{content}}
   rather than markup this theme wrote. Selectors stay generic (h2, blockquote, p) for
   that reason — the tool must not have to learn our class names.
   ========================================================================== */

.jobpost__strip .section-strip__name { text-decoration: none; }
.jobpost__strip-company {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* 9a: provenance reads as one of the facts, not as a badge shouting for attention. */
.jobpost__provenance {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  padding: 3px 7px;
}
/* Closed: the strip goes grey (01a §5, §8). The rating keeps its own tint — see below. */
.jobpost--closed .jobpost__strip { background: var(--sh-tint-closed); }

.jobpost__header {
  padding: 34px var(--sh-gutter) 30px;
  border-bottom: 2px solid var(--sh-ink);
}
.jobpost__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 64px;
  line-height: 0.98;
  letter-spacing: -0.022em;
  margin: 0;
  max-width: 26ch;
  text-wrap: balance;
}
.jobpost--closed .jobpost__title { color: #3a3a3a; }

.jobpost__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 22px;
}
/* The verdict's escape hatch: a shared-link reader meets BINGO here with no idea what it
   means, so the legend link sits beside the chip — the one place a rating is actually
   being looked at (critique P2, 12 Aug 2026; closes bad-job-bingo.hbs's stated contract). */
.jobpost__rating-how {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-link);
  text-decoration: none;
  white-space: nowrap;
}
.jobpost__rating-how:hover,
.jobpost__rating-how:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
/* The rating as a tinted bordered block rather than its own band (8a beat 1c's first
   draft). It keeps its tint on a closed listing: the rating is a permanent fact about the
   posting, and greying it would imply the reading expired with the link (01a §5). */
.jobpost__rating {
  font-family: var(--sh-font-display);
  font-size: 22px;
  line-height: 1;
  padding: 6px 12px;
  gap: 9px;
}
.jobpost__rating img { width: 20px; height: 20px; }
.jobpost__meta-fact {
  /* Serif 24px per adopted frame 1c/8a — job facts are serif values (01a §3/§4). */
  font-family: var(--sh-font-display);
  font-size: 24px;
}
.jobpost__arrangement::after { content: ", "; }
/* Open/Closed and Posted/Closed text pairs (01a §11). Both strings are rendered and CSS
   picks one, because the Handlebars alternative — an {{else}} inside {{#foreach tags}} —
   fires once per non-matching tag. The state class itself comes off the SLUG via
   {{#match}}, so the verdict of "is this closed" is still decided server-side. */
.chip.is-closed, .is-closed { display: none; }
.job-row--closed .chip.is-closed { display: inline-flex; }
.jobpost--closed .is-closed { display: inline; }
.job-row--closed .chip.is-open,
.job-row--closed .is-open,
.jobpost--closed .is-open { display: none; }
.jobpost--closed .jobrail__block--apply { display: none; }
/* 01a §5: the closed rail's date values grey (frame 7a draws them #3a3a3a). The
   POSTED · CLOSED range still waits on a stored closed date — NEEDS-RULING. */
.jobpost--closed .jobrail__block--dates .jobrail__value { color: var(--sh-grey-on-tint); }

/* Resource cards: events promote the excerpt to a date band and describe from the body;
   every other directory uses the excerpt as the description (02a §5–6). */
.library-card__body { display: contents; }
.library-card__when,
.library-card__desc--body { display: none; }
.library-card__body.is-event .library-card__when,
.library-card__body.is-event .library-card__desc--body { display: block; }
.library-card__body.is-event .library-card__desc--excerpt { display: none; }

/* Portfolio dates: undated pieces show the year alone (03a §1). */
.clip-file__credit .is-year,
.chip--plain .is-year { display: none; }
.is-undated .is-year { display: inline; }
.is-undated .is-full { display: none; }

/* The rating chip slot (partials/rating-chip.hbs, 01a §11). The verdict itself is resolved
   server-side by slug with {{#match}} — the only thing CSS decides here is whether the
   "Not yet rated" fallback shows, and it shows unless a real chip rendered. If :has() is
   missing both appear: visibly wrong, never silently empty (§11). */
.rating-slot { display: contents; }
.chip--unrated {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: #e6e4e2;
  border: 1px solid var(--sh-ink);
  padding: 4px 9px;
}
.rating-slot:has(.chip--rating) .chip--unrated { display: none; }

/* Company, salary and location are all revealed the same way: the markup prints every tag
   and CSS shows the one whose slug carries the right prefix. Handlebars has no prefix
   match, and — unlike {{primary_tag}} — this does not care what order the tags are in. */
.jobpost__company .fact-tag[data-slug^="job-company-"] { display: inline; }
/* Portfolio publication, same reasoning: #portfolio at sort order 0 kills primary_tag. */
.jobpost__company--pub .fact-tag[data-slug^="port-pub-"] { display: inline; }
.jobrail__company-link { display: none; }
.jobrail__company-link[data-slug^="job-company-"] { display: block; }
.jobpost__meta-fact--salary .fact-tag[data-slug^="job-salary-"] { display: inline; }
.jobpost__meta-fact--location .fact-tag[data-slug^="job-location-"] { display: inline; }
.jobpost__meta-fact--location .fact-tag[data-slug^="job-location-"] ~ .fact-tag[data-slug^="job-location-"]::before { content: " · "; }
.jobpost__meta-fact--salary:not(:has([data-slug^="job-salary-"])) .fact-fallback { display: inline; }

/* State callouts. Both sit above the notes so a reader meets them before the rating. */
.jobpost__callout {
  margin: 26px var(--sh-gutter) 0;
  border: 1px solid var(--sh-ink);
  padding: 18px 20px;
  max-width: 66ch;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.jobpost__callout p { font-size: 16px; line-height: 1.55; margin: 0; }
.jobpost__callout-label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.jobpost__callout--closed { background: var(--sh-tint-closed); }
/* 7b's light pink. A different axis from the rating: one says how bad the posting is, the
   other whether it is a posting at all, so it must not borrow a rating tint (01a §8). */
.jobpost__callout--ghost { background: #f5d9f1; }

.jobpost__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 60px;
  padding: 30px var(--sh-gutter) 0;
  align-items: start;
}

/* ---- the tool's body ---------------------------------------------------- */

.jobpost__content { font-family: var(--sh-font-body); }
.jobpost__content > * { max-width: 66ch; }
.jobpost__content p {
  font-size: 17px;
  line-height: 1.62;
  margin: 14px 0 0;
}
/* Section headings inside a page: Instrument Serif 36px with a coral ✦ over a 2px rule
   (01a §2.4). "Steph's Notes", "From the Reviews" and "3 Comments" are peers. */
.jobpost__content h2 {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 34px 0 0;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--sh-ink);
}
.jobpost__content h2::before {
  content: "✦";
  font-size: 26px;
  color: var(--sh-coral);
  line-height: 1;
  flex: none;
}
.jobpost__content h3 {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 30px;
  line-height: 1.08;
  margin: 34px 0 0;
  padding-top: 26px;
  border-top: 1px solid var(--sh-ink);
}
/* The company's own words. Same device as everywhere else on the site — a left bar means
   someone else is talking, and Steph's reply sits outside it as ordinary body copy with no
   marker at all (09 turns 23–25, 34). The tool emits blockquote > p > em for quoted lines
   and a bare <p> for commentary, so this needs no authoring discipline. */
.jobpost__content blockquote {
  margin: 26px 0 0 22px;
  border-left: 2px solid var(--sh-grey);
  padding: 2px 0 2px 16px;
}
.jobpost__content blockquote p {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 21px;
  line-height: 1.45;
  margin: 0;
}
/* The JD's subheads — What you'll do / Basic qualifications / Compensation and benefits.
   The tool emits them as h4; 1c draws them in the mono label voice, not display type
   (drift item 101 — they fell to default bold body before this rule existed). */
.jobpost__content h4 {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 26px 0 0;
}
/* The original JD is reference, not reading, so it takes the full column rather than the
   66ch measure (01a §4) — it is the one part of the page a reader scans against the source
   instead of reading through. */
.jobpost__content h3 ~ p,
.jobpost__content h3 ~ ul,
.jobpost__content h3 ~ h4 { max-width: none; }

/* The apply control is a kg-button-card the tool writes into the body. This is the one
   permanent theme rule 01a §5 calls for: on a closed listing it comes off the page rather
   than being edited out by hand, listing by listing. :last-of-type is deliberate (01a §5
   writes it verbatim): the tool also emits a Read-this-issue button card into the same
   body, and only the apply card — always last — comes off on close. */
.jobpost--closed .kg-button-card:last-of-type,
body.tag-job-status-closed .kg-button-card:last-of-type { display: none; }

.jobpost__content .kg-button-card { margin-top: 26px; }
/* The selector depth is load-bearing: ghost_head injects cards.min.css AFTER main.css,
   and its `.kg-button-card a.kg-btn-accent` (0-2-1) ties the button to the ADMIN accent
   color (#ff1a75, in no palette record, 3.7:1 with white) plus system font, 2.4em
   height and a 5px radius. Same lesson as the audio card — equal specificity loses to
   source order — so the highest-stakes control on a listing sits at 0-3-2 or an admin
   setting restyles Apply. */
main .jobpost__content .kg-button-card a.kg-btn,
main .jobpost__content .kg-button-card a.kg-btn-accent {
  display: inline-block;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 14px 26px;
  height: auto;
  line-height: 1;
  border-radius: 0;
}
main .jobpost__content .kg-button-card a.kg-btn:hover,
main .jobpost__content .kg-button-card a.kg-btn-accent:hover {
  background: var(--sh-grey-on-paper);
  color: var(--sh-paper);
  opacity: 1;
}

/* ---- the rail ----------------------------------------------------------- */

.jobpost__rail {
  position: sticky;
  top: 24px;
  display: flex;
  flex-direction: column;
}
/* Bordered cells with collapsed edges, 16px padding — frame 1c's construction (drift
   item 58; the shipped first draft was an open hairline stack). Salary, Type/location,
   Posted and Apply are ONE drawn cell in 1c, so the joins between those blocks are the
   frame's inset hairlines rather than cell edges — the --joined modifier does that. */
.jobrail__block {
  border: 1px solid var(--sh-ink);
  border-top: 0;
  padding: 16px;
}
.jobrail__block:first-child { border-top: 1px solid var(--sh-ink); }
.jobrail__block--joined { border-top: 0; padding-top: 0; }
.jobrail__block:has(+ .jobrail__block--joined) { border-bottom: 0; padding-bottom: 0; }
.jobrail__block--joined::before {
  content: "";
  display: block;
  height: 1px;
  background: var(--sh-hairline);
  margin: 14px 0;
}
/* On a closed listing the Apply block is gone entirely, so the dates block closes the
   drawn cell and takes the bottom edge back. After the :has() rule on purpose — they tie
   on specificity. */
.jobpost--closed .jobrail__block--dates { border-bottom: 1px solid var(--sh-ink); padding-bottom: 16px; }
.jobrail__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin: 0;
}
.jobrail__value {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.14;
  margin: 3px 0 0;
}
/* 1c's emphasis step: the salary is the rail's biggest value (drift item 58). */
.jobrail__value--salary { font-size: 26px; line-height: 1.1; margin-top: 4px; }
/* 1c draws Type/location as two lines: arrangement at 20px ink, the location line under
   it at 18px grey (above the 13px floor, so #6b6b6b is fine). */
.jobrail__value--location { font-size: 18px; line-height: 1.2; color: var(--sh-grey-on-paper); }
.jobrail__value--location .jobpost__arrangement {
  display: block;
  font-size: 20px;
  line-height: 1.14;
  color: var(--sh-ink);
}
.jobrail__value--location .jobpost__arrangement::after { content: none; }
/* The rail Apply button, 1c/12a (drift item 62). Hidden until job.js borrows the href
   from the body's apply kg-button-card — the URL lives only in {{content}}, and a
   button that goes nowhere is worse than no button. No JS → the body button alone. */
.jobrail__apply {
  display: block;
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-align: center;
  padding: 14px 0;
  margin-top: 14px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
}
.jobrail__apply[hidden] { display: none; }
.jobrail__company { display: flex; align-items: center; gap: 10px; margin-top: 7px; }
.jobrail__logo { width: 28px; height: 28px; object-fit: contain; flex: none; }
.jobrail__company-name { font-family: var(--sh-font-display); font-size: 20px; line-height: 1.2; }
.jobrail__link,
.jobrail__note { display: block; margin-top: 8px; }
.jobrail__link { font-family: var(--sh-font-mono); font-size: 11px; letter-spacing: 0.06em; }
/* 1c draws the note as mono small print under the button — 10px sits exactly at the
   size floor and #6b6b6b exactly at the paper floor, both compliant. */
.jobrail__note {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.7;
  color: var(--sh-grey-on-paper);
  margin-top: 10px;
}
.jobrail__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.jobrail__share { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.jobrail__share a,
.jobrail__copy {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 6px 10px;
  cursor: pointer;
}
/* 00 §5 where a reader is actually looking at a rating. Not small print — it does the same
   job as the Bad Job Bingo standing note inside an issue, so it takes body size. */
.jobrail__disclaimer {
  margin: 18px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--sh-ink);
  font-size: 14px;
  line-height: 1.5;
}

/* ---- similar jobs ------------------------------------------------------- */

.jobsimilar { padding: 40px var(--sh-gutter) 0; }
.jobsimilar__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--sh-ink);
}
.jobsimilar__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 0;
}
.jobsimilar__heading .sh-twinkle { color: var(--sh-coral); font-size: 26px; }
.jobsimilar__all { font-family: var(--sh-font-mono); font-size: 11px; letter-spacing: 0.06em; }

/* The similar-row mono meta line — 01a §4's "mono meta line", drawn in 1c as
   SUPABASE · TECHNICAL & ENGINEERING · MID-LEVEL · REMOTE, US at Space Mono 10px,
   .04em, #3a3a3a (drift item 59; the first build printed a bare company span).
   Facts are revealed off tag slugs by prefix like every other row fact. Each group
   after the first carries its own leading "·", so a hidden middle group never
   strands a separator — company and discipline always exist (every listing carries
   a company tag, and the whole partial is discipline-scoped). #3a3a3a already
   satisfies the ≤13px floor on the row's #fff6ef hover tint. */
.job-row__meta {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.job-row__meta-group--company .fact-tag[data-slug^="job-company-"],
.job-row__meta-group--discipline .fact-tag[data-slug^="job-discipline-"],
.job-row__meta-group--level .fact-tag[data-slug^="job-level-"],
.job-row__meta-group--where .fact-tag[data-slug^="job-location-"] { display: inline; }
.job-row__meta-group--where .fact-tag[data-slug^="job-location-"] ~ .fact-tag[data-slug^="job-location-"]::before { content: " · "; }
.job-row__meta-group + .job-row__meta-group::before { content: " · "; }
/* The arrangement is the {{#match}} span (deterministic order — tag order is not);
   its ", " ::after only earns its keep when a location actually follows. The hidden
   fact-tag spans double as existence tests for the :has() gates below. */
.job-row__meta-group--where:not(:has(.fact-tag[data-slug^="job-location-"])) .jobpost__arrangement::after { content: none; }
/* A group with nothing to reveal disappears, separator and all. */
.job-row__meta-group--level:not(:has(.fact-tag[data-slug^="job-level-"])),
.job-row__meta-group--where:not(:has(.fact-tag[data-slug^="job-arrangement-"], .fact-tag[data-slug^="job-location-"])) { display: none; }

/* 390px (12a). Three columns become one; the rail follows the body rather than being cut,
   because everything in it is a fact the reader still wants. */
@media (max-width: 900px) {
  .jobpost__header { padding-left: 18px; padding-right: 18px; }
  .jobpost__title { font-size: 36px; } /* 12a's named mobile size */
  .jobpost__layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
    padding-left: 18px;
    padding-right: 18px;
  }
  .jobpost__rail { position: static; }
  .jobpost__callout { margin-left: 18px; margin-right: 18px; }
  .jobsimilar { padding-left: 18px; padding-right: 18px; }
  .jobsimilar__heading { font-size: 28px; }
}

/* --------------------------------------------------------------------------
   /resources/{slug}/ — the single entry (partials/post-resource.hbs).
   Record: design/02a-index-resources-decisions.md §5; frames 4b (page) and
   4c (fact block). Same measure as /jobs/{slug}/: reading column + 320px rail
   + 60px gap. The canvas draws its labels at 9px; they rise to the 10px floor
   here (CLAUDE.md — never smaller than 10px), same correction the job rail made.
   -------------------------------------------------------------------------- */

/* Directory, collections and publisher are revealed off the tag slugs by prefix —
   the markup prints every tag, CSS shows the right ones (01a §10). Shared by the
   strip and the rail. */
.respost__dir .fact-tag[data-slug^="res-directory-"] { display: inline; }
.respost__dir .fact-tag[data-slug^="res-directory-"] ~ .fact-tag[data-slug^="res-directory-"]::before { content: " · "; }
.respost__collections .fact-tag[data-slug^="res-collection-"] { display: inline; }
.respost__collections .fact-tag[data-slug^="res-collection-"] ~ .fact-tag[data-slug^="res-collection-"]::before { content: " · "; }
.respost__publisher .fact-tag[data-slug^="res-publisher-"] { display: inline; }

/* The header is a grid area of its own (event pass, 24 Aug 2026 — 02a §13): the standard
   entry places it at the top of the reading column with the rail beside it, visually
   identical to the old header-inside-body markup (4b); the event entry spans it across
   both columns so the date band can run full-width beneath it (2a). Row gap is 0 — the
   22px header→body rhythm comes from the body children's own margin-top, as before. */
.respost__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "header rail"
    "body   rail";
  gap: 0 60px;
  padding: 38px var(--sh-gutter) 40px;
  align-items: start;
}
.respost__header { grid-area: header; }
.respost__body { grid-area: body; min-width: 0; }
.respost__rail { grid-area: rail; }
.respost--event .respost__layout {
  grid-template-rows: auto auto 1fr;
  grid-template-areas:
    "header header"
    "band   band"
    "body   rail";
}
/* Below the band, content and rail resume at 26px (spec §4: body grid padding 26px);
   children carry 22px of it themselves. */
.respost--event .respost__body > :first-child { margin-top: 26px; }
.respost--event .respost__rail { margin-top: 26px; }

/* ---- header: cover art + title + chips (4b) ------------------------------ */

.respost__header { display: flex; gap: 20px; align-items: flex-start; }
.respost__art {
  width: 104px;
  height: 104px;
  flex: none;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
}
.respost__art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.respost__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 52px;
  line-height: 0.98;
  letter-spacing: -0.02em;
  margin: 0;
}
.respost__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

/* ---- the date band (02a §13, spec §3; frames 2a live / 1d expired) --------
   Events only. Full-width under title + chips — the negative margins pull it to the
   page edge through the layout's gutter padding — peach, 1px black top and bottom.
   The when-line device the excerpt used to render under the title (old .respost__when)
   is superseded by this band: the excerpt now server-renders in the band's left slot
   until resource-post.js swaps in the <time> run's own text. The band exists for the
   field that expires, not for emphasis — no other directory ever gets one, and if
   Tooling ever wants a price band the answer is no (02a §13). */

.respost-band {
  grid-area: band;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 32px;
  background: var(--sh-tint-resources);
  border-top: 1px solid var(--sh-ink);
  border-bottom: 1px solid var(--sh-ink);
  margin: 22px calc(-1 * var(--sh-gutter)) 0;
  padding: 16px var(--sh-gutter);
}
.respost-band__date {
  font-family: var(--sh-font-display);
  font-size: 54px;
  line-height: 0.95;
  margin: 0;
}
.respost-band__side { text-align: right; }
.respost-band__side[hidden] { display: none; }
.respost-band__mode {
  font-family: var(--sh-font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  margin: 0;
}
.respost-band__place {
  font-family: var(--sh-font-display);
  font-size: 23px;
  line-height: 1.15;
  margin: 4px 0 0;
}
.respost-band__place[hidden] { display: none; }
/* Below 720px the band's two sides stack, date first, date at 38px — the date line
   wraps before it shrinks (spec §other-widths). */
@media (max-width: 720px) {
  .respost-band { flex-direction: column; align-items: flex-start; gap: 10px; }
  .respost-band__date { font-size: 38px; }
  .respost-band__side { text-align: left; }
}

/* ---- vendor disclosure band (02a §3/§5): who published it, nothing on top --- */

.respost__vendor {
  border: 1px solid var(--sh-ink);
  background: #f7cec7;
  padding: 12px 14px;
  margin-top: 22px;
}
.respost__vendor-line {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  line-height: 1.75;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0;
}

/* ---- the fact block (02a §5, 4c) — built by resource-post.js from the typed
   Label: value run; only the fields present render. Two columns like 4b; the
   border arithmetic keeps the bottom row clean at any count. ----------------- */

/* minmax(0, 1fr), never bare 1fr: a long unbreakable value (a domain like
   community.customersuccessmeetup.com) would otherwise widen its own column at the
   other column's expense — found live on /resources/moment-2026/, 4 Sep 2026, where
   VENUE wrapped one word per line beside a wide WEBSITE cell. */
.respost-facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  border: 1px solid var(--sh-ink);
  margin-top: 22px;
}
/* The event block spans the full reading column (spec §4: the 710px body grid), not
   the 66ch prose cap — event values (street-level venues, organizers) run longer than
   the evergreen directories'. Non-event entries keep the shipped 66ch. */
.respost--event .respost__content > .respost-facts { max-width: none; }
.respost-facts__row {
  display: flex;
  gap: 12px;
  padding: 9px 13px;
  border-bottom: 1px solid #e6e4e2;
}
.respost-facts__row:nth-child(odd) { border-right: 1px solid var(--sh-ink); }
/* of-type rather than :last-child so the arithmetic ignores the event links row —
   a <p> appended as the block's foot (02a §13); the rows are the only divs. */
div.respost-facts__row:last-of-type,
div.respost-facts__row:nth-child(odd):nth-last-of-type(2) { border-bottom: 0; }
/* The event links row (spec §content): Tickets · Schedule · Refund policy · Code of
   conduct, moved into the block's foot by resource-post.js. Same generic component as
   book retailers / podcast platforms, drawn at the block's foot for events only. */
.respost__content .respost-facts .respost__links {
  grid-column: 1 / -1;
  background: #f2f0ee;
  border-top: 1px solid var(--sh-ink);
  padding: 10px 13px;
  gap: 6px;
  margin: 0;
  max-width: none;
  /* The typed " · " separators between the links vanish here — the foot row is chips
     with a gap (2a); the chips restate their own size. */
  font-size: 0;
}
.respost__content .respost-facts .respost__links a { padding: 3px 7px; }
/* display: flex on the row would defeat the hidden attribute resource-post.js sets on
   past rows in "Coming up instead" — same guard as .respost-rail__open[hidden]. */
.resnearby__row[hidden] { display: none; }
.respost-facts__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  min-width: 96px;
  flex: none;
  padding-top: 5px;
}
.respost-facts__value {
  font-family: var(--sh-font-display);
  font-size: 19px;
  line-height: 1.1;
  /* Take the row's remaining width and wrap inside it — min-width: 0 lets a flex item
     shrink below its content, overflow-wrap catches the one word (a URL) that is
     itself wider than the cell. Same Moment 2026 finding as the minmax above. */
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ---- the body, as typed --------------------------------------------------- */

.respost__content { font-family: var(--sh-font-body); margin-top: 22px; }
.respost__content > * { max-width: 66ch; }
.respost__content p {
  font-size: 17px;
  line-height: 1.62;
  margin: 14px 0 0;
}
/* House section heading — "Where to find it", "Steph's Notes" (Tooling and Gear
   only, 00 §5), an event's Tickets / Schedule / Refunds. Same as /jobs/{slug}/. */
.respost__content h2 {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 34px 0 0;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--sh-ink);
}
.respost__content h2::before {
  content: "✦";
  font-size: 26px;
  color: var(--sh-coral);
  line-height: 1;
  flex: none;
}
.respost__content h3 {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 30px;
  line-height: 1.08;
  margin: 34px 0 0;
}
/* Their words (02a §5): the publisher's own description, Instrument Serif italic
   with the peach bar — the resources page marks the border in peach where the job
   page uses grey (4b). The credit sits under it in the meta voice. */
.respost__content blockquote {
  margin: 20px 0 0;
  border-left: 2px solid var(--sh-peach);
  padding: 2px 0 2px 16px;
  max-width: 60ch;
}
.respost__content blockquote p {
  font-family: var(--sh-font-display);
  font-style: italic;
  font-size: 21px;
  line-height: 1.45;
  margin: 0;
}
.respost__content .respost__credit {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin: 8px 0 0;
  padding-left: 18px;
}
/* The links row — an all-links paragraph, classed by resource-post.js. Generic on
   purpose: platforms, retailers and join links are the same component (02a §5). */
.respost__content .respost__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
  max-width: none;
}
.respost__content .respost__links a {
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  padding: 6px 10px;
}
.respost__content .respost__links a::after { content: " ↗"; }

/* ---- nearby in the library (4b) ------------------------------------------ */

/* Article-level since 12 Aug 2026 (02a §11): a full-width foot below the layout grid,
   so the mobile column order is content → rail (Open it ↗) → nearby. It carries the
   page gutter itself now that it's outside the padded layout. */
.resnearby { margin-top: 4px; padding: 0 var(--sh-gutter) 44px; }
.resnearby__head {
  display: flex;
  align-items: baseline;
  padding-bottom: 9px;
  border-bottom: 2px solid var(--sh-ink);
}
.resnearby__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 0;
}
.resnearby__heading .sh-twinkle { color: var(--sh-coral); font-size: 26px; }
.resnearby__row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.resnearby__row:hover .resnearby__title,
.resnearby__row:focus-visible .resnearby__title { text-decoration: underline; text-underline-offset: 3px; }
.resnearby__title {
  font-family: var(--sh-font-display);
  font-size: 24px;
  line-height: 1.06;
}
.resnearby__kind .fact-tag[data-slug^="res-directory-"] {
  display: inline-block;
  border: 1px solid var(--sh-ink);
  background: var(--sh-tint-resources);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  padding: 2px 6px;
  white-space: nowrap;
}
.resnearby__added {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  color: var(--sh-grey-on-paper);
  margin-left: auto;
  white-space: nowrap;
}

/* ---- the rail (4b): open button, bordered fact box, share, report ---------- */

.respost__rail { position: sticky; top: 24px; }
.respost-rail__open {
  display: block;
  background: var(--sh-ink);
  color: var(--sh-paper);
  text-align: center;
  padding: 15px 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
}
/* display: block above would defeat the hidden attribute — it stays hidden until
   resource-post.js finds a real destination. */
.respost-rail__open[hidden] { display: none; }
/* The page's one action answers the hand (delight pass, 02a §12): the system's
   primary-button hover plus the ↗ stepping where it points — the jobs ramps' icon
   nudge (01a §14). Same blanket reduced-motion guard, same :focus-visible parity. */
.respost-rail__open:hover,
.respost-rail__open:focus-visible { background: var(--sh-grey-on-paper); color: var(--sh-paper); }
/* The ↗ lean now rides .sh-arrow--out (extracted 16 Aug 2026); the class survives as the
   script's handle on the glyph (post-resource.hbs fills this link from the WEBSITE fact). */
.respost-rail__box { border: 1px solid var(--sh-ink); border-top: 0; }
.respost-rail__open[hidden] + .respost-rail__box { border-top: 1px solid var(--sh-ink); }
.respost-rail__row { padding: 11px 13px; border-top: 1px solid var(--sh-ink); }
.respost-rail__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  margin: 0;
}
.respost-rail__value {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.18;
  margin: 3px 0 0;
}
/* About and Publisher rows vanish when the entry has no tag on that axis — nothing
   marks an independent entry (02a §3), so an empty row would say the wrong thing. */
.respost-rail__row--about:not(:has(.fact-tag[data-slug^="res-collection-"])) { display: none; }
.respost-rail__row--publisher:not(:has(.fact-tag[data-slug^="res-publisher-"])) { display: none; }
.respost-rail__row--share { background: #f2f0ee; }
/* On the tinted share row the 10px label floors at #3a3a3a (CLAUDE.md ≤13px-on-tint). */
.respost-rail__row--share .respost-rail__label { color: var(--sh-grey-on-tint); }
.respost-rail__share { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.respost-rail__share a,
.respost-rail__copy {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid var(--sh-ink);
  background: var(--sh-paper);
  color: var(--sh-ink);
  text-decoration: none;
  padding: 6px 10px;
  cursor: pointer;
}
.respost-rail__report {
  display: block;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1.7;
  margin-top: 5px;
}
/* The organizer link (expired events only): link purple, no underline, same value slot. */
.respost-rail__organizer-link { color: #8f3f96; text-decoration: none; }
.respost-rail__organizer-link::after { content: " ↗"; }
.respost-rail__organizer-link:hover,
.respost-rail__organizer-link:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* ---- the expired event (02a §13, frame 1d) --------------------------------
   respost--ended is set by resource-post.js the day after the event's last day,
   derived from the body's own time[datetime] run — the same field the channel sorts
   and expires on. What changes, and nothing else (spec): strip and band go grey,
   band values drop to #3a3a3a, chips go grey, a notice block appears above the fact
   block, the CTA becomes a grey statement (never a dead link), the rail rows become
   Directory · Ended · Organizer, and Nearby becomes Coming up instead. Nothing is
   deleted; the page still resolves. */

.respost--ended .section-strip--resources { background: #e6e4e2; }
.respost--ended .respost__chips a { background: #e6e4e2; }
.respost--ended .respost-band { background: #e6e4e2; }
.respost--ended .respost-band__date,
.respost--ended .respost-band__place { color: var(--sh-grey-on-tint); }

/* The notice (spec: 1px border, grey, Space Mono 11px #3a3a3a) — inserted by
   resource-post.js as the first thing in the content column. */
.respost__ended-note {
  border: 1px solid var(--sh-ink);
  background: #e6e4e2;
  padding: 12px 14px;
}
.respost__ended-note-line {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  margin: 0;
}

/* The CTA statement: bordered grey block, never a dead link (1d). Sits above the open
   anchor so open[hidden] + box keeps its adjacency; when it shows, the box's top border
   yields to its bottom edge. */
.respost-rail__ended {
  border: 1px solid var(--sh-ink);
  background: #e6e4e2;
  text-align: center;
  padding: 15px 0;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
  margin: 0;
}
.respost-rail__ended[hidden] { display: none; }
.respost--ended .respost-rail__open { display: none; }
.respost--ended .respost-rail__open[hidden] + .respost-rail__box { border-top: 0; }

/* The rail becomes Directory · Ended · Organizer (+ share): the tag-and-date rows that
   describe a live listing hide with the report link — there is nothing left to report. */
.respost--ended .respost-rail__row--about,
.respost--ended .respost-rail__row--publisher,
.respost--ended .respost-rail__row--added,
.respost--ended .respost-rail__row--report { display: none; }

/* ---- 390px: one column, rail follows the body (same rule as /jobs/{slug}/) -- */

@media (max-width: 900px) {
  /* Row gap 0 here too — the 22px rhythm still comes from the body children's margins;
     the rail takes its former 32px gap as a margin so the header→body seam stays tight. */
  .respost__layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "header" "body" "rail";
    gap: 0;
    padding-left: 18px;
    padding-right: 18px;
  }
  .respost--event .respost__layout {
    grid-template-rows: auto;
    grid-template-areas: "header" "band" "body" "rail";
  }
  .respost__rail { position: static; margin-top: 32px; }
  .respost--event .respost__rail { margin-top: 32px; }
  .respost__title { font-size: 38px; }
  .respost__art { width: 84px; height: 84px; }
  /* The band's full-bleed margins track the narrower mobile gutter. */
  .respost-band { margin-left: -18px; margin-right: -18px; padding-left: 18px; padding-right: 18px; }
  .resnearby__heading { font-size: 28px; }
  .resnearby { padding-left: 18px; padding-right: 18px; }
  .respost-facts { grid-template-columns: 1fr; }
  .respost-facts__row:nth-child(odd) { border-right: 0; }
  div.respost-facts__row:nth-child(odd):nth-last-of-type(2) { border-bottom: 1px solid #e6e4e2; }
  div.respost-facts__row:last-of-type { border-bottom: 0; }
}

/* --------------------------------------------------------------------------
   /portfolio/{slug}/ — the single clip (partials/post-portfolio.hbs).
   Record: design/03a-index-portfolio-decisions.md §4 (option 2a); mobile 5b.
   The canvas draws its labels at 9px; they rise to the 10px floor here
   (CLAUDE.md), same correction as the job and resource rails.
   -------------------------------------------------------------------------- */

/* Topic and format reveals — publication rides the existing .jobpost__company--pub. */
.portpost__topics .fact-tag[data-slug^="port-topic-"] { display: inline; }
.portpost__topics .fact-tag[data-slug^="port-topic-"] ~ .fact-tag[data-slug^="port-topic-"]::before { content: " · "; }
.portpost__formats .fact-tag[data-slug^="port-format-"] { display: inline; }
.portpost__formats .fact-tag[data-slug^="port-format-"] ~ .fact-tag[data-slug^="port-format-"]::before { content: " · "; }

/* ---- header band: chips over the balanced 76px title (2a) ----------------- */

.portpost__header {
  padding: 40px var(--sh-gutter) 32px;
  border-bottom: 1px solid var(--sh-ink);
}
.portpost__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.portpost__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 76px;
  line-height: 0.96;
  letter-spacing: -0.015em; /* 00's blanket display tracking; the canvas's -0.018 loses */
  margin: 0;
  text-wrap: balance;
}

/* ---- layout: reading column against a bordered 320px rail (2a) ------------
   Unlike the job and resource pages this pair is divided by a rule, not a gap —
   the columns stretch so the border runs the full height. */

/* The main column shrink-wraps its measure instead of eating the row (critique, 13 Aug 2026).
   `1fr` gave it 1120px at 1440 to hold a 624px excerpt, so 452px of nothing sat between the last
   word and the rail's rule — the reading measure was right, the cell around it was not. The
   excerpt keeps its 66ch; the column is now that plus its gutters, and the leftover becomes an
   outer margin the pair sits inside. Falls back to 1fr below 1200 where there is no slack to give. */
.portpost__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  justify-content: center;
}
@media (min-width: 1200px) {
  .portpost__layout { grid-template-columns: minmax(0, 760px) 320px; }
}
.portpost__main {
  padding: 36px var(--sh-gutter) 0;
  border-right: 1px solid var(--sh-ink);
}

/* ---- the excerpt, fading mid-thought (03a §4) -----------------------------
   The system's one sanctioned gradient, reused for excerpt rather than paywall.
   An overlay on the tail of the real opening — no JS, no marker in the content. */

.portpost__excerpt {
  position: relative;
  max-width: 66ch;
  font-family: var(--sh-font-body);
  font-size: 17px;
  line-height: 1.62;
}
.portpost__excerpt p { margin: 18px 0 0; }
.portpost__excerpt > *:first-child { margin-top: 0; }
.portpost__excerpt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 10em;
  background: linear-gradient(to bottom, rgba(253, 253, 253, 0) 0%, rgba(253, 253, 253, 0.86) 58%, #fdfdfd 100%);
  pointer-events: none;
}

/* The fade means "there is more, go and get it" — the system's one sanctioned gradient, and a
   promise. On the three self-hosted PDFs there is no more: the body is a complete 28-word note
   from Steph explaining why the piece is a PDF, and the fade was swallowing 77% of it (measured
   at 390px: an 80px fade over a 104px block, taking the clause that did the explaining). Off
   there, along with the hand-off line that assumed the piece lived somewhere else.

   THE `:has()` MUST READ THE PAGE'S OWN FACTS, NOT THE WHOLE ARTICLE (found 14 Aug 2026, in
   the delight pass, on a staging clip that is not a PDF and was claiming to be one). The test
   was `.portpost:has(.fact-tag[data-slug="port-format-pdf"])`, and `.portpost` wraps the rail —
   where `portfolio-related.hbs` prints a `.fact-tag` span for every tag of every SIBLING piece.
   So any clip sharing a topic with one of the three Klaus PDFs inherited their branch: it lost
   its fade and told the reader "the whole thing lives here, exactly as published" directly above
   an outbound URL on someone else's domain — the exact falsehood the branch exists to prevent,
   moved onto a different page. Scoped to `.portfacts`, which is the post's own facts card and
   the one place its own format tag is printed. */
.portpost__cta-line--hosted { display: none; }
.portpost:has(.portfacts .fact-tag[data-slug="port-format-pdf"]) .portpost__cta-line--elsewhere { display: none; }
.portpost:has(.portfacts .fact-tag[data-slug="port-format-pdf"]) .portpost__cta-line--hosted { display: block; }
.portpost:has(.portfacts .fact-tag[data-slug="port-format-pdf"]) .portpost__excerpt::after { content: none; }

/* ---- the hand-off (2a): serif line + source URL + black button ------------
   Grid areas so 390px can reorder to line / button / URL (5b) without new markup. */

.portpost__cta {
  max-width: 66ch;
  border-top: 2px solid var(--sh-ink);
  margin-top: 4px;
  padding: 22px 0 36px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "line btn"
    "src  btn";
  align-items: center;
  column-gap: 24px;
}
.portpost__cta-line {
  grid-area: line;
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.1;
  margin: 0;
}
.portpost__cta-pub .fact-fallback { display: none; }
.portpost__cta-pub:not(:has(.fact-tag[data-slug^="port-pub-"])) .fact-fallback { display: inline; }
.portpost__cta-src {
  grid-area: src;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--sh-grey-on-paper);
  margin: 5px 0 0;
  overflow-wrap: anywhere;
}
.portpost__cta-btn {
  grid-area: btn;
  border: 1px solid var(--sh-ink);
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 13px 22px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
/* The door this whole page exists to open, and it did not answer the pointer (delight pass,
   14 Aug 2026). House primary-button hover; the arrow leans out on .sh-arrow. */
.portpost__cta-btn:hover,
.portpost__cta-btn:focus-visible {
  color: var(--sh-paper);
  background: var(--sh-grey-on-paper);
}

/* ---- the rail: facts, related, availability (2a) -------------------------- */

.portpost__rail {
  padding: 36px 30px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

.portfacts { border: 1px solid var(--sh-ink); }
.portfacts__head {
  background: var(--sh-tint-portfolio);
  border-bottom: 1px solid var(--sh-ink);
  padding: 8px 14px;
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0;
}
.portfacts__row {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--sh-hairline);
  align-items: baseline;
}
.portfacts__row:last-child { border-bottom: 0; }
.portfacts__label {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}
.portfacts__value {
  font-family: var(--sh-font-display);
  font-size: 19px;
  line-height: 1.16;
}
/* Format and Topic rows vanish when the piece has no tag on that axis. */
.portfacts__row--format:not(:has(.fact-tag[data-slug^="port-format-"])) { display: none; }
.portfacts__row--topic:not(:has(.fact-tag[data-slug^="port-topic-"])) { display: none; }

.portrail__related { display: flex; flex-direction: column; gap: 12px; }
/* Suppresses entirely, heading included, when the topic has no siblings — the heading
   renders outside the {{#get}} (see the partial), so CSS owns the empty case. */
.portrail__related:not(:has(.portrail__related-row)) { display: none; }
.portrail__related-head {
  border-bottom: 2px solid var(--sh-ink);
  padding-bottom: 8px;
}
.portrail__related-heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 26px;
  line-height: 1;
  margin: 0;
}
.portrail__related-heading .sh-twinkle { color: var(--sh-coral); font-size: 18px; }
.portrail__related-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--sh-hairline);
  text-decoration: none;
  color: var(--sh-ink);
}
.portrail__related-row:hover .portrail__related-title,
.portrail__related-row:focus-visible .portrail__related-title { text-decoration: underline; text-underline-offset: 3px; }
.portrail__related-title {
  font-family: var(--sh-font-display);
  font-size: 20px;
  line-height: 1.12;
}
.portrail__related-credit {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

.portrail__avail {
  border: 1px solid var(--sh-ink);
  background: var(--sh-peach);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.portrail__avail-line {
  font-family: var(--sh-font-display);
  font-size: 22px;
  line-height: 1.12;
  margin: 0;
}
.portrail__avail-link {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- 390px (5b): one column, shorter fade, button before the URL ---------- */

@media (max-width: 900px) {
  .portpost__header { padding: 22px 18px; }
  .portpost__title { font-size: 42px; line-height: 0.98; }
  .portpost__layout { grid-template-columns: minmax(0, 1fr); }
  .portpost__main { border-right: 0; padding: 22px 18px 0; }
  .portpost__excerpt { font-size: 16px; }
  .portpost__excerpt::after { height: 5em; }
  .portpost__cta {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "line"
      "btn"
      "src";
    row-gap: 12px;
    padding-top: 16px;
    padding-bottom: 24px;
  }
  .portpost__cta-line { font-size: 24px; line-height: 1.08; }
  .portpost__cta-btn { white-space: normal; padding: 14px; }
  .portpost__cta-src { text-align: center; margin: 0; }
  .portpost__rail { padding: 22px 18px; gap: 22px; }
}

/* ==========================================================================
   /career-suite/ — the route, not a tool index (career-suite.hbs).
   Record: design/23-career-suite-decisions.md, frames 2a/2b APPROVED chat 11.
   Six bordered step rows, step five deliberately bare. The strip and the closing
   "don't feel bad" band carry the Career Suite leaf green from the tint map
   (09 §4) — the canvas drew them jobs-blue, and the record wins.
   ========================================================================== */

.section-strip--career-suite { background: var(--sh-tint-career-suite); }

/* Hero — near-black, coral halftone at 0.16 (same event as who-pays'). */
.cs-hero {
  position: relative;
  overflow: clip;
  background: var(--sh-ink);
  color: var(--sh-paper);
  border-bottom: 1px solid var(--sh-ink);
  padding: 56px var(--sh-gutter) 52px;
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 56px;
  align-items: center;
}
.cs-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--sh-coral) 0.9px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.16;
  pointer-events: none;
}
.cs-hero__copy, .cs-hero__panel, .cs-stamp { position: relative; }
.cs-hero__copy { display: flex; flex-direction: column; gap: 18px; }
.cs-hero__eyebrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.cs-hero__eyebrow .sh-twinkle { font-size: 22px; line-height: 1; }
.cs-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 74px;
  line-height: 0.96;
  letter-spacing: -0.02em;
}
.cs-hero__title-accent { color: var(--sh-coral); }
.cs-hero__sub { font-size: 17px; line-height: 1.55; max-width: 58ch; color: #e6e4e2; }
.cs-hero__panel {
  border: 1px solid var(--sh-grey-on-paper);
  padding: 24px 22px 26px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cs-hero__panel-label {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sh-grey-on-ink);
}
.cs-hero__panel-answer {
  font-family: var(--sh-font-display);
  font-size: 48px;
  line-height: 0.94;
  color: var(--sh-coral);
}
.cs-hero__panel-note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--sh-grey-on-ink);
  border-top: 1px solid var(--sh-footer-rule);
  padding-top: 12px;
}

/* The 390px hero device — the rotated stamp (2b), same construction as wp-stamp.
   The breakpoint swaps it with the panel. */
.cs-stamp {
  display: none;
  transform: rotate(-5deg);
  align-self: flex-start;
  border: 3px double var(--sh-paper);
  background: var(--sh-coral);
  padding: 4px;
}
.cs-stamp__inner {
  border: 1px solid var(--sh-ink);
  padding: 10px 13px 9px;
  text-align: center;
  font-family: var(--sh-font-mono);
  color: var(--sh-ink);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.cs-stamp__stars { font-size: 10px; font-weight: 700; letter-spacing: 0.3em; }
.cs-stamp__text { font-size: 12px; font-weight: 700; letter-spacing: 0.07em; line-height: 1.34; text-transform: uppercase; }

/* The route — number cell, identity cell, explanation. The column rules are the
   cells' own right borders, so they run the full row height. */
.cs-step {
  display: grid;
  grid-template-columns: 108px 350px 1fr;
  border-bottom: 1px solid var(--sh-ink);
}
.cs-step__n {
  border-right: 1px solid var(--sh-ink);
  padding-top: 30px;
  text-align: center;
  font-family: var(--sh-font-display);
  font-size: 62px;
  line-height: 0.86;
  color: var(--sh-purple-display);
}
.cs-step__id {
  border-right: 1px solid var(--sh-ink);
  padding: 30px 30px 32px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 11px;
}
/* Canvas drew these at 9px; the 10px floor (CLAUDE.md) wins, same as the library labels. */
.cs-step__verb {
  border: 1px solid var(--sh-ink);
  font-family: var(--sh-font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
}
.cs-step__verb--find,
.cs-step__verb--capture { background: var(--sh-tint-jobs); }
.cs-step__verb--evaluate { background: var(--sh-tint-footnotes); }
.cs-step__verb--compare { background: #e5cde8; } /* deep-dives lilac — same value the series panels use */
.cs-step__verb--apply { background: var(--sh-tint-closed); }
.cs-step__verb--keep { background: var(--sh-tint-resources); }
.cs-step__name {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 38px;
  line-height: 1.02;
}
.cs-step__go { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.cs-step__cta {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-underline-offset: 3px;
}
/* Delight (18 Aug 2026): this page is built entirely out of doors to another domain — its own
   copy says "the tools live somewhere else, and they look it" — and the five links that do the
   handing over had no interactive state of any kind. The underline doubles, and the arrows
   ride the house device: `.sh-arrow--out` on the four that leave for
   careersuite.supporthuman.cx, plain `.sh-arrow` on step 01, which points at /jobs/ on this
   site. The distinction was already in the glyphs; now it is in the motion too. */
.cs-step__cta:hover,
.cs-step__cta:focus-visible { text-decoration-thickness: 2px; }
.cs-step__url { font-family: var(--sh-font-mono); font-size: 10px; color: var(--sh-grey-on-paper); }
.cs-step__copy { padding: 30px 34px 32px; display: flex; flex-direction: column; gap: 12px; }
.cs-step__body { font-size: 17px; line-height: 1.55; max-width: 58ch; }
.cs-step__note {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  line-height: 1.7;
  color: var(--sh-grey-on-paper);
  max-width: 83ch;
}

/* The two-site band (23 §2) — paper, portfolio-lilac code chip. */
.cs-elsewhere {
  padding: 30px var(--sh-gutter) 34px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 56px;
  align-items: center;
}
.cs-elsewhere__head { display: flex; flex-direction: column; gap: 10px; }
.cs-elsewhere__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.04;
  text-wrap: balance;
}
.cs-elsewhere__body { display: flex; flex-direction: column; gap: 11px; max-width: 60ch; }
.cs-elsewhere__body p { font-size: 17px; line-height: 1.55; }
.cs-elsewhere__code {
  font-family: var(--sh-font-mono);
  font-size: 14px;
  background: var(--sh-tint-portfolio);
  padding: 1px 5px;
}

/* The obligation-remover (23 §4) — leaf green ground. */
.cs-easy {
  background: var(--sh-tint-career-suite);
  border-bottom: 1px solid var(--sh-ink);
  padding: 40px var(--sh-gutter) 44px;
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 56px;
  align-items: center;
}
.cs-easy__head { display: flex; flex-direction: column; gap: 10px; }
.cs-easy__heading {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: 1.02;
  text-wrap: balance;
}
.cs-easy__body { display: flex; flex-direction: column; gap: 12px; max-width: 56ch; }
.cs-easy__body p { font-size: 17px; line-height: 1.55; }

/* ---- 390px (2b): panel becomes the stamp, steps stack with number + chip on one
   baseline row, CTA drops below the note. ---- */

@media (max-width: 900px) {
  .cs-hero { grid-template-columns: 1fr; gap: 16px; padding: 30px 18px 32px; }
  .cs-hero__title { font-size: 46px; line-height: 0.98; text-wrap: balance; }
  .cs-hero__sub { font-size: 16px; }
  .cs-hero__panel { display: none; }
  .cs-stamp { display: block; margin-top: 4px; }

  .cs-step {
    grid-template-columns: auto 1fr;
    gap: 10px 12px;
    padding: 18px;
    align-items: baseline;
  }
  .cs-step__id, .cs-step__copy { display: contents; }
  .cs-step__n {
    grid-row: 1;
    grid-column: 1;
    border-right: 0;
    padding-top: 0;
    text-align: left;
    font-size: 34px;
  }
  .cs-step__verb { grid-row: 1; grid-column: 2; justify-self: start; }
  .cs-step__name { grid-row: 2; grid-column: 1 / -1; font-size: 30px; }
  .cs-step__body { grid-row: 3; grid-column: 1 / -1; font-size: 16px; line-height: 1.5; }
  .cs-step__note { grid-row: 4; grid-column: 1 / -1; line-height: 1.65; }
  .cs-step__go { grid-row: 5; grid-column: 1 / -1; margin-top: 0; }

  .cs-elsewhere { grid-template-columns: 1fr; gap: 11px; padding: 22px 18px 24px; }
  .cs-elsewhere__heading { font-size: 28px; }
  .cs-elsewhere__body p { font-size: 15px; line-height: 1.5; }
  .cs-elsewhere__code { font-size: 13px; padding: 1px 4px; }

  .cs-easy { grid-template-columns: 1fr; gap: 12px; padding: 24px 18px 26px; }
  .cs-easy__heading { font-size: 32px; }
  .cs-easy__body p { font-size: 15px; line-height: 1.5; }
}

/* ==========================================================================
   The podcast on issue pages (partials/post-issue.hbs — 15 §1–2, 20 §1;
   Podcast canvas 19a/19b). The player is the body's kg-audio-card, lifted
   into the listen band by post.js; the card is restyled to the system here.
   Nothing anywhere says "no audio available".
   ========================================================================== */

/* The 19a band — between FILED UNDER and the article, full width. */
.post__listen {
  border-bottom: 1px solid var(--sh-ink);
  padding: 20px var(--sh-gutter) 22px;
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 40px;
  align-items: center;
}
.post__listen[hidden] { display: none; }
.post__listen-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.post__listen-heading {
  font-family: var(--sh-font-display);
  font-size: 26px;
  line-height: 1.05;
}
.post__listen-byline {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-tint);
}
.post__listen-slot { margin-top: 7px; }
.post__listen-aside {
  border-left: 1px solid var(--sh-hairline);
  padding-left: 30px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.post__listen-note { font-size: 14px; line-height: 1.5; }
.post__listen-subscribe {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-ink);
  text-underline-offset: 3px;
  align-self: flex-start;
}

/* Ghost's audio card, restyled to the system wherever it renders: square, ink
   border, mono facts, the small-text purple on the play control (15 §2 — the
   display purple fails contrast against the white glyph). Inside the band the
   card's own title is hidden — the serif heading does that job. */
/* ghost_head injects Ghost's card sheet AFTER main.css, so these carry the extra
   `main` ancestor to win equal-specificity ties against it. */
main .kg-audio-card {
  border: 1px solid var(--sh-ink);
  border-radius: 0;
  box-shadow: none;
  background: var(--sh-paper);
}
main .kg-audio-card .kg-audio-thumbnail { border-radius: 0; }
/* The placeholder is Ghost's accent-colored music-note block — 19a's player has no
   thumbnail at all, so the placeholder goes; a real uploaded thumbnail would stay. */
main .kg-audio-card .kg-audio-thumbnail.placeholder { display: none; }
main .kg-audio-card .kg-audio-title {
  font-family: var(--sh-font-body);
  font-size: 15px;
  font-weight: 700;
}
main .post__listen-slot .kg-audio-title { display: none; }
main .kg-audio-card .kg-audio-current-time,
main .kg-audio-card .kg-audio-time,
main .kg-audio-card .kg-audio-duration {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  color: var(--sh-grey-on-tint);
}
main .kg-audio-card .kg-audio-playback-rate {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  font-weight: 400;
  border: 1px solid var(--sh-ink);
  border-radius: 0;
  color: var(--sh-ink);
}
main .kg-audio-card .kg-audio-play-icon svg,
main .kg-audio-card .kg-audio-pause-icon svg { fill: var(--sh-link); }
main .kg-audio-card .kg-audio-seek-slider,
main .kg-audio-card .kg-audio-volume-slider { accent-color: var(--sh-ink); }

/* The 19b archive chip — existing chip vocabulary, no new pattern. Joins the
   issue-row meta line only when the internal #has-audio tag is present. */
.issue-row__listen {
  border: 1px solid var(--sh-ink);
  padding: 1px 8px 2px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.issue-row__listen [aria-hidden] { font-size: 8px; }

@media (max-width: 900px) {
  .post__listen { grid-template-columns: 1fr; gap: 14px; padding: 18px; }
  .post__listen-aside { border-left: 0; border-top: 1px solid var(--sh-hairline); padding-left: 0; padding-top: 12px; }
}

/* --------------------------------------------------------------------------
   Print — the site-wide chrome. The reading page's own print rules live in
   post.css.

   This existed nowhere until now, which mattered more than it sounds: the
   footnotes record states that the foot-of-page NOTES list "is what email, RSS
   and print get", and print was quietly the one of those three that got
   nothing. A Bad Job Bingo issue is a document somebody prints during a job
   search; it should come off the printer looking like the broadsheet it is.

   Paper is already the page color, so nothing here inverts anything. What
   goes is everything that only works on a screen: navigation you cannot
   follow, a subscribe form you cannot type into, a thread you cannot reply to.
   The support ask goes too — an ask nobody can act on is just noise on a page
   somebody paid ink for, and the sign-off inside the article still carries the
   no-obligation line.
   -------------------------------------------------------------------------- */

@media print {
  /* Let the browser paint the flat color blocks and tints; without this the
     verdict grounds and section strips print as white and the ratings lose the
     color that carries their meaning. */
  * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  body { background: #fff; }

  .sh-skip-link,
  .site-header,
  .site-footer,
  .funding-band,
  .search-bar,
  .shelf,
  .filter-shelf { display: none !important; }

  /* Widows and orphans are the whole reason a printed column reads well. */
  p, li, blockquote { orphans: 3; widows: 3; }
  h1, h2, h3, h4 { break-after: avoid-page; }
  figure, blockquote, table { break-inside: avoid; }
}

/* ==========================================================================
   /how-to-publish/ — the authoring guide as an unlisted page (how-to-publish.hbs).
   Design: handoff 5/06-authoring-guide canvas, turn 1 (1a desktop / 1b 390px).
   Composed from page.hbs vocabulary with two removals: no support block, no section
   strip — a black BACK OF HOUSE bar instead, and a minimal black footer band in place
   of the site footer. Specimen boxes reproduce body devices at reduced scale; their
   decorative glyphs are specimen content, aria-hidden in markup.
   ========================================================================== */

.htp-bar {
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 9px 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* 11px on ink: --sh-grey-on-ink is the small-text floor on the near-black ground. */
.htp-bar__detail { color: var(--sh-grey-on-ink); letter-spacing: 0.08em; }

.htp-hero {
  padding: 44px 44px 34px;
  border-bottom: 1px solid var(--sh-ink);
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 56px;
  align-items: end;
}
.htp-hero__title {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 76px;
  line-height: 0.96;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--sh-purple-header);
  text-wrap: balance;
}
.htp-hero__side { display: flex; flex-direction: column; gap: 10px; }
.htp-hero__dek { font-family: var(--sh-font-body); font-size: 17px; line-height: 1.55; margin: 0; }
.htp-hero__updated {
  font-family: var(--sh-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
}

/* The mobile contents chips (frame 1b). Desktop has the rail instead. */
.htp-jump {
  display: none;
  border-bottom: 1px solid var(--sh-ink);
  padding: 16px 18px;
  flex-direction: column;
  gap: 9px;
}
.htp-jump__label { font-family: var(--sh-font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; }
.htp-jump__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.htp-jump__chip {
  font-family: var(--sh-font-body);
  font-size: 13px;
  line-height: 1.3;
  color: var(--sh-ink);
  text-decoration: none;
  border: 1px solid var(--sh-ink);
  padding: 6px 9px;
}
.htp-jump__chip:hover, .htp-jump__chip:focus-visible { background: var(--sh-ink); color: var(--sh-paper); }

.htp-layout {
  padding: 40px 44px 44px;
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 64px;
  align-items: start;
}
.htp-body { display: flex; flex-direction: column; gap: 22px; max-width: 68ch; min-width: 0; }

.htp-lede { font-family: var(--sh-font-body); font-size: 18px; line-height: 1.62; margin: 0; }
.htp-note { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.55; margin: 0; color: var(--sh-grey-on-tint); }

.htp-h2 {
  font-family: var(--sh-font-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.06;
  margin: 6px 0 0;
  border-top: 1px solid var(--sh-ink);
  padding-top: 18px;
  scroll-margin-top: 90px;
}

/* The eight-things table. */
.htp-types {
  display: grid;
  grid-template-columns: 1.1fr 1fr 1fr;
  font-family: var(--sh-font-body);
  font-size: 14px;
  border-top: 1px solid var(--sh-ink);
}
.htp-types__head {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sh-grey-on-paper);
  padding: 8px 12px 8px 0;
  border-bottom: 1px solid var(--sh-ink);
}
.htp-types__cell { padding: 11px 12px 11px 0; border-bottom: 1px solid #e0ddd8; line-height: 1.4; }
.htp-types__cell--dim { color: var(--sh-grey-on-tint); }

/* Requirement cards. */
.htp-card { border: 1px solid var(--sh-ink); display: flex; flex-direction: column; }
.htp-card__head {
  border-bottom: 1px solid var(--sh-ink);
  padding: 11px 16px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.htp-card__title { font-family: var(--sh-font-body); font-weight: 700; font-size: 17px; }
.htp-card__note { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
.htp-card__rows { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 9px; }
.htp-kv { display: grid; grid-template-columns: 92px 1fr; gap: 14px; align-items: baseline; font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; }
.htp-kv__k { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sh-grey-on-paper); text-align: right; }

/* The per-type quick sheets: the card head takes that type's own documented tint
   (series tints for the newsletter, the section tints for jobs/resources) so the
   sheet reads as belonging to its surface. Ink on tint throughout — no new colors. */
.htp-card--roundup .htp-card__head { background: #cfe1ff; }
.htp-card--bingo .htp-card__head { background: #fcbcd2; }
.htp-card--deep .htp-card__head { background: #e5cde8; }
.htp-card--jobs .htp-card__head { background: var(--sh-tint-jobs); }
.htp-card--resources .htp-card__head { background: var(--sh-tint-resources); }
/* 10px mono on a tint: the on-tint floor, not the paper grey. */
.htp-card--roundup .htp-card__note, .htp-card--bingo .htp-card__note,
.htp-card--deep .htp-card__note, .htp-card--jobs .htp-card__note,
.htp-card--resources .htp-card__note { color: var(--sh-grey-on-tint); }

/* Theirs / yours. */
.htp-voices { border: 1px solid var(--sh-ink); display: grid; grid-template-columns: 1fr 1fr; }
.htp-voices__col { padding: 16px 18px; display: flex; flex-direction: column; gap: 8px; }
.htp-voices__col--theirs { border-right: 1px solid var(--sh-ink); }
.htp-voices__theirs { font-family: var(--sh-font-display); font-style: italic; font-size: 20px; line-height: 1.36; }
.htp-voices__yours { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.5; }

/* Peach callout — page.hbs's callout tint. */
.htp-callout { border: 1px solid var(--sh-ink); background: #fff6ef; padding: 18px 20px; display: flex; flex-direction: column; gap: 7px; }
.htp-callout__label { font-family: var(--sh-font-body); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.htp-callout__body { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.55; }

/* The not-built warning — same anatomy, the documented grey tint. */
.htp-warn { border: 1px solid var(--sh-ink); background: #e6e4e2; padding: 18px 20px; display: flex; flex-direction: column; gap: 7px; }
.htp-warn__label { font-family: var(--sh-font-body); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.htp-warn__body { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.55; }

/* A body device: name, one-line role, prose, specimen, "you type" row, snippet. */
.htp-device { border-top: 1px solid var(--sh-ink); padding-top: 14px; display: flex; flex-direction: column; gap: 9px; }
.htp-device__head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.htp-device__name { font-family: var(--sh-font-body); font-weight: 700; font-size: 18px; }
.htp-device__tag { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
/* The mechanism chip: how a device is authored. Grey = an HTML card (saved as a snippet);
   green = the editor's own feature, or typed directly — the theme styles it. Green pairs
   the documented pale ground #c9ead6 with its ≤15px value #356048 (the 01 ramp row). */
.htp-device__how {
  font-family: var(--sh-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: #e6e4e2;
  border: 1px solid var(--sh-ink);
  padding: 3px 6px;
  white-space: nowrap;
}
.htp-device__how--plain { background: #c9ead6; color: #356048; }
.htp-device__body { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.55; }

.htp-coral { color: var(--sh-coral); }

.htp-spec { border: 1px solid var(--sh-hairline); background: var(--sh-paper); padding: 16px 18px; }
.htp-spec--stack { display: flex; flex-direction: column; gap: 12px; }
.htp-spec__label { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
.htp-spec__bodytext { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.6; margin: 0; }

.htp-spec--margin { display: grid; grid-template-columns: 1fr 168px; gap: 22px; align-items: start; }
.htp-spec__sup { font-family: var(--sh-font-mono); font-size: 10px; color: var(--sh-link); font-weight: 700; }
.htp-spec__marginnote { display: flex; gap: 8px; align-items: flex-start; border-left: 1px solid var(--sh-hairline); padding-left: 14px; font-family: var(--sh-font-body); font-size: 13px; line-height: 1.45; color: var(--sh-grey-on-tint); }
.htp-spec__marginnum { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; color: var(--sh-link); flex: none; }

.htp-spec__quote { margin: 0 0 0 22px; border-left: 2px solid #6ea8f5; padding-left: 14px; display: flex; flex-direction: column; gap: 8px; }
.htp-spec__quote p { font-family: var(--sh-font-display); font-style: italic; font-size: 20px; line-height: 1.34; margin: 0; }
.htp-spec__attr { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sh-grey-on-paper); }

.htp-spec__pull { font-family: var(--sh-font-body); font-size: 25px; font-weight: 700; line-height: 1.24; letter-spacing: -0.01em; margin: 0; }

/* One-pass body mark, reusing the house paint tokens. */
.htp-spec__mark {
  background-image: var(--sh-mark-one-pass);
  background-repeat: no-repeat;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  padding: 0.02em 0.16em 0.05em;
  margin: 0 -0.12em;
}

.htp-spec__jobquote { padding-left: 16px; border-left: 3px solid #f7cac3; }
.htp-spec__jobquote p { font-family: var(--sh-font-display); font-style: italic; font-size: 20px; line-height: 1.35; margin: 0; }

.htp-spec__standing { border-top: 1px solid var(--sh-hairline); border-bottom: 1px solid var(--sh-hairline); padding: 13px 0; display: grid; grid-template-columns: 88px 1fr; gap: 18px; align-items: start; }
.htp-spec__standing-label { font-family: var(--sh-font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.12em; line-height: 1.5; text-transform: uppercase; color: var(--sh-grey-on-tint); }
.htp-spec__standing-body { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; margin: 0; color: var(--sh-grey-on-tint); }

.htp-spec__dept { display: flex; align-items: baseline; gap: 14px; }
.htp-spec__dept-num { font-family: var(--sh-font-display); font-size: 54px; line-height: 0.9; color: #d9b6e0; }
.htp-spec__dept-name { font-family: var(--sh-font-display); font-size: 30px; line-height: 1.05; }
.htp-spec__story { font-family: var(--sh-font-mono); font-size: 21px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.2; margin-top: 14px; }

.htp-spec__facade { border: 1px solid var(--sh-ink); max-width: 300px; }
.htp-spec__facade-head { border-bottom: 1px solid var(--sh-ink); padding: 9px 12px; display: flex; justify-content: space-between; gap: 10px; font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.1em; }
.htp-spec__facade-head span:first-child { font-weight: 700; text-transform: uppercase; }
.htp-spec__facade-head span:last-child { color: var(--sh-grey-on-tint); letter-spacing: 0.06em; }
.htp-spec__facade-body { padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; }
.htp-spec__facade-cta { font-family: var(--sh-font-body); font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.htp-spec__facade-note { font-family: var(--sh-font-body); font-size: 13px; line-height: 1.5; color: var(--sh-grey-on-tint); text-wrap: pretty; }

.htp-spec__bookmark { border-top: 1px solid var(--sh-ink); border-bottom: 1px solid var(--sh-ink); padding: 14px 0; display: flex; flex-direction: column; gap: 6px; }
.htp-spec__bookmark-title { font-family: var(--sh-font-display); font-style: italic; font-size: 21px; line-height: 1.3; }
.htp-spec__bookmark-desc { font-family: var(--sh-font-body); font-size: 14px; line-height: 1.5; color: var(--sh-grey-on-tint); }
.htp-spec__bookmark-meta { font-family: var(--sh-font-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--sh-grey-on-paper); }

.htp-type { display: grid; grid-template-columns: 78px 1fr; gap: 14px; align-items: baseline; padding-top: 2px; }
.htp-type__k { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sh-grey-on-paper); text-align: right; }
.htp-type__v { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); }

.htp-pre {
  margin: 4px 0 0;
  border: 1px solid var(--sh-ink);
  background: #f3f1ee;
  padding: 14px 16px;
  font-family: var(--sh-font-mono);
  font-size: 12px;
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre-wrap;
}

/* Banned cards. */
.htp-banned { border: 1px solid var(--sh-ink); padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 12px; }
.htp-banned__head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.htp-banned__title { font-family: var(--sh-font-body); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; }
.htp-banned__note { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
.htp-banned__row { display: grid; grid-template-columns: 172px 1fr; gap: 16px; align-items: baseline; border-top: 1px solid #e0ddd8; padding-top: 9px; }
.htp-banned__card { font-family: var(--sh-font-body); font-size: 15px; font-weight: 700; line-height: 1.4; }
.htp-banned__why { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); }

/* Never write. */
.htp-nevers { display: flex; flex-direction: column; gap: 12px; }
.htp-never { padding-left: 16px; border-left: 3px solid #94493a; display: flex; flex-direction: column; gap: 3px; }
.htp-never__rule { font-family: var(--sh-font-body); font-size: 16px; font-weight: 700; line-height: 1.4; }
.htp-never__why { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); }

/* The two money lines. */
.htp-money { margin: 0; padding: 0 0 0 20px; border-left: 3px solid #e5cde8; }
.htp-money p { font-family: var(--sh-font-display); font-size: 30px; line-height: 1.2; margin: 0; }
.htp-money--close p { font-style: italic; font-size: 23px; line-height: 1.34; }

/* The handled / breaks split. */
.htp-split { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.htp-split__col { display: flex; flex-direction: column; gap: 12px; }
.htp-split__head { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; border-bottom: 1px solid var(--sh-ink); padding-bottom: 8px; }
.htp-split__head--green { color: #356048; }
.htp-split__head--red { color: #94493a; }
.htp-split__item { padding-left: 14px; font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; }
.htp-split__item--green { border-left: 3px solid #356048; }
.htp-split__item--red { border-left: 3px solid #94493a; }

/* Tools. */
.htp-tool { display: flex; flex-direction: column; gap: 7px; border-top: 1px solid var(--sh-hairline); padding-top: 14px; }
.htp-tool__head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.htp-tool__name { font-family: var(--sh-font-body); font-weight: 700; font-size: 17px; }
.htp-tool__tag { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--sh-grey-on-paper); }
.htp-tool__body { font-family: var(--sh-font-body); font-size: 16px; line-height: 1.55; }
.htp-tool__watch { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; color: var(--sh-grey-on-tint); padding-left: 14px; border-left: 3px solid #94493a; }

/* Checklist. */
.htp-check { border: 1px solid var(--sh-ink); padding: 20px 22px 22px; display: flex; flex-direction: column; gap: 11px; }
.htp-check__row { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: baseline; border-bottom: 1px solid #e0ddd8; padding-bottom: 10px; font-family: var(--sh-font-body); font-size: 16px; line-height: 1.45; }
.htp-check__box { width: 13px; height: 13px; border: 1px solid var(--sh-ink); display: block; }
.htp-check__foot { font-family: var(--sh-font-mono); font-size: 10px; line-height: 1.6; color: var(--sh-grey-on-paper); }

/* Settled rows — the PENDING device with its chips come off. */
.htp-settled { display: flex; flex-direction: column; gap: 10px; }
.htp-settled__row { display: grid; grid-template-columns: 74px 1fr; gap: 14px; align-items: baseline; border-bottom: 1px solid #e0ddd8; padding-bottom: 10px; }
.htp-settled__chip { font-family: var(--sh-font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; background: #e6e4e2; border: 1px solid var(--sh-ink); padding: 3px 6px; text-align: center; }
.htp-settled__body { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; }

/* The desktop rail. */
.htp-rail { display: flex; flex-direction: column; gap: 20px; position: sticky; top: 24px; }
.htp-toc { border: 1px solid var(--sh-ink); padding: 20px 20px 22px; display: flex; flex-direction: column; gap: 0; }
.htp-toc__label { font-family: var(--sh-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; padding-bottom: 11px; }
.htp-toc__link { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.4; color: var(--sh-ink); text-decoration: none; border-top: 1px solid var(--sh-hairline); padding: 9px 0; }
.htp-toc__link:hover, .htp-toc__link:focus-visible { color: var(--sh-link); }
.htp-other { border: 1px solid var(--sh-ink); background: #f3f1ee; padding: 18px 20px; display: flex; flex-direction: column; gap: 8px; }
.htp-other__label { font-family: var(--sh-font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; }
.htp-other__body { font-family: var(--sh-font-body); font-size: 15px; line-height: 1.5; }
.htp-other__note { font-family: var(--sh-font-mono); font-size: 10px; line-height: 1.6; color: var(--sh-grey-on-tint); }

/* Back-of-house footer band. */
.htp-foot {
  background: var(--sh-ink);
  color: var(--sh-paper);
  padding: 22px 44px 24px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  flex-wrap: wrap;
}
.htp-foot__wordmark { width: 192px; height: 18px; display: block; flex: none; }
.htp-foot__note { font-family: var(--sh-font-mono); font-size: 11px; color: var(--sh-grey-on-ink); }

/* code spans inside the guide keep the house mono at a readable size. */
.htp code { font-family: var(--sh-font-mono); font-size: 0.85em; }

/* 390px (frame 1b): single column, chip contents, tighter hero. */
@media (max-width: 900px) {
  .htp-bar { padding: 8px 18px; }
  /* Frame 1b draws the bar with the name alone. */
  .htp-bar__detail { display: none; }
  .htp-hero { grid-template-columns: 1fr; gap: 11px; padding: 24px 18px 20px; align-items: start; }
  .htp-hero__title { font-size: 44px; line-height: 0.98; }
  .htp-hero__dek { font-size: 16px; }
  .htp-jump { display: flex; }
  .htp-layout { grid-template-columns: 1fr; gap: 0; padding: 20px 18px 24px; }
  .htp-rail { display: none; }
  .htp-h2 { font-size: 27px; }
  .htp-types { grid-template-columns: 1fr; }
  .htp-types__head { display: none; }
  .htp-types__cell { border-bottom: 0; padding: 2px 0; }
  .htp-types__cell--dim { color: var(--sh-grey-on-tint); }
  .htp-types__cell:nth-child(3n+1) { border-top: 1px solid #e0ddd8; padding-top: 10px; margin-top: 8px; }
  .htp-types__cell:nth-child(3n) { padding-bottom: 10px; }
  .htp-kv { grid-template-columns: 1fr; gap: 2px; }
  .htp-kv__k { text-align: left; }
  .htp-voices { grid-template-columns: 1fr; }
  .htp-voices__col--theirs { border-right: 0; border-bottom: 1px solid var(--sh-ink); }
  .htp-spec--margin { grid-template-columns: 1fr; gap: 12px; }
  .htp-split { grid-template-columns: 1fr; }
  .htp-banned__row { grid-template-columns: 1fr; gap: 3px; }
  .htp-type { grid-template-columns: 1fr; gap: 3px; }
  .htp-type__k { text-align: left; }
  .htp-settled__row { grid-template-columns: 1fr; gap: 6px; }
  .htp-settled__chip { justify-self: start; }
  .htp-foot { padding: 18px; align-items: center; }
  .htp-foot__wordmark { width: 170.66px; height: 16px; }
}
