/**
 * core/media-text — the media column always reaches the edge of the screen.
 *
 * The block keeps whatever alignment the editor picked: the text column stays
 * inside the content width, and only the media is pulled out to the edge of the
 * canvas on the side it happens to sit on. So a full-bleed image no longer costs
 * a full-width block plus a hand-constrained group around the text. The canvas is
 * the window up to `canvas-max-width`, and 2560px past that.
 *
 * Loaded by includes/styles/blocks/core-media-text.php as the block's default
 * style, so every instance gets it — the selectors below target the block
 * itself, never an `.is-style-*` class.
 */

.wp-block-media-text {
	/*
	 * The width the layout gave this block, and half of what the canvas has
	 * left over — the distance the media has to travel to reach the edge. Read
	 * from the layout tokens rather than hardcoded, so it follows
	 * contentSize/wideSize in theme.json: the `min(… - 2rem, …)` form those are
	 * written in is what collapses the bleed to the 1rem gutter on small screens
	 * without a breakpoint here.
	 *
	 * "Canvas" and not "viewport" because of the `min()`: the bleed stops at
	 * `canvas-max-width` (2560px, the widest frame the design is drawn at) even
	 * when the window is wider. Past that point the section is a 2560px-wide
	 * composition centred in the window rather than a text column marooned
	 * beside an ever-growing photograph — the split the design specifies holds
	 * at every width above it, and the media stops eating the extra pixels on
	 * its own. Below 2560px the `min()` resolves to the viewport and changes
	 * nothing.
	 *
	 * Written once, with each alignment below saying only which width it uses.
	 */
	--kg-media-text-layout-width: var(--wp--style--global--content-size);
	--kg-media-text-bleed: max(
		0px,
		(
				min(
						var(--screen-size, 100vw),
						var(--wp--custom--canvas-max-width)
					) - var(--kg-media-text-layout-width)
			) / 2
	);

	/* One side, until the block stacks and the media bleeds both ways. */
	--kg-media-text-bleed-total: var(--kg-media-text-bleed);

	/*
	 * The gutter between the two columns, and the gap between them once stacked.
	 * Why these replace core's percentage padding on the content column is
	 * written above that rule, further down.
	 */
	column-gap: var(--wp--preset--spacing--5-xl);
	row-gap: var(--wp--preset--spacing--xxl);
}

.wp-block-media-text.alignwide {
	--kg-media-text-layout-width: var(--wp--style--global--wide-size);
}

/* Already as wide as the screen, so the bleed works out to zero by itself. */
.wp-block-media-text.alignfull {
	--kg-media-text-layout-width: var(--screen-size, 100vw);
}

/*
 * The gutter between the two columns, replacing core's own.
 *
 * Core spaces the text off the media with `padding: 0 8%` on the content
 * column, and that is the one core rule this style cannot live with. The
 * *outer* half of it pushes the text inwards off the container every other
 * section on the page lines up against — so "the text keeps the block's own
 * alignment", which is the whole premise above, was never quite true. And being
 * a percentage of the block, both halves move whenever the media/text split
 * does: touch the Media width control and the text measure changes with it.
 *
 * A real `column-gap` puts the text back on the layout width and states the
 * gutter as a spacing token, so it scales with the rest of the page instead of
 * with the split. `5-xl` is the design's own 133px gutter at 1440, to 5px.
 *
 * Percentage tracks are unaffected by the gap — `grid-template-columns: 1fr 50%`
 * resolves the 50% against the container, not against what the gap leaves over
 * — so the media keeps exactly the share the editor gave it and the gap comes
 * out of the text column. At the design's 1440 that is 670px of media and
 * 542px of text against a drawn 710 and 547.
 *
 * `row-gap` is stated separately because it only ever applies to the stacked
 * layout, where core collapses the grid to one column and the two gaps mean
 * completely different things.
 *
 * `div` in front of core's class for the same reason `figure` is below: core
 * writes that padding at an equal specificity, and a tie would be settled by
 * whichever sheet the browser read last — which this theme deliberately does not
 * control, because a `sheet()` dependency on a core block handle loads on the
 * front end and silently not in the editor.
 *
 * The two gap declarations live in the block's first rule above rather than in a
 * second one of their own, which is what keeps this file free of a duplicate
 * selector.
 */
.wp-block-media-text > div.wp-block-media-text__content {
	padding-inline: 0;

	/*
	 * Vertical padding inside the text column, and the seam a style or a single
	 * block sets to inset the text from the top and bottom of the section.
	 *
	 * Zero by default, so this changes nothing on its own. It exists because it
	 * is the only place that padding can go: core's `spacing.padding` support
	 * writes onto the block *wrapper*, which is the grid — padding there insets
	 * the media too, and the media is the one thing in this block that is
	 * supposed to reach the edges. Padding the content column instead grows the
	 * grid row, so with "Crop image to fill" on it is also what makes the media
	 * *taller* than the text rather than exactly as tall — the design's "photo
	 * runs the full height of the section, text floats in the middle of it" comes
	 * out of this one declaration.
	 */
	padding-block: var(--kg-media-text-content-padding-block, 0px);
}

