/* Just Mercy · editorial furniture
   Breadcrumb, Sources & further reading, Subscribe row — the pieces that sit
   around an article rather than inside it.

   Split out of the single components.css so concurrent work on different
   areas cannot collide in one file, and so a page can eventually load only
   the CSS its elements need. Tokens come from tokens.css; no literal brand
   hex belongs in here (the page-quality gate's D2 criterion enforces it).

   Two shared things are used deliberately rather than restated:
     .jm-visually-hidden   defined in donation.css, already used by JM · Field.
                           It belongs in core.css; leaving it where it is beats
                           defining a second copy that can drift.
     .jm-button--primary   defined in core.css. The subscribe button IS the
                           primary button, so it inherits every state the Figma
                           "Spec — Button states & motion" panel lays down
                           instead of a near-copy of them living here.
   Selectors that override either are written two classes deep so they win
   whatever order inc/elements.php ends up loading the files in.

   Sizes are the Figma pixel value over 16 (the root is exactly 16px on the 1440
   board), with the original px in the comment beside it. The mobile blocks are
   the `· Mobile` component variants, drawn on the 390 board. */


/* =========================================================================
   JM Breadcrumb — Figma "Molecules / Breadcrumb" (437:630)
   and "Molecules / Breadcrumb · Mobile" (637:4587)

   Desktop: one row, gap 8, Label/S 13, ancestors Purple/400 Regular and the
   current page Purple/500 Medium.
   Mobile: same row, wrapping, row gap 4 and column gap 8.
   ========================================================================= */

.jm-breadcrumb {
  --jm-breadcrumb-ring: var(--purple-500);
  --jm-breadcrumb-crumb: var(--purple-400);
  --jm-breadcrumb-current: var(--purple-500);
}

/* Figma draws the desktop row as no-wrap at 214 wide. Wrapping is allowed here
   anyway: it changes nothing while the trail fits — which it does at every width
   the board draws — and stops a long page title pushing the row out of its
   container instead. The 4px row gap is the mobile variant's, applied at both
   sizes because it only ever shows once the row has actually wrapped. */
.jm-breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 0.5rem;                  /* 8 */
  row-gap: 0.25rem;                    /* 4 — the mobile variant's row gap */
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The separator lives inside its crumb's <li> so the two never split across a
   wrapped line, and so the "/" is not a stray list item of its own. The nested
   gap is the same 8, which reproduces Figma's even spacing exactly: every text
   node in the drawn row sits 8 from its neighbour. */
.jm-breadcrumb__item {
  display: flex;
  align-items: center;
  column-gap: 0.5rem;                  /* 8 */
}

.jm-breadcrumb__crumb,
.jm-breadcrumb__sep {
  font: 400 var(--text-label-s)/1.3 var(--font-sans);  /* Label/S 13; Figma measures the row at 17 tall */
  color: var(--jm-breadcrumb-crumb);
}

.jm-breadcrumb__crumb--current {
  font-weight: 500;                    /* Host Grotesk Medium, as drawn */
  color: var(--jm-breadcrumb-current);
}

.jm-breadcrumb__link {
  color: var(--jm-breadcrumb-crumb);
  text-decoration: none;

  /* WCAG 2.2 target size: breadcrumb crumbs are links in a line of text, which
     the "inline" exception to 2.5.8 covers, and the drawn row is only 17 tall —
     giving each crumb a 44px box would rebuild the component. The padding grows
     the hit area to 33 and the equal negative margin keeps the row exactly as
     drawn. It is deliberately smaller on mobile: see the media query. */
  padding-block: 0.5rem;               /* 8 */
  margin-block: -0.5rem;
}

