/*
 * Mondial theme styles. Mobile-first, vanilla CSS with custom
 * properties. navy on white palette, serif body, sans UI.
 *
 * Naming: classes live under the "m-" prefix to avoid collisions with
 * anything a shared host or plugin might ship.
 */

:root {
    /* Palette: deep, respectable navy on a warm off-white paper.
       Named --m-accent-* for backward compatibility with existing
       templates; values are now blue. Safe to rename in a follow-up. */
    --m-accent-900: #0b2545;  /* deepest ink navy, used for titles */
    --m-accent-700: #13315c;  /* primary accent, links and buttons */
    --m-accent-500: #3a5a8a;  /* mid accent, borders and chips */
    --m-accent-100: #e6ecf5;  /* pale wash, card backgrounds, hover */

    --m-ink:       #161a22;
    --m-muted:     #5a6478;
    --m-line:      #d9dde5;
    --m-surface:   #ffffff;  /* page ground: plain white (Eston,
                                2026-07-28; was warm paper #f7f5ef,
                                which striped against the white
                                masthead, cards, and topic band) */
    --m-warn:      #8a5a00;

    /* Light text tints on the navy accent (footer doormat + utility bar).
       Two steps so a maintainer edits a token, not nine scattered hexes:
       a brighter body tint and a muted link / credit tint. */
    --m-on-accent:        #dbe3f0;
    --m-on-accent-muted:  #b9c7de;

    /* Serif display for headlines; transitional serif body; clean sans UI.
       Display face is Fraunces (D4, Phase 5): a variable serif whose
       optical-size axis keeps it legible below 24px, where Playfair's
       didone contrast broke down. Fallbacks are sturdy workhorse serifs
       to match, not didones.
       The wordmark face is Instrument Serif (Eston, 2026-07-28:
       Fraunces went high-contrast and quirky at masthead size). It
       carries ONLY the standalone Mondial marks: the masthead title,
       the placeholder tiles, and the footer promo name. Headlines and
       card titles stay on the display face. One weight exists (400),
       so mark rules set the weight explicitly rather than inherit a
       bold that would be synthesized. */
    --m-font-wordmark: 'Instrument Serif', Georgia, 'Iowan Old Style', 'Times New Roman', serif;
    --m-font-display: 'Fraunces', Georgia, 'Iowan Old Style', 'Times New Roman', serif;
    --m-font-serif:   'Source Serif 4', 'Source Serif Pro', 'Source Serif', Georgia, 'Iowan Old Style', 'Palatino Linotype', serif;
    --m-font-sans:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

    /* Type scale, named by the job each size does. Anything not on this
       list is an off-scale one-off and should be justified in
       DESIGN-SYSTEM.md before it is added. Deliberate off-scale
       survivors: monogram initials and placeholder wordmarks (sized to
       their disc or tile, not to type jobs) and the pull-quote's
       three-step optical ramp.
       --m-text-lede and --m-text-card-sm deliberately share 1.1rem: one
       is running lede prose, the other a small card title, and they are
       tokenized apart so either can move without dragging the other. */
    --m-text-eyebrow: 0.72rem;  /* eyebrows, kickers, chips */
    --m-text-label:   0.78rem;  /* uppercase UI and section labels */
    --m-text-meta:    0.9rem;   /* bylines, captions, metadata, buttons */
    --m-text-lede:    1.1rem;   /* page and section lede prose, deks */
    --m-text-card-sm: 1.1rem;   /* small card titles */
    /* Display tier (Phase 5, with the Fraunces swap). Named by job;
       --m-text-standfirst shares the subhead value deliberately, same
       precedent as lede / card-sm: separate jobs, either can move. */
    --m-text-subhead:    1.25rem; /* in-body h3s, step titles, definition terms */
    --m-text-standfirst: 1.25rem; /* article standfirst below the hero */
    --m-text-card:       1.4rem;  /* card titles */
    --m-text-heading-sm: 1.4rem;  /* small display headings: voices row, doormat columns */
    --m-text-heading:    1.5rem;  /* article body h2 */
    --m-text-promo: clamp(2rem, 3vw, 2.5rem); /* footer promo lockup lines (D5) */
    --m-wordmark:    2.4rem;      /* masthead wordmark, mobile */
    --m-wordmark-lg: 3.4rem;      /* masthead wordmark, desktop */
    --m-display: clamp(1.8rem, 4vw + 0.6rem, 3.6rem);

    /* Tracking. Two steps carry every uppercase label in the theme. The
       negative tracking on display headings is optical, set per size on
       the heading rules themselves, and is not tokenized. */
    --m-track-label: 0.12em;
    --m-track-wide:  0.14em;

    /* Rules. Five, and only five, horizontal / vertical rules exist:
         --m-rule-double     SECTION separations sitewide: section title
                             underlines, the Voices frame, body h2 top
                             rules, the footer promo top (2026-08, Eston)
         --m-rule-hairline   micro-chrome only: card and input borders,
                             row separators, drawer lines
         --m-rule-masthead   the masthead bottom edge, and nothing else
         --m-rule-on-accent  hairline for use inside the navy footer
         --m-rule-bar        left accent bar on pull quote, definition,
                             publication card why line
       The double rule is the brand mark writ small; the masthead keeps
       its own token so the header can diverge later without a sweep. */
    --m-rule-double:    3px double var(--m-accent-900);
    --m-rule-hairline:  1px solid var(--m-line);
    --m-rule-masthead:  3px double var(--m-accent-900);
    --m-rule-on-accent: 1px solid rgba(255,255,255,0.08);
    --m-rule-bar:       3px solid var(--m-accent-500);

    --m-max-prose: 44rem;
    --m-max-wide:  72rem;

    /* Radius policy: 2px everywhere, 999px for pills, 50% for avatars and
       round badges. Nothing else. */
    --m-radius: 2px;
    --m-shadow-soft: 0 1px 2px rgba(11,37,69,0.06), 0 6px 24px rgba(11,37,69,0.08);

    /* Spacing ramp (UI-2 spacing-01). The dominant margin / padding / gap
       values, named so the rhythm is edited in one place. Off-scale
       one-offs stay as literals on purpose. */
    --m-space-1: 0.25rem;
    --m-space-2: 0.5rem;
    --m-space-3: 0.75rem;
    --m-space-4: 1rem;
    --m-space-5: 1.25rem;
    --m-space-6: 1.5rem;
    --m-space-7: 2rem;
    --m-space-8: 2.5rem;
    --m-space-9: 3rem;

    /* Page gutter (2026-07-28). One horizontal inset for every top-level
       container, so the masthead wordmark, section headings, card grids,
       the promo band and the footer all start on the same vertical line.
       Before this the same job was done by five different literals
       (1rem in the masthead, 1.25rem in main, 1.5rem on theme landings
       and the promo, plus a second 1.25rem nested inside main on the hub
       and theme templates), which is why left edges drifted page to page.
       --m-shell is the container width that produces the line: the wide
       measure plus one gutter each side, so a --m-max-wide child centred
       inside it lands at exactly the same x as a gutter-padded band on a
       full-bleed background. Two recipes, one result:
         own box     max-width: var(--m-shell); padding-inline: gutter
         full bleed  padding-inline: gutter on the band, inner child
                     max-width: var(--m-max-wide); margin-inline: auto
       Containers take a recipe, never a raw horizontal literal. */
    --m-gutter: var(--m-space-5);  /* 1.25rem, phone */
    --m-shell:  calc(var(--m-max-wide) + var(--m-gutter) * 2);
}

/* One step wider from the tablet breakpoint up. The desktop bands (promo,
   theme landing) already sat at 1.5rem, and above 75rem the gutter stops
   being visible at all: the content column pins at --m-max-wide and the
   gutter becomes the leftover margin. --m-shell resolves from the token
   at use time, so every container follows this override automatically. */
@media (min-width: 48rem) {
    :root { --m-gutter: var(--m-space-6); }  /* 1.5rem, tablet and up */
}

* { box-sizing: border-box; }

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

body {
    margin: 0;
    font-family: var(--m-font-serif);
    color: var(--m-ink);
    background: var(--m-surface);
    font-size: 1.0625rem;
    line-height: 1.65;
}

a { color: var(--m-accent-700); text-decoration: underline; text-underline-offset: 3px; }
a:hover, a:focus { color: var(--m-accent-900); }

/* Global keyboard focus indicator. Per-component rules can override
   when needed (m-button has its own at line ~1274), but this provides
   a visible ring on every interactive element by default. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--m-accent-500);
    outline-offset: 3px;
    border-radius: 2px;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 { font-family: var(--m-font-display); line-height: 1.15; letter-spacing: -0.01em; }

.m-skip-link {
    position: absolute;
    left: -9999px;
    top: auto;
}
.m-skip-link:focus {
    left: 1rem; top: 1rem;
    background: var(--m-accent-900); color: #fff;
    padding: var(--m-space-2) var(--m-space-4); border-radius: var(--m-radius);
    z-index: 1000;
}

/* Visually-hidden but available to assistive tech. position:absolute
   keeps it out of grid/flex flow so an sr-only heading inside a grid
   (e.g. the home sub-features) does not consume a cell. */
.m-sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Respect a reduced-motion preference: collapse the hamburger transform,
   the drawer slide, and every hover / card / button transition to near
   zero for users who asked the OS to reduce motion. One global guard
   covers all transitions and animations in the sheet. */
@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;
    }
}

/* ---------- Label ----------
   One small-uppercase-sans label treatment for every section heading and
   group label in the theme. Before this block there were eight near-copies
   at five different sizes and four different trackings; now there is one
   definition and the per-context rules below carry only their genuine
   deltas (colour, rule, spacing).

   The component selectors are listed here rather than added to markup so
   existing templates need no change. New markup should just use .m-label.
   Anything listed here appears LATER in this sheet, so a per-context rule
   still wins on equal specificity. */

.m-label,
.m-site-nav__heading,
.m-site-footer__col-heading,
.m-article__authors-heading,
.m-article__related-heading,
.m-author__articles-heading,
.m-hub__heading,
.m-contrib__letter-heading {
    margin: 0 0 var(--m-space-4) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    font-weight: 600;
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    color: var(--m-muted);
}

/* ---------- Site chrome ---------- */

.m-site-header {
    background: #fff;
    border-bottom: var(--m-rule-masthead);
}
/* Mobile-first: brand on the left, hamburger on the right (standard
   pattern). The primary nav drops down full-width below when toggled.
   Above 48rem the header switches to the desktop centered stack.
   Rides the shared shell + gutter recipe: the wordmark's left edge is
   the line every left-aligned asset further down the page starts on. */
.m-site-header__inner {
    max-width: var(--m-shell);
    margin: 0 auto;
    padding: 1.1rem var(--m-gutter);
    display: grid;
    grid-template-columns: 1fr auto auto;
    grid-template-areas:
        "brand search toggle"
        "nav   nav    nav";
    gap: var(--m-space-2) var(--m-space-3);
    align-items: center;
}
.m-site-header__brand {
    grid-area: brand;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    min-width: 0;
}
.m-site-title {
    font-family: var(--m-font-wordmark);
    font-size: var(--m-wordmark);
    /* Instrument Serif ships 400 only; a heavier value here would be
       browser-synthesized. Tracking sits at zero: the face is already
       narrow, and the display faces' negative tracking crowds it. */
    font-weight: 400;
    font-style: italic;
    letter-spacing: 0;
    text-decoration: none;
    color: var(--m-accent-900);
    line-height: 1;
}
@media (min-width: 48rem) {
    .m-site-header__inner {
        display: flex;
        flex-direction: column;
        align-items: center;
        text-align: center;
        padding: var(--m-space-7) var(--m-gutter) var(--m-space-5);
        gap: var(--m-space-4);
    }
    .m-site-header__brand {
        align-items: center;
        text-align: center;
    }
    .m-site-title { font-size: var(--m-wordmark-lg); }
}
.m-site-nav__list {
    list-style: none;
    margin: 0; padding: 0;
    display: flex;
    gap: var(--m-space-5);
    justify-content: center;
    flex-wrap: wrap;
    align-items: center;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    font-weight: 600;
}

