/* ════════════════════════════════════════════════════════════════
   MLO 2026 — Global Classes
   Variables come from theme.json (--wp--preset--*)

   STANDARD BREAKPOINTS (used throughout):
   - Mobile:  0 — 767px       (single column, hamburger menu)
   - Tablet:  768 — 1023px    (2-column layouts; hamburger still active)
   - Desktop: 1024px+         (full horizontal nav, multi-column, max-width 75rem)

   Header snippet uses 1023.98px as mobile cutoff (.98 avoids browser rounding edge case).
   Footer link grid drops from 4 to 2 columns at 540px (smaller phones).
   ════════════════════════════════════════════════════════════════ */

/* ── DESIGN TOKENS ── */
/* Mockup-derived spacing and color tokens used by the section system and any
   block that needs to align with section-level rhythm. Values match the EDGE,
   SECTION_PAD, bgSoft, and borderLight constants used consistently across all
   .jsx mockup files. */
:root {
  --mlo-edge: clamp(1.5rem, 4vw, 3.5rem);
  --mlo-section-pad: clamp(3.5rem, 8vw, 5rem);
  --mlo-bg-soft: #F7F8FA;
  --mlo-border-light: #F0F0F0;
  /* Inset / mat around artworks inside .mlo-artwork-image-area. Fluid clamp()
     follows the same pattern as --mlo-edge and --mlo-section-pad so the frame
     thickness scales naturally with viewport width. */
  --mlo-card-inset: clamp(1rem, 2.5vw, 1.5rem);
}

/* ── BUTTON ── */
/* `.mlo-btn-sky` works in three contexts:

   (1) Direct `<a class="mlo-btn-sky">…</a>` inside Custom HTML (e.g. Page Header
       CTA) — the <a> needs ALL button styling because it is not a Gutenberg button.

   (2) `<button class="mlo-btn-sky">` or `<input type="submit" class="mlo-btn-sky">`
       inside custom forms (e.g. EmailOctopus newsletter Subscribe button) —
       same: needs full button styling.

   (3) Gutenberg Button block — theme.json already provides full button styling
       (sky bg, white text, padding, font, uppercase). The class can be applied
       to either the inner Button block (wp-block-button) or the outer Buttons
       wrapper (wp-block-buttons); in either case, `.mlo-btn-sky` only adds the
       animated → arrow to the inner <a class="wp-block-button__link">.

   We deliberately do NOT style the Gutenberg wrapper or block container —
   applying display/padding to the wrapper breaks the section system's
   max-width/margin centering and doubles up styles the Gutenberg button
   already has from theme.json.

   Implementation: target ANY element with `.mlo-btn-sky` EXCEPT Gutenberg's
   wrapper divs (.wp-block-buttons and .wp-block-button). This catches anchors,
   form buttons, and submit inputs, while leaving the Gutenberg containers
   alone so margin: auto centering still works.

   The .wp-site-blocks ancestor selector is needed to override the GoDaddy
   Site Designer mu-plugin
   (.wp-site-blocks button[type="submit"]:not(.wp-element-button)) which
   auto-loads on GoDaddy hosting and has higher specificity. */

/* Cases 1 + 2: direct interactive element (a, button, input) — full styling */
.mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button),
.wp-site-blocks .mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button) {
  font-family: var(--wp--preset--font-family--body) !important;
  font-size: var(--wp--preset--font-size--ui) !important;
  font-weight: 600 !important;
  letter-spacing: var(--wp--custom--letter-spacing--normal) !important;
  text-transform: uppercase !important;
  color: var(--wp--preset--color--white) !important;
  background: var(--wp--preset--color--sky) !important;
  padding: 0.5625rem 1.375rem !important;
  text-decoration: none !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 0.5rem !important;
  line-height: 1 !important;
  border: 0 !important;
  cursor: pointer !important;
  transition: background 0.25s ease !important;
}
.mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button):hover,
.wp-site-blocks .mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button):hover {
  background: var(--wp--preset--color--hover) !important;
}
.mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button)::after {
  content: '→';
  display: inline-block;
  transition: transform 0.3s;
}
.mlo-btn-sky:not(.wp-block-buttons):not(.wp-block-button):hover::after {
  transform: translateX(2px);
}

/* Case 3: Gutenberg Button block — only add the → arrow; theme.json handles rest.
   Works whether the class lands on .wp-block-buttons (wrapper) or .wp-block-button
   (inner block) — both end up matching `.mlo-btn-sky .wp-block-button__link`. */
.mlo-btn-sky .wp-block-button__link::after {
  content: '→';
  display: inline-block;
  margin-left: 0.5rem;
  transition: transform 0.3s;
}
.mlo-btn-sky .wp-block-button__link:hover::after { transform: translateX(2px); }

/* ── ARROW LINK ── */
.mlo-arrow-link {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--ui);
  font-weight: 600;
  color: var(--wp--preset--color--sky);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  transition: color 0.2s;
}
.mlo-arrow-link::after {
  content: '→';
  transition: transform 0.3s;
}
.mlo-arrow-link:hover { color: var(--wp--preset--color--hover); }
.mlo-arrow-link:hover::after { transform: translateX(4px); }

/* ── TAG ── */
.mlo-tag {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  font-weight: 400;
  letter-spacing: var(--wp--custom--letter-spacing--tag);
  text-transform: uppercase;
  color: var(--wp--preset--color--sky);
  margin: 0;
}

/* Compact muted-mono row for "year · count · status" style meta lines.
   Used under H2 row titles in archives (e.g. collections) and beneath
   the H1 on collection single pages. Distinct from .mlo-tag, which is
   sky-colored uppercase signage; this is text-light, mixed-case, and
   typically holds metadata rather than category labels. The middot
   separators in the content itself (·) carry the visual rhythm; this
   class only handles font, size, color, and a vertical breathing
   margin matching the mockup. */
.mlo-meta-line {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
  margin: 0 0 1.5rem;
}

/* ── HEADINGS ── */
.mlo-heading-hero {
  font-family: var(--wp--preset--font-family--display);
  font-size: clamp(1.75rem, 3.5vw, 2.75rem);
  font-weight: 400;
  font-style: italic;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0;
}
.mlo-heading-page {
  font-family: var(--wp--preset--font-family--display);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 400;
  font-style: italic;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0.5rem 0;
}
.mlo-heading-section {
  font-family: var(--wp--preset--font-family--display);
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  font-weight: 400;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0 0 1rem;
}
.mlo-heading-newsletter {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.375rem;
  font-weight: 400;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0 0 0.5rem;
}

/* ── BODY ── */
.mlo-body-text {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body);
  line-height: var(--wp--custom--line-height--relaxed);
  color: var(--wp--preset--color--text-body);
  margin: 0 0 1rem;
}
.mlo-body-small {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  line-height: var(--wp--custom--line-height--snug);
  color: var(--wp--preset--color--text-body);
  margin: 0 0 0.5rem;
}
.mlo-mono-label {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  letter-spacing: var(--wp--custom--letter-spacing--tight);
  color: var(--wp--preset--color--sky);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
}
.mlo-mono-rule {
  display: inline-block;
  width: 1.25rem;
  height: 1px;
  background: var(--wp--preset--color--sky);
}

/* ── SECTION SYSTEM ── */
/* Sections are full-bleed background containers with constrained inner content.
   Each section is a `core/group` block in the editor with `mlo-section` plus
   one variant modifier class. The base class handles the full-viewport
   breakout, horizontal padding (from --mlo-edge), and inner-content constraint
   (max 75rem, centered).

   The width: 100vw + left: 50% + margin-left: -50vw trick breaks the section
   wrapper out of the constrained post-content layout to span the full
   viewport. box-sizing: border-box ensures the horizontal padding is included
   in the 100vw width (otherwise the section would overflow horizontally).

   The padding-inline lives on the section ITSELF, not on direct children.
   This is critical: putting it on `.mlo-section > *` works for simple block
   children (h1, p) but breaks for flex containers like wp-block-columns,
   where Gutenberg's column wrap behavior on mobile bypasses parent padding
   and content ends up flush to the viewport edges. With padding on the
   outer box, EVERY child — heading, paragraph, columns, HTML block, or any
   other block — sits at the same inner edge automatically.

   Variants:
     .mlo-section--header     sky-tint gradient fading to transparent (page top)
     .mlo-section--default    no background — sits on white page bg
     .mlo-section--soft       soft-grey bg with hairline borders top + bottom

   Order on a typical page: header (optional) then default / soft alternating.
   The transparent fade at the bottom of --header dissolves into the white of
   the next --default section, creating the "gradient runs into white" effect
   without any special structural handling. */
.mlo-section,
.mlo-section.has-global-padding,
.mlo-section.is-layout-constrained {
  width: 100vw !important;
  max-width: none !important;
  position: relative;
  left: 50%;
  margin-left: -50vw !important;
  margin-right: -50vw !important;
  padding-block: var(--mlo-section-pad);
  /* Both shorthand and longhand to defeat WordPress's longhand .has-global-padding
     rule, which sets padding-left/right to var(--wp--style--root--padding-*) = 0px. */
  padding-inline: var(--mlo-edge);
  padding-left: var(--mlo-edge) !important;
  padding-right: var(--mlo-edge) !important;
  box-sizing: border-box;
}

.mlo-section > * {
  max-width: var(--wp--style--global--content-size);
  margin-inline: auto;
}

/* Variant rules below need specificity matching the universal `.mlo-section`
   block above (which uses .mlo-section.is-layout-constrained = 0,2,0) so they
   actually win on cascade. We chain .mlo-section with the variant class to
   reach 0,2,0. Without this chaining, the variant rules silently lose to the
   universal rule. */

/* Header variant: sky-tint gradient. Matches mockup spec
   (padding: 3.5rem ${EDGE} 0; pills marginBottom: 5rem). We move the 5rem
   pills marginBottom into the section's bottom padding, so the breathing
   room lives at the section level (cleaner — the .mlo-pill-row class can be
   reused elsewhere without baking in this specific layout assumption). */
.mlo-section.mlo-section--header {
  padding-block: 3.5rem 5rem;
  background: linear-gradient(180deg, rgba(57,120,172,0.07) 0%, transparent 100%);
}

/* Default variant: no background, no border. Inherits base padding-block. */
.mlo-section.mlo-section--default {
  /* Intentionally empty — base section padding applies. */
}

/* Soft variant: alternating bg with hairline top + bottom borders. The
   borders are what create the visual rhythm between consecutive --default
   and --soft sections; --default has no borders, so transitions only show
   where the background shifts. */
.mlo-section.mlo-section--soft {
  background: var(--mlo-bg-soft);
  border-block: 1px solid var(--mlo-border-light);
}

/* The first section immediately after the page header gets 0 top padding
   AND 0 top margin. The header's 5rem bottom padding (above) provides
   all the breathing room between the pills/title area and the next
   section's content, matching the mockup's "header padding-bottom: 0 +
   pills marginBottom: 5rem + hero padding-top: 0" stacking. Total
   visible gap: 5rem (80px).

   Two selectors so the rule fires whether the page header carries the
   .mlo-section--header modifier (the recipe's intended setup) OR is
   just a plain .mlo-section--default (the actual state on the
   Publications page as built). The second selector — ".wp-block-post-
   content > .mlo-section:first-child + .mlo-section" — targets "the
   .mlo-section that immediately follows the FIRST .mlo-section inside
   the post-content container," which by convention IS the page header.
   This makes the override structural rather than dependent on a
   specific modifier class.

   The rule is !important and zeros both padding-block-start and
   margin-block-start because in practice the override has to defeat:
     - the base .mlo-section padding-block at 0,2,0,
     - any padding set via the editor's Dimensions panel (which Gutenberg
       emits as a 0,1,0 inline style on the rendered element),
     - the block-gap-driven margin-block-start (24px from theme.json)
       the parent layout-flow container injects between sibling sections.

   The second selector zeros margin-block-start on the section's first
   child so that a first-child Columns block (which itself becomes a
   layout-flow container) can't push its inner contents — the section
   tag, the H2 — down by block-gap. */
.mlo-section--header + .mlo-section,
.wp-block-post-content > .mlo-section:first-child + .mlo-section {
  padding-block-start: 0 !important;
  margin-block-start: 0 !important;
}
.mlo-section--header + .mlo-section > *:first-child,
.wp-block-post-content > .mlo-section:first-child + .mlo-section > *:first-child {
  margin-block-start: 0 !important;
}

/* Page Header section: explicit breadcrumb → H1 vertical rhythm.
   The header appears on both /work/studio-notes/ (Gutenberg-composed
   .wp-block-group with .is-layout-flow) and /work/studio-notes/{slug}/
   (PHP-rendered div, no .is-layout-flow). On the Gutenberg page, the
   flow-layout rule (.wp-block-group.is-layout-flow > * + * { margin-
   block-start: var(--wp--style--block-gap) }) automatically gives the
   H1 a block-gap top margin. On the PHP-rendered page, no such rule
   fires and the gap falls back to whatever the .mlo-breadcrumb base
   (margin-block: 0 1rem) and .mlo-heading-page base (margin: 0.5rem 0)
   produce — visibly tighter than the studio archive's block-gap.

   The two rules below force the same value on every header section:
     - Breadcrumb: zero margins, so the gap "belongs" entirely to the H1.
     - H1: margin-block-start = block-gap, margin-block-end = 0.

   The H1 → filter-row gap is handled separately in the NEWS SYSTEM
   section (the .mlo-page-subtitle + .mlo-news-filter-row and
   .mlo-heading-page + .mlo-news-filter-row rules give that gap 2-3rem).
   The .mlo-section--header--note-category class is still emitted by the
   server-renderer for any future category-archive-specific tweaks. */