.jm-breadcrumb__link:hover,
.jm-breadcrumb__link:focus-visible {
  color: var(--jm-breadcrumb-current);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

/* The site-wide focus rule, stated on all four of the board's spec panels. */
.jm-breadcrumb__link:focus-visible {
  outline: 3px solid var(--jm-breadcrumb-ring);
  outline-offset: 2px;
}

/* JUDGEMENT: Figma never draws a breadcrumb on a dark band, so these two
   mappings are ours. Purple/400 disappears on Purple/500 or darker, so the trail
   steps up to Purple/100 and the current page to Stone/100, and the focus ring
   turns Gold — the same swap the button spec makes for dark surfaces. */
.jm-breadcrumb--dark {
  --jm-breadcrumb-crumb: var(--purple-100);
  --jm-breadcrumb-current: var(--stone-100);
  --jm-breadcrumb-ring: var(--gold-500);
}


/* =========================================================================
   JM Sources — Figma "Molecules / Sources & further reading" (514:2966)

   1px Purple/500 rule above, 32 of padding under it, column gap 12.
   Heading Caption/M 15 Medium in capitals; source lines Body/S Medium 16 at 1.2.
   ========================================================================= */

.jm-sources {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;                        /* 12 */
  padding-top: 2rem;                   /* 32 */
  border-top: 1px solid var(--purple-500);

  /*
   * Fill the column. Bricks blocks are `align-items: flex-start`, so this shrank
   * to its widest source line and the rule above it stopped wherever the longest
   * title happened to end instead of spanning the measure.
   *
   * FOURTH component to need this, after .jm-field, .jm-subscribe and
   * .jm-faq-row. Any component that should fill its column has to say so.
   */
  align-self: stretch;
}

.jm-sources--no-rule {
  padding-top: 0;
  border-top: 0;
}

.jm-sources__heading {
  margin: 0;
  font: 500 var(--text-caption-m)/1.2 var(--font-sans);  /* Caption/M 15 Medium */
  /* Figma records "letterSpacing: 2.5" on Caption/M, which is 2.5% — the node
     itself resolves it to 0.375px at 15px, i.e. 0.025em. (tokens.css's
     .text-style-caption-m reads the 2.5 as pixels and is 6.7x too loose; the
     callout kicker in content.css already has it right.) */
  letter-spacing: 0.025em;
  text-transform: uppercase;
  color: var(--purple-500);
}

.jm-sources__list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;                        /* 12 — the same step as the outer stack */
  margin: 0;
  padding: 0;
  list-style: none;
}

.jm-sources__item {
  font: 500 var(--text-body)/1.2 var(--font-sans);      /* Body/S Medium 16 */
  color: var(--purple-500);
}

/* No underline at rest, exactly as drawn: the arrow is the affordance, and it is
   a non-colour one, so a linked line is still distinguishable from the unlinked
   line the Figma case study includes. Hover and focus add the underline. */
.jm-sources__link {
  color: inherit;
  text-decoration: none;
}

.jm-sources__link:hover,
.jm-sources__link:focus-visible {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

.jm-sources__link:focus-visible {
  outline: 3px solid var(--purple-500);
  outline-offset: 2px;
}

/* <cite> is the right element for the title of a work, and this undoes the
   browser's italic so the line reads as the Figma draws it. */
.jm-sources__title {
  font-style: normal;
}

.jm-sources__arrow {
  display: inline-flex;
  align-items: center;
  transition: transform var(--motion-fast) var(--motion-ease-out);
}
.jm-sources__link:hover .jm-sources__arrow { transform: translateX(0.25em); }

@media (prefers-reduced-motion: reduce) {
  .jm-sources__arrow { transition: none; }
  .jm-sources__link:hover .jm-sources__arrow { transform: none; }
}

/* ---- Collapsed sources (Phil, 2026-09-03) -------------------------------
   The facts page cites its evidence without ending on a wall of references:
   one line the reader opens. The toggle keeps the underlined purple wording
   the board drew, and swaps the board's right-pointing arrow for the site's
   caret, because an arrow that points away from a panel opening downwards
   tells the reader the wrong thing. */

.jm-sources--collapsible {
  padding-top: 0;
  border-top: 0;
}

/* Hug the words, do not span the measure: the summary IS the click target and
   the focus ring, and a full-width one on a 1280 container reads as a band
   rather than a link. The panel below still gets the full width. */
.jm-sources__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;                         /* 8 */
  cursor: pointer;
  list-style: none;
  color: var(--purple-500);
  font: 500 var(--text-body)/1.2 var(--font-sans);
}
/* Safari paints the triangle without this, even at inline-flex. */
.jm-sources__toggle::-webkit-details-marker { display: none; }
.jm-sources__toggle::marker { content: ''; }