/* Mobile hamburger toggle: CSS-only via the checkbox-hack pattern.
   The button sits in the right column of the header grid on mobile;
   above 48rem the toggle hides and the nav lays out as a row. */
/* Keyboard-operable CSS-only toggle: the checkbox IS the control. It
   overlays the visible button at opacity:0, so a pointer tap toggles it
   while Tab lands on a real, focusable control whose :checked state the
   AT announces (open / closed) with no JS. The button below is the paint;
   its focus ring is drawn via the sibling rule at .m-nav-toggle:focus-visible.
   It must NOT sit off-screen (left:-9999px) or keyboard focus would scroll
   the page sideways to reach it. */
.m-nav-toggle {
    grid-area: toggle;
    align-self: stretch;
    width: 100%;
    min-height: 44px;
    margin: 0;
    appearance: none;
    -webkit-appearance: none;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
}
.m-nav-toggle__button {
    grid-area: toggle;
    display: inline-flex;
    align-items: center;
    gap: var(--m-space-2);
    padding: var(--m-space-2) 0.7rem;
    cursor: pointer;
    background: transparent;
    color: var(--m-accent-900);
    font-family: var(--m-font-sans);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    font-weight: 700;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
}
.m-nav-toggle:focus-visible ~ .m-nav-toggle__button {
    outline: 2px solid var(--m-accent-500);
    outline-offset: 3px;
}
.m-nav-toggle__bars,
.m-nav-toggle__bars::before,
.m-nav-toggle__bars::after {
    content: '';
    display: block;
    width: 20px;
    height: 2px;
    background: currentColor;
    border-radius: 1px;
    transition: transform 150ms ease, opacity 150ms ease;
}
.m-nav-toggle__bars { position: relative; }
.m-nav-toggle__bars::before { position: absolute; top: -6px; left: 0; }
.m-nav-toggle__bars::after  { position: absolute; top:  6px; left: 0; }
.m-nav-toggle:checked ~ .m-nav-toggle__button .m-nav-toggle__bars { background: transparent; }
.m-nav-toggle:checked ~ .m-nav-toggle__button .m-nav-toggle__bars::before { transform: translateY(6px) rotate(45deg); }
.m-nav-toggle:checked ~ .m-nav-toggle__button .m-nav-toggle__bars::after  { transform: translateY(-6px) rotate(-45deg); }

/* Default (mobile): primary nav collapsed, toggled by checkbox.
   Lives in the second grid row, full width below brand + toggle.
   Two sections inside the drawer: Topics (themes) and Dive deeper
   (utility links pulled in from the standalone bar above). */
.m-site-nav {
    grid-area: nav;
    width: 100%;
    max-height: 0;
    overflow: hidden;
    /* visibility:hidden removes the collapsed drawer from the tab order and
       the accessibility tree (overflow:hidden alone does not); the 200ms
       delay holds it visible through the closing slide. */
    visibility: hidden;
    transition: max-height 200ms ease, visibility 0s linear 200ms;
    border-top: 0;
    padding-top: 0;
    margin-top: 0;
}
.m-nav-toggle:checked ~ .m-site-nav {
    max-height: 80vh;
    overflow: auto;
    visibility: visible;
    transition: max-height 200ms ease, visibility 0s;
    border-top: var(--m-rule-hairline);
}
/* Drawer rows carry no horizontal padding of their own: the masthead
   gutter is the left edge, so the drawer's labels and links stack on the
   wordmark's line instead of 0.5rem inboard of it. The rows are full-width
   flex boxes, so the 44px hit target is unchanged. */
.m-site-nav__heading {
    margin: 0;
    padding: 0.85rem 0 0.4rem;
    border-top: var(--m-rule-hairline);
}
.m-site-nav__heading:first-child { border-top: 0; }
.m-site-nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    margin: 0 0 var(--m-space-1);
}
.m-site-nav__list > li {
    border-top: var(--m-rule-hairline);
}
.m-site-nav__list > li:first-child {
    border-top: 0;
}
.m-site-nav__list a,
.m-site-nav__list .m-theme-item__link {
    display: flex;
    min-height: 44px;
    align-items: center;
    padding: var(--m-space-3) 0;
    text-decoration: none;
    color: var(--m-ink);
    font-size: 0.85rem;
    text-transform: none;
    letter-spacing: 0.02em;
    font-weight: 600;
}
.m-site-nav__list--utility a {
    color: var(--m-accent-700);
}

/* Desktop: hide the toggle and the drawer-only sections; restore
   the row layout for the topics nav. The utility links live in the
   site footer on desktop, so the drawer copy is hidden there to
   avoid duplication. */
@media (min-width: 48rem) {
    .m-nav-toggle,
    .m-nav-toggle__button { display: none; }
    .m-site-nav__heading { display: none; }
    .m-site-nav__list--utility { display: none; }
    /* No hairline above the strip (Eston, 2026-07-28: one rule style
       in the header). The masthead's double rule below the topic band
       is the header's only rule now. */
    .m-site-nav {
        width: 100%;
        max-height: none;
        overflow: visible;
        visibility: visible;
        padding-top: 0.85rem;
        margin-top: var(--m-space-1);
    }
    .m-nav-toggle:checked ~ .m-site-nav {
        border-top: 0;
    }
    .m-site-nav__list {
        flex-direction: row;
        align-items: center;
        justify-content: center;
        gap: var(--m-space-5);
        padding: 0;
        margin: 0;
    }
    .m-site-nav__list > li { border-top: 0; }
    .m-site-nav__list a,
    .m-site-nav__list .m-theme-item__link {
        display: inline-flex;
        min-height: 0;
        padding: 0;
        font-size: var(--m-text-label);
        text-transform: uppercase;
        letter-spacing: var(--m-track-label);
        font-weight: 600;
        color: var(--m-ink);
    }
}
.m-site-nav__list--topics { gap: 1.1rem 1.35rem; }
.m-site-nav__list a {
    text-decoration: none;
    color: var(--m-ink);
    padding-bottom: 4px;
}
.m-site-nav__list a:hover { color: var(--m-accent-700); }

/* Masthead search affordance (D11, Phase 6). Mobile: a 44px bordered
   icon button between the brand and the Menu toggle, on the toggle's
   chrome; the drawer's Dive deeper list carries a text "Search" entry
   too. Desktop: a quiet uppercase label link pinned to the masthead's
   top right (the centered stack has no visible utility row to join).
   Deliberately NOT in the theme strip: themes are editorial nav, search
   is utility. The loupe is border-drawn like the pagination chevrons,
   so there is no glyph for a screen reader to stumble on. */
.m-site-search {
    grid-area: search;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--m-space-2);
    min-height: 44px;
    min-width: 44px;
    padding: var(--m-space-2) 0.7rem;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    text-decoration: none;
    color: var(--m-accent-900);
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
}
.m-site-search:hover,
.m-site-search:focus-visible { color: var(--m-accent-700); }
.m-site-search__label { display: none; }
.m-site-search__icon {
    display: block;
    width: 11px;
    height: 11px;
    border: 2px solid currentColor;
    border-radius: 50%;
    position: relative;
}
.m-site-search__icon::after {
    content: '';
    position: absolute;
    right: -1px;
    bottom: -5px;
    width: 2px;
    height: 7px;
    background: currentColor;
    border-radius: 1px;
    transform: rotate(-45deg);
    transform-origin: top center;
}
@media (min-width: 48rem) {
    .m-site-header__inner { position: relative; }
    .m-site-search {
        position: absolute;
        top: var(--m-space-5);
        /* Pinned to the gutter, not to its own literal, so the search
           label ends on the same line the content column ends on. */
        right: var(--m-gutter);
        min-height: 0;
        min-width: 0;
        padding: 0.35rem 0.1rem;
        border: 0;
    }
    .m-site-search__label { display: inline; }
    .m-site-search__icon { width: 10px; height: 10px; }
}

/* Full-bleed navy band: the background runs edge to edge, the gutter
   pads it, and the doormat / credit children carry --m-max-wide so their
   text lands on the same line as the content above. */
.m-site-footer {
    background: var(--m-accent-900);
    color: var(--m-on-accent);
    padding: var(--m-space-9) var(--m-gutter);
    margin-top: 4rem;
}
/* When the latest-issue promo sits directly above the footer, drop the 4rem
   gap so the promo band and the navy footer meet flush (B1). */
.m-footer-promo + .m-site-footer { margin-top: 0; }
.m-site-footer__org p { margin: 0 0 0.35rem 0; }
.m-site-footer__org-name {
    font-weight: 700;
    font-size: 1rem;
    color: #fff;
    letter-spacing: 0.01em;
    margin-bottom: var(--m-space-3) !important;
}
.m-site-footer__org-address {
    line-height: 1.5;
    color: var(--m-on-accent);
}
.m-site-footer__org-phone a,
.m-site-footer__org-url a {
    color: var(--m-on-accent-muted);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 120ms ease, color 120ms ease;
}
.m-site-footer__org-phone a:hover,
.m-site-footer__org-url a:hover,
.m-site-footer__org-phone a:focus-visible,
.m-site-footer__org-url a:focus-visible {
    color: #fff;
    border-bottom-color: #fff;
}
.m-site-footer a { color: var(--m-on-accent-muted); }
/* The global accent-500 focus ring is 2.21:1 against the navy footer
   (fails WCAG 1.4.11 non-text contrast); use white inside the footer. */
.m-site-footer a:focus-visible,
.m-site-footer button:focus-visible {
    outline-color: #fff;
}

/* Footer identity block (LR1, 2026-08-18): full-width brand row above
   the doormat. The wordmark is the master SVG (brand/wordmark/
   mondial-wordmark-master.svg) inlined with its fill controlled here,
   white on the navy band, so the mark recolors from a token instead of
   a hardcoded hex. It replaces the old About column, which netted only
   about 300px at desktop, too narrow for a mark that must read large. */
.m-site-footer__brand {
    max-width: var(--m-max-wide);
    margin: 0 auto var(--m-space-8);
}
.m-site-footer__wordmark {
    display: block;
    width: 100%;
    max-width: 20rem;
    height: auto;
    fill: var(--m-surface);
}
.m-site-footer__brand-lede {
    font-family: var(--m-font-serif);
    font-size: 1.02rem;
    line-height: 1.55;
    color: var(--m-on-accent);
    max-width: var(--m-max-prose);
    margin: var(--m-space-4) 0 0;
}
@media (max-width: 47.9375rem) {
    .m-site-footer__wordmark { max-width: 14rem; }
}

/* ---------- Site footer doormat (Phase 9) ----------
 * Fat-footer mirroring primary nav with the Subscribe block embedded as
 * column 2. Three columns since LR1 (2026-08-18) moved the About column
 * up into the brand row above. Mobile collapses to 1-col; tablet 2-col;
 * desktop 3-col. Mirrors LRB / NYRB / Boston Review / Harper's / n+1
 * patterns documented in 09-RESEARCH.md sections 2 and 6. */