.mlo-section.mlo-section--header > .mlo-breadcrumb {
  margin-block: 0 !important;
}
.mlo-section.mlo-section--header > .mlo-heading-page {
  margin-block-start: var(--wp--style--block-gap, 1.5rem) !important;
  margin-block-end: 0 !important;
}

/* Remove WordPress's default 24px top margin between the fixed header and the
   main content area. WP applies `:where(.wp-site-blocks) > * { margin-block-start: 24px }`
   which targets <main> as the second direct child of .wp-site-blocks. The !important
   defeats any cache-layer staleness. */
.wp-site-blocks > main {
  margin-block-start: 0 !important;
}

/* Editor-only override: in the post editor and Site Editor, the 100vw breakout
   on .mlo-section causes backgrounds (gradient, soft-grey) to extend behind
   the right sidebar — the iframe is the full browser width but the visible
   canvas isn't, so unconstrained sections look shifted right and clipped.
   Inside the editor we constrain every section to its parent (~75rem wide,
   centered in the canvas), which is the right preview affordance. The
   front-end behavior (true 100vw backgrounds) is unaffected. The
   `.editor-styles-wrapper` class is added by WP only to the editor canvas
   body, so this rule is inert on the front-end. */
.editor-styles-wrapper .mlo-section {
  width: auto;
  left: auto;
  margin-left: 0;
}

/* ── COLUMNS GAP INSIDE SECTIONS ── */
/* Gutenberg's default column gap (--wp--style--block-gap = 24px) is too tight
   for the mockup design language. Inside sections, columns get a wider gap
   matching the mockup's clamp(4rem, 8vw, 7rem) on desktop, with 1.5rem on
   mobile when columns stack vertically (Gutenberg's stacking breakpoint is
   782px).

   A specific Columns block can override this by setting Block Spacing in the
   sidebar (Dimensions → Block Spacing), which generates inline gap that wins
   over this rule. Useful for tight grids like the Press Kit cards. */
.mlo-section .wp-block-columns {
  gap: 1.5rem;
}

@media (min-width: 782px) {
  .mlo-section .wp-block-columns {
    gap: clamp(4rem, 8vw, 7rem);
  }
}

/* When multiple Columns blocks stack within a section (e.g. the CV grid uses
   three Columns blocks for a 3-row × 2-col layout), give them more vertical
   breathing than Gutenberg's default 24px block-gap. Matches the mockup's
   row-gap of 2.5rem in the original CSS-Grid implementation. */
.mlo-section .wp-block-columns + .wp-block-columns {
  margin-block-start: 2.5rem;
}

/* Editor-only: align the "Add title" field with constrained content. */
.editor-styles-wrapper .editor-post-title,
.editor-styles-wrapper .editor-post-title__input,
.editor-styles-wrapper .editor-post-title__block,
.editor-styles-wrapper .wp-block-post-title {
  max-width: var(--wp--style--global--content-size) !important;
  margin-inline: auto !important;
  padding-inline: clamp(1.5rem, 4vw, 3.5rem) !important;
  box-sizing: border-box !important;
}

/* Editor-only: the "Type / to choose a block ..." prompt isn't actually a
   `block-editor-default-block-appender` component (the documented appender
   classes don't apply). It's a regular empty `core/paragraph` block sitting
   at the end of an inner-blocks list, with `data-empty="true"` set by Gutenberg
   to flag the placeholder state. (Rank Math's Content AI extends the placeholder
   text via `data-custom-placeholder="true"` but the underlying element is
   still a vanilla empty paragraph.) Targeting the data-empty attribute aligns
   the placeholder with constrained content; once the user starts typing, the
   attribute flips to false and the rule stops applying so the live content
   block gets normal layout treatment. */
.editor-styles-wrapper [data-empty="true"][data-type="core/paragraph"] {
  max-width: var(--wp--style--global--content-size) !important;
  margin-inline: auto !important;
  padding-inline: clamp(1.5rem, 4vw, 3.5rem) !important;
  box-sizing: border-box !important;
}
.mlo-page-subtitle {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body);
  line-height: var(--wp--custom--line-height--normal);
  color: var(--wp--preset--color--text-muted);
  max-width: 40rem;
  margin: 1rem 0 0;
}
.mlo-breadcrumb {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  letter-spacing: var(--wp--custom--letter-spacing--normal);
  color: var(--wp--preset--color--text-light);
  margin-block: 0 1rem;
}
.mlo-breadcrumb a {
  color: var(--wp--preset--color--text-light);
  text-decoration: none;
}
.mlo-breadcrumb a:hover { color: var(--wp--preset--color--sky); }
.mlo-breadcrumb .current { color: var(--wp--preset--color--text-muted); }

/* ── PILLS ── */
.mlo-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wp--preset--spacing--sm);
  margin-top: 1.5rem;
}
.mlo-pill {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--meta);
  font-weight: 500;
  line-height: 1.4;
  color: var(--wp--preset--color--text-muted);
  background: transparent;
  border: 1px solid var(--wp--preset--color--border);
  border-radius: 1rem;
  padding: var(--wp--preset--spacing--xs) 0.875rem;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.2s;
}
.mlo-pill:hover {
  border-color: var(--wp--preset--color--sky);
  color: var(--wp--preset--color--sky);
}
.mlo-pill-active {
  background: var(--wp--preset--color--sky-light);
  border-color: var(--wp--preset--color--sky);
  color: var(--wp--preset--color--sky);
}

/* ── LAYOUT HELPERS ── */
.mlo-max-width {
  max-width: 75rem;
  margin: 0 auto;
}
.mlo-section-padding {
  padding: clamp(3.5rem, 8vw, 5rem) clamp(1.5rem, 4vw, 3.5rem);
}
.mlo-section-grey {
  background: var(--wp--preset--color--bg-soft);
}
.mlo-two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
/* Override .mlo-two-col's align-items: center for cards specifically.
   When cards have uneven content height, align-items: center makes
   shorter cards sit lower than taller ones. Cards should top-align
   and stretch to equal height instead. */
.mlo-two-col > .mlo-note-card,
.mlo-two-col > .mlo-definition-card,
.mlo-two-col > .mlo-card-explore {
  align-self: stretch;
}
@media (max-width: 768px) {
  .mlo-two-col { grid-template-columns: 1fr; }
}
/* Three-column grid for artwork grids and similar listings. Explicit column
   count (not auto-fit) so the editor and front-end render identically — fluid
   auto-fit was producing 2 cols in narrow editor canvas, 4 cols in wide canvas,
   3 cols on the front-end, all from the same markup. WYSIWYG drift. */
.mlo-three-col {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.5rem;
}

@media (max-width: 1024px) {
  .mlo-three-col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
  .mlo-three-col { grid-template-columns: minmax(0, 1fr); }
}

/* Zero out WP's :root :where(.is-layout-constrained) > *{margin-block-start:24px}
   on grid children. In CSS Grid that 24px doesn't just nudge later items down
   — it shrinks their stretched height by 24px (since the cell is fixed and
   the item now starts 24px in). Effect: card 1 (exempt via :first-child) fills
   its cell, cards 2+ are 24px shorter and start lower, so the row looks
   uneven. WP's rule is (0,1,0) and loads after classes.css, so the override
   needs !important to win on equal-specificity source-order.
   `gap` on the grid handles inter-item spacing instead. */
.mlo-three-col > *,
.mlo-two-col > * {
  margin-block-start: 0 !important;
}

/* === CARD INTERNAL RHYTHM OVERRIDES ===
   WP's global-styles inline CSS loads AFTER classes.css in this build and
   imposes two rules that bleed uniform 24px spacing into every card:
     :root :where(.is-layout-constrained) > * { margin-block-start: 24px }
     :root :where(.is-layout-flex)        { gap: 24px }
   Every direct child of a constrained Group gets 24px top margin (image,
   date, title, excerpt — uniformly). Every flex Group gets 24px gap (Row
   between num+title, stack between Row/description/venues — uniformly).
   That uniform rhythm matches the publication-card body design but is
   wrong for stat blocks, topic cards, and note cards, which want tight
   per-element spacing controlled by each child's own margin-bottom (already
   defined on __date, __title, __excerpt, __media etc).

   We zero margin-block-start on direct children, and set explicit small
   flex gaps on the topic-card flex column and its inner Row. The cards'
   own padding rules (1.25rem / 1.5rem / 1rem) and the children's own
   margin-bottom values then control the actual rhythm. */
.mlo-stat-block > *,
.mlo-card-blue-border > *,
.mlo-note-card > * {
  margin-block-start: 0 !important;
}

/* Topic card is is-layout-flex (column). Override WP's default 24px flex
   gap with a tighter value matching the mockup. Same override for the
   inner Row block (num + title), which is also is-layout-flex. */
.mlo-card-blue-border,
.mlo-card-blue-border > .is-layout-flex {
  gap: 0.5rem !important;
}

/* ── CARDS ── */
.mlo-card-explore {
  display: block;
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
  padding: var(--wp--preset--spacing--lg);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.25s;
}
.mlo-card-explore:hover {
  border-color: var(--wp--preset--color--sky);
}
/* Grey variant — mirrors the existing --soft convention used by
   .mlo-note-card--soft and .mlo-publication-card--soft. On the homepage
   the Research deep-dive cards sit in a white (default) section, so the
   grey fill restores the card definition they have on the research
   landing page (where the same cards sit white-on-soft). Add alongside
   the base class: class="mlo-card-explore mlo-card-explore--soft". */
.mlo-card-explore--soft {
  background: var(--wp--preset--color--bg-soft);
}
/* ── Images inside .mlo-card-explore ──
   The card was originally built for text-only Continue Reading entries,
   so no img rule was needed. When the research-landing page added Deep
   Dive cards with images inside via Custom HTML (raw <img> tags, not
   .wp-block-image figures), the images rendered at their intrinsic width
   and overflowed the card horizontally — WordPress only applies its
   default max-width:100% to .wp-block-image, not to raw img elements.

   This rule scopes the constraint to images inside explore-cards
   specifically (so it doesn't blanket-apply to every img on the site).
   width:100% fills the card content box; height:auto preserves the
   image's natural aspect ratio (16:9, 4:3, whatever was uploaded);
   display:block removes the baseline-gap whitespace below the image
   that inline-img elements otherwise introduce. */
.mlo-card-explore img {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: 1.25rem;   /* matches the mockup's image-to-tag gap;
                               .mlo-mono-tag has no top margin so this
                               is the sole source of vertical rhythm
                               between the image and the tag below it */
}
.mlo-card-title {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--base);
  font-weight: 400;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0 0 0.5rem;
}
.mlo-card-blue-border {
  background: var(--wp--preset--color--bg-soft);
  border: 1px solid var(--wp--preset--color--border-light);
  border-left: 3px solid var(--wp--preset--color--sky);
  padding: 1.5rem !important;
  padding-left: 1.75rem !important;
}

/* ── STAT BLOCK ── */
.mlo-stat-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--wp--preset--spacing--xxs);
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
  padding: 1.25rem !important;
  height: 100%;
}
.mlo-stat-number {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.75rem;
  font-weight: 400;
  line-height: var(--wp--custom--line-height--tight);
  color: var(--wp--preset--color--text);
  margin: 0;
}
.mlo-stat-label {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--sm);
  color: var(--wp--preset--color--text-muted);
  margin: 0;
}

/* ── ARTWORK CARD ──
   Used on the artwork catalogue page (/work/catalogue/) and anywhere an
   artwork is presented in a grid (Related Artworks blocks, Selected Works,
   etc).

   Design: the image-area is a square soft-grey backdrop that frames any
   artwork aspect ratio. Landscape works sit letterboxed (whitespace top +
   bottom), portrait works sit pillarboxed (whitespace left + right), square
   works fit edge-to-edge inside the inset. This gives a consistent grid
   rhythm across all formats so cards line up horizontally regardless of
   orientation. Implementation notes:

   - object-fit: contain on the img preserves the source aspect ratio. We
     deliberately do NOT use object-fit: cover here — cropping every artwork
     to a square would defeat the catalogue's purpose.
   - --mlo-card-inset (clamp-based, fluid) scales the visible "mat" around
     the artwork with viewport width.
   - .mlo-artwork-card__meta is left-aligned with title + edition stacked. */
.mlo-artwork-card {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  transition: transform 0.3s ease;
}
.mlo-artwork-card:hover {
  transform: translateY(-3px);
}
.mlo-artwork-card__link {
  text-decoration: none;
  color: inherit;
  display: block;
}
.mlo-artwork-image-area {
  aspect-ratio: 1 / 1;
  background: var(--mlo-bg-soft);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--mlo-card-inset);
  margin-bottom: 0.875rem;
}
.mlo-artwork-image-area img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
/* Backdrop modifier: when the card carries .mlo-artwork-card--bg-white,
   swap the soft-grey image-area backdrop for white. Used on hub pages
   where the surrounding section is already soft-grey and the cards need
   to lift off it (Work landing previews). The base grey remains the
   default — used by the catalogue archive and anywhere the card sits
   on a white section. */
.mlo-artwork-card--bg-white .mlo-artwork-image-area {
  background: #fff;
}
/* Legacy badge overlay — kept for any pre-catalogue templates that may still
   use it (e.g. Related Artworks blocks). The catalogue cards don't render
   this; type appears in filter pills instead. */
.mlo-artwork-badge {
  position: absolute;
  top: 0.625rem;
  right: 0.625rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  letter-spacing: var(--wp--custom--letter-spacing--wide);
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
  background: rgba(255,255,255,0.85);
  padding: 0.1875rem 0.5rem;
}
.mlo-artwork-card__meta {
  /* Title + edition stacked, left-aligned. No padding-top — the image-area
     handles its own margin-bottom. */
}
.mlo-artwork-card__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--base);
  font-weight: 400;
  line-height: 1.4;
  margin: 0 0 0.375rem;
  color: var(--wp--preset--color--text);
}
/* Edition row: "Edition n/n" + optional collected dot, inline. */
.mlo-artwork-card__edition {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
}
/* Collected indicator dot — appears only when the artwork's ACF status
   field === "collected". Style is the same red used in other "sold" /
   "collected" indicators across the site. */