.jm-sources__toggle-label {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

.jm-sources__toggle-caret {
  display: inline-flex;
  align-items: center;
  width: 1rem;                         /* 16 */
  height: 1rem;
  transition: transform var(--motion-fast) var(--motion-ease-out);
}
.jm-sources__disclosure[open] .jm-sources__toggle-caret { transform: rotate(180deg); }

.jm-sources__toggle:focus-visible {
  outline: 3px solid var(--purple-500);
  outline-offset: 2px;
}

.jm-sources__panel {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;                        /* 12 — the element's own step */
  padding-top: 1rem;                   /* 16 — clear of the toggle's underline */
}

/* TRAP 8 AGAIN, and it cost a round here too: an explicit `display` on a
   <details>'s own content beats the way the browser hides it while closed, so
   the panel above rendered its six citations under a shut toggle (measured 191px
   tall with [open] absent). The collapse panels hit the same thing. Say it
   outright rather than relying on the UA — and never rely on how a particular
   browser hides that content, since Chrome now uses ::details-content. */
.jm-sources__disclosure:not([open]) .jm-sources__panel { display: none; }

/* The panel arrives rather than appearing. No height animation: a <details>
   cannot animate its own height without a script, and the fade carries it. */
.jm-sources__disclosure[open] .jm-sources__panel {
  animation: jm-sources-open var(--motion-base) var(--motion-ease-out) both;
}
@keyframes jm-sources-open {
  from { opacity: 0; transform: translateY(-0.375rem); }
}

@media (prefers-reduced-motion: reduce) {
  .jm-sources__toggle-caret { transition: none; }
  .jm-sources__disclosure[open] .jm-sources__panel { animation: none; }
}


/* =========================================================================
   JM Subscribe row — Figma "Molecules / Subscribe row" (440:625)
   and "Molecules / Subscribe row · Mobile" (638:4586)

   Desktop: row, gap 16. Field 360 x 55 on Stone/100 with 24 side padding.
   Button 55 tall on Gold/500 with 24 side padding.
   Mobile: column, gap 12, both full width and 52 tall, 16 side padding, 15 type.

   Built to the two spec panels that govern a form and a button — see the element
   file header for both, quoted in full.
   ========================================================================= */

.jm-subscribe {
  --jm-subscribe-ring: var(--purple-500);
  --jm-subscribe-label: var(--purple-500);
  --jm-subscribe-error: var(--feedback-error);

  display: flex;
  flex-wrap: wrap;                     /* so the error message can take its own line */
  align-items: flex-end;               /* Figma is items-start, and with the label
                                          hidden both children are 55 tall so the
                                          two are identical. End-aligned keeps the
                                          field and the button on one baseline once
                                          a visible label sits above the field. */
  column-gap: 1rem;                    /* 16 */
  row-gap: 0.5rem;                     /* 8 — the field-to-message step, as JM · Field */

  /*
   * Never narrower than the drawn control, but free to shrink on a small screen.
   *
   * The board's row is 497: a 360 field, a 16 gap and a 121 button (430:605).
   * This sits as a flex ITEM inside a row-direction block, so it was sizing to
   * content and coming out 377.8 wide — which pushed the Subscribe button onto a
   * second line under the input on desktop, and left it 201px inside a 342px
   * column at 390. `align-self: stretch` is the wrong tool here: the parent is a
   * row, so align-self governs height, not width.
   *
   * `min()` gives the floor where there is room and yields to the column where
   * there is not, so the wrap is the mobile behaviour rather than a bug.
   */
  min-width: min(100%, 31.0625rem);    /* 497 */
}

.jm-subscribe__field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;                         /* 8 — the JM · Field label gap */
  flex: 0 1 22.5rem;                   /* 360 */
  min-width: 0;                        /* so it can shrink instead of overflowing */
}