.m-site-footer__doormat {
    max-width: var(--m-max-wide);
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-8);
}
@media (min-width: 48rem) {
    .m-site-footer__doormat {
        grid-template-columns: 1fr 1fr;
        gap: var(--m-space-8) var(--m-space-9);
    }
}
@media (min-width: 64rem) {
    .m-site-footer__doormat {
        grid-template-columns: 0.8fr 1fr 1.1fr;
        gap: var(--m-space-9);
    }
}
.m-site-footer__col { min-width: 0; }
.m-site-footer__col-heading {
    color: var(--m-on-accent-muted);
}
.m-site-footer__col-lede {
    font-family: var(--m-font-serif);
    font-size: 1.02rem;
    line-height: 1.55;
    color: var(--m-on-accent);
    margin: 0 0 0.85rem;
}
.m-site-footer__col-title {
    font-family: var(--m-font-display);
    font-size: var(--m-text-heading-sm);
    line-height: 1.25;
    color: #fff;
    margin: 0 0 0.85rem 0;
}
.m-site-footer__col-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.m-site-footer__col-list li { margin: 0 0 var(--m-space-2) 0; }
.m-site-footer__col-list a {
    font-family: var(--m-font-sans);
    font-size: 0.95rem;
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.m-site-footer__col-list a:hover,
.m-site-footer__col-list a:focus-visible {
    color: var(--m-accent-100);
}
.m-site-footer__col-link {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    font-weight: 600;
    margin-top: var(--m-space-2);
}
.m-site-footer__col-link a {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.m-site-footer__col-cta { margin: var(--m-space-4) 0 0 0; }
.m-site-footer__col .m-button {
    background: var(--m-accent-500);
    border-color: var(--m-accent-500);
    color: #fff;
}
/* The base hover fills with accent-900, which on the navy doormat would
   erase the button into its own background. So this one follows the ghost
   hover instead: the accent-100 pale wash rather than a hard white flash. */
.m-site-footer__col .m-button:hover,
.m-site-footer__col .m-button:focus-visible {
    background: var(--m-accent-100);
    border-color: var(--m-accent-100);
    color: var(--m-accent-900);
}
.m-site-footer__col--contact .m-site-footer__org { margin-bottom: var(--m-space-6); }
.m-site-footer__col--contact .m-site-footer__org:last-child { margin-bottom: 0; }
.m-site-footer__credit {
    max-width: var(--m-max-wide);
    margin: var(--m-space-8) auto 0;
    padding-top: var(--m-space-6);
    border-top: var(--m-rule-on-accent);
    font-family: var(--m-font-serif);
    font-size: var(--m-text-meta);
    color: var(--m-on-accent-muted);
}

/* The page shell. Every template's content sits in here, so the gutter is
   set once at this level instead of per template (which is how the hub
   and theme-landing sections ended up one step inboard of the archive:
   they added their own horizontal padding on top of this one). max-width
   is the wide measure plus both gutters, which makes main's CONTENT box
   exactly --m-max-wide: a 72rem child (.m-archive, .m-home) fills it edge
   to edge, and a narrower one (.m-article's reading measure) centres
   inside it. Sections below add vertical rhythm only. */
.m-main {
    max-width: var(--m-shell);
    margin: 0 auto;
    padding: var(--m-space-7) var(--m-gutter);
}

/* ---------- Single article ---------- */

.m-article {
    max-width: var(--m-max-prose);
    margin: 0 auto;
}
.m-article__hero { margin-bottom: var(--m-space-7); }
.m-article__lead-image {
    margin: 0 0 var(--m-space-6) 0;
    border-radius: var(--m-radius);
    overflow: hidden;
    box-shadow: var(--m-shadow-soft);
}
/* Without this the global img{max-width:100%} let a portrait or small
   lead render at intrinsic width, leaving most of the 44rem column
   empty. Fill the measure and crop to the same 16/9 band the rest of
   the theme uses; object-position keeps faces in frame. */
.m-article__lead-image img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    object-position: center 30%;
}
/* Placeholder hero (D7 extended to the article single, 2026-09-22).
   The tile brings its own 16/9 ratio, so it only needs the wordmark
   sized to hero scale, matching .m-theme-featured__media. */
.m-article__lead-image .m-ph-navy { font-size: 2rem; }
/* Photo credit lines (LR12, 2026-08-18): render only when the
   attachment's description or caption opens with an attribution
   marker; mondial_photo_credit() never invents one. The hero credit
   sits inside the rounded shadowed card, under the image. */
.m-article__lead-credit {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
    margin: var(--m-space-2) var(--m-space-3) 0;
    padding-bottom: var(--m-space-2);
}
.m-article__inline-credit {
    display: block;
    margin-top: 0.25rem;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
/* Phase 7 (ART-03): the kicker selector serves the eyebrow text from
   the _mondial_kicker meta value, joined to the issue month. It is
   plain text since 2026-08-18 (plan SL2). The separate
   .m-article__issue-meta line it once shared this typography with
   retired with the foot citation, which now renders inside
   .m-article__about below. */
.m-article__kicker {
    margin: 0 0 0.4rem 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-wide);
    font-weight: 700;
    color: var(--m-accent-700);
    line-height: 1.2;
}
.m-article__title {
    margin: 0 0 var(--m-space-4) 0;
    font-family: var(--m-font-display);
    /* Shared hero clamp (--m-display) handles responsive scaling from a
       low mobile floor up to the desktop max, so a long headline does not
       run many lines on a 360 px screen. */
    font-size: var(--m-display);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--m-accent-900);
}
@media (min-width: 48rem) {
    .m-article__title { line-height: 1.05; }
}
.m-article__byline {
    margin: 0 0 var(--m-space-4) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
.m-article__byline a { color: var(--m-accent-700); }
.m-article__excerpt {
    margin: var(--m-space-7) 0 0;
    font-family: var(--m-font-serif);
    font-size: var(--m-text-standfirst);
    line-height: 1.5;
    font-weight: 600;
    color: var(--m-ink);
}
/* The journal name flips to a lighter italic accent inside the
   heavier roman dek (LR7, 2026-08-18): italic 400 is the one italic
   weight Source Serif 4 loads, so nothing is synthesized. */
.m-article__excerpt em { font-style: italic; font-weight: 400; }
.m-article__body { font-size: 1.125rem; line-height: 1.75; }
.m-article__body p { margin: 0 0 var(--m-space-5) 0; }
.m-article__body h2 {
    margin: 2.25rem 0 var(--m-space-4);
    padding-top: var(--m-space-5);
    border-top: var(--m-rule-double);
    font-family: var(--m-font-display);
    font-size: var(--m-text-heading);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.005em;
    color: var(--m-accent-900);
    clear: both;
}
.m-article__body h3 {
    margin: 1.75rem 0 var(--m-space-2);
    font-family: var(--m-font-sans);
    font-size: var(--m-text-subhead);
    font-weight: 600;
    line-height: 1.3;
    color: var(--m-accent-900);
    clear: both;
}
/* PDF extractor's --detect-subheads pass emits h3.m-article__subhead at
 * mid-article section breaks. Render as a sans subhead with extra space
 * above so it reads as a distinct topical shift rather than another
 * paragraph of body prose. The .wp-block-heading sibling class is
 * inserted by the importer to match WordPress block markup. */
.m-article__body h3.m-article__subhead {
    margin: 2.25rem 0 var(--m-space-2);
    font-family: var(--m-font-sans);
    font-weight: 600;
    font-size: var(--m-text-subhead);
    line-height: 1.3;
    letter-spacing: 0.01em;
    color: var(--m-accent-900);
    text-transform: none;
}
.m-article__body figure { margin: var(--m-space-6) 0; }
.m-article__body figcaption {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
    margin-top: var(--m-space-2);
}

/* Body lists (item 33). Source bullet and numbered lists are stored as
 * wp:list blocks; harmonize their rhythm with the prose column: same
 * vertical spacing as a paragraph, a comfortable indent, and tighter
 * spacing for nested sub-lists (e.g. the recommendation bullets under
 * each numbered area in post 703 "Our Common Agenda").
 *
 * Scoped to :not([class]) so these only touch prose lists that came out
 * of the article body. Unscoped, `.m-article__body ul` (0,1,1) outranked
 * every component list that sets list-style:none (0,1,0), which put stray
 * bullets on the Get Mondial and About membership cards and double markers
 * on the Contribute steps. Component lists own their own markers. */
.m-article__body ul:not([class]),
.m-article__body ol:not([class]) {
    margin: 0 0 var(--m-space-5) 0;
    padding-left: 1.5rem;
}
.m-article__body ul:not([class]) { list-style: disc; }
.m-article__body ol:not([class]) { list-style: decimal; }
.m-article__body ul:not([class]) > li,
.m-article__body ol:not([class]) > li { margin: 0 0 var(--m-space-2) 0; padding-left: 0.25rem; }
.m-article__body ul:not([class]) > li:last-child,
.m-article__body ol:not([class]) > li:last-child { margin-bottom: 0; }
.m-article__body li > ul:not([class]),
.m-article__body li > ol:not([class]) {
    margin: var(--m-space-2) 0 var(--m-space-2) 0;
}
.m-article__body li > ul:not([class]) { list-style: circle; }

/* Dictionary-style definition epigraph (item 33; the "sovereign"
 * definition that opens post 715). A navy left rule like the pull-quote,
 * set a touch smaller in the body serif. Rendered as a <div> (no <p>) so
 * the pull-quote injector, which targets the first </p>, lands after the
 * first real paragraph instead of splitting the definition. */
.m-article__definition {
    margin: 0 0 var(--m-space-5) 0;
    padding: var(--m-space-1) 0 var(--m-space-1) var(--m-space-6);
    border-left: var(--m-rule-bar);
    font-size: 1rem;
    line-height: 1.6;
}
.m-article__definition-word {
    font-weight: 700;
    color: var(--m-accent-900);
    font-variant: small-caps;
    letter-spacing: 0.02em;
}

/* Inline figures spliced into the body by the importer (Phase 3b).
 * Mobile-first: figure spans the full prose column with caption beneath
 * in muted sans. At wider viewports it breaks out to the right of the
 * prose so the body keeps reading flow alongside the image. The
 * pullquote already breaks out left on the same breakpoint; right-float
 * here keeps the two layouts visually distinct when both appear. */
.m-article__inline-figure {
    margin: 1.75rem 0;
}
.m-article__inline-figure img {
    width: 100%;
    height: auto;
    display: block;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
}
.m-article__inline-figure figcaption {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
    margin-top: var(--m-space-2);
    line-height: 1.45;
}
@media (min-width: 60rem) {
    .m-article__inline-figure {
        float: right;
        clear: right;
        width: 18rem;
        margin: var(--m-space-2) 0 var(--m-space-5) var(--m-space-6);
    }
}

/* Pull quote: a single striking sentence lifted from the body and set
 * in display serif. Sits in the prose column on narrow screens; breaks
 * out to the left on wider viewports so it catches the eye during a
 * scroll past. The left accent bar is its only ornament. */
.m-article__pullquote {
    /* Mobile-first: live in the prose column, no negative margin or
       browser-default blockquote padding-left to push us off the
       visible column on narrow phones. */
    margin: 2.25rem 0;
    margin-inline-start: 0;
    padding: var(--m-space-1) 0 var(--m-space-1) var(--m-space-6);
    border-left: var(--m-rule-bar);
    font-family: var(--m-font-display);
    font-style: italic;
    font-weight: 500;
    /* The pull quote's three sizes (1.25 / 1.5 / 1.75) are an optical
       ramp tied to its layout states (in-column, wide, floated inset),
       deliberately off the named scale like the display trackings. */
    font-size: 1.25rem;
    line-height: 1.4;
    color: var(--m-accent-900);
}
@media (min-width: 40rem) {
    .m-article__pullquote { font-size: 1.5rem; line-height: 1.35; }
}
.m-article__pullquote p {
    margin: 0;
}
@media (min-width: 60rem) {
    .m-article__pullquote {
        float: left;
        width: 16rem;
        max-width: 16rem;
        margin: var(--m-space-2) var(--m-space-7) var(--m-space-4) -6rem;
        font-size: 1.75rem;
    }
}
/* Extra clearance when a heading and a pullquote sit directly next to
 * each other in the prose. Headings already carry clear: both for the
 * 60rem+ float case, but on mobile (where pullquote stays in the prose
 * column) the default 2.25rem margins can read as cramped, especially
 * with h2's hairline rule pulling the eye. */
.m-article__pullquote + h2,
.m-article__pullquote + h3,
.m-article__body h2 + .m-article__pullquote,
.m-article__body h3 + .m-article__pullquote {
    margin-top: var(--m-space-9);
}

/* Inline pull quotes (wp:pullquote blocks, carried in the body since
 * the V9I1 repair) render identically to the meta pull quote above.
 * The block nests figure > blockquote > p, so the box treatment
 * (margins, the wide-view float) sits on the figure while the accent
 * bar and type sit on the blockquote. Core wp-block-library styles
 * load on this classic theme, so its centered, top-and-bottom
 * bordered look is explicitly neutralized here. */
.m-article__body .wp-block-pullquote {
    margin: 2.25rem 0;
    padding: 0;
    border: 0;
    text-align: left;
}
.m-article__body .wp-block-pullquote blockquote {
    margin: 0;
    padding: var(--m-space-1) 0 var(--m-space-1) var(--m-space-6);
    border-left: var(--m-rule-bar);
    font-family: var(--m-font-display);
    font-style: italic;
    font-weight: 500;
    font-size: 1.25rem;
    line-height: 1.4;
    color: var(--m-accent-900);
}
@media (min-width: 40rem) {
    .m-article__body .wp-block-pullquote blockquote {
        font-size: 1.5rem;
        line-height: 1.35;
    }
}
.m-article__body .wp-block-pullquote p {
    margin: 0;
    font-size: inherit;
    line-height: inherit;
}
@media (min-width: 60rem) {
    .m-article__body .wp-block-pullquote {
        float: left;
        width: 16rem;
        max-width: 16rem;
        margin: var(--m-space-2) var(--m-space-7) var(--m-space-4) -6rem;
    }
    .m-article__body .wp-block-pullquote blockquote { font-size: 1.75rem; }
}
.m-article__body .wp-block-pullquote + h2,
.m-article__body .wp-block-pullquote + h3,
.m-article__body h2 + .wp-block-pullquote,
.m-article__body h3 + .wp-block-pullquote {
    margin-top: var(--m-space-9);
}

/* LR2 fix (2026-08-18): a pull quote (floats left) and an inline figure
 * (floats right) can land close enough in the body to float side by
 * side, squeezing body prose into a narrow channel between them
 * (Eston's report; example: post 929, /articles/2023/12/
 * defense-idealist-approach-un-reform/). The pull quote is spliced in
 * by a separate the_content filter after the figure is already stored
 * in post_content, so neither knows about the other at authoring time.
 * Fix: whichever of the two lands SECOND in the body clears the other
 * and drops below it, so the floats never occupy the same vertical
 * band. CSS has no true previous-sibling selector, but the
 * subsequent-sibling combinator (~) reaches the same outcome read from
 * the other direction ("figure that comes after a pull quote"), and
 * is safe to apply unconditionally: clear is a no-op once an element
 * is already positioned below the float it would clear, so a figure
 * many paragraphs after a pull quote, or vice versa, is unaffected.
 * Covers both pull quote kinds (the meta blockquote and the inline
 * wp:pullquote block) even though no live article currently combines
 * a figure with the block variant, so the fix will not go stale the
 * day one does. */
@media (min-width: 60rem) {
    .m-article__pullquote ~ .m-article__inline-figure,
    .m-article__body .wp-block-pullquote ~ .m-article__inline-figure {
        clear: both;
    }
    .m-article__inline-figure ~ .m-article__pullquote,
    .m-article__body .m-article__inline-figure ~ .wp-block-pullquote {
        clear: both;
    }
}

/* About this article: end-matter section (plan SL5, 2026-08-18).
   Replaces three stacked blocks, each of which drew its own rule: the
   syndication credit, the foot citation, and the standalone topics
   nav. Two of those rules could land 40px apart with dead space
   between them. One section, one double rule, on the sitewide section
   separator (the .m-article__body h2 precedent above). */
.m-article__about {
    margin-top: var(--m-space-8);
    border-top: var(--m-rule-double);
    padding-top: var(--m-space-5);
}
.m-article__about-title {
    margin: 0 0 var(--m-space-4);
    font-family: var(--m-font-display);
    font-size: var(--m-text-heading);
    font-weight: 700;
    color: var(--m-accent-900);
}
.m-article__about-line {
    margin: 0 0 var(--m-space-3);
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    line-height: 1.55;
    color: var(--m-muted);
}
.m-article__about-line a { color: var(--m-accent-700); }

/* Excerpt-mode sign-off (LR10, 2026-08-19). Sits between the body and
   the About section, on the about-line's type so it reads as the
   archive speaking rather than as a last paragraph of the article. */
.m-article__read-rest {
    margin: var(--m-space-5) 0 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    line-height: 1.55;
    color: var(--m-muted);
}
.m-article__read-rest a { color: var(--m-accent-700); }
.m-article__about .m-chip-list { margin-top: var(--m-space-5); }

.m-chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--m-space-2); }
.m-chip {
    display: inline-block;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    font-weight: 600;
    color: var(--m-accent-700);
    padding: 0.35rem 0.65rem;
    border: var(--m-rule-hairline);
    border-radius: 999px;
    text-decoration: none;
    background: #fff;
}
.m-chip:hover, .m-chip:focus {
    background: var(--m-accent-100);
    color: var(--m-accent-900);
}