/*
 * And the gap *down* the text column, which nothing else provides.
 *
 * `blockGap` is 0 across this site and stated per container, and core/media-text
 * declares no `spacing.blockGap` support to state it with — so its content column
 * gets neither WordPress's layout margins (it is not a layout container: no
 * `is-layout-flow` class, no `--wp--style--block-gap` rule reaching it) nor the
 * theme's own. What is left is the user agent's `margin: 1em 0`, which is a
 * different number for every font size in the column and collapses between
 * siblings — the design's even 32px rhythm by accident, and never.
 *
 * So: zero the UA margins and state the gap once. `xl` is the design's 32px at
 * the width it is drawn, and shrinks with the viewport like the rest of the
 * scale.
 */
.wp-block-media-text > div.wp-block-media-text__content > * {
	margin-block: 0;
}

.wp-block-media-text > div.wp-block-media-text__content > * + * {
	margin-block-start: var(--wp--preset--spacing--xl);
}

/*
 * Pull the figure out of its grid area instead of resizing the area, so the
 * column tracks — and with them the text — stay exactly where the layout put
 * them.
 *
 * That is also what makes this indifferent to the media/text ratio. Core sizes
 * the media track as a percentage of the block: 50% from its own stylesheet, or
 * an inline `grid-template-columns: 30% auto` the moment the Media width
 * control is touched. A percentage track resolves against the container and
 * never against its item, so a negative margin on the figure cannot feed back
 * into the track — every ratio bleeds by the same amount and keeps the split it
 * was given.
 *
 * Logical properties even though the block never flips: core forces
 * `direction: ltr` on the wrapper and hardcodes the media to `grid-column: 1`,
 * so inline-start stays the left edge in RTL too — which is the side the media
 * is actually on.
 *
 * The `figure` in the selector is load-bearing. Core zeroes the same margins
 * from `.wp-block-media-text > .wp-block-media-text__media`, an equal
 * specificity that would leave this at the mercy of which sheet the browser
 * reads last. Naming the element — the media is always a figure, for video as
 * much as for an image — settles it without an !important or a doubled class.
 */
.wp-block-media-text > figure.wp-block-media-text__media {
	margin-inline-start: calc(-1 * var(--kg-media-text-bleed));
}

.wp-block-media-text.has-media-on-the-right
	> figure.wp-block-media-text__media {
	margin-inline-start: 0;
	margin-inline-end: calc(-1 * var(--kg-media-text-bleed));
}

/*
 * Stacked — and stacked earlier than core does.
 *
 * Core stacks "on mobile" at 600px, and everywhere above it up to about a
 * laptop the two columns are still side by side while neither has room to be
 * read. Half of a 768px window is 260px of text: the design's 56px headline gets
 * three words a line, and the photograph beside it is a slot rather than a
 * picture. So the theme moves the threshold all the way up to
 * **`viewport.tablet` in theme.json (72rem)** — the end of the tablet band, and
 * the point above which half the layout width is a real measure again. At the
 * first two-column width, ~1200px, the text column lands at about 430px; at
 * 1152px it would have been 380px and falling.
 *
 * Below 72rem, then: one full-width column, the media bleeding both ways, the
 * text under it keeping the layout width. Core's own three rules are restated
 * here rather than extended, because core's live in a `max-width: 600px` query
 * this cannot reach into — between 600px and 72rem they simply are not there.
 *
 * `!important` on the tracks for the same reason core needs it: the Media width
 * control writes `grid-template-columns` as an *inline* style, and nothing but
 * `!important` beats that. The two `grid-column`/`grid-row` pairs carry an
 * element name so they outrank core's `has-media-on-the-right` rules on
 * specificity instead of on which sheet the browser read last.
 *
 * The 72rem is a literal because a media query cannot read a custom property.
 * It has to be changed here **and** in `theme.json`'s `viewport.tablet` together;
 * they are two halves of one number.
 */