.mlo-artwork-card__dot {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: #C45A5A;
  flex-shrink: 0;
}
.mlo-collection-link {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  letter-spacing: var(--wp--custom--letter-spacing--tight);
  color: var(--wp--preset--color--sky);
  text-decoration: none;
  margin: 0;
  transition: color 0.2s;
}
.mlo-collection-link:hover { color: var(--wp--preset--color--hover); }

/* ── CATALOGUE — FILTER ROW + 4-COL GRID ──
   The catalogue page (/work/catalogue/) extends the news / studio-notes
   archive pattern in two ways:

   1. Filter row 1 puts Type (left) and Status (right) on the same row via
      .mlo-catalogue-filter-row. flex-wrap lets each group drop to its own
      row at narrow desktop widths. Filter row 2 (Year) is a standard
      .mlo-news-filter-row, full width, below.

   2. .mlo-year-grid--catalogue is a modifier on .mlo-year-grid that gives
      a 4-column grid at desktop. The base .mlo-year-grid handles mobile
      (1 col) and tablet (3 cols, min-width 782px). At 1024px+ we override
      to 4 cols for catalogue density. */
.mlo-catalogue-filter-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}
@media (max-width: 767px) {
  .mlo-catalogue-filter-row {
    flex-direction: column;
    align-items: flex-start;
  }
}
/* Inside the catalogue's two-up wrapper, override the news-archive flex-grow
   so each inner pill row sizes to its content (pills). Without this, the
   pill row inherits .mlo-news-filter-row > .mlo-pill-row { flex: 1 1 0 },
   which causes each child .mlo-news-filter-row to expand to fill all the
   available width — pushing the Status row to wrap to a new line below Type.
   With flex: 0 1 auto, Type and Status sit side-by-side and justify-content:
   space-between distributes the remaining space between them. */
.mlo-catalogue-filter-row > .mlo-news-filter-row > .mlo-pill-row {
  flex: 0 1 auto;
}
/* Reset margin-top on the second inner news-filter-row (Status). The general
   .mlo-news-filter-row + .mlo-news-filter-row { margin-top: 1rem } rule in
   the NEWS SYSTEM block below is written for vertically-stacking news /
   studio-notes archives — but inside the catalogue's flex
   .mlo-catalogue-filter-row, that 1rem margin lives on Status's margin-box,
   which then gets centered by align-items: center, shifting Status's
   visible box ~0.5rem lower than Type and misaligning their bottoms.
   The selector below is intentionally one level more specific (0,3,0) than
   the rule it's overriding (0,2,0) so it wins the cascade regardless of
   the fact that it appears earlier in the file. */
.mlo-catalogue-filter-row > .mlo-news-filter-row + .mlo-news-filter-row {
  margin-top: 0;
}
@media (min-width: 1024px) {
  .mlo-year-grid--catalogue {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ── HISTORY TIMELINE ── */

/* The timeline wrapper sits in the same .mlo-section--default as the
   YEAR pill row above it, so the only gap separating them is WordPress's
   default block-gap (1.5rem ≈ 24px). That's tighter than the equivalent
   pill-row-to-controls gap on /news/ and /studio-notes/, where the pill
   row lives in the header section and the .mlo-news-controls sits in the
   following default section — the section's padding-block-start provides
   the gap there (~5rem).

   On the history page that section-boundary mechanism doesn't apply, so
   we add an explicit margin here (~50% larger than WP's block-gap) to
   restore some breathing room above the count + expand/collapse controls.
   Scoped to the #mlo-history-timeline id so it stays history-only and
   does not bleed into other archives. */
#mlo-history-timeline {
  margin-block-start: 2.25rem;
}

.mlo-history-year {
  margin: 3rem 0;
  scroll-margin-top: 6rem;
}
.mlo-history-year__heading {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--lg);
  font-weight: 400;
  color: var(--wp--preset--color--text);
  border-bottom: 1px solid var(--wp--preset--color--border);
  padding-bottom: 0.5rem;
  margin: 0 0 1.5rem;
}
.mlo-history-year__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
/* History timeline entry — full-width ROW matching the mockup's
   TimelineEntry: a 15rem featured-image column on the left and the content
   (date + badges, title, description, links) on the right, stacked
   vertically down the year. On mobile it becomes a single block (image
   above content). Rendered by mlo_render_history_entry(). Entries sit in
   .mlo-year-grid--stack so the year accordion's collapse rule still applies.
   Every inner element is optional; the markup omits anything with no data. */

/* Timeline stack: override the news 3-column .mlo-year-grid so timeline
   entries are full-width rows. The base .mlo-year-grid collapse rule
   (display:none when the year section is collapsed) still governs it. */
/* Chained selector (.mlo-year-grid.mlo-year-grid--stack) so this beats the
   base .mlo-year-grid { display: grid } regardless of source order — the
   base rule appears LATER in the file, so a single-class override would lose
   the cascade. The collapse rule (.mlo-year-section[data-expanded="false"]
   .mlo-year-grid) is still more specific, so collapsing a year still works. */
.mlo-year-grid.mlo-year-grid--stack {
  display: block;
}

.mlo-history-entry {
  display: grid;
  grid-template-columns: 15rem 1fr;
  gap: 3rem;
  align-items: start;
  background: var(--wp--preset--color--bg-soft);
  border: 1px solid var(--wp--preset--color--border-light);
  padding: 1.75rem;
  margin-bottom: 2.5rem;
}
.mlo-history-entry:last-child {
  margin-bottom: 0;
}
@media (max-width: 781px) {
  .mlo-history-entry {
    display: block;
    padding: 1.25rem;
    margin-bottom: 2rem;
  }
}

.mlo-history-entry__media {
  margin: 0;
}
.mlo-history-entry__img {
  display: block;
  width: 100%;
  height: auto;
}
/* Entries with no featured image render content-only (no empty media column). */
.mlo-history-entry--no-media {
  grid-template-columns: 1fr;
}
@media (max-width: 781px) {
  .mlo-history-entry__media {
    margin-bottom: 1.25rem;
  }
}

.mlo-history-entry__body {
  min-width: 0;
}
.mlo-history-entry__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.625rem;
}
.mlo-history-entry__date {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
}
.mlo-history-entry__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
  margin: 0 0 0.5rem;
  color: var(--wp--preset--color--text);
}
@media (max-width: 781px) {
  .mlo-history-entry__title {
    font-size: 0.9375rem;
  }
}
.mlo-history-entry__title a {
  color: var(--wp--preset--color--text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
}
.mlo-history-entry__title a:hover {
  border-bottom-color: var(--wp--preset--color--sky);
}
.mlo-history-entry__desc {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  line-height: 1.7;
  color: var(--wp--preset--color--text-body);
  margin: 0 0 1rem;
}
@media (max-width: 781px) {
  .mlo-history-entry__desc {
    font-size: 0.75rem;
  }
}
.mlo-history-entry__footnote {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-muted);
  margin: 0.75rem 0 0;
  line-height: 1.6;
}
.mlo-history-entry__links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.25rem;
}

/* Suggest a Milestone form — matches the mockup exactly: two stacked
   columns (left: Email/Title/Date, right: Source URL/Description), boxed
   white inputs on the soft-grey section, and a plain sky submit button
   (NO injected arrow, unlike .mlo-btn-sky). Posts via htmx; the status
   span is swapped with a confirmation/error message. */
.mlo-suggest-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem clamp(4rem, 8vw, 7rem);
}
@media (max-width: 768px) {
  .mlo-suggest-form { grid-template-columns: 1fr; gap: 1.25rem; }
}
.mlo-suggest-form__col {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.mlo-suggest-form__field--grow {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.mlo-suggest-form__label {
  display: block;
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--wp--preset--color--text-muted);
  margin: 0 0 0.375rem;
}
/* !important + .wp-site-blocks prefix required to beat the GoDaddy Site
   Designer rule body .wp-site-blocks input:not([type="submit"])... (0,9,2),
   same as the newsletter input above. Without this the theme repaints these
   fields and the boxed styling never shows. */
.wp-site-blocks .mlo-suggest-form__input,
.mlo-suggest-form__input {
  width: 100% !important;
  height: 2.5rem !important;
  box-sizing: border-box !important;
  font-family: var(--wp--preset--font-family--body) !important;
  font-size: var(--wp--preset--font-size--ui) !important;
  color: var(--wp--preset--color--text) !important;
  background: var(--wp--preset--color--white) !important;
  border: 1px solid var(--wp--preset--color--border) !important;
  border-radius: 0 !important;
  padding: 0 0.75rem !important;
}
.wp-site-blocks .mlo-suggest-form__textarea,
.mlo-suggest-form__textarea {
  width: 100% !important;
  min-height: 5.5rem !important;
  box-sizing: border-box !important;
  font-family: var(--wp--preset--font-family--body) !important;
  font-size: var(--wp--preset--font-size--ui) !important;
  color: var(--wp--preset--color--text) !important;
  background: var(--wp--preset--color--white) !important;
  border: 1px solid var(--wp--preset--color--border) !important;
  border-radius: 0 !important;
  padding: 0.625rem 0.75rem !important;
  resize: vertical !important;
}
.mlo-suggest-form__field--grow .mlo-suggest-form__textarea {
  flex: 1 1 auto;
}
.wp-site-blocks .mlo-suggest-form__input:focus,
.mlo-suggest-form__input:focus,
.wp-site-blocks .mlo-suggest-form__textarea:focus,
.mlo-suggest-form__textarea:focus {
  outline: none !important;
  border-color: var(--wp--preset--color--sky) !important;
}
.mlo-suggest-form__helper {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.6875rem;
  color: var(--wp--preset--color--text-light);
  margin: 0.375rem 0 0;
  line-height: 1.5;
}
.mlo-suggest-form__actions {
  margin-top: 1.5rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
/* .wp-site-blocks prefix + !important to beat the GoDaddy mu-plugin rule
   .wp-site-blocks button[type="submit"]:not(.wp-element-button) — the same
   override .mlo-btn-sky needs. (No injected arrow here, unlike .mlo-btn-sky.) */
.wp-site-blocks .mlo-suggest-form__submit,
.mlo-suggest-form__submit {
  display: inline-block !important;
  font-family: var(--wp--preset--font-family--body) !important;
  font-size: 0.75rem !important;
  font-weight: 600 !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  color: var(--wp--preset--color--white) !important;
  background: var(--wp--preset--color--sky) !important;
  border: none !important;
  border-radius: 0 !important;
  padding: 0.625rem 1.75rem !important;
  cursor: pointer !important;
  transition: background 0.25s !important;
}
.wp-site-blocks .mlo-suggest-form__submit:hover,
.mlo-suggest-form__submit:hover {
  background: #2D2D2D !important;
}
.mlo-suggest-form__status {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--ui);
}
.mlo-suggest-form__status--ok { color: var(--wp--preset--color--sky); }
.mlo-suggest-form__status--err { color: #c0392b; }

/* ── LOGO ── */
.mlo-logo {
  display: inline-block;
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--base);
  color: var(--wp--preset--color--text);
  text-decoration: none;
  white-space: nowrap;
  letter-spacing: -0.01em;
  line-height: 1.2;
  transition: color 0.25s;
}
.mlo-logo:hover { color: var(--wp--preset--color--sky); }
.mlo-logo strong { font-weight: 700; }

/* ── FOOTER ── */
.mlo-footer {
  margin-top: 4rem;
}
.mlo-footer__newsletter {
  background: var(--wp--preset--color--bg-soft);
  border-top: 1px solid var(--wp--preset--color--border-light);
  border-bottom: 1px solid var(--wp--preset--color--border-light);
  padding: 3rem clamp(1.5rem, 4vw, 3.5rem);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.625rem;
}
.mlo-footer__newsletter-intro {
  font-size: var(--wp--preset--font-size--body-sm);
  color: var(--wp--preset--color--text-muted);
  margin: 0 0 1rem;
  max-width: 32rem;
}
.mlo-footer__newsletter-form {
  display: flex;
  gap: 0.5rem;
  max-width: 24rem;
  width: 100%;
  margin: 0 auto;
}
/* !important required to override GoDaddy Site Designer mu-plugin which targets
   body .wp-site-blocks input:not([type="submit"])...:not([type="hidden"]) — that selector
   has specificity (0,9,2) and applies background, color, and border to all our inputs. */
.wp-site-blocks .mlo-footer__newsletter-input,
.mlo-footer__newsletter-input {
  flex: 1 !important;
  padding: 0.6875rem 1rem !important;
  border: 1px solid var(--wp--preset--color--border) !important;
  background: var(--wp--preset--color--white) !important;
  font-family: var(--wp--preset--font-family--body) !important;
  font-size: var(--wp--preset--font-size--body-sm) !important;
  color: var(--wp--preset--color--text) !important;
}
.mlo-footer__newsletter-input:focus {
  outline: 2px solid var(--wp--preset--color--sky) !important;
  outline-offset: 2px !important;
}
.mlo-footer__newsletter-fineprint {
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
  margin: 0.75rem 0 0;
}

.mlo-footer__links {
  display: grid;
  grid-template-columns: 2.5fr 1fr 1fr 1fr 1fr;
  gap: 2rem;
  padding: 2.5rem clamp(1.5rem, 4vw, 3.5rem);
  max-width: 75rem;
  margin: 0 auto;
}
@media (max-width: 768px) {
  .mlo-footer__links { grid-template-columns: repeat(4, 1fr); }
  .mlo-footer__brand { grid-column: 1 / 5; }
}
@media (max-width: 540px) {
  .mlo-footer__links { grid-template-columns: 1fr 1fr; }
  .mlo-footer__brand { grid-column: 1 / 3; }
}
.mlo-footer__tagline {
  font-size: var(--wp--preset--font-size--ui);
  line-height: var(--wp--custom--line-height--snug);
  color: var(--wp--preset--color--text-muted);
  margin: 0.5rem 0 0;
}
.mlo-footer__col {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.mlo-footer-heading {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--meta);
  font-weight: 700;
  letter-spacing: var(--wp--custom--letter-spacing--wide);
  text-transform: uppercase;
  color: var(--wp--preset--color--text);
  margin: 0;
}
.mlo-footer-heading a {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s;
}
.mlo-footer-heading a:hover { color: var(--wp--preset--color--sky); }
.mlo-footer-link {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--ui);
  color: var(--wp--preset--color--text-muted);
  text-decoration: none;
  transition: color 0.2s;
}
.mlo-footer-link:hover { color: var(--wp--preset--color--sky); }
.mlo-footer__contact-link { margin-top: 1rem; margin-bottom: 0; }

