/* ========================================================================================
 * tmj-spacing.css — STANDARDIZED VERTICAL FLOW SPACING (loads last of the design layers)
 *
 * WHY THIS FILE EXISTS
 * --------------------
 * The .s section system sets the spacing BETWEEN sections (.s--pt-* / .s--pb-*), but until
 * now nothing owned the spacing between the stacked blocks INSIDE a section. Each module
 * carried its own margin-bottom, so a block that happened to end in something with no
 * bottom margin (an .ac-accordion, an .info-features grid, an embedded form) left the next
 * module sitting flat against it. A 2026-08-18 audit of all 45 published pages, measured in
 * a headless browser at 1440px and 390px, found 60+ such flush (0px) module boundaries —
 * the most common being .info-content -> .hero-buttons (21 instances across 16 pages, e.g.
 * the FAQ accordion butting straight into the CTA row on /sleep-apnea/snoring/).
 *
 * HOW IT WORKS — "spacing floors", not fixed spacing
 * --------------------------------------------------
 * Each layout wrapper declares a MINIMUM gap between its direct children, applied as
 * margin-top on every child after the first (the "owl" selector, `> * + *`).
 *
 * In a normal BLOCK-FLOW container, an element's margin-top and its previous sibling's
 * margin-bottom COLLAPSE to the larger of the two. So the floor does not stack on top of
 * existing spacing — the result is exactly max(existing gap, floor). Modules that already
 * space themselves correctly are untouched; only the too-tight ones are lifted. That is
 * what makes it safe to apply site-wide.
 *
 * WHERE A NAIVE FLOOR BREAKS — three mechanisms, all found the hard way by measuring:
 *
 *   0. AN EXISTING, LARGER margin-top ON THE CHILD ITSELF. These tiers set margin-top, so a
 *      normal-specificity rule would REPLACE a bigger authored value instead of flooring it
 *      — a ceiling, not a floor (measured: .info-features lost its 40px top margin and
 *      .hero-trust its 48px). That is why EVERY tier selector below is wrapped in :where(),
 *      giving it ZERO specificity: any authored margin-top carrying even one class beats it,
 *      so the floor only fills in where nothing else has an opinion.
 *
 *   The other two are margin-collapsing exceptions, where the floor ADDS to the existing
 *   margin instead of flooring it:
 *
 *   1. ATOMIC INLINES. An `inline-flex` / `inline-block` sibling does not collapse with the
 *      block next to it. .section-label and .hero-label are inline-flex, so the floor
 *      doubled the eyebrow-to-heading gap across 343 instances. See EYEBROW EXEMPTION below.
 *   2. FLEX / GRID CONTAINERS. These never margin-collapse their children at all.
 *      .cta-content is a flex column and is excluded from tier 2 for exactly this reason.
 *
 * So: before adding a wrapper to a tier, check its computed `display`, and check whether its
 * children are atomic inlines. If either exception applies, the floor will inflate spacing
 * rather than protect it — leave that wrapper's own margins alone instead.
 *
 * Three tiers, coarse to fine:
 *   --flow-section : between major modules inside a section container (.s-container)
 *   --flow-block   : between blocks inside a column / content wrapper (.s-col-text, ...)
 *   --flow-prose   : between text-level blocks inside a copy block (.info-content, ...)
 * plus --flow-module, a larger floor used when a *block-level component* (accordion,
 * grid, image, list, form, embed) sits inside a prose wrapper and needs more air than a
 * paragraph does.
 *
 * TO RETUNE SITE-WIDE SPACING, EDIT THE TOKENS BELOW — nothing else.
 *
 * PER-INSTANCE ESCAPE HATCHES (add to the WRAPPER, in the page HTML):
 *   .flow-flush  — remove the floor entirely (children space themselves)
 *   .flow-tight  — halve the floor
 *   .flow-loose  — 1.5x the floor
 *   .flow        — opt any new wrapper INTO block-level flow spacing
 * And on a single CHILD: .flow-skip (no floor above it), .flow-gap-lg (extra air above it).
 * ======================================================================================== */