.jm-subscribe__label {
  font: 500 var(--text-body)/1.2 var(--font-sans);      /* 16 Medium, as JM · Field */
  color: var(--jm-subscribe-label);
}

.jm-subscribe__input {
  width: 100%;
  min-height: 3.4375rem;               /* 55 */
  padding: 0.75rem 1.5rem;             /* 24 sides; the vertical padding keeps the 55 */
  border: 1px solid transparent;       /* reserved so no state shifts the layout */
  border-radius: 0;
  background-color: var(--stone-100);
  color: var(--purple-700);
  font: 400 var(--text-body)/1.4 var(--font-sans);      /* Body/S 16 at 1.4 */
  transition: border-color var(--motion-fast) var(--motion-ease-out);              /* the forms spec's 150ms */
  appearance: none;
}

/* "Placeholders are examples, not labels" — so it is styled as the quieter of
   the two. opacity:1 stops Firefox fading it further and dropping the contrast. */
.jm-subscribe__input::placeholder {
  color: var(--purple-400);
  opacity: 1;
}

.jm-subscribe__input:hover { border-color: var(--purple-400); }

.jm-subscribe__input:focus-visible,
.jm-subscribe__input:focus {
  outline: 3px solid var(--jm-subscribe-ring);
  outline-offset: 2px;
  border-color: transparent;
}

.jm-subscribe__input[aria-invalid='true'] { border: 2px solid var(--jm-subscribe-error); }

/* Never colour alone: the message is the signal, the border only supports it.
   Empty and hidden until Phase 3b's validator writes into it. */
.jm-subscribe__error {
  flex: 0 0 100%;                      /* forces the wrap, so the message sits under
                                          the row rather than inside the field */
  margin: 0;
  font: 500 var(--text-label-s)/1.3 var(--font-sans);   /* 13 */
  color: var(--jm-subscribe-error);
}
.jm-subscribe__error[hidden] { display: none; }

/* The same region carries the success line ("check your inbox"): the ground
   decides the ink. On the dark Stay informed band that is gold, on light the
   brand purple. */
.jm-subscribe__error.is-ok { color: var(--purple-500); }
.jm-subscribe--dark .jm-subscribe__error.is-ok { color: var(--gold-500); }

/* Two classes deep so it wins over core.css's .jm-button regardless of the order
   inc/elements.php loads the two files in. Only the height and the side padding
   differ from the primary button — every state comes from core.css. */
.jm-subscribe .jm-subscribe__button {
  flex: 0 0 auto;
  min-height: 3.4375rem;               /* 55 */
  padding-inline: 1.5rem;              /* 24 */
}

/* On dark: the "Stay informed" band in Figma sits on a dark purple, and a
   Purple/500 ring is invisible there. The button spec's own answer is Gold on
   dark, so both rings switch and the label goes Stone/100.
   JUDGEMENT: the error colour follows. feedback/error (#947306) is a dark gold
   that fails against a dark band, so the message steps up to Gold/400, which is
   the nearest token that carries. */
.jm-subscribe--dark {
  --jm-subscribe-ring: var(--gold-500);
  --jm-subscribe-label: var(--stone-100);
  --jm-subscribe-error: var(--gold-400);
}
.jm-subscribe--dark .jm-subscribe__button { --jm-button-ring: var(--gold-500); }