@media (width <= 72rem) {
	.wp-block-media-text.is-stacked-on-mobile {
		grid-template-columns: 100% !important;
		--kg-media-text-bleed-total: calc(2 * var(--kg-media-text-bleed));
	}

	.wp-block-media-text.is-stacked-on-mobile
		> figure.wp-block-media-text__media {
		grid-row: 1;
		grid-column: 1;
	}

	.wp-block-media-text.is-stacked-on-mobile
		> div.wp-block-media-text__content {
		grid-row: 2;
		grid-column: 1;

		/*
		 * Half the inset goes, and only half.
		 *
		 * In one column the text no longer has to be shorter than anything, so the
		 * padding is not doing the job it was added for. But it is doing a second
		 * one at the bottom: it is the only thing between the last line — usually a
		 * button — and whatever section follows. Dropping both left the button
		 * sitting flush on the section boundary.
		 *
		 * So the *start* goes, because `row-gap` above already separates the
		 * photograph from the first line and the two together would read as a hole,
		 * and the *end* stays, inherited from the base rule. A block with no inset
		 * set is unaffected either way: the token is `0px` until something asks for
		 * it.
		 */
		padding-block-start: 0;
	}

	.wp-block-media-text.is-stacked-on-mobile
		> figure.wp-block-media-text__media,
	.wp-block-media-text.is-stacked-on-mobile.has-media-on-the-right
		> figure.wp-block-media-text__media {
		margin-inline: calc(-1 * var(--kg-media-text-bleed));
	}
}

/*
 * Border radius, moved onto the media.
 *
 * Core's border support writes the radius as an inline style on the block
 * wrapper, where there is nothing to round: the wrapper is a bare grid, so the
 * control appears to do nothing at all. `inherit` hands the computed value down
 * to the figure and from there to the image, which is the box anyone rounding a
 * Media & Text block means. The wrapper keeps its own radius rather than having
 * it zeroed, so a block that does carry a background or a border still rounds
 * with it — and that is also what the two rules below have to inherit from.
 *
 * On the media element rather than by clipping the figure: the editor puts the
 * resize handles inside that figure, half of each one hanging over the edge, and
 * an `overflow: clip` would slice them off.
 */
.wp-block-media-text > figure.wp-block-media-text__media,
.wp-block-media-text > figure.wp-block-media-text__media :is(img, video) {
	border-radius: inherit;
}

/*
 * Media aspect ratio — the "Media aspect ratio" control in the Dimensions panel,
 * added by src/editor/filters/media-text-aspect-ratio.js. That file stores the
 * ratio and hands it over as a custom property on the wrapper; where it lands is
 * decided here, and it depends on whether the media is cropped.
 *
 * Uncropped, the media is whatever shape the file is, at every width. The ratio
 * goes on the media element itself, with `object-fit` so a ratio that disagrees
 * with the file crops instead of stretching it.
 */
.wp-block-media-text.kg-has-media-aspect-ratio:not(.is-image-fill-element)
	> figure.wp-block-media-text__media
	:is(img, video) {
	aspect-ratio: var(--kg-media-text-aspect-ratio);
	object-fit: cover;
}

/*
 * Cropped, and still in two columns: the media is matched to the height of the
 * text beside it, which is the whole point of "Crop image to fill". A ratio
 * would only fight it, so it stays out.
 *
 * Cropped and stacked: there is no text beside it any more, and core falls back
 * to a hardcoded `min-height: 250px`. That is the number the ratio replaces —
 * and the floor has to go with it, or a wide ratio on a narrow screen is silently
 * held at 250px. The `kg-has-media-aspect-ratio` class is what keeps that
 * `min-height: 0` away from every block that has no ratio set: CSS cannot ask
 * whether a custom property exists.
 *
 * `72rem`, matching the stacking query above — the two have to agree on when
 * "stacked" starts or the ratio applies to a block that still has text beside it.
 */
@media (width <= 72rem) {
	.wp-block-media-text.kg-has-media-aspect-ratio.is-image-fill-element.is-stacked-on-mobile
		> figure.wp-block-media-text__media {
		aspect-ratio: var(--kg-media-text-aspect-ratio);
		min-height: 0;
	}
}

/*
 * Editor only.
 *
 * On the front end the figure is a stretched grid item, so the negative margin
 * widens it: used width is the grid area minus the margins. In the editor it is
 * not — MediaContainer wraps the media in a ResizableBox, which writes
 * `width: 50%; max-width: 100%` as an *inline* style. The margin then only slides
 * the figure towards the edge at its original width, leaving a gap between the
 * media and the text that the front end does not have. Nothing but !important
 * beats an inline style, so: !important, on a class only the editor has.
 *
 * The Media width handle keeps working, for two reasons worth writing down
 * before anyone is tempted to make this rule conditional. The handle sits on the
 * media's *inner* edge and the bleed only ever grows the outer one, so it stays
 * exactly where it would otherwise be. And dragging it calls onWidthChange on
 * every tick, which re-renders the block's `grid-template-columns` from the
 * in-progress width — so the grid area, and with it the `100%` below, follows
 * the cursor live.
 */
.block-editor-block-list__block.wp-block-media-text
	> figure.wp-block-media-text__media {
	inline-size: calc(100% + var(--kg-media-text-bleed-total)) !important;
	max-inline-size: none !important;
}