:root {
	--flow-prose:   20px;  /* paragraph-to-paragraph rhythm inside a copy block   */
	--flow-module:  32px;  /* a component (grid/accordion/image/form) inside copy */
	--flow-block:   32px;  /* block-to-block inside a column wrapper             */
	--flow-section: 40px;  /* module-to-module inside a section container        */
}

/* Mobile: tighten the two coarse tiers so stacked columns don't sprawl.
   Matches the 900px breakpoint tmj-sections.css already uses for .s-2col. */
@media (max-width: 900px) {
	:root {
		--flow-module:  28px;
		--flow-block:   28px;
		--flow-section: 32px;
	}
}


/* ----------------------------------------------------------------------------------------
   TIER 1 — SECTION BODY
   Direct children of a section container are whole modules (a header, a 2-col band, a card
   grid, a button row). Floor: --flow-section.
   ---------------------------------------------------------------------------------------- */
:where(.s > .s-container, .ac-container, .s-loc > .s-container) > * + * {
	margin-top: var(--flow-section);
}


/* ----------------------------------------------------------------------------------------
   TIER 2 — COLUMN / CONTENT WRAPPERS
   Direct children are blocks within one column: a copy block, a button row, a media block,
   an embedded widget. Floor: --flow-block.

   .s-col-text > .info-content + .hero-buttons is the single most common flush pair on the
   site; this rule is what fixes it, and it fixes it everywhere at once.
   ---------------------------------------------------------------------------------------- */
:where(.s-col-text, .s-col-img, .hero-text, .info-header,
        .ac-card-content, .quiz-card-content, .flow) > * + * {
	margin-top: var(--flow-block);
}
/* .cta-content is deliberately absent: it is `display:flex; flex-direction:column`, and a
   flex container NEVER margin-collapses its children. The floor would therefore ADD to each
   child's existing margin-bottom instead of flooring it (measured: cta-title -> cta-subtitle
   went 16px -> 48px). It had no flush boundaries to fix in the first place, so it keeps its
   own margins. Same reasoning applies to any future flex/grid wrapper — see the
   "Where the floor does NOT apply" note at the top of this file. */


/* ----------------------------------------------------------------------------------------
   TIER 3 — PROSE / COPY BLOCKS
   Direct children are text-level: eyebrow, heading, paragraph, list. Floor: --flow-prose,
   which matches the 20px paragraph rhythm the site already uses, so this tier is a no-op
   on well-formed copy and only lifts the outliers (12px sub-heading gaps, 0px after an
   embedded form).
   ---------------------------------------------------------------------------------------- */
/* `.info-features .info-feature` used to be in this list and had to come out
   (2026-08-25). .info-feature is a horizontal FLEX ROW — [diamond, text block] —
   so `> * + *` did not reach the h4/p pair it was written for; it reached the TEXT
   BLOCK itself and pushed it 20px down the row. With align-items:flex-start the
   diamond stayed at the top, the copy sank, and the two stopped reading as one
   item: the reported "misaligned diamonds". This is exactly the flex/grid-wrapper
   case the note at the top of this file warns about — the floor assumes children
   stack vertically, and in a row it becomes cross-axis displacement instead of
   rhythm. The h4/p gap it was aiming at is already owned by
   `.info-feature h4 { margin-bottom: 0.25rem }` in tmj-modules.css, and the
   diamond-to-copy gap by that row's own `gap: 1rem`, so nothing is left unspaced.
   Do not re-add it without giving the text block a class of its own to target. */
:where(.info-content, .section-header) > * + * {
	margin-top: var(--flow-prose);
}

/* A block-level COMPONENT inside a prose block needs more air than a paragraph does.
   Covers both directions — component after copy, and copy after component. */
:where(.info-content) > * + :where(.ac-accordion, .info-features, .conditions-grid,
       .s-imgwrap, .diamond-frame, .hero-buttons, figure, table, form, iframe, img,
       div[data-ctm-form-token], [class*="anchor-"]),
/* .featured-list is deliberately NOT in the list above. It carries `margin: 0 !important`
   in tmj-modules.css, and the companion rule `.info-subtitle:has(+ .featured-list)` groups a
   list tightly under the sub-heading that labels it — a heading and its list should read as
   one unit, not as two spaced modules. Listing it here would have been a dead selector that
   the !important silently beat. Spacing for that pair stays owned by tmj-modules.css. */