/* ---- Mobile · the "· Mobile" component variants ----
   47.99rem is the site's mobile step (see chrome.css); media queries resolve rem
   against the initial 16px, so this is a dependable 768. */

@media (max-width: 47.99rem) {
  /* A wrapped breadcrumb line sits on a 21px pitch (17 tall plus the 4 row gap),
     so the desktop 8px hit-area padding would overlap the line above and below.
     Overlapping targets are worse than small ones; this fills the pitch exactly
     and stops there. The 2.5.8 inline-text exception still covers it. */
  .jm-breadcrumb__link {
    padding-block: 0.125rem;           /* 2 */
    margin-block: -0.125rem;
  }

  /* "Field stacks above a full-width button, both 52 tall. The desktop
     side-by-side row does not fit 342." — the component's Figma description.

     JUDGEMENT: the mobile variant fills the field with a plain #ffffff rather
     than the Stone/100 the desktop variant is bound to. Stone/100 is #fdfcfb —
     the difference is not perceivable — and tokens.css deliberately has no white
     token, so this keeps Stone/100 at both sizes and treats the mobile fill as an
     unbound layer rather than a decision. */
  .jm-subscribe {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;                      /* 12 */
  }

  .jm-subscribe__field {
    flex: 1 1 auto;
    width: 100%;
  }

  /* flex-basis is the main axis, and the main axis is now vertical — a 100% basis
     here would set the message's HEIGHT to the row's. */
  .jm-subscribe__error {
    flex: 0 0 auto;
    width: 100%;
  }

  .jm-subscribe__input {
    min-height: 3.25rem;               /* 52 */
    padding-inline: 1rem;              /* 16 */
    font-size: var(--text-label);      /* 15 */
  }

  .jm-subscribe .jm-subscribe__button {
    width: 100%;
    min-height: 3.25rem;               /* 52 */
    font-size: var(--text-label);      /* 15 */
  }
}


/* =========================================================================
   JM Venn — Figma "Venn / Theory of Change" (419:1080)

   One inline SVG on a 620 x 600 viewBox, plus the same seven pieces of copy
   as a list for columns too narrow to draw it in. A container query decides
   which of the two you get.

   Sizes INSIDE the viewBox are the board's own units and live in the element
   (they are how an SVG scales, not CSS lengths). Everything here is rem or a
   token, like the rest of the site.
   ========================================================================= */

/* The container is the element itself, so the switch below reacts to the width
   of the COLUMN the diagram is standing in rather than the width of the window.
   That is the honest question: a 620-wide drawing is legible or not depending on
   how much room it was given, and on this page the same viewport gives it very
   different amounts either side of the two-column breakpoint. */
.jm-venn {
  container-type: inline-size;
}

/* 38.75rem is the board's 620. Below that the drawing scales down with its
   column; above it, it stops growing and centres, so a wide single column does
   not blow 15-unit body copy up past the size it was drawn at. In rem, so it
   still tracks the fluid root above 1440 exactly as --container-max does. */
.jm-venn__diagram {
  display: block;
  width: 100%;
  max-width: 38.75rem;                 /* 620 */
  height: auto;
  margin-inline: auto;
}

/* ---- The three fill levels ----
   Written as opacities over whatever is behind, never as the composited hex.
   Figma samples #d6cfd2 and #b0a0c3 over this section's Stone/600; 8% and 28.5%
   of Purple/500 compute to #d5cfd2 and #b0a1c3 over that ground, so these are
   the real values and they follow the section if its background ever changes.

   Each region is painted ONCE — see the element for why. Two 8% layers make
   15.4%, not the 28.5% the board draws, so nothing here may be allowed to
   stack. */
.jm-venn__field {
  fill: var(--purple-500);
  fill-opacity: 0.08;
}

.jm-venn__overlap {
  fill: var(--purple-500);
  fill-opacity: 0.285;
}

.jm-venn__core {
  fill: var(--purple-700);
}

