.gaia-heading--h2.gaia-heading--h2 {
  font-size: var(--font-size-h2, 24px);
  line-height: var(--line-height-h2, 36px);
  font-weight: var(--font-weight-bold, 700);
  color: var(--color-text-body, #1a1a1a);
  border-bottom: 2px solid var(--color-text-body, #1a1a1a);
  padding-bottom: 0.4rem;
  margin-bottom: 1.5rem;
  letter-spacing: 0.02em;
}

.gaia-heading--h2.gaia-heading--plain {
  border-bottom: none;
  padding-bottom: 0;
}

/* Default margin-top: 4rem, when no manual "上マージン" override
   (mt-0/1/2/3) is selected in the Inspector. This block never sets its
   own margin-top otherwise, so without a manual override it falls
   through to the parent theme's cascade: 0 from `.post_content
   h1,h2,...{margin:0 0 15px 0}` if this h2 is the very first element,
   or 40px/30px/20px (desktop/tablet/mobile) from design-plus.css's
   `.post_content :not(h2..h6) + h2 {...!important}` otherwise —
   confirmed live, both cases. Scoped with :not() to every mt-X class
   specifically so this NEVER competes with a manual override: when one
   of those classes is present this selector simply doesn't match that
   element at all, leaving the existing mt-0/1/2/3 utility classes (and
   whatever their own relationship with design-plus.css already is)
   completely untouched. Each :not(.class) argument adds a class to this
   selector's specificity, so the un-overridden case (0,6,0) still
   easily beats design-plus.css's !important rule (0,1,6) — the class
   column is compared first. */
.gaia-heading--h2.gaia-heading--h2:not(.gaia-heading--mt-0):not(
    .gaia-heading--mt-1
  ):not(.gaia-heading--mt-2):not(.gaia-heading--mt-3) {
  margin-top: 4rem !important;
}

/* "Section" variant (blog posts only, see render.php) — an eyebrow row
   ("SECTION 01" + a line filling the rest of the row, matching the same
   pattern already used for the blog title's category badge) sitting
   above the actual H2 text. No border-bottom at all here, unlike the
   default variant — this is a deliberately different, standalone look,
   not the default styling with a toggle. Matches the Figma reference's
   first-H2 treatment.

   Unlike the default variant, .gaia-heading-section is the <h2> element
   ITSELF, not a wrapper around a separate inner h2 — see render.php's
   own long comment for why: the parent theme's TOC generator finds the
   first heading via a plain regex against the raw HTML and splices its
   own markup in right before whatever it matches, with zero ancestor
   awareness. A wrapper div outside the h2 let the TOC land between the
   eyebrow and the title, visually splitting them (confirmed live from a
   real post). Keeping everything inside one bare, undivided <h2> — same
   shape the default/plain variants already have — means the TOC still
   only ever finds one heading to insert before, landing correctly
   ahead of the whole thing. display:flex + flex-direction:column here
   is what stacks the eyebrow row and the title text as two lines
   without needing a separate wrapper element for that stacking. */
.gaia-heading-section.gaia-heading-section {
  display: flex;
  flex-direction: column;
  margin-bottom: 1rem;
  font-size: var(--font-size-h2, 24px);
  line-height: var(--line-height-h2, 36px);
  font-weight: var(--font-weight-bold, 700);
  color: var(--color-text-body, #1a1a1a);
  letter-spacing: 0.02em;
}
/* Default margin-top: 4rem, same fixed value and same reasoning as the
   default/plain variant's rule above — this selector is what the
   earlier version of this comment block (margin-top deliberately left
   alone, relying on design-plus.css's contextual 40/30/20px) applied
   to, but a later request made the 4rem default apply uniformly to
   every h2 variant, superseding that earlier contextual choice. Same
   :not() scoping against every mt-X class so a manual "上マージン"
   override still works normally instead of being fought by this rule. */
.gaia-heading-section.gaia-heading-section:not(.gaia-heading--mt-0):not(
    .gaia-heading--mt-1
  ):not(.gaia-heading--mt-2):not(.gaia-heading--mt-3) {
  margin-top: 4rem !important;
}
/* No `gap` here — a shared gap would space every child evenly, but only
   the label-to-bar spacing should exist; the bar and the line need to
   sit flush against each other with zero gap so they read as one
   continuous piece. That spacing lives on the ::before label's own
   margin-right instead, scoped to just that one gap. */
.gaia-heading-section__eyebrow {
  display: flex;
  align-items: flex-end;
  margin-bottom: 8px;
}
/* The label itself — rendered as generated content from the eyebrow's
   own data-label attribute, NOT a real text node/span (see render.php's
   long comment: a real text node here is what the parent theme's TOC
   generator glues onto the title with no separator, and fixing that via
   a JS post-pass after page load caused a visible flash). CSS-generated
   content is never present in the raw HTML the TOC's regex operates on,
   so there's nothing for it to capture, and nothing to fix up after the
   fact either — this renders correctly on the very first paint. */
.gaia-heading-section__eyebrow::before {
  content: attr(data-label);
  color: var(--color-brand-accent-solid, #f0701c);
  font-size: var(--font-size-caption, 12px);
  /* Without this, the generated content inherits the outer h2's own
     line-height (36px, for 24px title text) — the 12px glyph then
     renders centered inside a much taller box than it actually needs,
     so align-items:flex-end above (aligning to the BOTTOM of that
     inflated box) puts it well below the line's own y-position instead
     of level with it. Confirmed live on the previous real-span version
     of this label: text box height was a full 36px against a ~12-14px
     glyph, before this fix — same box-model behavior applies to
     generated content sized by the same inherited properties. */
  line-height: 1;
  font-weight: var(--font-weight-bold, 700);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  margin-right: 4px;
}
/* Short solid accent bar right after the label, before the thin gray
   line takes over for the rest of the row — matches the Figma
   reference (a user screenshot flagged this as missing from the first
   pass, which only had the plain gray line). Same accent color as the
   label text itself. No margin-bottom — sits flush at the row's own
   bottom edge via align-items:flex-end, same as the line, per explicit
   request rather than the earlier version's center-aligned nudge. */
.gaia-heading-section__eyebrow-accent {
  flex: 0 0 auto;
  width: 100px;
  height: 2px;
  background: var(--color-brand-accent-solid, #f0701c);
  margin-bottom: 1px;
}
.gaia-heading-section__eyebrow::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--color-border-subtle, #ddd);
  margin-bottom: 1px;
}
/* No separate rule needed for .gaia-heading-section__title-text — it's a
   plain <span>, not an h2, so it was never matched by the parent's
   `.post_content h2` rule in the first place, and simply inherits the
   font-size/line-height/font-weight/color/letter-spacing already set on
   the outer h2 above. */

.gaia-heading--left {
  text-align: left !important;
}
.gaia-heading--center {
  text-align: center !important;
}
.gaia-heading--right {
  text-align: right !important;
}

/* ── Margin bottom ────────────────────────────────── */
.gaia-heading--mb-0 {
  margin-bottom: 0 !important;
}
.gaia-heading--mb-1 {
  margin-bottom: 1em !important;
}
.gaia-heading--mb-2 {
  margin-bottom: 2em !important;
}
.gaia-heading--mb-3 {
  margin-bottom: 3em !important;
}

/* ── Margin top ───────────────────────────────────── */
.gaia-heading--mt-0 {
  margin-top: 0 !important;
}
.gaia-heading--mt-1 {
  margin-top: 1em !important;
}
.gaia-heading--mt-2 {
  margin-top: 2em !important;
}
.gaia-heading--mt-3 {
  margin-top: 3em !important;
}
/* Discovered while adding the default-margin-top rule above: these
   utility classes are (0,1,0) specificity, same tier as mb-X — but
   unlike margin-bottom, margin-top has a competing !important rule to
   contend with (design-plus.css's `.post_content :not(h2..h6) + h2`,
   (0,1,6)), which wins whenever this h2 follows non-heading content —
   confirmed live: picking "0" or "2em" from the 上マージン Inspector
   control both still rendered as the design-plus.css value (40px),
   not the chosen one. This was true before the 4rem default above was
   added too — that change just made it visible by giving a stronger
   contrast to compare against. h2-scoped compound selectors (not
   touching the bare .gaia-heading--mt-X rules above, which heading-h3/
   h4/h5 each keep their own separate, identically-named copies of in
   their own style.css — safe to leave alone) push specificity to
   (0,2,0), same technique as .gaia-heading--h2.gaia-heading--h2
   elsewhere in this file. */
.gaia-heading--h2.gaia-heading--mt-0 {
  margin-top: 0 !important;
}
.gaia-heading--h2.gaia-heading--mt-1 {
  margin-top: 1em !important;
}
.gaia-heading--h2.gaia-heading--mt-2 {
  margin-top: 2em !important;
}
.gaia-heading--h2.gaia-heading--mt-3 {
  margin-top: 3em !important;
}
/* Same boost, for the "section" variant — it's a real <h2> too (see the
   long comment further up), so it's just as subject to design-plus.css's
   competing !important rule as the default/plain variant, and needs the
   same manual-override fix now that its own default margin-top is also
   a forced 4rem instead of being left contextual. */
.gaia-heading-section.gaia-heading--mt-0 {
  margin-top: 0 !important;
}
.gaia-heading-section.gaia-heading--mt-1 {
  margin-top: 1em !important;
}
.gaia-heading-section.gaia-heading--mt-2 {
  margin-top: 2em !important;
}
.gaia-heading-section.gaia-heading--mt-3 {
  margin-top: 3em !important;
}

/* ── Text color — same 8 tokens as gaia/paragraph's own 文字色.
   Also recolors the default variant's border-bottom (plain/section have
   none to affect) — it's styled from the same --color-text-body as the
   text itself by default, so leaving it un-recolored would look like a
   mismatch rather than a deliberate two-tone choice. ── */
.gaia-heading--color-black      { color: var(--color-text-heading, #000000) !important; border-bottom-color: var(--color-text-heading, #000000) !important; }
.gaia-heading--color-grey       { color: var(--color-text-muted, #999999) !important; border-bottom-color: var(--color-text-muted, #999999) !important; }
.gaia-heading--color-grey-light { color: var(--color-text-muted-light, #bbbbbb) !important; border-bottom-color: var(--color-text-muted-light, #bbbbbb) !important; }
.gaia-heading--color-blue       { color: var(--color-status-info, #49352D) !important; border-bottom-color: var(--color-status-info, #49352D) !important; }
.gaia-heading--color-green      { color: var(--color-status-success, #F0701C) !important; border-bottom-color: var(--color-status-success, #F0701C) !important; }
.gaia-heading--color-red        { color: var(--color-status-danger, #E8501E) !important; border-bottom-color: var(--color-status-danger, #E8501E) !important; }
.gaia-heading--color-white      { color: var(--color-text-inverse, #ffffff) !important; border-bottom-color: var(--color-text-inverse, #ffffff) !important; }
