/**
 * Theme Name: Blocksy Child
 * Description: Child theme for New Mexico Breweries.
 * Author: Patrick Iverson
 * Template: blocksy
 * Version: 1.0.0
 * Text Domain: blocksy-child
 */

/* -----------------------------------------------------------------------------
   Block / layout cleanup

   Standard across Iverson Creative Blocksy child themes. The block editor and
   Blocksy each apply their own vertical rhythm and together they double up:
   spacers land under a margin that is already there, covers carry padding the
   design did not ask for, and headings arrive with a top margin fighting
   whatever spacing was set deliberately.

   The !important throughout is deliberate — these override theme and core block
   styles that are themselves specific. Softening them stops the snippet working.

   Ported 2026-10-08 from the New Mexico Community Care child theme, the
   reference copy of this set (~/Sites/nmcommunitycare). The two sections below
   (block/layout cleanup, Media & Text) are taken verbatim apart from the custom
   property prefix; the derivation notes still cite NMCC measurements.
----------------------------------------------------------------------------- */

.alignfull,
.wp-block-cover.alignwide {
	margin-bottom: 0 !important;
}

.wp-block-blocksy-query,
.wp-block-columns {
	margin-bottom: 0 !important;
}

/* COVER PADDING, IN TWO LAYERS.

   The base rule keeps the standing override's behaviour — no padding on a cover —
   but says it on both axes explicitly, because only one of them is now negotiable.
   The inline zeroing applies to EVERY cover and is not the same decision as the
   block axis: a cover's inner container is is-layout-constrained, so the content
   inset comes from the layout, not the cover's padding. Verified when this rule
   first took 16px off the RC01 hero and its text stayed exactly in line with the
   paragraphs either side (75px at 1440, 23px at 390).

   The second rule gives vertical padding to THE HERO ONLY, so Patrick stops adding
   spacer blocks to heroes in the editor. It is a narrower selector layered on the
   base rule, not a competing one: the base sets both axes for all covers, the hero
   rule overrides one axis for one cover per page.

   IT HAS TO WORK IN GUTENBERG TOO, because dropping the spacer blocks is the whole
   point and Patrick reviews heroes in the editor. The editor canvas has no
   .entry-content — root-level blocks sit under
   .block-editor-block-list__layout.is-root-container — so a rule scoped to
   .entry-content alone loads via add_editor_style and matches nothing there.
   Both containers are named in one :is(), so the declaration exists ONCE and cannot
   drift between contexts; a shared token across two rules would still be two rules
   to keep in step. WP prefixes editor styles with .editor-styles-wrapper, which the
   root container sits inside, so the editor arm resolves.

   WHY THIS SELECTOR. "A cover with no cover before it."
     :first-of-type matches by ELEMENT type, and every block here is a DIV, so it
       would pick the wrong element the moment any div-based block precedes the hero.
     :first-child works on today's markup and breaks the moment anything is placed
       above the hero.
     :not(.wp-block-cover ~ .wp-block-cover) is neither — it excludes any cover that
       has a cover before it among its siblings, which is the actual rule.
   The Resource Center is the case that proves it: two covers, both direct children
   of .entry-content, and only the first takes the padding. The same holds in the
   editor, where both are direct children of the root container.

   FLUID, NOT STEPPED, AND EQUAL TOP AND BOTTOM (Patrick, 2026-10-02). One
   expression, used for both edges, scaling linearly from 56px at a 390px viewport
   to 140px at 1440px:
       slope     (140 - 56) / (1440 - 390) = 84/1050 = 0.08  -> 8vw
       intercept 56 - 0.08 * 390 = 24.8px                    -> 1.55rem
       check     390:  24.8 + 31.2  = 56
                 820:  24.8 + 65.6  = 90.4
                 1440: 24.8 + 115.2 = 140
   The rem + vw pair is preferred over bare vw so the term still responds if the
   root font size changes. 1.55rem assumes a 16px root, which is what this site
   computes at every width (measured, 2026-10-02); if the root is ever changed the
   rem term has to be re-derived or the low end drifts.

   WHAT THIS REPLACED WAS BROKEN, which is worth recording so it is not reinstated.
   The previous rule read
       clamp(110px, 3.16rem + 15.24vw, 100px)
   on both edges, from a derivation that intended 270px top / 100px bottom. The min
   (110px) is GREATER than the max (100px), and CSS clamp resolves min over max, so
   every hero on the site got a flat 110px at every width and the fluid behaviour
   the comment described never happened once. Measured 110px at both 390 and 1440
   before this change. If you are tempted to write a two-ended clamp here, check
   that the min really is below the max.

   Above 1440 it clamps at 140px, so a wide desktop does not keep growing; below
   390 it holds at 56px.

   Note !important beats a non-important inline style, so a per-cover padding set in
   the editor is still overridden ON A HERO. Non-hero covers now DO honour the
   editor's padding — see the per-axis guard on the base rule above. */