.mlo-footer__bottom {
  border-top: 1px solid var(--wp--preset--color--border-light);
  padding: 1.25rem clamp(1.5rem, 4vw, 3.5rem);
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: 75rem;
  margin: 0 auto;
  flex-wrap: wrap;
  gap: 1rem;
}
@media (max-width: 540px) {
  .mlo-footer__bottom { flex-direction: column; align-items: center; }
}
.mlo-footer-meta {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
  text-decoration: none;
  margin: 0;
  transition: color 0.2s;
}
.mlo-footer-meta:hover { color: var(--wp--preset--color--sky); }
.mlo-footer__socials {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  justify-content: center;
}

/* ── HERO INTRO (about page) ── */
.mlo-hero-intro__image {
  aspect-ratio: 4 / 5;
  background: var(--wp--preset--color--bg-soft);
}

/* ── INFO CARD (about page biography short-bio card) ── */
.mlo-mono-tag-uppercase {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
  margin: 0 0 0.75rem;
}

/* Mono tag — lowercase variant. Used on topic-card venue lines
   (e.g. "Kunsthalle Zürich · Crypto Art Seoul · NFC Lisbon") where
   the source casing should be preserved and no auto-margin is
   wanted (caller controls vertical rhythm via block-spacing). */
.mlo-mono-tag {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  letter-spacing: 0.06em;
  color: var(--wp--preset--color--text-light);
  margin: 0;
}

.mlo-copy-btn {
  margin-top: 1rem;
  padding: 0.5rem 1rem;
  background: none;
  border: 1px solid var(--wp--preset--color--border);
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-muted);
  cursor: pointer;
  letter-spacing: 0.04em;
  transition: border-color 0.25s, color 0.25s;
}
.mlo-copy-btn:hover {
  border-color: var(--wp--preset--color--sky);
  color: var(--wp--preset--color--sky);
}

/* ── CV LIST (about page Curriculum Vitae section) ── */
.mlo-cv-heading {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--meta);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text);
  margin: 0 0 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 2px solid var(--wp--preset--color--sky);
  display: inline-block;
}
.mlo-cv-list {
  display: flex;
  flex-direction: column;
}
.mlo-cv-item {
  display: flex;
  gap: 1rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--mlo-border-light);
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  color: var(--wp--preset--color--text-body);
  line-height: 1.5;
}
.mlo-cv-item:last-child {
  border-bottom: none;
}
.mlo-cv-year {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--ui);
  color: var(--wp--preset--color--text-light);
  min-width: 3rem;
  flex-shrink: 0;
}

/* ── PRESS KIT CARDS (about page Press Kit section) ── */
.mlo-presskit-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  max-width: 42rem;
}
@media (min-width: 782px) {
  .mlo-presskit-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}
.mlo-presskit-card {
  padding: 1rem;
  background: var(--mlo-bg-soft);
  border: 1px solid var(--mlo-border-light);
}
.mlo-presskit-card__label {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  font-weight: 600;
  color: var(--wp--preset--color--text);
  margin-bottom: 0.25rem;
}
.mlo-presskit-card__format {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  color: var(--wp--preset--color--text-light);
}

/* ── htmx loading state ── */
.htmx-request {
  opacity: 0.5;
  pointer-events: none;
  transition: opacity 0.15s;
}
.htmx-indicator {
  display: none;
}
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  display: inline-block;
}

/* ── NEWSLETTER ── */
/* Honeypot: hidden visually but still in the DOM as a normal text input. NOT
   type="hidden" because some bots skip those (browsers auto-fill them) and target
   only visible inputs. Real users never see this; bots that scan visible form
   fields fill it and get silently rejected by the REST handler. */
.mlo-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Subscription feedback messages — shown inline where the form was, after htmx
   swaps the response into the form's place. */
.mlo-newsletter-message {
  padding: 0.875rem 1.25rem;
  border-radius: 4px;
  font-size: var(--wp--preset--font-size--body-sm);
  margin: 0 auto;
  max-width: 24rem;
  text-align: center;
}
.mlo-newsletter-message--success {
  background: rgba(57, 120, 172, 0.08);
  color: var(--wp--preset--color--sky-dark);
  border: 1px solid rgba(57, 120, 172, 0.2);
}
.mlo-newsletter-message--error {
  background: rgba(220, 38, 38, 0.06);
  color: #b91c1c;
  border: 1px solid rgba(220, 38, 38, 0.2);
  margin-bottom: 0.75rem;
}

/* ──────────────────────────────────────────────────────────────────
   NEWS SYSTEM
   ──────────────────────────────────────────────────────────────────
   Powers /news/, /news/exhibitions-events/, /news/press-mentions/,
   /news/blog-posts/. Reuses .mlo-section--header gradient on top,
   .mlo-pill / .mlo-pill-row for the filter pills, and
   .mlo-mono-tag-uppercase for the "CATEGORY" / "YEAR" / "TAG" labels.
   ────────────────────────────────────────────────────────────────── */

/* ── NEWS: filter row (label + pill row inline) — used inside the news
   page header to lay out the Category/Tag and Year filter rows under
   the H1 + subtitle. ── */
.mlo-news-filter-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}
.mlo-news-filter-row + .mlo-news-filter-row,
.mlo-catalogue-filter-row + .mlo-news-filter-row {
  margin-top: 1rem;
}
/* Push the first filter row away from the subtitle so it doesn't sit too
   tight under the descriptive paragraph. Matches mockup's H1 marginBottom
   2.5rem visual rhythm even with subtitle inserted between H1 and pills. */
.mlo-page-subtitle + .mlo-news-filter-row {
  margin-top: 2rem;
}
/* H1 → filter-row adjacency, the no-subtitle case.
   On the parent /work/studio-notes/ archive a (possibly empty) .mlo-page-subtitle
   sits between H1 and the first filter row; the rule above gives that filter
   row 2rem of top-margin, and the subtitle's own margin-top: 1rem (collapsed
   with H1's 0.5rem bottom-margin) adds another 1rem of effective space — total
   visible gap ≈ 3rem.
   The note-category archive renders no subtitle, so neither path fires and the
   gap collapses to just H1's 0.5rem bottom-margin. This rule restores parity:
   when H1 sits directly next to a filter row inside any .mlo-section--header,
   give that filter row the same 3rem top-margin the subtitle path produces.
   Effect: parent unchanged (H1 not adjacent to filter row there); note-category
   archive's H1 → YEAR gap now matches the parent's H1 → CATEGORY gap.
   The catalogue archive uses .mlo-catalogue-filter-row (Type+Status wrapper)
   as the first filter row instead of .mlo-news-filter-row, so it's listed
   here as a second selector — same 3rem gap, same visual rhythm. */
.mlo-section--header .mlo-heading-page + .mlo-news-filter-row,
.mlo-section--header .mlo-heading-page + .mlo-catalogue-filter-row {
  margin-top: 3rem;
}

/* News page header H1: slightly looser line-height than the global page
   heading default, so titles like "Exhibitions & Events" don't look
   cramped if they wrap to two lines on narrow viewports. */
.mlo-section--header .mlo-heading-page {
  line-height: 1.35;
}

/* Inside the filter row, override the standalone defaults */
.mlo-news-filter-row > .mlo-mono-tag-uppercase {
  margin: 0;                /* override default 0 0 0.75rem */
  flex-shrink: 0;
  min-width: 4rem;          /* aligns CATEGORY and YEAR labels */
  font-size: var(--wp--preset--font-size--sm); /* one step up from --xs */
}
.mlo-news-filter-row > .mlo-pill-row {
  margin-top: 0;            /* override default 1.5rem */
  /* flex-basis MUST be 0 (not auto) so the flexbox line-break algorithm
     does not see the pill row's max-content width when deciding whether
     to wrap. With flex-basis: auto, archives with many pills (e.g. the
     History timeline's 17+ year pills) push the pill row's hypothetical
     main size beyond the container's 75rem max-width, triggering a wrap
     that drops the pill row below the YEAR label. With flex-basis: 0
     the line algorithm always fits YEAR + pill row on one line, then
     flex-grow: 1 expands the pill row to fill the remaining width and
     the pill row's own internal flex-wrap: wrap handles wrapping pills
     within that allocated width. The catalogue override at
     `.mlo-catalogue-filter-row > .mlo-news-filter-row > .mlo-pill-row`
     (above) is more specific and intentionally uses `flex: 0 1 auto`
     for its side-by-side Type/Status layout — unaffected. */
  flex: 1 1 0;
  min-width: 0;
}

/* ── NEWS: disabled pill state (year pills with no posts in scope) ── */
.mlo-pill[disabled],
.mlo-pill-disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
  color: var(--wp--preset--color--text-light);
  background: transparent;
}

/* ── NEWS: count + expand/collapse-all controls.
   No margin-block-start: the gap above this element is provided entirely
   by the header section's padding-block-end (var(--mlo-section-pad)).
   Adding margin here doubles it up to ~10rem above "X posts across Y years",
   which reads as excessive whitespace. */
.mlo-news-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding-bottom: 1rem;
}
.mlo-news-controls__count {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
  letter-spacing: 0.06em;
}
.mlo-news-controls__actions {
  display: flex;
  align-items: center;
  gap: 0.875rem;
}
.mlo-news-controls__actions button {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--sky);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  letter-spacing: 0.04em;
}
.mlo-news-controls__sep {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  color: var(--wp--preset--color--border-light);
}

/* ── NEWS: year accordion (section wrapper) ── */
.mlo-year-section {
  scroll-margin-top: 5rem;
  margin-bottom: 4rem;
}

/* Year heading: chevron · "2025" · hairline · "12 posts" */
.mlo-year-heading {
  width: 100%;
  padding: 0.5rem 0;
  display: flex;
  align-items: center;
  gap: 1rem;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  margin-bottom: 0;
}
.mlo-year-section[data-expanded="true"] .mlo-year-heading {
  margin-bottom: 2rem;
}
.mlo-year-heading__chev {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-muted);
  width: 0.875rem;
  display: inline-block;
  transform: rotate(-90deg);
  transition: transform 0.25s ease, color 0.2s;
}
.mlo-year-section[data-expanded="true"] .mlo-year-heading__chev {
  transform: rotate(0deg);
}
.mlo-year-heading h2 {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.625rem;
  font-weight: 400;
  color: var(--wp--preset--color--text);
  margin: 0;
  transition: color 0.2s;
}
.mlo-year-heading__line {
  flex: 1;
  height: 1px;
  background: var(--wp--preset--color--border-light);
  margin: 0 0.5rem;
  transition: background 0.25s;
}
.mlo-year-heading__count {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
}
.mlo-year-heading:hover h2,
.mlo-year-heading:hover .mlo-year-heading__chev {
  color: var(--wp--preset--color--sky);
}
.mlo-year-heading:hover .mlo-year-heading__line {
  background: rgba(57, 120, 172, 0.25);
}

/* ── NEWS: year posts grid + SEO-safe collapse ──
   Posts stay in DOM when collapsed (display:none only), so search
   engines index every post on the URL regardless of expanded state.
   Gap matches mockup (3.75rem on desktop, modest on mobile single-col). */
.mlo-year-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
}
@media (min-width: 782px) {
  .mlo-year-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 3.75rem;
  }
}
.mlo-year-section[data-expanded="false"] .mlo-year-grid {
  display: none;
}

/* ── NEWS: post card (image · date·category · serif title · excerpt) ── */
.mlo-news-card {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform 0.3s;
}
.mlo-news-card:hover {
  transform: translateY(-3px);
}
.mlo-news-card__image {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  margin-bottom: 0.875rem;
  background: var(--wp--preset--color--bg-soft);
}
.mlo-news-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.mlo-news-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.mlo-news-card__date {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--text-light);
}
/* Category/tag label on the right of the meta row. Matches the date's
   font (mono, meta size) — color is the only thing that distinguishes
   it from the date. Per-category color modifiers override the default
   sky color below. On sub-pages the PHP renderer outputs the post's
   tag(s) here instead of the category name, but the color still comes
   from the post's parent category. */
.mlo-news-card__category {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--sky);
  text-align: right;
}
/* Per-category color modifiers. */
.mlo-news-card__category--exhibition { color: #0096ff; } /* bright blue */
.mlo-news-card__category--press      { color: #aa8555; } /* gold */
.mlo-news-card__category--blog       { color: #3d6c9f; } /* highlight blue */

/* Title — no margin-bottom now (excerpt removed; title is last on card). */
.mlo-news-card__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--base);
  font-weight: 400;
  color: var(--wp--preset--color--text);
  line-height: 1.4;
  margin: 0;
}

/* news-grid wrapper. flow-root kept as a safety net against margin
   collapse from the parent section into news-controls. */
#news-grid {
  display: flow-root;
}