/* 2px dashed, dash 4.6 gap 3.5, as drawn. The dash is in viewBox units so it
   scales with the circle it is on, which keeps the rhythm identical to the
   board at every size. */
.jm-venn__ring {
  fill: none;
  stroke: var(--purple-500);
  stroke-width: 2;
  stroke-dasharray: 4.6 3.5;
}

/* ---- The labels ----
   dominant-baseline is set on the <text> in the markup as well; it is repeated
   here for the tspans, because a multi-line block is one <text> holding one
   <tspan> per line and each line's y has to land on the centre of its line box.
   Everything else about a label — its size, its position — is in viewBox units
   inside the SVG, so the type scales with the circles instead of sliding across
   them. */
.jm-venn__diagram text,
.jm-venn__diagram tspan {
  font-family: var(--font-sans);
  dominant-baseline: central;
}

.jm-venn__area-title {
  font-weight: 700;                    /* Body/L Bold 24 */
  fill: var(--purple-500);
}

.jm-venn__area-body,
.jm-venn__overlap-text {
  font-weight: 400;                    /* Body/XS 15 */
  fill: var(--purple-500);
}

.jm-venn__core-text {
  font-weight: 700;                    /* 14 Bold on the solid lens */
  fill: var(--stone-100);
}

/* ---- The narrow-column list ----
   Not a stripped-down apology for the diagram: it carries all seven pieces of
   copy and reuses the diagram's own three fill levels as its surfaces, so a
   single area, a pairing and the centre stay visibly different things.

   34rem was the first threshold tried and it fell inside the band where this
   page's two-column grid gives the diagram between 27 and 32rem — which put the
   switch in the middle of a grid step and made the diagram flicker in and out
   across a 1152px gutter change. 32rem clears that band in one piece. It works
   out at a floor of about 12.4px for the 15-unit body copy: below that the
   drawing is a smudge, and a list is simply better.

   Measured on this page (root is a flat 16px from 480 to 1440):
     >= 1235   two columns, diagram, body copy 12.4px up to 15px at 1440
     992-1234  two columns, list — the board's layout needs about 1250px to
               seat a 560 text column beside a legible 620 diagram
     562-991   one column, diagram at its full drawn size
     < 562     one column, list. At 390 the column is 342, where the diagram
               would have set its body copy at 8px.
   If the 992-1234 band matters, the fix is on the page and not here: move the
   body row's single-column switch from tablet_portrait to tablet_landscape and
   give the text stack a max-width so it does not run to a 1100px measure. */
/* The text alternative. The SVG carries role="img" with a composed <desc>, so
   this is belt and braces for anyone navigating the copy directly; it is out of
   the visual flow at every width. */