.m-article__authors { margin: var(--m-space-8) 0; }
.m-author-card-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--m-space-6); }
.m-author-card {
    display: flex;
    gap: var(--m-space-4);
    background: #fff;
    border: var(--m-rule-hairline);
    padding: var(--m-space-4);
    border-radius: var(--m-radius);
}
/* flex 0 0 auto stops the photo cell shrinking under long header
   text, which squeezed the fixed-size img into a subtle oval (the
   img's max-width 100% capped width while the explicit height held).
   The monogram variants already carry it. */
.m-author-card__photo { flex: 0 0 auto; }
.m-author-card__photo img { width: 72px; height: 72px; aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
.m-author-card__text { flex: 1; min-width: 0; }
.m-author-card__name { margin: 0 0 var(--m-space-1) 0; font-weight: 700; }
.m-author-card__name a { text-decoration: none; color: var(--m-ink); }
.m-author-card__affiliation {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
.m-author-card__bio { font-size: 0.95rem; }
.m-author-card__bio p { margin: 0 0 var(--m-space-2) 0; }

.m-article__related { margin: var(--m-space-8) 0; }
.m-card-grid.m-card-grid--related { margin: 0; gap: var(--m-space-6); }
@media (min-width: 64rem) {
    .m-card-grid--related { grid-template-columns: repeat(3, 1fr); }
}
/* Rail cards render through the shared partial as the 'related' variant
   (image, date eyebrow, title) since Phase 2. Only the title scale is
   rail-specific; the old .m-card--minimal and .m-card__date pair died
   with the hand-rolled rail markup. */
.m-card-grid--related .m-card__title { font-size: 1.05rem; line-height: 1.25; }

/* The "Photos from this article" foot-gallery styles were removed at the
   Track A sunset (session 17, 2026-06-11): the gallery markup is gone from
   single-mondial_article.php now that every attached image is spliced
   inline, serving as the hero, or deliberately detached. */

/* ---------- Single article: side-banner rail (Track A, 2026-06-03) ----------
   At >=64rem the single-article page (.m-article--single) becomes a two
   column grid: the 44rem reading column plus a right rail holding the
   author card, related articles, and a subscribe CTA. Below 64rem none of
   this applies: .m-article--single inherits the base single-column
   .m-article and the rail blocks fall into the normal stack. The base
   .m-article (static About / Get Mondial / Contribute pages) is
   untouched. */

.m-article__aside-cta {
    /* The subscribe CTA is rail furniture. On mobile the site-wide footer
       promo already carries the subscribe message, so the rail CTA is hidden
       under the rail breakpoint to avoid two stacked CTAs; it is shown again
       inside the rail at >=64rem below. */
    display: none;
    margin: var(--m-space-8) 0;
    padding: var(--m-space-5);
    background: var(--m-accent-100);
    border-radius: var(--m-radius);
    text-align: center;
}
.m-article__aside-cta-text {
    margin: 0 0 var(--m-space-3) 0;
    font-family: var(--m-font-display);
    font-size: var(--m-text-subhead);
    line-height: 1.2;
    color: var(--m-accent-900);
}
.m-article__aside-cta-link { display: inline-block; }

@media (min-width: 64rem) {
    .m-article--single {
        max-width: 64rem;
        display: grid;
        grid-template-columns: minmax(0, 1fr) 20rem;
        column-gap: var(--m-space-8);
        align-items: start;
    }
    .m-article__main { grid-column: 1; min-width: 0; }
    .m-article__aside {
        grid-column: 2;
        align-self: start;
    }

    /* Tighten the section rhythm inside the narrow rail (the in-flow blocks
       carry generous space-8 margins that are too loose stacked in a rail). */
    .m-article__aside > section { margin: 0; }
    .m-article__aside > section + section { margin-top: var(--m-space-7); }
    .m-article__aside .m-article__authors-heading,
    .m-article__aside .m-article__related-heading { margin-bottom: var(--m-space-3); }

    /* Author card goes vertical (photo above text) so the bio gets the full
       rail width. */
    .m-article__aside .m-author-card { flex-direction: column; align-items: flex-start; gap: var(--m-space-3); }
    /* A3 safety: clamp the rail bio so an unusually long short bio cannot
       run away in the narrow rail. */
    .m-article__aside .m-author-card__bio p {
        display: -webkit-box;
        -webkit-line-clamp: 5;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    /* Related: single-column in the rail, images fill their 16/9 box. */
    .m-article__aside .m-card-grid--related { grid-template-columns: 1fr; gap: var(--m-space-4); margin: 0; }

    /* Subscribe CTA fills the rail width. */
    .m-article__aside-cta { display: block; margin: 0; }
    .m-article__aside-cta-link { display: block; text-align: center; }

    /* The pull-quote's -6rem left breakout assumes a centered single column
       with a wide gutter; in the two-column grid that gutter is gone at the
       low end of the breakpoint, so neutralize the negative margin. The
       quote still floats left, flush with the reading column. */
    .m-article--single .m-article__pullquote { margin-left: 0; }
    .m-article--single .wp-block-pullquote { margin-left: 0; }
}

/* ---------- Archive + cards ---------- */

.m-archive { max-width: var(--m-max-wide); margin: 0 auto; }
.m-archive__header { margin-bottom: var(--m-space-7); }
.m-archive__eyebrow {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-wide);
    color: var(--m-muted);
}
.m-archive__title {
    margin: 0 0 var(--m-space-2) 0;
    /* Display face sitewide (LR6, 2026-08-18): every page h1 rides
       Fraunces; the wordmark face survives only in the masthead and
       the footer wordmark. */
    font-family: var(--m-font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: var(--m-display);
    line-height: 1.15;
    color: var(--m-accent-900);
}
.m-archive__lede {
    margin: 0 0 var(--m-space-6) 0;
    font-size: var(--m-text-lede);
    color: var(--m-muted);
    max-width: var(--m-max-prose);
}
.m-archive__meta { font-family: var(--m-font-sans); font-size: var(--m-text-meta); }

.m-archive__filters {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-3);
    background: #fff;
    border: var(--m-rule-hairline);
    padding: var(--m-space-4);
    border-radius: var(--m-radius);
    font-family: var(--m-font-sans);
}
@media (min-width: 48rem) {
    .m-archive__filters {
        grid-template-columns: 1.5fr 1fr 1fr auto;
        align-items: end;
    }
    /* Repository experiment: one or two extra selects join the row, so
       the tracks wrap instead of being counted. */
    .m-archive__filters--repo {
        grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    }
    .m-archive__filters--repo .m-archive__filter--search { grid-column: span 2; }
}
.m-archive__filter { display: flex; flex-direction: column; gap: var(--m-space-1); font-size: var(--m-text-meta); }
.m-archive__filter span { color: var(--m-muted); }
.m-archive__filter input,
.m-archive__filter select {
    /* 16px font-size avoids iOS Safari auto-zoom on focus. */
    font-size: 16px;
    padding: var(--m-space-2) var(--m-space-3);
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    font-family: var(--m-font-sans);
    background: #fff;
}
.m-card-grid {
    list-style: none; margin: var(--m-space-7) 0; padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-6);
}
@media (min-width: 48rem) {
    .m-card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 64rem) {
    .m-card-grid { grid-template-columns: repeat(3, 1fr); }
}

.m-card {
    background: #fff;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    overflow: hidden;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
    display: flex;
    flex-direction: column;
}
.m-card:hover {
    border-color: var(--m-accent-500);
    box-shadow: var(--m-shadow-soft);
    transform: translateY(-1px);
}
/* Teaser media anchors (Phase 2): the image sits in its own aria-hidden
   tabindex=-1 link and the title carries the accessible link, the same
   idiom as .m-theme-featured__media and .m-issue-card__cover. Nothing
   may wrap a whole card in one big anchor: the byline holds author
   links and anchors cannot nest. */
.m-card__media,
.m-feed__media,
.m-sub-feature__media,
.m-home__lead-media {
    display: block;
    /* The placeholder tile's wordmark is anchor text; keep it plain. */
    text-decoration: none;
}
/* Leaves-the-site cue on a link-mode teaser (LR10, 2026-08-19). One
   class for one affordance, so the arrow is identical on the card, the
   subfeature and the feed row; em-relative so it tracks whichever
   title size it follows. */
.m-card__external {
    font-size: 0.8em;
    margin-left: 0.3ch;
    color: var(--m-accent-700);
}

.m-card__title a { text-decoration: none; color: inherit; }
.m-card__title a:hover,
.m-card__title a:focus-visible {
    text-decoration: underline;
    text-decoration-color: var(--m-accent-500);
    text-underline-offset: 3px;
}
.m-card__image { margin: 0; aspect-ratio: 16 / 9; overflow: hidden; background: var(--m-accent-100); }
.m-card__image img { width: 100%; height: 100%; object-fit: cover; }
/* (The pale hairline placeholder retired 2026-08-11, design D7: one
   recipe everywhere, the navy .m-ph-navy tile below. The card grid
   sizing rule for it lives with the tile.) */
.m-card__image .m-ph-navy { width: 100%; height: 100%; }
.m-card__text { padding: var(--m-space-4) var(--m-space-5); }
/* Date eyebrow: the one kicker spec every teaser shares (Phase 2).
   Volume labels left cards for the article-page citation; what sits
   above a teaser title now is the issue date. Kept on accent-700:
   --m-muted is banned below 12px and this renders at 11.5px. Contexts
   below carry only their margin deltas. */
.m-card__kicker,
.m-feed__kicker,
.m-sub-feature__kicker,
.m-home__lead-kicker,
.m-theme-featured__kicker {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    font-weight: 600;
    color: var(--m-accent-700);
}
.m-card__kicker { margin: 0 0 var(--m-space-2) 0; }
.m-card__title {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-display);
    font-size: var(--m-text-card);
    line-height: 1.2;
    letter-spacing: -0.005em;
    color: var(--m-accent-900);
}
.m-card__byline {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
.m-card__excerpt { margin: 0; font-size: 0.95rem; color: var(--m-ink); }
/* Whichever slot renders last (title on the rail and author grid,
   excerpt elsewhere) sits flush against the card's bottom padding. */
.m-card__text > :last-child { margin-bottom: 0; }

.m-archive__empty { color: var(--m-muted); font-style: italic; }

/* ---------- Issues page (cover-card grid) ---------- */

.m-issue-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-6);
}
@media (min-width: 40rem) {
    .m-issue-grid { grid-template-columns: repeat(2, 1fr); gap: var(--m-space-6); }
}
@media (min-width: 64rem) {
    .m-issue-grid { grid-template-columns: repeat(3, 1fr); }
}
.m-issue-card {
    display: flex;
    flex-direction: column;
    background: #fff;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    overflow: hidden;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}
.m-issue-card:hover {
    border-color: var(--m-accent-500);
    box-shadow: var(--m-shadow-soft);
    transform: translateY(-1px);
}
.m-issue-card__cover {
    display: block;
    aspect-ratio: 3 / 4;
    background: var(--m-accent-100);
    overflow: hidden;
}
.m-issue-card__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.m-issue-card__cover--placeholder,
.m-issue-card--no-cover .m-issue-card__cover {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--m-space-2);
    padding: var(--m-space-4);
    text-align: center;
    box-shadow: inset 0 0 0 1px var(--m-line);
}
.m-issue-card__cover-placeholder {
    font-family: var(--m-font-wordmark);
    font-style: italic;
    font-size: 2rem;
    line-height: 1;
    color: var(--m-accent-500);
    letter-spacing: 0.02em;
}
.m-issue-card__cover-kicker {
    font-family: var(--m-font-sans);
    font-weight: 700;
    font-size: 0.66rem;
    line-height: 1.25;
    letter-spacing: var(--m-track-wide);
    text-transform: uppercase;
    color: var(--m-accent-700);
}
.m-issue-card__body { padding: var(--m-space-4) var(--m-space-5) var(--m-space-5); }
.m-issue-card__kicker {
    margin: 0 0 0.35rem 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    font-weight: 600;
    color: var(--m-accent-700);
}
.m-issue-card__title {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-display);
    font-size: var(--m-text-card);
    line-height: 1.2;
    color: var(--m-accent-900);
}
.m-issue-card__title a { color: inherit; text-decoration: none; }
.m-issue-card__title a:hover,
.m-issue-card__title a:focus-visible {
    text-decoration: underline;
    text-decoration-color: var(--m-accent-500);
    text-underline-offset: 3px;
}
.m-issue-card__meta {
    margin: 0 0 var(--m-space-3) 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
.m-issue-card__empty {
    margin: 0;
    font-style: italic;
    color: var(--m-muted);
}

/* Pagination sits under centered card grids, so it centres too. Every
   archive, search, topic, and theme page renders this same component via
   paginate_links(), so the rules here apply sitewide. */
.m-pagination {
    margin-top: var(--m-space-7);
    font-family: var(--m-font-sans);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.35rem;
}
/* Pager links: a 44px minimum hit target. */
.m-pagination .page-numbers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0.4rem 0.85rem;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    text-decoration: none;
    margin: 0;
    color: var(--m-accent-700);
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.m-pagination a.page-numbers:hover,
.m-pagination a.page-numbers:focus-visible {
    background: var(--m-accent-100);
    border-color: var(--m-accent-500);
    color: var(--m-accent-900);
}
.m-pagination .page-numbers.current {
    background: var(--m-accent-700);
    color: #fff;
    border-color: var(--m-accent-700);
}
/* The gap ellipsis is a label, not a target: no box, no hit area. */
.m-pagination .page-numbers.dots {
    border-color: transparent;
    background: transparent;
    color: var(--m-muted);
    min-width: 0;
    padding-left: var(--m-space-2);
    padding-right: var(--m-space-2);
}
/* Previous / Next read as direction, not as two more page numbers. The
   chevrons are drawn from borders rather than set as arrow characters so
   a screen reader announces only the "Previous" / "Next" text. */
.m-pagination .prev,
.m-pagination .next { font-weight: 600; }
.m-pagination .prev::before,
.m-pagination .next::after {
    content: '';
    flex: 0 0 auto;
    width: 0.4em;
    height: 0.4em;
    border-top: 2px solid currentColor;
    border-right: 2px solid currentColor;
}
.m-pagination .prev::before { transform: rotate(-135deg); margin-right: 0.45em; }
.m-pagination .next::after  { transform: rotate(45deg);   margin-left:  0.45em; }

/* (The full-width utility bar above the wordmark was removed 2026-06-01.
   Its links -- About, Issues, Articles, Companion Reading, Subscribe --
   live in the site footer on every viewport and in the mobile drawer's
   "Dive deeper" section.) */

/* ---------- About page extras ---------- */

/* Masthead run-in paragraph (SL8, 2026-08-18): the About page's closing
   note, set quieter than body copy so it reads as end matter rather than
   argument. Scoped inside the body because `.m-article__body p` (0,1,1)
   sets the margin shorthand and would otherwise outrank a lone class. */
.m-article__body .m-about__masthead {
    margin-top: var(--m-space-7);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}

.m-substack-placeholder {
    border: 1px solid var(--m-accent-500);
    background: var(--m-accent-100);
    padding: var(--m-space-7) var(--m-space-5);
    margin: var(--m-space-4) 0 var(--m-space-6);
    text-align: center;
    color: var(--m-accent-900);
    border-radius: var(--m-radius);
}
.m-substack-placeholder__label {
    margin: 0 0 var(--m-space-2);
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--m-track-wide);
    font-weight: 700;
    color: var(--m-accent-700);
}