/* ──────────────────────────────────────────
   SWIPER — MLO DESIGN SYSTEM OVERRIDES
   ──────────────────────────────────────────
   Used by .mlo-note-media--slider rendered from
   /blocks/note-media/render.php in slider mode, AND by .mlo-slider
   rendered from /blocks/slider/render.php (generic Image Slider block
   used on artwork singles, contact page, posts).

   Shared rules below match both selectors. Two rules lower in this
   block stay scoped to .mlo-note-media--slider only — the 4:5 aspect
   lock and object-fit cover — because those enforce Studio Notes'
   Instagram-portrait expectation. The generic .mlo-slider lets the
   uploaded image dictate the frame (natural aspect ratio, no crop). */

.mlo-note-media--slider,
.mlo-slider {
  --swiper-theme-color: var(--wp--preset--color--sky);
  --swiper-pagination-color: var(--wp--preset--color--sky);
  --swiper-pagination-bullet-inactive-color: var(--wp--preset--color--border);
  --swiper-pagination-bullet-inactive-opacity: 1;
  --swiper-pagination-bullet-size: 7px;
  --swiper-pagination-bullet-horizontal-gap: 4px;
  --swiper-navigation-color: var(--wp--preset--color--text);
  --swiper-navigation-size: 24px;
}

.mlo-note-media--slider .swiper-pagination,
.mlo-slider .swiper-pagination {
  position: static;
  margin-top: 1rem;
  text-align: center;
}

.mlo-note-media--slider .swiper-button-prev,
.mlo-note-media--slider .swiper-button-next,
.mlo-slider .swiper-button-prev,
.mlo-slider .swiper-button-next {
  background: rgba(255, 255, 255, 0.85);
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  transition: opacity 0.25s, background 0.25s;
  opacity: 0;
}

.mlo-note-media--slider:hover .swiper-button-prev,
.mlo-note-media--slider:hover .swiper-button-next,
.mlo-slider:hover .swiper-button-prev,
.mlo-slider:hover .swiper-button-next {
  opacity: 1;
}

.mlo-note-media--slider .swiper-button-prev:hover,
.mlo-note-media--slider .swiper-button-next:hover,
.mlo-slider .swiper-button-prev:hover,
.mlo-slider .swiper-button-next:hover {
  background: #fff;
}

/* Arrows match the mockup: a thin dark-grey arrow centered in the circle with
   clear padding to the edge, not Swiper's bold sky chevron. */
.mlo-note-media--slider .swiper-button-prev::after,
.mlo-note-media--slider .swiper-button-next::after,
.mlo-slider .swiper-button-prev::after,
.mlo-slider .swiper-button-next::after {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--wp--preset--color--text);
}
.mlo-note-media--slider .swiper-button-prev::after,
.mlo-slider .swiper-button-prev::after {
  content: "\2190";
}
.mlo-note-media--slider .swiper-button-next::after,
.mlo-slider .swiper-button-next::after {
  content: "\2192";
}
/* Swiper injects its own arrow element into the button; hide it so only the
   ::after arrow above shows (otherwise both render and the arrows look doubled). */
.mlo-note-media--slider .swiper-button-prev > *,
.mlo-note-media--slider .swiper-button-next > *,
.mlo-slider .swiper-button-prev > *,
.mlo-slider .swiper-button-next > * {
  display: none;
}

@media (hover: none) {
  .mlo-note-media--slider .swiper-button-prev,
  .mlo-note-media--slider .swiper-button-next,
  .mlo-slider .swiper-button-prev,
  .mlo-slider .swiper-button-next {
    display: none;
  }
}

.mlo-note-media--slider .swiper,
.mlo-slider .swiper {
  width: 100%;
  overflow: hidden;
}

/* SCOPED TO .mlo-note-media--slider ONLY — Studio Notes Instagram-portrait lock.
   Do NOT extend to .mlo-slider; the generic slider lets the uploaded image's
   natural aspect ratio drive the slide height. */
.mlo-note-media--slider .swiper-slide {
  aspect-ratio: 4 / 5;
}

.mlo-note-media--slider .swiper-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Generic .mlo-slider slide layout — figure wrapper + image + optional
   figcaption. No aspect lock; image scales to slide width, height auto. */
.mlo-slider .swiper-slide figure {
  margin: 0;
}

.mlo-slider .swiper-slide img {
  display: block;
  width: 100%;
  height: auto;
}

.mlo-slider .swiper-slide figcaption {
  margin-top: 0.625rem;
}

/* ──────────────────────────────────────────
   STUDIO NOTES — ARCHIVE
   ────────────────────────────────────────── */

/* Masonry variant of .mlo-year-grid — used by the studio notes archive
   (and category archives). Inherits the base .mlo-year-grid 3-column
   layout, then switches to a JS-driven TRUE masonry: cards flow row-first
   (newest top-left, second-newest top-middle, third-newest top-right,
   then second row, etc.) with variable card heights — instead of CSS
   columns' column-first ordering which made the rightmost column look
   like it only contained old posts.

   The .is-masonry-ready class is added by mlo-masonry.js once it has
   measured each card's natural height and assigned grid-row-end: span N.
   Without JS, the grid falls back to the regular uniform-height grid
   (still readable, just not packed). The base .mlo-year-grid collapse
   rule still governs visibility when a year section is collapsed. */
@media (min-width: 782px) {
  .mlo-year-grid--masonry.is-masonry-ready {
    grid-auto-rows: 1px;
    row-gap: 0;
  }
  .mlo-year-grid--masonry.is-masonry-ready > .mlo-note-card {
    align-self: start;
    margin-bottom: 0;
  }
}

/* Note card */
.mlo-note-card {
  break-inside: avoid;
  margin-bottom: 3.75rem;
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform 0.3s ease, border-color 0.3s ease;
  background: var(--wp--preset--color--white);
  border: 1px solid var(--mlo-border-light, #F0F0F0);
  padding-inline: 1.25rem !important;
  padding-bottom: 1.25rem !important;
}
/* Soft-grey background variant. Add `mlo-note-card--soft` alongside
   `mlo-note-card` in the editor's Additional CSS Class(es) field to give
   the card a soft-grey background — useful when the card sits inside a
   .mlo-section--default (white) section and needs visual definition
   against the surrounding background. Border kept for consistency.
   Convention mirrors .mlo-publication-card--soft and .mlo-section--soft. */
.mlo-note-card--soft {
  background: var(--wp--preset--color--bg-soft);
}
.mlo-note-card:hover {
  transform: translateY(-3px);
  border-color: var(--mlo-border, #E8E8E8);
}
.mlo-note-card > .mlo-note-card__media {
  position: relative;
  margin-bottom: 1.25rem;
  margin-inline: -1.25rem !important;
  background: var(--wp--preset--color--artwork-grey);
  overflow: hidden;
}
.mlo-note-card--image .mlo-note-card__media,
.mlo-note-card--slider .mlo-note-card__media {
  aspect-ratio: 4 / 5;
}
.mlo-note-card--video .mlo-note-card__media {
  aspect-ratio: 9 / 16;
}
.mlo-note-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Video play overlay + VIDEO badge */
.mlo-note-card__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.mlo-note-card__play-icon {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
  color: #fff;
  font-size: 1.125rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 0.25rem;
}
.mlo-note-card__badge {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  padding: 0.1875rem 0.4375rem;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.06em;
}

/* Slider count badge + dots indicator */
.mlo-note-card__count {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.1875rem 0.4375rem;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.06em;
}
.mlo-note-card__count::before {
  content: "▦ ";
  margin-right: 2px;
}
.mlo-note-card__dots {
  position: absolute;
  bottom: 0.625rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 0.3125rem;
}
.mlo-note-card__dot {
  width: 0.3125rem;
  height: 0.3125rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.55);
}
.mlo-note-card__dot--active {
  background: #fff;
}

/* Card text content — margins per JSX mockup ImageCard spec:
   date span margin 0, title h3 margin 0.375rem 0, venue div margin 0.
   Vertical rhythm comes from image's margin-bottom and the card padding,
   not per-element spacing. */
.mlo-note-card__date {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  color: var(--wp--preset--color--text-light);
  display: block;
  margin: 0;
}
.mlo-note-card__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--wp--preset--color--text);
  margin: 0.375rem 0 !important;
}
.mlo-note-card__excerpt {
  font-size: 0.8125rem;
  line-height: 1.65;
  color: var(--wp--preset--color--text-muted);
  margin: 0;
}
.mlo-note-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-block-start: 0.375rem !important;
}
.mlo-note-card__tag {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: capitalize;
  color: var(--wp--preset--color--text-light);
  padding: 0.125rem 0.375rem;
  border: 1px solid var(--wp--preset--color--border-light);
  border-radius: 0.5rem;
}

/* ──────────────────────────────────────────
   STUDIO NOTES — CATEGORIES OVERVIEW
   ────────────────────────────────────────── */

/* Browse Categories section: explicit vertical rhythm.
   The section appears on both /work/studio-notes/ (parent archive,
   Gutenberg-composed) and /work/studio-notes/{slug}/ (note-category
   archive, PHP-rendered). Same structural HTML on both:
     .mlo-section--soft
       > p.mlo-tag
       > h2.mlo-heading-section
       > div.mlo-categories-overview

   Earlier attempts set margin-top on the H2 and grid to make both gaps
   equal. Those produced equal numeric margins but unequal *visible*
   gaps because the H2's own line-box leading sits below the baseline,
   adding apparent space below the H2 that the tag → H2 gap doesn't have.

   This rule sidesteps the problem entirely:
     1. Zero every margin (with !important) on all three direct children
        so margin collapse and Gutenberg's block-gap can't sneak in.
     2. Tighten the H2's line-height to 1 inside this section, removing
        the leading that was inflating the H2 → grid visible distance.
     3. Use padding-top on the H2 and the grid as the actual gap. Padding
        can't margin-collapse and isn't measured from the baseline, so the
        visible distance from the previous element to this one's content
        box top is exactly the padding value.

   Both gaps are wired to var(--wp--style--block-gap), the same theme.json
   token Gutenberg uses everywhere — change spacing.blockGap to retune
   both gaps and both pages at once. */
.mlo-section.mlo-section--soft > .mlo-tag,
.mlo-section.mlo-section--soft > .mlo-heading-section,
.mlo-section.mlo-section--soft > .mlo-categories-overview {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  margin-block: 0 !important;
}
.mlo-section.mlo-section--soft > .mlo-heading-section {
  line-height: 1 !important;
  padding-top: var(--wp--style--block-gap, 1.5rem) !important;
}
.mlo-section.mlo-section--soft > .mlo-categories-overview {
  /* tag → H2 visible gap = block-gap + (tag's bottom leading), which is
     noticeably more than block-gap + (H2 descender area only). Add 0.5rem
     to the grid's padding-top so the visible H2 → grid gap matches the
     tag → H2 gap. Tune up/down if Martin reports it's still off. */
  padding-top: calc(var(--wp--style--block-gap, 1.5rem) + 0.5rem) !important;
}
.mlo-categories-overview {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3.75rem;
}
@media (max-width: 48rem) {
  .mlo-categories-overview {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
  }
}
.mlo-category-card {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform 0.3s ease;
}
.mlo-category-card:hover {
  transform: translateY(-3px);
}
.mlo-category-card__thumb {
  aspect-ratio: 1;
  background-size: cover;
  background-position: center;
  background-color: var(--wp--preset--color--artwork-grey);
  margin-bottom: 0.875rem;
  /* Hairline contour matches the border treatment on .mlo-card-explore and
     .mlo-presskit-card. Visible against light category thumbs that fade
     into the section background; harmless against darker artwork crops. */
  border: 1px solid var(--wp--preset--color--border-light);
}
.mlo-category-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.25rem;
}
.mlo-category-card__name {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--wp--preset--color--text);
  margin: 0;
}
.mlo-category-card__count {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  color: var(--wp--preset--color--text-light);
}
.mlo-category-card__cta {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wp--preset--color--sky);
}

/* ──────────────────────────────────────────
   STUDIO NOTES — NOTE-CATEGORY ARCHIVE OVERRIDES
   ──────────────────────────────────────────
   Overrides for /work/studio-notes/{category-slug}/ taxonomy archives.
   Scoped via the WP body class `.tax-note-category` (auto-emitted by
   body_class() on note-category term archives), so the parent
   /work/studio-notes/ post-type archive — which uses a post-type-archive
   body class — keeps its collapsible-year toggle UI untouched.

   On a single-category archive the collapse affordance adds friction without
   saving meaningful visual space (a category typically spans only a few
   years), so every year section renders expanded by default and the toggle
   UI is removed entirely. The four rules below:
     1. force the year grid visible regardless of data-expanded state,
     2. remove the heading's pointer cursor so it doesn't look interactive,
     3. disable pointer events so clicks pass through (toggle JS doesn't fire),
     4. hide the chevron — it's a toggle hint that no longer applies,
   plus a margin-bottom on the heading that mirrors the expanded-state rule
   so the heading → grid gap matches the rhythm of an expanded year on the
   parent archive.

   NOTE on masonry: the .is-masonry-ready class is added by mlo-masonry.js
   once it measures each card. If the masonry init gates on data-expanded
   being "true", these CSS-only overrides won't trigger packed masonry —
   cards then fall back to the uniform-height 3-column grid (the documented
   no-JS fallback, still readable). For true masonry on category archives,
   the cleaner fix is in /blocks/studio-notes-category-archive/render.php:
   output data-expanded="true" per year section, which lets the existing
   CSS path work naturally and the masonry init fire. */
.tax-note-category .mlo-year-section .mlo-year-grid {
  display: grid;
}
.tax-note-category .mlo-year-heading {
  cursor: default;
  pointer-events: none;
  margin-bottom: 2rem;
}
.tax-note-category .mlo-year-heading__chev {
  display: none;
}

/* ──────────────────────────────────────────
   STUDIO NOTE — MEDIA ZONE (used on single posts)
   ────────────────────────────────────────── */