.jm-venn__list {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* NO narrow-column fallback. A Venn is a Venn at every width.

   There used to be a container query here that swapped the diagram for a stacked
   list of the same seven strings below 32rem. That list is not in the Figma file
   and was never asked for — it was my instruction to the build, and it was wrong:
   the whole point of this section is that the three areas OVERLAP, which a list
   cannot say. The drawing scales with its column via the viewBox, so it stays a
   diagram all the way down.

   `.jm-venn__list` is kept in the markup as the accessible text alternative and
   stays visually hidden; see the rule below. */

.jm-venn__item {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;                         /* 8 */
  padding: 1rem 1.25rem;               /* 16 / 20 — the key panel's inset */
  border-radius: var(--radius-m);
}

/* The dashed edge is the circle's stroke: it says "this is one of the three
   areas". CSS cannot take the board's 4.6/3.5 dash pattern, so this is an echo
   rather than a copy. */
.jm-venn__item--area {
  background: color-mix(in srgb, var(--purple-500) 8%, transparent);
  border: 2px dashed var(--purple-500);
}

.jm-venn__item--overlap {
  background: color-mix(in srgb, var(--purple-500) 28.5%, transparent);
}

.jm-venn__item--core {
  background: var(--purple-700);
  text-align: center;
}

.jm-venn__item-title {
  font: 600 var(--text-body-m)/1.2 var(--font-sans);   /* 18 SemiBold */
  color: var(--purple-500);
}

.jm-venn__item-body {
  font: 400 var(--text-body-s)/1.4 var(--font-sans);   /* 15 */
  color: var(--purple-500);
}

.jm-venn__item--core .jm-venn__item-body {
  font-weight: 700;
  color: var(--stone-100);
}

/* =========================================================================
   Figure captions sit UNDER the image

   Bricks makes `.bricks-image-caption` `position: absolute; bottom: 0` inside a
   `position: relative` figure, so a caption is an overlay laid across the bottom
   of the picture. On the article and case study figures that put purple type on
   top of the photograph — unreadable over a light area, and not what a caption is
   for. Phil: captions under images.

   Unlayered, so it beats Bricks' layered rule without a specificity fight, and
   scoped to the caption class so an image someone deliberately builds with an
   overlay caption elsewhere is unaffected... there is no such image today, and if
   one is ever wanted it should be its own modifier rather than the default.
   ========================================================================= */

.brxe-image:has(> .bricks-image-caption) {
  position: static;
}

.bricks-image-caption {
  position: static;
  display: block;
  margin-top: 0.75rem;                 /* 12 */
  padding: 0;
  background: none;
  font: 400 var(--text-label-s)/1.4 var(--font-sans);
  color: var(--purple-400);
  text-align: left;
}

/* =========================================================================
   Content-type archives (/type/case-study/ and friends)

   The same shape as every other page: a purple hero carrying the eyebrow and the
   heading, then the card grid on the light ground. The header overlays the page,
   so the hero reserves its height the way the built pages do.
   ========================================================================= */

.jm-archive__hero {
  padding-top: calc(var(--header-h) + var(--page-top));
  padding-bottom: 5rem;                /* 80 */
  background-color: var(--purple-500);
}

.jm-archive__eyebrow {
  margin: 0 0 var(--space-m);          /* 24 — the site's eyebrow gap */
  color: var(--gold-500);
  text-transform: uppercase;
}

.jm-archive__title {
  margin: 0;
  color: var(--cream-500);
}

.jm-archive__intro {
  margin-top: var(--hero-lede);        /* 64 — the site's heading-to-body gap */
  max-width: 40.5625rem;               /* 649, the measure the boards use */
  color: var(--stone-100);
}

.jm-archive__intro p {
  margin: 0;
  font: 400 var(--text-body)/1.4 var(--font-sans);
}

.jm-archive__body {
  padding-block: 6rem;                 /* 96 */
  background-color: var(--stone-500);
}

.jm-archive__empty {
  margin: 0;
  font: 400 var(--text-body)/1.4 var(--font-sans);
  color: var(--purple-400);
}

/* ---- Pagination ---- */

.jm-archive__pagination { margin-top: 4rem; }        /* 64 */

.jm-archive__pagination .nav-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;                         /* 8 */
}

.jm-archive__pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;                  /* 44 */
  min-height: 2.75rem;
  padding: 0 0.75rem;
  border: 1px solid var(--purple-100);
  color: var(--purple-500);
  font: 500 var(--text-caption-m)/1.2 var(--font-sans);
  text-decoration: none;
  transition: background-color var(--motion-fast) var(--motion-ease-out), border-color var(--motion-fast) var(--motion-ease-out);
}

.jm-archive__pagination .page-numbers:hover {
  background-color: var(--purple-50);
  border-color: var(--purple-500);
}

.jm-archive__pagination .page-numbers.current {
  background-color: var(--purple-500);
  border-color: var(--purple-500);
  color: var(--stone-100);
}

@media (prefers-reduced-motion: reduce) {
  .jm-archive__pagination .page-numbers { transition: none; }
}