/* THE GLOBAL RESET NOW STANDS DOWN WHEN THE EDITOR HAS AN OPINION.
 *
 * What it is for: core gives EVERY cover `padding: 1em` in
 * wp-includes/blocks/cover/style.min.css, which this build does not want, so the
 * reset zeroes it and the hero rule below then sets real padding on heroes only.
 *
 * What went wrong (2026-10-02): because the reset is `!important`, it beat the
 * inline style the block's own Dimensions panel writes, on every cover on the
 * site. Patrick set vertical padding Large on the navy disclaimer banner
 * (#disclaimer on the Resource Center); it saved correctly as
 * style.spacing.padding and rendered as
 * `style="padding-top:var(--wp--preset--spacing--60);padding-bottom:..."`, and
 * then this rule zeroed it. The hero rule was NOT the cause and was never
 * matching that banner — it is correctly narrowed to a cover with no cover before
 * it, and the disclaimer has five.
 *
 * The guard is per-axis on purpose. A single :not([style*="padding"]) would let a
 * cover that sets only vertical padding fall back to core's 1em on the sides,
 * which is the horizontal padding this build removed in the first place. Matching
 * the longhands core actually emits keeps each axis independent: set vertical
 * padding in the editor and you get it, with the horizontal reset still in force.
 *
 * Heroes are unaffected either way: the rule below is !important and wins on both
 * specificity and order, so a hero's padding stays fluid even if someone sets a
 * value on it in the editor. That caveat in the comment above still holds.
 */

.wp-block-cover:not([style*="padding-left"]):not([style*="padding-right"]):not([style*="padding-inline"]) {
	padding-inline: 0 !important;
}

.wp-block-cover:not([style*="padding-top"]):not([style*="padding-bottom"]):not([style*="padding-block"]) {
	padding-block: 0 !important;
}

/* front end: .entry-content   |   block editor: .is-root-container */
:is(.entry-content, .is-root-container) > .wp-block-cover:not(.wp-block-cover ~ .wp-block-cover) {
	padding-block:
		clamp(56px, 1.55rem + 8vw, 140px)
		clamp(56px, 1.55rem + 8vw, 140px) !important;
}

/* Remove bottom margin before spacer blocks to avoid double vertical rhythm. */

*:has(+ .wp-block-spacer) {
	margin-bottom: 0 !important;
}

/* Headings lose their top margin EXCEPT after a paragraph or a list, where the
   gap is doing real work: it separates the previous section's prose from the
   next section's heading. Narrowing the rule rather than zeroing and restoring,
   because `revert` would fall back to the user-agent value, not the theme's —
   we would be replacing the theme's spacing with the browser's.

   This is Trout's rule, not LANL's blunt `.wp-block-heading { margin-top: 0 }`.
   Taken deliberately: LANL's version also kills the gap after prose, which is
   the one place the margin is earning its keep. Trout's is the later thinking
   and the better rule. */

.wp-block-heading:not(:is(p, ul, ol, .wp-block-list) + .wp-block-heading) {
	margin-top: 0 !important;
	margin-block-start: 0 !important;
}

/* NOT PORTED, and worth knowing why rather than rediscovering it:
   LANL carries `.wp-block-cover__inner-container { padding: 0 !important }`.
   Trout dropped it, so it is not part of the common set, and on this site it
   would reach the RC01 hero and the RD01 resource-detail hero, both of which are
   covers whose inner container is doing real layout. Left out on the
   "where they differ, take Trout's" rule. */