/* Live Substack signup embed (D1): centered, placeholder-box width. */
.m-substack-embed { display: flex; justify-content: center; margin: var(--m-space-6) 0; }
.m-substack-embed iframe { max-width: 100%; }


.m-home { max-width: var(--m-max-wide); margin: 0 auto; padding-top: var(--m-space-2); }

.m-home__lead {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-6);
    padding-bottom: var(--m-space-8);
    border-bottom: var(--m-rule-double);
}
/* Flip to two columns at 48rem (was 56rem) so the hero pivots at the
   same breakpoint as the nav and grids. Below 56rem the figure used to
   stay full-width and stack ABOVE the headline, rendering a ~546px band
   that pushed the lead story below the fold at tablet width. */
@media (min-width: 48rem) {
    .m-home__lead { grid-template-columns: 1.35fr 1fr; gap: var(--m-space-8); }
}
.m-home__lead-text { display: flex; flex-direction: column; justify-content: center; order: 2; }
.m-home__lead-media { order: 1; }
.m-home__lead-figure { margin: 0; }
@media (min-width: 48rem) {
    .m-home__lead-text { order: 1; }
    .m-home__lead-media { order: 2; }
}
/* Theme-hero frame (2026-08): rounded clipped wrapper, no img border. */
.m-home__lead-media {
    border-radius: var(--m-radius);
    overflow: hidden;
    background: var(--m-accent-100);
    align-self: start;
}
.m-home__lead-figure img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
    /* Cap the stacked (single-column) band so large phones and the
       40-48rem range do not get an oversized hero. Inert once the lead
       is two-column, where the narrow figure track is already shorter. */
    max-height: 24rem;
}
.m-home__lead-figure .m-ph-navy { font-size: 2rem; }
/* D1 parity: the lead crops to the same deliberate 1:1 square as the
   theme/topic heroes from 60rem. */
@media (min-width: 60rem) {
    .m-home__lead-figure img,
    .m-home__lead-figure .m-ph-navy {
        aspect-ratio: 1;
        max-height: none;
    }
}
.m-home__lead-kicker { margin: 0 0 var(--m-space-3); }
.m-home__lead-title {
    margin: 0 0 var(--m-space-4);
    font-family: var(--m-font-display);
    font-weight: 700;
    font-size: var(--m-display);
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--m-accent-900);
}
@media (min-width: 48rem) {
    .m-home__lead-title { line-height: 1.05; }
}
.m-home__lead-title a { color: inherit; text-decoration: none; }
.m-home__lead-title a:hover { text-decoration: underline; text-decoration-color: var(--m-accent-500); text-decoration-thickness: 2px; text-underline-offset: 4px; }
/* Recipe order (Phase 2): byline above the dek, matching the article
   hero and every card. */
.m-home__lead-byline {
    margin: 0 0 var(--m-space-4);
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
}
.m-home__lead-byline a { color: var(--m-accent-700); }
.m-home__lead-dek {
    margin: 0;
    font-family: var(--m-font-serif);
    font-size: var(--m-text-lede);
    line-height: 1.45;
    color: var(--m-ink);
}

/* (The "More from Mondial" home section title came out 2026-08-11,
   design D5 batch: the Voices band's own double rule now hands
   straight into the feed.) */

/* Two secondary features side-by-side. No bottom rule: the Voices frame
   directly below carries the section double rule (2026-08). */