.mlo-note-media {
  margin: 0 0 2rem 0;
}
.mlo-note-media__img {
  width: 100%;
  height: auto;
  display: block;
}
.mlo-note-media__video {
  width: 100%;
  height: auto;
  max-height: 90vh;
  display: block;
}
.mlo-note-media--video-embed iframe {
  width: 100%;
  aspect-ratio: 9 / 16;
  display: block;
}

/* ════════════════════════════════════════════════════════════════
   EXPERIMENT — SITE HEADER: align logo + Collect button with content edges
   Removable. Goal: pull the header's inner flex row (logo on the left,
   nav + Collect button on the right) inward so its left edge matches the
   left edge of the page content (max-width 75rem, centered in viewport)
   and its right edge matches the right edge of content. The <header>
   element stays full-width so its background still bleeds edge-to-edge.

   The header lives in parts/header.html and ships with its own inline
   <style> block where .mlo-h__inner has padding: 0 clamp(1.5rem, 4vw,
   3.5rem). That inline rule has specificity 0,1,0 and appears later in
   source order than classes.css, so a flat .mlo-h__inner selector here
   would lose the cascade. Using .mlo-h > .mlo-h__inner (0,2,0) wins on
   specificity regardless of source order.

   Math: padding-inline = max(--mlo-edge, (100vw − 75rem) / 2)
     - At viewport 1920px: max(56px, 360px) = 360px → matches content edge
     - At viewport 1280px: max(51.2px, 40px) = 51.2px → matches content edge
     - At viewport  600px: max(24px, 0px)    = 24px   → matches content edge
   Same formula the page content uses (--mlo-edge fallback below 75rem +
   2*edge; gutter to centered 75rem above that). The two should align
   visually at every viewport width.
   ════════════════════════════════════════════════════════════════ */
.mlo-h > .mlo-h__inner {
  padding-inline: max(
    var(--mlo-edge, clamp(1.5rem, 4vw, 3.5rem)),
    calc((100vw - var(--wp--style--global--content-size, 75rem)) / 2)
  );
}

/* ════════════════════════════════════════════════════════════════
   PUBLICATIONS PAGE
   Publication cards (Academic Papers, Book Chapters, Educational
   Installations, Magazine Articles) and the Overview credential card.
   Cards are built from the patterns/publication-card.php block pattern;
   every Group in that pattern is a plain default-layout group, and all
   visual work is done here, matching the project convention.
   ════════════════════════════════════════════════════════════════ */

/* ── Publication card ──
   A Group laid out as a two-column grid: a fixed image column and a
   flexible body column. Collapses to one column below 768px. Default
   background is white; the --soft modifier swaps to soft grey for cards
   that sit on a white (--default) section, so a card always contrasts
   the section behind it. */
.mlo-publication-card,
.mlo-publication-card--soft {
  display: grid;
  grid-template-columns: 33% 1fr;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: start;
  padding: clamp(1.25rem, 3vw, 1.75rem);
  border: 1px solid var(--mlo-border-light, #F0F0F0);
  margin-bottom: 2.5rem;
}
.mlo-publication-card {
  background: var(--wp--preset--color--white);
}
.mlo-publication-card:last-child,
.mlo-publication-card--soft:last-child {
  margin-bottom: 0;
}
.mlo-publication-card--soft {
  background: var(--wp--preset--color--bg-soft);
}

/* Image column: fixed-ratio matted frame, image contained (never cropped)
   so portrait book covers and landscape journal covers both sit cleanly.
   align-items: flex-start on the inner flex centering keeps the visible
   image's top edge flush with the top of the figure so it aligns with
   the top of the body column ("year" line) rather than floating in the
   vertical middle of the matted frame. justify-content: center is kept
   so portrait images still pillarbox horizontally inside the frame. */
/* The figure is a pure pass-through wrapper: no aspect-ratio lock, no
   background, no overflow clip, no flex centering. Margin: 0 only
   strips the browser default on <figure>. The image inside dictates
   the figure's rendered height — the figure has zero presence beyond
   what the image takes up, so nothing shows behind or below the
   image inside the figure itself. (The grid cell still extends to
   the row's tallest item — usually the body column — so a card with
   a short image and tall body will show empty cell space below the
   image. That space reveals the card's own background: white on the
   base .mlo-publication-card, soft-grey on .mlo-publication-card--soft.
   To eliminate that too, use --default for cards whose images are
   shorter than their body content.) */
.mlo-publication-card__media {
  margin: 0;
}
.mlo-publication-card__media img {
  width: 100%;
  height: auto;
  display: block;
}

/* Body column: all text content, flows vertically.
   position: relative establishes the positioning context for the
   absolutely-positioned __badge (top-right of body). */
.mlo-publication-card__body {
  min-width: 0;
  position: relative;
}

/* Meta row: contains the year (and, when present, the absolutely-positioned
   peer-reviewed badge). Since the badge is taken out of flow via position:
   absolute, the meta wrapper effectively contains only the year — its height
   collapses to the year's height (~11px), matching cards without a badge
   exactly. This is what gives badge-bearing cards the identical title spacing
   as non-badge cards. */
.mlo-publication-card__meta {
  margin-bottom: 1.5rem;
}
.mlo-publication-card__year {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  letter-spacing: var(--wp--custom--letter-spacing--tag);
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
  /* line-height: 1 collapses the line box to the font's em-square so the
     visible "2025" glyph top sits flush with the figure top instead of
     ~5px below it (default 1.4-1.5 line-height adds leading above the
     cap-height). Combined with align-items: flex-start on __media this
     produces visual top-alignment between the cover and the body's
     first row. */
  line-height: 1;
  margin: 0;
}
/* Specificity note: compounded selector (0,2,0) is required to beat WP's
   global layout rule `:root :where(.is-layout-flow) > *{margin-block-start: 24px}`
   which is (0,1,0). Both __meta and __body carry is-layout-flow, so without
   this prefix, WP's 24px block-gap margin on the badge (the second child of
   __meta) would win over our `margin: 0` and push the absolutely-positioned
   badge 24px below where `top` puts it. Position/top/right have no WP
   competitor, but margin does — and on an abs-positioned element, margin
   adds to the computed offset. */
.mlo-publication-card__meta .mlo-publication-card__badge {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #5A9E6F; /* peer-reviewed accent; no green color token exists */
  border: 1px solid #5A9E6F;
  padding: 0.125rem 0.5rem;
  position: absolute;
  top: -0.1875rem;
  right: 0;
  margin: 0;
  line-height: 1;
  white-space: nowrap;
}

/* Title: italic serif, the page's display voice. */
.mlo-publication-card__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--base);
  font-weight: 400;
  font-style: italic;
  line-height: var(--wp--custom--line-height--tight, 1.3);
  color: var(--wp--preset--color--text);
  margin: 0 0 1.3125rem;
}

/* Authors line. */
.mlo-publication-card__authors {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  color: var(--wp--preset--color--text-muted);
  line-height: 1.5;
  margin: 0 0 0.9375rem;
}

/* Venue line. */
.mlo-publication-card__venue {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  color: var(--wp--preset--color--text-body);
  line-height: 1.5;
  margin: 0 0 1.875rem;
}

/* Abstract panel: soft-tinted box with a sky left-border accent. Top
   and bottom padding bumped 75% (was clamp(0.875rem, 2vw, 1rem); now
   clamp(1.5rem, 3.5vw, 1.75rem)) so the label and abstract body have
   more breathing room inside the panel. On a --soft card the panel
   flips to white so it still reads as inset. */
.mlo-publication-card__abstract {
  background: var(--wp--preset--color--bg-soft);
  border-left: 2px solid var(--wp--preset--color--sky-light);
  padding: clamp(1.5rem, 3.5vw, 1.75rem) clamp(1rem, 2.5vw, 1.125rem);
  margin-bottom: 1.875rem;
}
.mlo-publication-card--soft .mlo-publication-card__abstract {
  background: var(--wp--preset--color--white);
}
.mlo-publication-card__abstract-label {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
  margin: 0 0 0.375rem;
}
.mlo-publication-card__abstract p:not(.mlo-publication-card__abstract-label) {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  line-height: 1.85;
  color: var(--wp--preset--color--text-body);
  margin: 0;
}

/* DOI / ISBN identifier + arrow links, wrapping row. */
.mlo-publication-card__ids {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body-sm);
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
}
.mlo-publication-card__doi {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--sky);
}

/* Preprint note: faint sky-tinted callout under the links. */
.mlo-publication-card__preprint {
  margin-top: 0.75rem;
  padding: 0.625rem 0.875rem;
  background: rgba(74, 144, 196, 0.05);
  border: 1px solid rgba(74, 144, 196, 0.15);
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--xs);
  color: var(--wp--preset--color--text-muted);
}

/* Single-column collapse on mobile; image renders at its natural ratio at
   full column width (no aspect-ratio override). */