/* -----------------------------------------------------------------------------
   Media & Text: two cases, and the distinction is alignment

   SCOPED TO .alignfull (Patrick, 2026-10-05). The first version of this applied to
   every Media & Text block on the site and broke the one that was already right:
   the Resource Center's Find Help intro ("Search for help near you." with the Find
   Help logo on the right) is a CONSTRAINED block, and insetting its text pulled it
   out of line with the left edge of the ZIP panel directly beneath it. Those two
   reading as one column is the whole point of that section.

   So the two cases are now separated by the thing that actually distinguishes them:

   1. ALIGNFULL blocks bleed to the viewport. There is no page margin to line up
      with, so with the outer padding zeroed the text ran to the very edge of the
      screen — the reported bug on Patrick's page. These get equal padding on all
      four sides.

   2. CONSTRAINED blocks already sit inside the content column. Their text SHOULD
      line up with the paragraphs and panels above and below, so they keep the
      original treatment: zero the padding on the side away from the media, keep
      the gutter next to it. Core puts a symmetric `padding: 0 8%` on the content
      (wp-includes/blocks/media-text/style.css); the 8% beside the image earns its
      keep, the 8% on the outer edge does not.

   Case 2 is restored byte-for-byte to what it was before 2026-10-05, including its
   600px media query, so nothing that was previously correct has moved.

   THE FLUID VALUE TRACKS THE PAGE GUTTER, measured on this build 2026-10-05: the
   distance from the viewport edge to normal body text is 23px at 390 and 41px at
   820. clamp(24px, 5vw, 80px) resolves to 24px / 41px / 72px at 390 / 820 / 1440,
   so the mobile floor lands on the 23px gutter and the 820 value matches exactly.
   A stacked full-bleed block on a phone therefore sits in line with the rest of
   the page rather than being specially inset.

   SPECIFICITY. Blocksy ships two mobile rules in bundle/main.min.css, which loads
   AFTER this stylesheet:
       @media (max-width: 600px) {
         .wp-block-media-text .wp-block-media-text__content { padding: var(--theme-content-spacing) }
         .wp-block-media-text:not(.has-background) .wp-block-media-text__content
             { padding-inline: 0; padding-bottom: 0 }
       }
   The second is (0,3,0) — `:not()` takes its argument's specificity — so a (0,3,0)
   selector here ties and loses on source order. Case 2's media query answers that
   with a doubled block class, (0,4,0). The alignfull rule doubles both class names
   for (0,5,0), which also puts it above case 2, so the two cannot fight regardless
   of order. Blocksy is not more specific here, it is simply later.

   PHYSICAL `padding`, not logical: core forces `direction: ltr` on this block and
   wraps its column swaps in rtl:ignore, so padding-inline-* would follow the text
   direction and disagree with core's own geometry.

   No !important anywhere, so a padding set in the editor's spacing controls still
   wins through its inline style.
----------------------------------------------------------------------------- */

/* 1. FULL-BLEED: the text column lines up with the page's content grid.
 *
 * Equal padding all round was the first version and it was not enough: a full-bleed
 * row's text started at the clamp value (72px at 1440) while the constrained section
 * below it started at the grid edge (75px), so the two were 3px out and read as a
 * misalignment. At 1920 it was far worse, 80px against 315px.
 *
 * THE GRID EDGE, DERIVED NOT HARDCODED. Measured on this build 2026-10-05, the
 * constrained content container is
 *     --theme-container-edge-spacing : 90vw desktop/tablet, 88vw at mobile
 *     --wp--style--global--content-size -> --theme-block-max-width (1290px here)
 * and Gutenberg centres the narrower of the two, so the distance from the viewport
 * edge to body text is (viewport - min(contentSize, edgeSpacing)) / 2. Checked
 * against "Ready for the next step?" on Home: 315 / 75 / 51 / 41 / 23 at
 * 1920 / 1440 / 1024 / 820 / 390, and the expression reproduces all five.
 *
 * Note this one expression also covers the narrow case. Below ~1434px the container
 * is the 90vw/88vw term rather than 1290px, so the result IS the page gutter and no
 * separate max() or mobile override is needed — which is why the stacked phone case
 * lands on the same 23px as every other section without special handling.
 *
 * 100vw, NOT 100%. Percentage padding on a grid item resolves against the grid AREA
 * (the column), not the block, so 100% here would measure the wrong box entirely.
 * The trade is that 100vw includes a classic scrollbar's width where one exists, so
 * on a platform with non-overlay scrollbars the edge can sit a few px out. macOS
 * overlay scrollbars have no width, so it is exact here; if that ever bites, the fix
 * is to publish the block's own width as a custom property from the block, not to
 * swap in 100%.
 *
 * WHICH SIDE GETS THE EDGE depends on which column the text is in, and core's class
 * names describe the MEDIA, not the text:
 *     default (media left)        -> text is the RIGHT column  -> edge on the END
 *     .has-media-on-the-right     -> text is the LEFT column   -> edge on the START
 * The other side keeps the clamp, which is the gap between the text and the image.
 *
 * Logical properties are safe here, unlike the constrained case below: these two
 * declarations are symmetric mirror images, so there is nothing for an RTL document
 * to disagree with.
 */