.m-home__subfeatures {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-7);
    padding: var(--m-space-7) 0;
}
@media (min-width: 48rem) {
    .m-home__subfeatures { grid-template-columns: 1fr 1fr; gap: var(--m-space-8); }
    .m-home__subfeatures > article + article { padding-left: var(--m-space-8); border-left: var(--m-rule-hairline); }
}
.m-sub-feature { margin: 0; }
.m-sub-feature__figure { margin: 0 0 var(--m-space-4); border-radius: var(--m-radius); overflow: hidden; background: var(--m-accent-100); }
.m-sub-feature__figure img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
.m-sub-feature__kicker { margin: 0 0 var(--m-space-2); }
.m-sub-feature__title {
    margin: 0 0 var(--m-space-2);
    font-family: var(--m-font-display);
    font-size: var(--m-text-card);
    line-height: 1.25;
    letter-spacing: -0.005em;
    color: var(--m-accent-900);
}
.m-sub-feature__title a { color: inherit; text-decoration: none; }
.m-sub-feature__title a:hover { text-decoration: underline; }
/* Recipe order (Phase 2): byline above the dek. */
.m-sub-feature__byline { margin: 0 0 var(--m-space-2); font-family: var(--m-font-sans); font-size: var(--m-text-meta); color: var(--m-muted); }
.m-sub-feature__dek { margin: 0; font-family: var(--m-font-serif); font-size: 1rem; line-height: 1.5; color: var(--m-ink); }

/* Story feed: compact list with small thumbnail */
.m-feed { list-style: none; margin: var(--m-space-4) 0 0; padding: 0; }
.m-feed__item {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-3);
    padding: var(--m-space-6) 0;
    border-bottom: var(--m-rule-hairline);
}
@media (min-width: 40rem) {
    .m-feed__item { grid-template-columns: 1fr 12rem; gap: var(--m-space-6); align-items: start; }
}
.m-feed__media { order: -1; }
.m-feed__figure { margin: 0; border-radius: var(--m-radius); overflow: hidden; background: var(--m-accent-100); }
@media (min-width: 40rem) {
    .m-feed__media { order: 2; }
}
.m-feed__figure img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
.m-feed__kicker { margin: 0 0 0.35rem; }
.m-feed__title {
    margin: 0 0 0.4rem;
    font-family: var(--m-font-display);
    font-size: var(--m-text-card);
    line-height: 1.25;
    letter-spacing: -0.005em;
    color: var(--m-accent-900);
}
.m-feed__title a { color: inherit; text-decoration: none; }
.m-feed__title a:hover { text-decoration: underline; }
/* Recipe order (Phase 2): byline above the dek. */
.m-feed__byline { margin: 0 0 0.35rem; font-family: var(--m-font-sans); font-size: var(--m-text-meta); color: var(--m-muted); }
.m-feed__dek { margin: 0; font-family: var(--m-font-serif); font-size: 0.98rem; line-height: 1.5; color: var(--m-ink); }

/* Centering wrapper only. The link inside is a .m-button--ghost; it used
   to be a bespoke bordered CTA with its own tracking, weight, and square
   corners, which made it the one button on the site outside the system. */
.m-home__footer-cta {
    display: flex;
    justify-content: center;
    margin: var(--m-space-8) 0 0;
}

/* ---------- Volume TOC ---------- */

.m-toc { list-style: none; margin: var(--m-space-7) 0; padding: 0; max-width: var(--m-max-prose); }
.m-toc__item {
    display: flex;
    gap: var(--m-space-4);
    align-items: baseline;
    padding: var(--m-space-4) 0;
    border-bottom: var(--m-rule-hairline);
}
.m-toc__page {
    font-family: var(--m-font-sans);
    font-size: 0.85rem;
    color: var(--m-muted);
    min-width: 3.5rem;
}
.m-toc__title { margin: 0; font-size: var(--m-text-card-sm); }
.m-toc__title a { text-decoration: none; color: var(--m-accent-900); }
.m-toc__byline { margin: var(--m-space-1) 0 0; font-family: var(--m-font-sans); font-size: var(--m-text-meta); color: var(--m-muted); }

/* ---------- Author page ---------- */

.m-author { max-width: var(--m-max-prose); margin: 0 auto; }
.m-author__header {
    display: flex;
    gap: var(--m-space-5);
    align-items: center;
    margin-bottom: var(--m-space-6);
}
.m-author__photo { margin: 0; flex: 0 0 auto; }
.m-author__photo img { width: 112px; height: 112px; aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
/* Author monogram fallback (A1): one shared component for every disc,
   defined after the Voices mini card block (it must out-cascade the
   mini __photo base tint). See "Author monogram" below. */
.m-author__name { margin: 0 0 var(--m-space-1) 0; color: var(--m-accent-900); }
.m-author__affiliation { margin: 0; font-family: var(--m-font-sans); color: var(--m-muted); }
.m-author__bio { font-size: 1.05rem; margin-bottom: var(--m-space-7); }
.m-author__bio p { margin: 0 0 var(--m-space-4) 0; }
.m-author__bio p:last-child { margin-bottom: 0; }
.m-author__articles { margin-top: var(--m-space-7); }
/* Author-page article grid: a 3-up at 64rem, 2-up at 48rem, 1-up on
 * mobile. Inherits the .m-card-grid base layout. Cards use slightly
 * smaller titles than archive cards because they are paged in
 * triplet rhythm rather than a long scrolling feed. Phase 3 (THEME-02). */
.m-card-grid--author { margin: var(--m-space-6) 0 0; }
.m-card--author .m-card__title { font-size: var(--m-text-card-sm); }
/* Author-grid cards render through the shared partial as the 'author'
   variant (image, date eyebrow, title; no byline, the page IS
   the author). Only the title scale differs. */

/* ---------- Fallback ---------- */

.m-page { max-width: var(--m-max-prose); margin: 0 auto; }
.m-fallback-list { list-style: none; margin: 0; padding: 0; }
.m-fallback-list li { padding: var(--m-space-3) 0; border-bottom: var(--m-rule-hairline); }
.m-fallback-list a { text-decoration: none; font-size: var(--m-text-lede); color: var(--m-accent-900); }

/* ---------- Theme-based primary nav ---------- */

.m-site-nav__list--themes {
    gap: var(--m-space-1) var(--m-space-4);
}
.m-theme-item { position: relative; }
.m-theme-item__link {
    display: inline-flex;
    align-items: center;
    padding: 0.35rem 0.1rem;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    color: var(--m-ink);
    text-decoration: none;
    transition: color 0.15s ease;
}
.m-theme-item__link:hover,
.m-theme-item__link:focus-visible {
    color: var(--m-accent-700);
}
/* Active theme marker (Phase 4): a real pill instead of the old
   near-invisible color shift. The .current-menu-item selector covers
   the admin-managed wp_nav_menu path, which previously had no active
   styling at all. Mobile drawer rows take the wash without the pill
   box; the 48rem block below adds the pill itself. */
.m-theme-item--current .m-theme-item__link,
.m-site-nav__list--topics .current-menu-item > a {
    background: var(--m-accent-100);
    color: var(--m-accent-900);
}

/* Drawer-only indented topics under the active theme (Phase 4). At
   desktop the masthead band below carries the same links as chips. */
.m-theme-item__topics {
    list-style: none;
    margin: 0;
    padding: 0 0 var(--m-space-2) var(--m-space-5);
}
.m-theme-item__topics a {
    display: flex;
    min-height: 40px;
    align-items: center;
    /* Horizontal padding zeroed with the drawer rows above: the list's
       own padding-left is the whole indent, one clean step of 1.25rem. */
    padding: 0.35rem 0;
    text-decoration: none;
    color: var(--m-accent-700);
    font-size: 0.8rem;
    font-weight: 500;
}
.m-theme-item__topics a[aria-current="page"] {
    font-weight: 700;
    color: var(--m-accent-900);
}

@media (min-width: 48rem) {
    .m-site-nav__list--themes {
        flex-wrap: wrap;
        justify-content: center;
        gap: var(--m-space-2) var(--m-space-6);
        align-items: flex-start;
    }
    /* Keep each theme label whole: never let a two-word label (e.g.
       "International Justice") break mid-phrase in the 48 to 56 rem band.
       If the row runs out of width, whole labels wrap to a second line. */
    .m-site-nav__list--themes .m-theme-item__link { white-space: nowrap; }
    .m-theme-item--current .m-theme-item__link,
    .m-site-nav__list--topics .current-menu-item > a {
        border: 1px solid var(--m-accent-700);
        border-radius: 999px;
        padding: 0.3rem 0.85rem;
        margin: -0.3rem 0;
    }
    .m-theme-item__topics { display: none; }
}

/* ---------- Theme topic band (Phase 4) ----------
   The active theme's topics as chips with counts. Since 2026-07-28 the
   band renders INSIDE .m-site-header, above the masthead double rule
   (Eston: one rule style in the header, topics above the rule), so it
   carries no ground or rule of its own: the header's white and the
   double rule below do both jobs. Desktop only: the drawer indent
   above carries these links on mobile. */
.m-theme-subnav {
    display: none;
}
@media (min-width: 48rem) {
    .m-theme-subnav { display: block; }
    .m-theme-subnav__list {
        /* Same shell + gutter as the masthead around it: the band's
           chips are centred, but its edges have to agree with
           everything else. The top spacing is the header inner's own
           bottom padding; only the gap to the double rule lives here. */
        max-width: var(--m-shell);
        margin: 0 auto;
        padding: 0 var(--m-gutter) var(--m-space-5);
        justify-content: center;
    }
}
.m-chip--current {
    background: var(--m-accent-100);
    border-color: var(--m-accent-700);
    color: var(--m-accent-900);
}

/* ---------- Featured article hero (topic and theme landing) ---------- */

/* No horizontal padding: the hero sits inside .m-archive (topic pages) or
   .m-theme-landing (theme pages), both already on the page gutter. Its
   own 1.25rem used to indent the hero one step past the card grid
   directly below it on the same page, and the theme landing carried a
   second rule to undo it. */
.m-theme-featured {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-5);
    margin: 0 0 var(--m-space-8);
    max-width: var(--m-max-wide);
    margin-left: auto;
    margin-right: auto;
}
.m-theme-featured__media {
    display: block;
    text-decoration: none;
    overflow: hidden;
    border-radius: var(--m-radius);
    background: var(--m-accent-100);
}
.m-theme-featured__media img {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
}
/* Shared navy placeholder tile: the ONE placeholder recipe sitewide
   since 2026-08-11 (design D7): heroes, home figures, and every card
   grid. Contexts override the size and ratio. */
.m-ph-navy {
    aspect-ratio: 16 / 9;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--m-accent-700);
    color: #fff;
    font-family: var(--m-font-wordmark);
    font-style: italic;
    font-size: 1.6rem;
}
.m-theme-featured__media .m-ph-navy { font-size: 2rem; }
.m-theme-featured__text { display: flex; flex-direction: column; gap: var(--m-space-2); }
/* Kicker spec comes from the shared date-eyebrow block (card section);
   the flex gap spaces the kicker and the slots below. */
.m-theme-featured__kicker { margin: 0; }
.m-theme-featured__title {
    font-family: var(--m-font-display);
    font-size: var(--m-display);
    line-height: 1.1;
    margin: 0;
    color: var(--m-accent-900);
}
.m-theme-featured__title a { color: inherit; text-decoration: none; }
.m-theme-featured__title a:hover {
    text-decoration: underline;
    text-decoration-color: var(--m-accent-500);
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
}
.m-theme-featured__dek {
    font-family: var(--m-font-serif);
    font-size: 1.05rem;
    line-height: 1.5;
    color: var(--m-ink);
    margin: 0;
}
.m-theme-featured__byline {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    color: var(--m-muted);
    margin: 0;
}
.m-theme-featured__byline a { color: var(--m-accent-700); }

@media (min-width: 60rem) {
    .m-theme-featured {
        grid-template-columns: 1.1fr 1fr;
        gap: var(--m-space-8);
    }
    /* D1 (Phase 3): the featured media is a deliberate 1:1 square on
       desktop, cut from the mondial-square crop. align-self keeps the
       media cell at its own height; the old stretch let headline
       length set the ratio. Mobile stays 16:9 like every other
       teaser image. */
    .m-theme-featured__media { align-self: start; }
    .m-theme-featured__media img,
    .m-theme-featured__media .m-ph-navy { aspect-ratio: 1; }
    .m-theme-featured__text { justify-content: center; }
}