@media (max-width: 768px) {
  .mlo-publication-card,
  .mlo-publication-card--soft {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
}

/* ── Block-gap overrides for is-layout-flow containers ──
   The body, abstract, and meta Groups in the pattern all carry
   is-layout-flow because they use "layout":{"type":"default"} (which
   Gutenberg treats as flow). WordPress emits inline per-container CSS
   at the top of the page like
     .wp-container-{id} > * + * { margin-block-start: var(--wp--style--block-gap) }
   That selector has specificity 0,1,0 — exactly the same as a
   single-class .mlo-publication-card__title rule — and since inline
   <head> CSS ships after enqueued classes.css, source order makes WP
   win on every tie. Result: every sibling inside the body and the
   abstract gets ~1.5rem (24px) of extra top margin on top of whatever
   the per-element rules above set, and the card reads as loosely
   spaced.

   The rules below chain the .mlo-publication-card class with the
   inner-container class (or fall back to element selector for the
   classless inner div in the credential card) to reach 0,2,0 / 0,1,1,
   defeating WP's auto-spacing so the margin-bottom values on the
   individual element rules above produce the actual visible gaps.
   :is() wrapping lets these rules also apply when the card carries
   only .mlo-publication-card--soft (no base class). */
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__body > * + *,
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__abstract > * + * {
  margin-block-start: 0;
}
/* Re-add the optional preprint note's top spacing at higher specificity
   than the zero rule above. */
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__body > .mlo-publication-card__preprint {
  margin-block-start: 0.75rem;
}

/* ── Publication-card row spacing: chained-class margin-bottom rules ──
   Each rule reaches 0,2,0 specificity via :is() wrapping the outer
   card class. This is necessary because WP, when it sees
   style.spacing.blockGap on the body Group in the pattern, emits
   per-container inline CSS like:
       .wp-container-{id} > * {
           margin-block-start: 0;
           margin-block-end: 0;
       }
   That selector is 0,1,0 — exactly the same as a single-class
   .mlo-publication-card__title { margin: 0 0 X } — and since the
   inline <head> CSS ships AFTER the enqueued classes.css, source order
   gives WP the win and every row's margin-bottom gets reset to 0.
   The :is() chain produces 0,2,0 which beats WP regardless of source
   order, and the rules apply equally whether the card has the base
   class, the --soft modifier, or both. */
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__meta {
  margin-bottom: 1.5rem;
}
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__title {
  margin-bottom: 1.3125rem;
}
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__authors {
  margin-bottom: 0.9375rem;
}
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__venue {
  margin-bottom: 1.875rem;
}
:is(.mlo-publication-card, .mlo-publication-card--soft) .mlo-publication-card__abstract {
  margin-bottom: 1.875rem;
}

/* ── Overview credential card ──
   Small researcher-identity card in the Overview section: a square
   avatar beside name / role / affiliation. Plain default-layout Group;
   the flex layout is applied here. */
.mlo-credential-card {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1rem 1.125rem;
  background: var(--wp--preset--color--bg-soft);
  border: 1px solid var(--mlo-border-light, #F0F0F0);
  margin-bottom: 1.75rem;
}

/* On-soft modifier — overrides the base bg-soft to white. Use when the
   credential card sits inside a section-soft (e.g., the /contact/ form),
   where the grey-on-grey default would lose contrast. Combine with the
   base .mlo-credential-card class. */
.mlo-credential-card--on-soft {
  background: var(--wp--preset--color--white);
}

/* ── Defeat WordPress's is-layout-flow auto-spacing on card children ──
   The credential card and publication cards are styled via display:flex
   / display:grid, but Gutenberg renders their outer Group with the
   .is-layout-flow class (because the patterns use default / flow
   layout). theme.json emits this global rule:
       :root :where(.is-layout-flow) > * { margin-block-start: 24px; }
       :root :where(.is-layout-flow) > :first-child { margin-block-start: 0; }
   That means the FIRST direct child (avatar / image) gets 0 top margin
   but the SECOND direct child (inner text Group on the credential
   card, __body Group on the publication card) gets 24px top margin —
   which after flex / grid alignment leaves the text starting exactly
   24px below the image's top edge. Visible offset matches the symptom
   the user reported.

   The selector below zeros margin-block-start on every direct child of
   both card types at !important. Specificity of "single-class > *" is
   0,1,0, same as ":root :where(.is-layout-flow) > *", and !important
   resolves the tie in our favour. Image and text now share the same
   top edge. */
.mlo-credential-card > *,
.mlo-publication-card > *,
.mlo-publication-card--soft > * {
  margin-block-start: 0 !important;
}

.mlo-credential-card__avatar {
  flex-shrink: 0;
  width: 4.5rem;
  height: 4.5rem;
  margin: 0;
  overflow: hidden;
  background: var(--wp--preset--color--artwork-grey);
}
.mlo-credential-card__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.mlo-credential-card__name {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--body);
  font-weight: 500;
  color: var(--wp--preset--color--text);
  /* line-height: 1 collapses the line box to the font's em-square so the
     visible "M" of "Martin" sits flush with the avatar's top edge. The
     larger 24px offset that originally looked like a font issue was
     actually WP's is-layout-flow rule pushing the entire inner text
     Group down by 24px — addressed by the .mlo-credential-card > *
     rule above. */
  line-height: 1;
  margin: 0 0 0.125rem;
}
.mlo-credential-card__role {
  font-family: var(--wp--preset--font-family--body);
  font-size: var(--wp--preset--font-size--sm);
  color: var(--wp--preset--color--text-muted);
  margin: 0 0 0.375rem;
}
.mlo-credential-card__affiliation {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  letter-spacing: 0.04em;
  color: var(--wp--preset--color--sky);
  margin: 0;
}

/* Block-gap override for the credential card's inner Group (the one
   that holds name / role / affiliation). The inner Group carries no
   class in the pattern; we use the descendant-element selector
   ".mlo-credential-card > div > * + *" which reaches 0,1,1 specificity,
   enough to beat WordPress's 0,1,0 inline .wp-container-{id} > * + *
   block-gap rule (same root cause as the publication card overrides
   above). Once the auto top margins are zeroed, the per-element
   margin-bottom values on __name (0.125rem) and __role (0.375rem)
   produce the tight visible rhythm the mockup specifies. */
.mlo-credential-card > div > * + * {
  margin-block-start: 0;
}

/* ──────────────────────────────────────────────────────────────────────
   WHAT IS CRYPTO ART? — PAGE COMPONENTS
   Components introduced for /research/what-is-crypto-art/.
   See MLO-What-Is-Crypto-Art-Recipe.md for usage context.
   ────────────────────────────────────────────────────────────────────── */

/* ── FIGCAPTION
   Italic muted caption text for images and diagrams. Apply to the
   caption paragraph of an Image block, or to a paragraph immediately
   after an image when WP's native caption isn't being used. */
.mlo-figcaption {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.75rem;
  font-style: italic;
  color: var(--wp--preset--color--text-muted);
  text-align: center;
  margin: 0.625rem 0 0;
  line-height: 1.6;
}

/* ── DEFINITION CARD
   Color-coded card for the Crypto Art Framework section. The
   --accent CSS custom property controls the top-border color and
   the number color, so a single class serves all 5 cards:
     <div class="mlo-definition-card" style="--accent: <color>;">
   Defaults to text-light if --accent is not set. */
.mlo-definition-card {
  --accent: var(--wp--preset--color--text-light);
  background: var(--wp--preset--color--bg-soft);
  border-top: 3px solid var(--accent);
  padding: 1.75rem !important;
  align-self: stretch;
}
/* Modifier classes for the 5 framework cards. Use these instead of
   inline style="--accent:..." — Gutenberg's Group block strips
   inline style attributes via block-validation. Add the modifier
   alongside .mlo-definition-card in the Additional CSS Class(es)
   field. Card 01 (Blockchain-Related Art) needs no modifier — it
   uses the default grey accent from the base rule above. */
.mlo-definition-card--crypto    { --accent: var(--wp--preset--color--sky); }
.mlo-definition-card--contract  { --accent: #aa8555; }
.mlo-definition-card--ft        { --accent: #0096ff; }
.mlo-definition-card--nft       { --accent: #3d6c9f; }
/* Defeat WP's :root :where(.is-layout-flow){margin-block-start:24px}
   on direct children so internal vertical rhythm is controlled by
   each child's own margin-bottom. */
.mlo-definition-card > * {
  margin-block-start: 0 !important;
}
/* Inner Row block (num + title side-by-side) — tighten gap from
   WP's default 24px, set baseline alignment per mockup. */
.mlo-definition-card > .is-layout-flex {
  gap: 0.5rem !important;
  align-items: baseline;
  margin-bottom: 0.5rem;
}
/* Number text styling. Color picks up the card's --accent so it
   matches the top border. Works on either a paragraph carrying
   the existing .mlo-mono-label class or a dedicated __num class. */
.mlo-definition-card__num,
.mlo-definition-card .mlo-mono-label {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  color: var(--accent);
  margin: 0;
}
/* Scope subtitle — small uppercase mono label between the title
   and the definition paragraph. */
.mlo-definition-card__scope {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
  display: block;
  margin: 0 0 1rem !important;
}
/* The note paragraph at the bottom of each card — italic muted */
.mlo-definition-card > p:last-child {
  font-style: italic;
  color: var(--wp--preset--color--text-muted);
  font-size: 0.75rem;
  line-height: 1.7;
  margin: 0;
}

/* ── CALLOUT (SKY)
   Sky-tinted callout used for the Framework "Key Takeaway".
   Used as Group(Flow) with class .mlo-callout--sky. Paragraphs
   inside are styled large + italic display by default; a mono
   uppercase label paragraph (.mlo-mono-tag-uppercase) sits at
   the top in sky color. */
.mlo-callout--sky {
  background: rgba(74, 144, 196, 0.08);
  border: 1px solid rgba(74, 144, 196, 0.20);
  padding: 1.5rem 2rem !important;
}
.mlo-callout--sky > * {
  margin-block-start: 0 !important;
}
.mlo-callout--sky .mlo-mono-tag-uppercase {
  color: var(--wp--preset--color--sky);
  letter-spacing: 0.14em;
  margin: 0 0 0.75rem !important;
}
.mlo-callout--sky > p:not(.mlo-mono-tag-uppercase):not(.mlo-meta-line) {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.0625rem;
  font-style: italic;
  line-height: 1.7;
  color: var(--wp--preset--color--text-body);
  margin: 0;
}

/* ── PULLQUOTE (SKY)
   Side-bordered pullquote used for the Origins position quote.
   Distinct from .mlo-callout--sky: bg-soft + sky LEFT border only.
   Italic display body paragraph + optional attribution line. */
.mlo-pullquote--sky {
  background: var(--wp--preset--color--bg-soft);
  border-left: 3px solid var(--wp--preset--color--sky);
  padding: 1.5rem 2rem !important;
}
.mlo-pullquote--sky::before {
  content: "\201C"; /* left double quotation mark */
  display: block;
  font-family: var(--wp--preset--font-family--display);
  font-size: 2.5rem;
  line-height: 0.8;
  color: var(--wp--preset--color--sky);
  opacity: 0.2;
  margin-block-end: 0.5rem;
}
.mlo-pullquote--sky > * {
  margin-block-start: 0 !important;
}
.mlo-pullquote--sky > p:first-of-type {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.0625rem;
  font-style: italic;
  line-height: 1.7;
  color: var(--wp--preset--color--text-body);
  margin: 0;
}
.mlo-pullquote--sky .mlo-meta-line {
  margin: 0.75rem 0 0 !important;
  font-weight: 600;
  color: var(--wp--preset--color--text);
}

/* ── CITATION BOX
   Used inside the cite-resource block. White card with mono
   format label + monospace citation text. Pairs with the
   existing .mlo-copy-btn class for the action below. */
.mlo-citation-box {
  padding: 1.25rem 1.5rem;
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
}
.mlo-citation-box__label {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-light);
  display: block;
  margin: 0 0 0.625rem;
}
.mlo-citation-box__text {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.75rem;
  line-height: 1.7;
  color: var(--wp--preset--color--text-body);
  margin: 0;
  word-wrap: break-word;
}

/* ── GLOSSARY
   Used inside the glossary block. Semantic <dl> rendered as a
   responsive 2-col grid (collapses to 1-col under 768px). Each
   entry uses an HTML5 <div> wrapper inside <dl> grouping a
   <dt> term and <dd> definition. */
.mlo-glossary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem clamp(2rem, 4vw, 4rem);
  margin: 0;
}
@media (max-width: 768px) {
  .mlo-glossary { grid-template-columns: 1fr; }
}
.mlo-glossary__item {
  padding: 1rem 0;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
}
.mlo-glossary__term {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--wp--preset--color--text);
  margin: 0 0 0.375rem;
}
.mlo-glossary__def {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--wp--preset--color--text-muted);
  margin: 0;
}

/* ── REFERENCES
   Used inside the references block. Numbered citation list with
   mono number column + body containing authors, italic title,
   and venue. Each entry has a bottom border for separation. */
.mlo-references {
  list-style: none;
  margin: 0;
  padding: 0;
}
.mlo-references__item {
  display: flex;
  gap: 0.75rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
}
.mlo-references__num {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  color: var(--wp--preset--color--sky);
  min-width: 1.5rem;
  flex-shrink: 0;
  line-height: 1.6;
  padding-top: 0.125rem;
}
.mlo-references__body {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--wp--preset--color--text-muted);
}
.mlo-references__title {
  font-family: var(--wp--preset--font-family--display);
  font-style: italic;
  color: var(--wp--preset--color--text);
}

/* ── FAQ CARD
   Used inside the faq block. White card with display H3 question
   and body answer. Sits in a .mlo-two-col grid wrapper rendered
   by the block. */
.mlo-faq-card {
  padding: 1.5rem;
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
}
.mlo-faq-card__question {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.35;
  color: var(--wp--preset--color--text);
  margin: 0 0 0.875rem;
}
.mlo-faq-card__answer {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.8125rem;
  line-height: 1.75;
  color: var(--wp--preset--color--text-body);
  margin: 0;
}

/* ── RELATED CARDS (INLINE / SIDEBAR)
   Wrapper for the inline variant of [mlo_continue_exploring].
   Stacks the cards vertically with consistent spacing so the same
   shortcode + preset combo can serve both top-level sections (3-col)
   and sidebar columns (1-col stack) via the format="inline" param.
   The .mlo-card-explore class (defined earlier) provides the card
   chrome — display:block, white bg, light border, lg padding. */
.mlo-related-cards {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* ───────────────────────────────────────────────────────────────────
 * HISTORY OF CRYPTO ART — minimal additions
 *
 * The page reuses these existing classes verbatim (no new CSS needed):
 *   .mlo-section--header / --default / --soft  section variants
 *   .mlo-credential-card                       author bio in page header
 *   .mlo-citation-box                          APA + MLA boxes (via [mlo_cite_resource])
 *   .mlo-pullquote--sky                        Quaranta + Schachter quotes
 *   .mlo-callout--sky                          htmx implementation note
 *   .mlo-two-col / .mlo-three-col              section grids
 *   .mlo-tag / .mlo-heading-section            section tag + H2
 *   .mlo-mono-tag-uppercase                    YEAR label in filter row
 *   .mlo-news-filter-row / .mlo-news-controls  filter row + count/expand controls
 *   .mlo-year-section / .mlo-year-heading      year accordion (reused from News)
 *   .mlo-pill / .mlo-pill-active / --disabled  filter pills
 *   .mlo-publication-card--soft                history timeline entry cards
 *   .mlo-note-card__tag                        category + event-type badges
 *   .mlo-card-explore / .mlo-card-title        Continue Reading cards
 *   .mlo-stat-block / .mlo-stat-number / __label  page-header stats
 *   .mlo-arrow-link                            sky body-font link with →
 *   .mlo-body-text / .mlo-body-small / .mlo-mono-meta  typography
 *
 * Only three minimal additions follow.
 * ───────────────────────────────────────────────────────────────── */

/* 2×2 grid inside the credential-card column of the page header.
   Tighter than .mlo-two-col (which uses clamp(2rem, 5vw, 4rem)).
   Items are .mlo-stat-block; the grid just provides 2-col placement
   with a controlled gap. Collapses to 1fr on narrow viewports. */
.mlo-stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  /* Don't let the grid (or its cells) stretch vertically when the
     surrounding flex column is taller than the stats content. */
  align-items: start;
  align-content: start;
}
@media (max-width: 480px) {
  .mlo-stats-grid { grid-template-columns: 1fr; }
}

/* Page-header stat tiles: left-aligned, sky left-border only, compact.
   The base .mlo-stat-block is centered / fully-bordered / height:100%
   (the Speaking-page tile style). Inside .mlo-stats-grid we override it
   to the page-header treatment from the mockup. Scoped to the grid, so
   the Speaking-page tiles are unaffected. */
.mlo-stats-grid .mlo-stat-block {
  align-items: flex-start;
  justify-content: flex-start;
  text-align: left;
  height: auto;
  border: 0;
  border-left: 2px solid var(--wp--preset--color--sky);
}

/* Stacked variant of the cite-resource layout (APA above MLA), for when
   the block sits in a narrow column. Default cite-resource layout stays
   the side-by-side .mlo-two-col. */
.mlo-cite-stack {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Sky-accent modifier for the stat-block: tints the number sky-blue
   to match the page-header visual treatment. Used as:
     <div class="mlo-stat-block mlo-stat-block--accent">
       <p class="mlo-stat-number">[mlo_history_span]</p>
       <p class="mlo-stat-label">Years of history</p>
     </div>
   Base .mlo-stat-block (centered, white bg, bordered) stays unchanged. */
.mlo-stat-block--accent .mlo-stat-number {
  color: var(--wp--preset--color--sky);
}

/* Era card for the Key Milestones section.
   Inside an .mlo-section--soft, the white bg makes the card stand
   forward. Body content (mono number + H3 title row, period meta,
   body paragraph) is built with existing primitives — no further
   per-element classes needed. */
.mlo-era-card {
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
  padding: 1.5rem;
}

/* ───────────────────────────────────────────────────────────────────
 * HISTORY: Step 5 (Publications & Citations) compact record list
 *
 * Academic-style row list: fixed-width year column + flexible
 * title/meta column, rows divided by hairline borders. The whole row
 * may be a link. No existing class produced this layout, so it is a
 * small dedicated component.
 * ───────────────────────────────────────────────────────────────── */
.mlo-record-list {
  display: block;
}
.mlo-record {
  display: flex;
  gap: 1rem;
  padding: 1.125rem 0;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
  text-decoration: none;
  transition: background 0.2s;
}
.mlo-record-list .mlo-record:last-child {
  border-bottom: 0;
}
.mlo-record:hover {
  background: var(--wp--preset--color--bg-soft);
}
.mlo-record__year {
  flex: 0 0 auto;
  min-width: 2.75rem;
  padding-top: 0.125rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.75rem;
  color: var(--wp--preset--color--text-light);
}
.mlo-record__body {
  flex: 1 1 auto;
}
.mlo-record__title {
  display: block;
  margin: 0 0 0.25rem;
  font-family: var(--wp--preset--font-family--display);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--wp--preset--color--text);
}
.mlo-record__meta {
  display: block;
  margin: 0;
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.75rem;
  color: var(--wp--preset--color--text-muted);
}