.wp-block-media-text.alignfull.wp-block-media-text > .wp-block-media-text__content.wp-block-media-text__content {
	--nmb-mt-gap: clamp(24px, 5vw, 80px);
	--nmb-mt-edge: calc(
		(100vw - min(var(--wp--style--global--content-size, 1290px),
		             var(--theme-container-edge-spacing, 90vw))) / 2
	);
	padding-block: var(--nmb-mt-gap);
	/* media left -> text on the right -> grid edge on the right */
	padding-inline-start: var(--nmb-mt-gap);
	padding-inline-end: var(--nmb-mt-edge);
}

/* media right -> text on the left -> grid edge on the left */
.wp-block-media-text.alignfull.wp-block-media-text.has-media-on-the-right > .wp-block-media-text__content.wp-block-media-text__content {
	padding-inline-start: var(--nmb-mt-edge);
	padding-inline-end: var(--nmb-mt-gap);
}

/* STACKED: the image is above the text, so there is no gap to protect and both sides
   take the grid edge, putting the text in line with every other section. Core stacks
   only .is-stacked-on-mobile, and only at 600px and under. */
@media (max-width: 600px) {

	.wp-block-media-text.alignfull.wp-block-media-text.is-stacked-on-mobile > .wp-block-media-text__content.wp-block-media-text__content {
		padding-inline: var(--nmb-mt-edge);
	}
}

/* 2. Constrained: unchanged from the original rules. */
.wp-block-media-text > .wp-block-media-text__content {
	padding-right: 0;
}

.wp-block-media-text.has-media-on-the-right > .wp-block-media-text__content {
	padding-left: 0;
	padding-right: 8%;
}

/* Core only stacks blocks carrying .is-stacked-on-mobile, and only at 600px and
   under. A block with stacking switched off stays side by side at every width, and
   there the override above is still what we want. Stacked blocks are left alone on
   purpose: the media is ABOVE the text, so there is no gutter to protect, and what
   Blocksy does (zero the inline padding so the text meets the page margin) is
   correct. Note that differs from core-only behaviour, so do not "fix" it by
   comparing against core in isolation. */
@media (max-width: 600px) {

	.wp-block-media-text.wp-block-media-text:not(.is-stacked-on-mobile) > .wp-block-media-text__content {
		padding-left: 8%;
		padding-right: 0;
	}

	.wp-block-media-text.wp-block-media-text.has-media-on-the-right:not(.is-stacked-on-mobile) > .wp-block-media-text__content {
		padding-left: 0;
		padding-right: 8%;
	}
}

/* -----------------------------------------------------------------------------
   Leaflet maps: keep their stacking inside the map

   Leaflet panes run to z-index 400-1000 (markers 600, popups 700, controls 1000)
   against whatever stacking context they land in, so the map painted over the
   header dropdowns and Blocksy's shortcuts bar. The wrapper takes a stacking
   context of its own, which caps every Leaflet value inside it. Same fix as the
   LANL Foundation child theme.
----------------------------------------------------------------------------- */

.wplm-map-wrap {
	position: relative;
	z-index: 0;
	isolation: isolate;
}