/* ---------- Theme landing page ---------- */

/* Vertical rhythm only. The horizontal inset is .m-main's gutter: this
   section used to add 1.25rem (1.5rem at 60rem) of its own on top of it,
   which put every theme page one step inboard of the archive and the
   masthead. Top padding is zero (2026-07-28): theme landings and topic
   archives are the same page family now, and stacking a second space-7
   on .m-main's started theme pages 2rem lower than topic pages. */
.m-theme-landing {
    max-width: var(--m-max-wide);
    margin: 0 auto;
    padding: 0 0 var(--m-space-9);
}
/* No visible page header since 2026-07-28 (superseding D3's compact
   intro): the masthead theme strip and topic band mark the current
   theme, so the nav is the header on theme and topic pages. The H1 is
   sr-only in the template. */
/* Chip badge count: used by the masthead topic band's chips. */
.m-chip__count {
    font-size: 0.7rem;
    font-weight: 600;
    /* 11.2px: --m-muted is banned below 12px, so the badge follows the
       date-eyebrow precedent onto accent-700. */
    color: var(--m-accent-700);
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    background: var(--m-surface);
    border: var(--m-rule-hairline);
}
.m-chip:hover .m-chip__count,
.m-chip:focus .m-chip__count { background: #fff; }

@media (min-width: 60rem) {
    .m-theme-landing { padding: 0 0 4rem; }
}

/* ---------- Button ----------
   One button system for every CTA: 2px theme radius, accent-700 fill, lifts
   to accent-900 on hover/focus, presses a pixel on :active, and shows a
   visible focus ring via outline. Modifiers:
     .m-button--ghost  transparent fill with accent border (secondary CTA);
     .m-button--sm     smaller padding and font for card contexts.
*/

.m-button {
    display: inline-block;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    font-weight: 600;
    letter-spacing: var(--m-track-label);
    text-transform: uppercase;
    text-decoration: none;
    padding: 0.7rem var(--m-space-6);
    background: var(--m-accent-700);
    color: #fff;
    border: 1px solid var(--m-accent-700);
    border-radius: var(--m-radius);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease;
}
.m-button:hover,
.m-button:focus-visible {
    background: var(--m-accent-900);
    border-color: var(--m-accent-900);
    color: #fff;
}
.m-button:focus-visible {
    outline: 2px solid var(--m-accent-500);
    outline-offset: 3px;
}
.m-button:active {
    transform: translateY(1px);
}

/* Ghost variant: transparent fill with accent border. Pairs with a
   filled .m-button as a secondary CTA (e.g., footer-promo "Browse all
   issues" alongside "Read this issue"). */
.m-button--ghost {
    background: transparent;
    color: var(--m-accent-900);
    border-color: var(--m-accent-700);
}
.m-button--ghost:hover,
.m-button--ghost:focus-visible {
    background: var(--m-accent-100);
    color: var(--m-accent-900);
    border-color: var(--m-accent-900);
}

/* Size modifier: smaller padding and font so a CTA fits inside a card. */
.m-button--sm { padding: 0.45rem 0.9rem; font-size: 0.75rem; letter-spacing: var(--m-track-label); }

/* ---------- Footer promo ----------
   Wash-ground CTA block that sits above the dark site footer on every
   page (suppressed on author archives per the Phase 3 guard in
   footer.php). Leads with the latest issue's cover and a "Read this
   issue" CTA. The standalone Subscribe aside that used to live
   alongside this promo is gone in Phase 9; the Subscribe surface now
   lives inside the fat-footer doormat as column 3. */

/* Full-bleed wash band, same recipe as the navy footer: gutter on the
   band, --m-max-wide on __inner. The background keeps running edge to
   edge; only its content answers to the gutter. */
.m-footer-promo {
    background: var(--m-accent-100);
    border-top: var(--m-rule-double);
    padding: var(--m-space-8) var(--m-gutter);
}
.m-footer-promo__inner {
    max-width: var(--m-max-wide);
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem;
    align-items: center;
}
@media (min-width: 48rem) {
    .m-footer-promo { padding: var(--m-space-9) var(--m-gutter); }
    .m-footer-promo__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: var(--m-space-9); }
}
.m-footer-promo__cover {
    display: block;
    max-width: 18rem;
    margin: 0 auto;
    line-height: 0;
}
@media (min-width: 48rem) {
    .m-footer-promo__cover { max-width: none; }
}
.m-footer-promo__cover img {
    width: 100%;
    height: auto;
    border-radius: var(--m-radius);
    box-shadow: var(--m-shadow-soft);
    border: var(--m-rule-hairline);
}
.m-footer-promo__copy { color: var(--m-ink); }
/* Two-line lockup (D5, Phase 6): "Read the latest" over "Mondial" at
   --m-text-promo, about 40px. The old single line rode --m-display,
   identical to page H1s, and dominated About; the lockup returns the
   page H1 to the top of the hierarchy. The "Latest issue" eyebrow died
   with it (Eston's ask). */
.m-footer-promo__title {
    margin: 0 0 var(--m-space-2) 0;
    font-family: var(--m-font-display);
    font-size: var(--m-text-promo);
    line-height: 1.1;
    color: var(--m-accent-900);
}
.m-footer-promo__line { display: block; }
/* The name line is the wordmark, so it rides the wordmark face; the
   "Read the latest" line above it stays on the display face. */
.m-footer-promo__name {
    display: block;
    font-family: var(--m-font-wordmark);
    font-weight: 400;
}
.m-footer-promo__meta {
    margin: 0 0 var(--m-space-3) 0;
    font-family: var(--m-font-sans);
    font-size: 0.95rem;
    color: var(--m-muted);
}
.m-footer-promo__lede {
    margin: 0 0 var(--m-space-5) 0;
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--m-ink);
    max-width: 36rem;
}
.m-footer-promo__cta {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--m-space-3);
}

/* ---------- Publication feature cards (Companion Reading, Phase 8) ----------
   One stacked feature card per allied publication (mondial_partner
   records with kind = publication). Media rides soft sizes over the
   accent wash and letterboxes (object-fit: contain): a journal cover
   or banner should never be cropped, so these deliberately skip the
   hard crops. Records without an image render a quiet wash tile
   carrying the publication name in the display italic (1.6rem is the
   documented placeholder-tile off-scale family). The why line borrows
   the standfirst grammar: accent bar, italic serif, 1.1rem inset.
   The bento card chrome this replaces retired with the old
   three-section hub; Companion was its only consumer. */

.m-pub-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--m-space-5);
}
.m-pub-card {
    background: #fff;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    overflow: hidden;
    display: grid;
    grid-template-columns: 1fr;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}
.m-pub-card:hover {
    border-color: var(--m-accent-500);
    box-shadow: var(--m-shadow-soft);
}
.m-pub-card__media {
    margin: 0;
    background: var(--m-accent-100);
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 9;
    overflow: hidden;
}
.m-pub-card__media img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
/* Portrait art (book covers): letterbox on the wash, never crop (D8).
   Same intent as .m-pub-card__media: a cover should never be cropped.
   The class rides any article figure (hero lead image, card, feed,
   subfeature); each context keeps its own aspect box. */
.m-media--contain { background: var(--m-accent-100); }
.m-media--contain img { object-fit: contain; }
.m-pub-card__media-mark {
    font-family: var(--m-font-display);
    font-style: italic;
    font-size: 1.6rem;
    color: var(--m-accent-700);
    text-align: center;
    padding: 0 var(--m-space-5);
}
.m-pub-card__body { padding: var(--m-space-5); }
.m-pub-card__name {
    margin: 0 0 var(--m-space-3);
    font-family: var(--m-font-display);
    font-size: var(--m-text-card);
    line-height: 1.2;
    color: var(--m-accent-900);
}
.m-pub-card__desc {
    margin: 0 0 var(--m-space-4);
    font-family: var(--m-font-serif);
    color: var(--m-ink);
    max-width: var(--m-max-prose);
}
.m-pub-card__why {
    margin: 0 0 var(--m-space-5);
    font-family: var(--m-font-serif);
    font-style: italic;
    color: var(--m-accent-900);
    border-left: var(--m-rule-bar);
    padding-left: 1.1rem;
    max-width: var(--m-max-prose);
}
.m-pub-card__cta { margin: 0; }
@media (min-width: 48rem) {
    .m-pub-card { grid-template-columns: 280px 1fr; }
    .m-pub-card__media { aspect-ratio: auto; }
    .m-pub-card__body { padding: var(--m-space-6); }
}

/* ---------- Movement hub (Companion Reading, item 29) ----------
   Shared chrome: Companion Reading and the Get Mondial mock below.
   The eyebrow rule is the mock's alone since 2026-07-28, when
   Companion dropped its "Kindred journals" kicker; the title is that
   page's first header element and its top gap is the .m-hub padding. */
/* Vertical rhythm only, same as .m-theme-landing: .m-main's gutter is the
   horizontal inset, so Companion and Get Mondial start their titles and
   cards on the archive's line rather than one step inboard of it. */