/* ───────────────────────────────────────────────────────────────────
 * HISTORY: Step 6 (Key Milestones) era-card internals
 *
 * .mlo-era-card already exists (white bg, light border, padding).
 * These add the head row (number + title on one baseline) and the
 * sky number. Period uses the existing .mlo-mono-tag; title uses the
 * existing .mlo-card-title; body uses the existing .mlo-body-small.
 * ───────────────────────────────────────────────────────────────── */
.mlo-era-card__head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.mlo-era-card__head .mlo-card-title {
  margin: 0;
}
.mlo-era-card__num {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  color: var(--wp--preset--color--sky);
}

/* ── Era-card accent variant ──
   Sky-stripe-left modifier on .mlo-era-card. Used on the /contact/ Inquiry
   Routing cards and the Studio Visits block to signal "channel/route" rather
   than the default "documentation entry" reading of the base card. Background
   drops to bg-soft (instead of white) and a 3px sky stripe runs down the left
   edge. Re-uses .mlo-era-card's padding, border, and __head + __num structure
   unchanged. */
.mlo-era-card--accent {
  background: var(--wp--preset--color--bg-soft);
  border-left: 3px solid var(--wp--preset--color--sky);
}

/* Stripe-only accent — sky left edge, NO background change. Used where
   the card needs to read distinctly on a soft section (e.g., Studio Visits
   block inside the /contact/ form's section-soft) — base .mlo-era-card's
   white background provides the contrast against the grey parent.
   Pair with the base .mlo-era-card class; do NOT combine with --accent
   (which would override the background back to bg-soft). */
.mlo-era-card--stripe {
  border-left: 3px solid var(--wp--preset--color--sky);
}

/* ── TOPICS LIST ──
   Clean hairline-divider list of numbered items: number on the left (mono,
   sky, weight 500), title on the right (display font, matching .mlo-record__title
   so list-row titles read identically across the site). Used on /research/'s
   Book a Talk section.

   Distinct from .mlo-era-card (which is a bordered card with tag +
   description — heavier visual treatment, more content-rich) and from
   .mlo-record-list (which is an anchor-based list with display-font titles
   and a hover background — implies clickability). This pattern is for
   non-clickable summary lists where content is brief and visual weight
   should stay light.

   Default tag is <div> so items don't trigger anchor behaviour; if you
   ever want clickable items, swap <div> for <a> in markup — no CSS
   change needed, but consider whether .mlo-record-list would suit
   better in that case. */
.mlo-topics-list {
  /* container; natural block flow — no explicit display needed */
}
.mlo-topics-list__item {
  display: flex;
  gap: 1.5rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
}
.mlo-topics-list__item:last-child {
  border-bottom: none;
}
.mlo-topics-list__num {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--wp--preset--color--sky);
  min-width: 2rem;
  flex-shrink: 0;
}
.mlo-topics-list__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--wp--preset--color--text);
  /* Matches .mlo-record__title (line 2952) in family, size, weight, and
     line-height so list-row titles read identically across the site
     (topics-list + record-list). The display font's smaller x-height
     also means 0.9375rem reads visually equivalent here as it does in
     the record-list rows above, whereas the body font's larger x-height
     would make the same numeric size appear larger by comparison. */
}

/* ───────────────────────────────────────────────────────────────────
 * COLLECT CARD
 *
 * Reusable artwork card for works sold through EXTERNAL channels — used
 * on the /collect/ page and the homepage Featured Works section. Unlike
 * .mlo-artwork-card (CPT-driven, links to internal singles, no price),
 * this card is hand-populated, carries a price + chain badge, and links
 * out to marketplaces/galleries or to /collect/.
 *
 * Sits inside .mlo-three-col or .mlo-two-col, which own the responsive
 * column collapse (3→2→1), so this class styles only the card chrome —
 * no internal breakpoints needed. The __links row holds 1–3
 * .mlo-arrow-link anchors (one "View →" on the homepage; up to three —
 * Preview / View on-chain / Acquire — on Collect).
 * ─────────────────────────────────────────────────────────────────── */
.mlo-collect-card {
  display: flex;
  flex-direction: column;
  background: var(--wp--preset--color--white);
  border: 1px solid var(--wp--preset--color--border-light);
}

.mlo-collect-card__media {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--mlo-bg-soft);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--mlo-card-inset);
}

.mlo-collect-card__media img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  min-width: 0; /* flex child: let max-width win over intrinsic min-width
                   (raw <img> in Custom HTML carries no srcset, so its
                   intrinsic width is the full file — without this it
                   refuses to shrink and overflows on mobile) */
  object-fit: contain; /* never crop the artwork */
  display: block;
}

.mlo-collect-card__badge {
  position: absolute;
  top: 0.625rem;
  right: 0.625rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
  background: rgba(255, 255, 255, 0.85);
  padding: 0.1875rem 0.5rem;
}

.mlo-collect-card__body {
  padding: 1.25rem 1.5rem 1.5rem;
}

.mlo-collect-card__title {
  margin: 0 0 0.5rem;
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.0625rem;
  font-weight: 400;
  font-style: italic;
  line-height: 1.35;
  color: var(--wp--preset--color--text);
}

.mlo-collect-card__series {
  display: inline-block;
  margin-bottom: 0.375rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--wp--preset--color--sky);
  text-decoration: none;
  transition: color 0.2s;
}
.mlo-collect-card__series:hover {
  color: var(--wp--preset--color--hover);
}

.mlo-collect-card__medium {
  margin: 0 0 1.25rem;
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  line-height: 1.4;
  color: var(--wp--preset--color--text-light);
}

.mlo-collect-card__price {
  margin-bottom: 0.125rem;
  font-family: var(--wp--preset--font-family--body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--wp--preset--color--text);
}

.mlo-collect-card__price-sub {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.75rem;
  color: var(--wp--preset--color--text-muted);
}

.mlo-collect-card__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin-top: 1rem;
}

/* ───────────────────────────────────────────────────────────────────
 * ARTWORK ROW  (Collect page)
 *
 * One artwork per row: two media columns + an info column. Sits inside a
 * section's content container. The background variant lets each row
 * contrast its section: grey rows (--soft) in the white Do Not Accumulate
 * section, white rows (--white) in the soft KUU section.
 *
 * Responsive: 3 columns on desktop; at <=1024px the two media sit side by
 * side with the info column spanning full width beneath them; single
 * column at <=600px. Wrap consecutive rows in .mlo-artwork-rows for the
 * vertical rhythm between them.
 * ─────────────────────────────────────────────────────────────────── */
.mlo-artwork-rows {
  display: flex;
  flex-direction: column;
  gap: clamp(1.75rem, 3.5vw, 3rem);
}

.mlo-artwork-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(2.25rem, 4.5vw, 3.75rem);
  align-items: start;
  padding: clamp(1.75rem, 3.5vw, 2.75rem);
}
.mlo-artwork-row--white { background: var(--wp--preset--color--white); }
.mlo-artwork-row--soft  { background: var(--mlo-bg-soft); }

@media (max-width: 1024px) {
  .mlo-artwork-row { grid-template-columns: 1fr 1fr; }
  .mlo-artwork-row > :last-child { grid-column: 1 / -1; }
}
@media (max-width: 600px) {
  .mlo-artwork-row { grid-template-columns: 1fr; }
  .mlo-artwork-row > :last-child { grid-column: auto; }
}

/* info-column internals, type only; the vertical rhythm is owned by the
   .mlo-artwork-row__info rules below so it survives the editor block-gap. */
.mlo-artwork-row__badge {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
}
.mlo-artwork-row__title {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.25rem;
  font-weight: 400;
  font-style: italic;
  line-height: 1.3;
  color: var(--wp--preset--color--text);
}
.mlo-artwork-row__medium {
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  line-height: 1.4;
  color: var(--wp--preset--color--text-light);
}
.mlo-artwork-row__price {
  font-family: var(--wp--preset--font-family--body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--wp--preset--color--text);
}
.mlo-artwork-row__price-sub {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.75rem;
  color: var(--wp--preset--color--text-muted);
}
.mlo-artwork-row__links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.625rem;
}
.mlo-artwork-row__note {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.75rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--wp--preset--color--text-muted);
}

/* Info column owns its vertical rhythm so it is immune to the editor's
   block-gap. Scoped under .mlo-artwork-row to outrank WordPress flow-layout
   spacing (which otherwise zeroes child margins and inserts a uniform gap).
   The 1rem default step applies between any two children, so the links row and
   the CTA button keep their spacing with or without the __links wrapper; the
   three refinements below tighten the badge/title/medium/price-sub steps. */
.mlo-artwork-row .mlo-artwork-row__info > * { margin-block: 0; }
.mlo-artwork-row .mlo-artwork-row__info > * + * { margin-block-start: 1rem; }
.mlo-artwork-row .mlo-artwork-row__info > .mlo-artwork-row__title     { margin-block-start: 0.625rem; }
.mlo-artwork-row .mlo-artwork-row__info > .mlo-artwork-row__medium    { margin-block-start: 0.5rem; }
.mlo-artwork-row .mlo-artwork-row__info > .mlo-artwork-row__price-sub { margin-block-start: 0.125rem; }

/* ───────────────────────────────────────────────────────────────────
 * ARTWORK SINGLE  (single-artwork.php)
 *
 * Gallery wall-text hero (media + label), an auto-drawn Details "table
 * view", and the status indicator. Sits inside the existing section
 * patterns: header (hero), soft (about), default (details).
 * ─────────────────────────────────────────────────────────────────── */

/* hero: media beside the wall text.
   minmax(0, ...) is essential: a plain fr track's implicit minimum is its
   content size, so once Swiper lays the slides out as a wide horizontal row
   the media track expands to that row's max-content width and pushes the page
   out of the viewport. Capping the minimum at 0 lets the track clip the slider
   (which is overflow:hidden) instead of growing to it. */
.mlo-artwork-hero {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
  margin-top: 1.5rem;
}
@media (max-width: 900px) {
  .mlo-artwork-hero { grid-template-columns: minmax(0, 1fr); }
}

/* media: image(s) render at natural ratio, height capped so a tall portrait
   shows fully without pushing the page, width capped to the column. Applies to
   the single featured image and to each slider slide. min-width:0 on the column
   reinforces the track cap above so the slider can shrink/clip. */
.mlo-artwork-hero__media {
  min-width: 0;
}
.mlo-artwork-hero__media > img,
.mlo-artwork-hero__media > figure img,
.mlo-artwork-hero__media .mlo-slider .swiper-slide img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: min(80vh, 760px);
  margin-inline: auto;
}

/* wall text */
.mlo-artwork-hero__artist {
  margin: 0.5rem 0 0.25rem;
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.875rem;
  color: var(--wp--preset--color--text-muted);
}
.mlo-artwork-hero__meta {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
.mlo-artwork-hero__line {
  margin: 0;
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.9375rem;
  color: var(--wp--preset--color--text-body, #3D3D3D);
}

/* status indicator (dot + label) */
.mlo-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.9375rem;
  color: var(--wp--preset--color--text-body, #3D3D3D);
}
.mlo-status__dot {
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--wp--preset--color--text-light);
}
.mlo-status--available { color: #5A9E6F; }
.mlo-status--available .mlo-status__dot { background: #5A9E6F; }

/* about: the body is a section child, so it centers to content-size exactly
   like the eyebrow and H2 (their left edges align). The readable measure is
   applied to the inner blocks instead, left-aligned, so the prose lines up
   under the eyebrow rather than centering away from it.
   The section follows the hero (a --header section), so the header+section rule
   would zero its top padding; but it is a distinct soft band with its own
   border, so restore normal top padding. Both scoped to this section. */
.mlo-section:has(> .mlo-artwork-about__body) {
  padding-block-start: var(--mlo-section-pad) !important;
}
.mlo-artwork-about__body {
  margin-top: var(--wp--style--block-gap, 1.5rem);
}
.mlo-artwork-about__body > * {
  max-width: 44rem;
}
.mlo-artwork-about__body > *:first-child {
  margin-top: 0;
}

/* Details head spacing: Gutenberg auto-applies block-gap between an eyebrow and
   an H2, but this section is PHP-rendered (raw markup), so that gap is missing
   and the tag sits flush against the H2. Re-add the same block-gap margin
   Gutenberg uses, scoped via :has() to the Details section only (the one
   containing .mlo-artwork-details) so no other section is affected. */
.mlo-section:has(> .mlo-artwork-details) > .mlo-tag + .mlo-heading-section {
  margin-top: var(--wp--style--block-gap, 1.5rem);
}

/* details: two columns, each a labelled run of meta rows */
.mlo-artwork-details {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
  margin-top: 1.5rem;
}
@media (max-width: 768px) {
  .mlo-artwork-details { grid-template-columns: 1fr; }
}
.mlo-details-subhead {
  margin: 0 0 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
  font-family: var(--wp--preset--font-family--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wp--preset--color--sky);
}
.mlo-meta-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--wp--preset--color--border-light);
}
.mlo-meta-row__label {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.8125rem;
  color: var(--wp--preset--color--text-muted);
}
.mlo-meta-row__value {
  font-family: var(--wp--preset--font-family--body);
  font-size: 0.8125rem;
  color: var(--wp--preset--color--text);
  text-align: right;
}