:where(.info-content) > :where(.ac-accordion, .info-features, .conditions-grid, .s-imgwrap,
       .diamond-frame, form, iframe, div[data-ctm-form-token], [class*="anchor-"]) + * {
	margin-top: var(--flow-module);
}


/* ----------------------------------------------------------------------------------------
   BUTTON ROW — spacing that must survive a flex parent

   .hero-buttons is a CTA row; it always wants air above it. It carries its own margin rather
   than relying on a tier floor because .cta-content is a flex column, where the tiers
   deliberately do not apply — without this, cta-subtitle -> buttons collapsed 72px -> 40px.
   Real specificity (not :where) so it beats the zero-specificity tiers.

   This replaces `.s--dark:not(.s-hero) .hero-buttons { margin-top: 2rem }` from
   tmj-sections.css, which only ever covered DARK sections — the reason every light-section
   FAQ/CTA boundary sat flush. In a block parent this margin collapses (acts as a floor); in
   a flex parent it adds, which is exactly what is wanted there.
   ---------------------------------------------------------------------------------------- */
.hero-buttons {
	margin-top: var(--flow-block);
}


/* ----------------------------------------------------------------------------------------
   EYEBROW EXEMPTION  (must come after the tiers — same specificity, wins on source order)

   .section-label / .hero-label are `display: inline-flex`. An atomic inline box does NOT
   margin-collapse with the block that follows it, so a flow floor ADDS to the eyebrow's own
   margin-bottom rather than flooring it — measured across 343 instances, the eyebrow-to-
   heading gap blew out from 16px to 36px (.section-label) and 24px to 56px (.hero-label).

   An eyebrow is typographically bound to the heading it introduces: it is meant to sit
   CLOSE. That gap is owned by the eyebrow's own margin-bottom (tmj-modules.css) and nothing
   else should contribute to it.
   ---------------------------------------------------------------------------------------- */
:is(.info-content, .section-header, .info-header, .hero-text, .cta-content,
    .s-col-text, .s-col-img, .s-container, .quiz-card-content, .ac-card-content, .flow)
	> :is(.section-label, .hero-label, .ac-rev-eyebrow, .eyebrow) + * {
	/* !important because this is an invariant, not a default: NOTHING except the eyebrow's
	   own margin-bottom may contribute to this gap. Without it, any authored margin-top on
	   the heading wins on specificity and re-detaches the eyebrow — e.g.
	   `.info-content.dark .info-subtitle { margin-top: 2rem }` (0,3,0) was holding
	   "WHAT TO EXPECT" 48px off its heading on /sleep-apnea/sleep-appliances/. */
	margin-top: 0 !important;
}


/* ----------------------------------------------------------------------------------------
   PER-INSTANCE MODIFIERS
   ---------------------------------------------------------------------------------------- */

/* On the wrapper — scale or remove its floor. */
.flow-flush > * + * { margin-top: 0; }
.flow-tight > * + * { margin-top: calc(var(--flow-block) / 2); }
.flow-loose > * + * { margin-top: calc(var(--flow-block) * 1.5); }
.s > .s-container.flow-tight > * + * { margin-top: calc(var(--flow-section) / 2); }
.s > .s-container.flow-loose > * + * { margin-top: calc(var(--flow-section) * 1.5); }

/* On a single child — opt that one boundary out of, or up from, the floor. */
* > .flow-skip   { margin-top: 0 !important; }
* > .flow-gap-lg { margin-top: calc(var(--flow-section) * 1.5); }


/* ----------------------------------------------------------------------------------------
   EXCLUSIONS — wrappers whose children carry their own section padding.
   Anchor Tools blocks ([anchor_block]) each render their own <section class="s s--pt-*">,
   so the full-bleed wrapper must NOT add spacing on top of that padding.
   ---------------------------------------------------------------------------------------- */
.anchor-block-fullwidth > * + *,
.anchor-block > * + * {
	margin-top: 0;
}

/* A section is spaced by its own padding, never by a flow floor — this keeps the tier-1
   rule from double-spacing a section nested inside a container. */
.s > .s-container > section.s + section.s,
.s-container > * + section.s {
	margin-top: 0;
}