.m-hub {
    max-width: var(--m-max-wide);
    margin: 0 auto;
    padding: var(--m-space-7) 0 var(--m-space-9);
}
.m-hub__header { margin-bottom: var(--m-space-7); max-width: var(--m-max-prose); }
.m-hub__title {
    margin: 0 0 var(--m-space-3);
    /* Display face sitewide (LR6, 2026-08-18): every page h1 rides
       Fraunces; the wordmark face survives only in the masthead and
       the footer wordmark. */
    font-family: var(--m-font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: var(--m-display);
    line-height: 1.05;
    color: var(--m-accent-900);
}
/* Spacing modifier for h1s that share .m-article__title on static
   pages (Contribute, Subscribe): the display face comes from
   .m-article__title; this class only widens the gap below the title. */
.m-page-title {
    margin-bottom: var(--m-space-6);
}
/* Mondial-as-name mark: the journal's name rides the wordmark face
   wherever it appears in headings and kickers (2026-08, Eston).
   Body prose keeps its ordinary italics; buttons keep Inter (the
   uppercase button system fights an italic serif mid-label). */
.m-wordmark {
    font-family: var(--m-font-wordmark);
    font-style: italic;
    font-weight: 400;
}
.m-hub__lede {
    margin: 0;
    font-family: var(--m-font-serif);
    font-size: var(--m-text-lede);
    line-height: 1.55;
    color: var(--m-muted);
}
.m-hub__section { margin: var(--m-space-8) 0; }
.m-hub__cta {
    margin: var(--m-space-9) 0 0;
    padding: var(--m-space-8) var(--m-space-6);
    background: var(--m-accent-900);
    color: var(--m-on-accent);
    border-radius: var(--m-radius);
    text-align: center;
}
.m-hub__cta-title { margin: 0 0 var(--m-space-2); font-family: var(--m-font-display); font-size: var(--m-text-card); color: #fff; }
.m-hub__cta-text { margin: 0 auto var(--m-space-5); max-width: 40rem; color: var(--m-on-accent); }
.m-hub__cta-actions { margin: 0; display: flex; flex-wrap: wrap; gap: var(--m-space-3); justify-content: center; }
.m-hub__cta .m-button--ghost { color: #fff; border-color: var(--m-on-accent-muted); }
.m-hub__cta .m-button--ghost:hover,
.m-hub__cta .m-button--ghost:focus-visible { background: rgba(255, 255, 255, 0.12); color: #fff; border-color: #fff; }

/* ---------- Voices row (top authors on home + theme pages) ----------
   Mini author card: round photo + name + affiliation + article count.
   On the home page it sits between the subfeatures and the feed. On
   each theme landing it sits below the featured article. Horizontal
   scroll on mobile, grid at desktop. */

/* Voices band is framed by the section double rule, top and bottom
   (2026-08, Eston): on theme landings it also stands in for the
   removed "All articles" heading rule. */
.m-home__voices,
.m-theme-landing__voices {
    margin: var(--m-space-8) 0;
    padding: var(--m-space-6) 0;
    border-top: var(--m-rule-double);
    border-bottom: var(--m-rule-double);
}
.m-home__voices-title,
.m-theme-landing__voices-title {
    margin: 0 0 var(--m-space-5) 0;
    font-family: var(--m-font-display);
    font-size: var(--m-text-heading-sm);
    color: var(--m-accent-900);
    letter-spacing: -0.005em;
}
.m-author-row {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--m-space-4);
}
/* Home + theme voices rows cap at 4 columns from 48rem up so each author
   keeps a readable track (resp-04: the old 8-up squeezed names at 1280). */
@media (min-width: 48rem) {
    .m-author-row { grid-template-columns: repeat(4, 1fr); }
}
.m-author-row--theme { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 48rem) {
    .m-author-row--theme { grid-template-columns: repeat(4, 1fr); }
}

.m-author-card--mini {
    background: transparent;
    border: 0;
    padding: 0;
    border-radius: 0;
}
.m-author-card--mini__link {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
    text-decoration: none;
    color: var(--m-ink);
}
.m-author-card--mini__photo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    aspect-ratio: 1;
    border-radius: 50%;
    overflow: hidden;
    background: var(--m-accent-100);
    border: var(--m-rule-hairline);
}
.m-author-card--mini__photo img {
    width: 100%;
    height: 100%;
    aspect-ratio: 1;
    object-fit: cover;
}
/* The --placeholder variant is styled by the shared author monogram
   component below; only the disc geometry comes from the base above. */
.m-author-card--mini__text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.m-author-card--mini__name {
    font-family: var(--m-font-display);
    font-size: var(--m-text-card-sm);
    line-height: 1.2;
    color: var(--m-accent-900);
    font-weight: 600;
}
.m-author-card--mini__link:hover .m-author-card--mini__name,
.m-author-card--mini__link:focus-visible .m-author-card--mini__name {
    text-decoration: underline;
    text-decoration-color: var(--m-accent-500);
    text-underline-offset: 3px;
}
.m-author-card--mini__affiliation {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    color: var(--m-muted);
    line-height: 1.3;
    /* D7: the slot now takes short-bio fallback lines too, which run
       clause-length; clamp keeps the strip rows even. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.m-author-card--mini__count {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-eyebrow);
    /* Eyebrow size renders at 11.5px: --m-muted is banned below 12px,
       so this follows the date-eyebrow precedent onto accent-700. */
    color: var(--m-accent-700);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
}

/* ---------- Author monogram (one component, three discs) ----------
   Filled navy disc, white initials, wherever an author has no headshot:
   author-page hero (112px), article and contributors cards (72px), and
   the Voices mini card placeholder (64px disc from the mini __photo
   base). Decorative, aria-hidden in the markup; the inner span inherits
   color and type from the disc. Initials are sized to their disc, not
   to type jobs; deliberately off the named scale. Sits after the mini
   card block so its background out-cascades the mini __photo base tint.
   Merged from two prior implementations in Phase 7 (workstream G). */
.m-author__photo--monogram,
.m-author-card__photo--monogram,
.m-author-card--mini__photo--placeholder {
    margin: 0;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--m-accent-700);
    color: var(--m-surface);
    border-radius: 50%;
    font-family: var(--m-font-display);
    font-weight: 700;
    line-height: 1;
}
.m-author__photo--monogram { width: 112px; height: 112px; font-size: 2.3rem; }
.m-author-card__photo--monogram { width: 72px; height: 72px; font-size: 1.5rem; }
.m-author-card--mini__photo--placeholder { font-size: 1.25rem; border-color: transparent; }

/* ---------- Static content pages (Contribute, Get Mondial) ----------
 * Reusable building blocks that sit inside .m-article__body and reuse the
 * design-system tokens: a numbered process list, a definition list, simple
 * guideline/criteria lists, and a downloads grid. Shared so the Contribute
 * and Get Mondial pages stay visually consistent. */

/* Numbered process steps. The visible badge comes from a CSS counter; the
   <ol> keeps the ordered semantics for assistive tech. */
.m-steps {
    list-style: none;
    counter-reset: m-step;
    margin: var(--m-space-6) 0 var(--m-space-7);
    padding: 0;
}
.m-steps > li {
    counter-increment: m-step;
    position: relative;
    padding: 0 0 var(--m-space-6) 3.5rem;
}
.m-steps > li:last-child { padding-bottom: 0; }
.m-steps > li::before {
    content: counter(m-step);
    position: absolute;
    left: 0;
    top: 0;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--m-accent-700);
    color: #fff;
    border-radius: 50%;
    font-family: var(--m-font-sans);
    font-weight: 700;
    font-size: 1rem;
}
/* Connector line tying the step badges together (decorative). */
.m-steps > li:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 1.0625rem;
    top: 2.5rem;
    bottom: 0;
    width: 2px;
    background: var(--m-line);
}
.m-steps__title {
    display: block;
    margin-bottom: 0.15rem;
    font-family: var(--m-font-display);
    font-weight: 700;
    font-size: var(--m-text-subhead);
    line-height: 1.25;
    color: var(--m-accent-900);
}
.m-steps p { margin: 0; }

/* Definition list: a term in display serif with its description beneath. */
.m-deflist { margin: var(--m-space-6) 0 var(--m-space-7); }
.m-deflist dt {
    margin: var(--m-space-5) 0 var(--m-space-1);
    font-family: var(--m-font-display);
    font-weight: 700;
    font-size: var(--m-text-subhead);
    line-height: 1.25;
    color: var(--m-accent-900);
}
.m-deflist dt:first-child { margin-top: 0; }
.m-deflist dd { margin: 0; }

/* Plain guideline / criteria lists keep the body's reading rhythm. */
.m-guidelines,
.m-criteria {
    margin: var(--m-space-5) 0 var(--m-space-7);
    padding-left: var(--m-space-5);
}
.m-guidelines li,
.m-criteria li { margin: 0 0 var(--m-space-3); }
.m-guidelines li:last-child,
.m-criteria li:last-child { margin-bottom: 0; }

/* Downloads grid: bordered tiles, one per file. */
.m-resource-list {
    list-style: none;
    margin: var(--m-space-6) 0 var(--m-space-7);
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.85rem;
}
@media (min-width: 40rem) {
    .m-resource-list { grid-template-columns: 1fr 1fr; }
}
.m-resource-list > li { margin: 0; }
.m-resource-list a {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    height: 100%;
    padding: var(--m-space-4) 1.1rem;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    background: #fff;
    text-decoration: none;
    color: var(--m-accent-900);
    transition: border-color 120ms ease, background 120ms ease;
}
.m-resource-list a:hover,
.m-resource-list a:focus-visible {
    border-color: var(--m-accent-500);
    background: var(--m-accent-100);
}
.m-resource-list__name {
    font-family: var(--m-font-sans);
    font-weight: 600;
    font-size: 1rem;
}
.m-resource-list__meta {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-label);
    text-transform: uppercase;
    letter-spacing: var(--m-track-label);
    color: var(--m-muted);
}

/* ---------- Contributors index ---------- */
/* archive-mondial_author.php (session 18). One page, letter-grouped.
   Cards reuse .m-author-card (white surface, line border); the grid
   replaces the article-page vertical list. Letter headings reuse the
   small uppercase sans label treatment of .m-author__articles-heading. */

.m-contrib__letters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--m-space-2);
    margin: 0 0 var(--m-space-4) 0;
    font-family: var(--m-font-sans);
}
.m-contrib__letter {
    margin-top: var(--m-space-7);
    scroll-margin-top: var(--m-space-6);
}
.m-contrib-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: var(--m-space-4);
}
.m-author-card__count {
    margin: var(--m-space-1) 0 0 0;
    font-family: var(--m-font-sans);
    font-size: 0.85rem;
    color: var(--m-muted);
}
/* D7: two-line clamp, replacing the old single-line ellipsis; the slot
   now takes clause-length short-bio fallbacks, and one line cut most
   real affiliations mid-org anyway. */
.m-author-card--index .m-author-card__affiliation {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ===================================================================
   Ticket widget: floating Submit Ticket button plus dialog form.
   =================================================================== */
/* Mobile-first: a 44px round icon button. The full "Submit Suggestion"
   pill sat on top of article bylines at 375px, so under 40rem the label is
   dropped and the button's aria-label carries the accessible name. From
   40rem up there is room for the labelled pill. */
.m-ticket-button {
    position: fixed;
    right: var(--m-space-4);
    bottom: var(--m-space-4);
    z-index: 1000;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--m-space-2);
    width: 44px;
    height: 44px;
    padding: 0;
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    font-weight: 600;
    color: #fff;
    background: var(--m-accent-700);
    border: 0;
    border-radius: 50%;
    box-shadow: var(--m-shadow-soft);
    cursor: pointer;
}
.m-ticket-button:hover,
.m-ticket-button:focus-visible {
    background: var(--m-accent-900);
}
.m-ticket-button__icon { display: block; width: 20px; height: 20px; }
.m-ticket-button__label { display: none; }
@media (min-width: 40rem) {
    .m-ticket-button {
        width: auto;
        height: auto;
        padding: var(--m-space-3) var(--m-space-5);
        border-radius: var(--m-radius);
    }
    .m-ticket-button__icon { display: none; }
    .m-ticket-button__label { display: inline; }
}

.m-ticket-dialog {
    width: min(32rem, calc(100vw - 2rem));
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    padding: var(--m-space-6);
    background: var(--m-surface);
    color: var(--m-ink);
    box-shadow: var(--m-shadow-soft);
}
.m-ticket-dialog::backdrop {
    background: rgba(11, 37, 69, 0.45);
}
.m-ticket-form__title {
    font-family: var(--m-font-display);
    margin: 0 0 var(--m-space-2);
}
.m-ticket-form__intro {
    font-size: 0.95rem;
    color: var(--m-muted);
    margin: 0 0 var(--m-space-5);
}
.m-ticket-field {
    margin-bottom: var(--m-space-4);
}
.m-ticket-field label {
    display: block;
    font-family: var(--m-font-sans);
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: var(--m-space-1);
}
.m-ticket-optional {
    font-weight: 400;
    color: var(--m-muted);
}
.m-ticket-field input,
.m-ticket-field select,
.m-ticket-field textarea {
    width: 100%;
    font-family: var(--m-font-sans);
    /* 16px font-size avoids iOS Safari auto-zoom on focus. */
    font-size: 16px;
    padding: var(--m-space-2) var(--m-space-3);
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    background: #fff;
    color: var(--m-ink);
    box-sizing: border-box;
}
.m-ticket-field input[readonly] {
    color: var(--m-muted);
    background: var(--m-accent-100);
}
.m-ticket-hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.m-ticket-form__error {
    color: var(--m-warn);
    font-size: var(--m-text-meta);
    margin: 0 0 var(--m-space-4);
}
.m-ticket-form__actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--m-space-3);
}
/* font: inherit pulled the body serif into the dialog controls; the rest
   of the theme's UI is sans, and these are UI. */
.m-ticket-cancel {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    background: transparent;
    border: var(--m-rule-hairline);
    border-radius: var(--m-radius);
    padding: var(--m-space-2) var(--m-space-4);
    cursor: pointer;
    color: var(--m-ink);
}
.m-ticket-submit {
    font-family: var(--m-font-sans);
    font-size: var(--m-text-meta);
    font-weight: 600;
    background: var(--m-accent-700);
    color: #fff;
    border: 0;
    border-radius: var(--m-radius);
    padding: var(--m-space-2) var(--m-space-5);
    cursor: pointer;
}
.m-ticket-submit:hover {
    background: var(--m-accent-900);
}
.m-ticket-submit:disabled {
    opacity: 0.6;
    cursor: default;
}
.m-ticket-thanks {
    text-align: center;
}
