/*
Theme Name: AI Becom FSE
Theme URI: https://ai.becom.digital
Description: Empty Full Site Editing canvas for AI/MCP-driven site building.
Author: Baldwin Agency
Author URI: https://baldwin.agency
Version: 1.7.0
Requires at least: 6.6
Tested up to: 6.9
Requires PHP: 8.3
Text Domain: ai-becom-fse
License: MIT License
License URI: https://opensource.org/licenses/MIT
Tags: full-site-editing, block-themes, block-editor, blank
*/

/*
 * Block styles
 * ============
 * Kept deliberately small. Anything expressible through theme.json presets
 * belongs there; this file is only for what a preset cannot say — here, a
 * pseudo-element.
 */

/* Quiet eyebrow — the meta label above a heading. Registered as a paragraph
   block style rather than left to the patterns, so an author can pick it by
   name; it had tokens and no handle until the Components page had to name it. */
.is-style-eyebrow-quiet {
	font-size: var(--bc-eyebrow-font-size);
	font-weight: var(--bc-eyebrow-font-weight);
	letter-spacing: var(--bc-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--bc-eyebrow-content);
}

/* Accent eyebrow — the green section opener with its leading rule.
   Registered as a paragraph block style, so it is pickable in the editor. */
.is-style-eyebrow-accent {
	display: inline-flex;
	align-items: center;
	gap: var(--bc-eyebrow-accent-gap);
	font-size: var(--bc-eyebrow-accent-font-size);
	font-weight: var(--bc-eyebrow-font-weight);
	letter-spacing: var(--bc-eyebrow-accent-tracking);
	text-transform: uppercase;
	color: var(--bc-eyebrow-accent-content);
}

.is-style-eyebrow-accent::before {
	content: "";
	display: block;
	flex: none;
	width: var(--bc-eyebrow-accent-rule-width);
	height: var(--bc-eyebrow-accent-rule-height);
	background: currentColor;
}

/* Lead paragraph — the opening sentence of a section or a panel.
   Registered as a block style from the first commit, demoed on the Components
   page, and styled by nothing anywhere: it rendered as an ordinary paragraph
   and its four tokens had no reader. The same failure the status pill had, and
   the same rule it proves — a block style needs both a rule and a caller.

   Colour is the surface's, not the lead's: --bc-lead-content is content-secondary
   on the light half and rebound to the inverse secondary on the dark, so a lead
   in a hero or a closing panel comes out right without its author pinning it. */
.is-style-lead {
	max-width: var(--bc-lead-measure);
	font-size: var(--bc-lead-font-size);
	line-height: var(--bc-lead-line-height);
	color: var(--bc-lead-content);
}

/* Centred where the block is: core marks that on the paragraph, and a measure
   narrower than the column has to be centred with it or the text sits left of
   a centred heading. */
.is-style-lead.has-text-align-center {
	margin-inline: auto;
}

/* Outline buttons.
   WordPress core gives .is-style-outline its own padding and border, which made
   an outline button a different size from a filled one on the same row. The
   geometry has to come from the same tokens as every other button.

   The colour and the border reach every outline button, icon-only included —
   that is what makes it an outline button at all. */
.wp-block-button.is-style-outline > .wp-block-button__link {
	border-width: var(--bc-size-border);
	line-height: var(--bc-button-line-height);
	/* The INK, which had no reader anywhere in the theme. --bc-button-outline-content
	   existed, the dark-context list rebound it, and the only thing reading it was
	   the preview's own .btn--outline demo class — so the rebinding was decorative
	   and every real outline button got its colour by accident of being an <a> and
	   inheriting the link. The values coincide, which is why nothing looked wrong.
	   A <button> is not a link and does not inherit it: the filter bar's submit had
	   to pin has-content-primary-color, with a comment explaining that an unpinned
	   one "is dark on dark". Reading the token here is what retires that comment. */
	color: var(--bc-button-outline-content);
	background: var(--bc-button-outline-bg);
	backdrop-filter: blur(var(--bc-button-outline-blur));
	-webkit-backdrop-filter: blur(var(--bc-button-outline-blur));
}

/* The padding is the one declaration that must NOT reach an icon-only button:
   that button has no padding, because its box is its size.

   Without the exclusion this rule wins — three classes against the icon-only
   rule's two — and a border-box element cannot shrink below its own padding,
   so the box came out 50px wide against a 44px height. It had been that way
   since the Social links pattern shipped. Nothing showed it: the documentation
   page demonstrates an icon-only button with the preview's own .btn markup,
   which has no wrapper for .is-style-outline to sit on and so was never wrong.
   A second implementation agreeing with the design while the real one
   disagreed is the exact failure the Tag and the Filter moved to avoid. */
.wp-block-button.is-style-outline:not(.becom-button--icon-only) > .wp-block-button__link {
	padding: var(--bc-button-padding-block) var(--bc-button-padding-inline);
}

/* The outline button fills on hover. It is the only variant that does — a
   filled button already has a colour and lifts instead — and the source gives
   every one of its outline buttons this, on both halves: `hover:bg-secondary`
   on the light one, and one rung up the glass ladder on the dark. Ours had no
   hover fill at all, so on a photograph the only feedback was the lift. */
.wp-block-button.is-style-outline > .wp-block-button__link:hover {
	background: var(--bc-button-outline-bg-hover);
}

/* Hero copy column.
   The hero's text sits in a narrower measure than the 1280 container. It cannot
   be expressed as a layout contentSize: WordPress runs that through
   safecss_filter_attr, which strips var(), leaving no max-width at all.
   Three classes deep because core's own .alignwide rule is two, and an equal
   specificity would come down to stylesheet order. */
.wp-block-group.alignwide.becom-copy-column {
	max-width: var(--bc-size-content-wide);
	margin-inline: auto;
}

/* Mesh overlay.
   A second gradient layered over a dark section's own, softened. It cannot be a
   block: it needs a pseudo-element behind the content, and Gutenberg has no way
   to express one.

   Named for the thing, not for its first caller. It was .becom-hero, which is
   the mistake §5 already corrected once at the token level — bg-hero named one
   caller instead of the gradient, and the contact band wanting the same overlay
   is exactly the second caller that shows it up. */
.becom-mesh {
	position: relative;
	isolation: isolate;
}

.becom-mesh::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var(--bc-bg-inverse-mesh);
	opacity: 0.7;
	pointer-events: none;
}


/* The accent full stop that closes the hero heading. */
.becom-accent {
	color: var(--bc-content-accent-on-inverse, var(--bc-bg-accent));
}

/* Prose column inside a banner panel.
   The panel spans the container; its text should not. Same constraint as the
   hero copy column, applied to the children rather than the element, and for
   the same reason: a layout contentSize cannot carry a token. */
.becom-prose-column > * {
	max-width: var(--bc-size-content);
	margin-inline: auto;
}

/* Root-level rhythm.
   WordPress puts the global blockGap between the top-level children — header,
   main, footer. Those three carry their own padding and run edge to edge, so
   the gap only ever shows as a stripe of page background between the header and
   whatever the page opens with. Blocks *inside* the content keep their gap. */
.wp-site-blocks > * + * {
	margin-block-start: 0;
}

/* Buttons.
   The interaction is ported from becom.digital's .cta-shine: a lift with a
   highlight sweeping across, not the underline an <a> would otherwise get. A
   pseudo-element cannot be expressed in block markup, so it lives here — the
   values are all tokens. */
.wp-element-button {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	text-decoration: none;
	transition: var(--bc-button-transition);
}

.wp-element-button::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: var(--bc-button-shine);
	transform: translate(-120%);
	transition: var(--bc-button-shine-transition);
}

.wp-element-button:hover {
	transform: var(--bc-button-hover-transform);
	filter: var(--bc-button-hover-filter);
	text-decoration: none;
}

.wp-element-button:hover::after {
	transform: translate(120%);
}

.wp-element-button:active {
	transform: var(--bc-button-active-transform);
}

.wp-element-button:focus-visible {
	outline: none;
	box-shadow: var(--bc-button-focus-shadow);
}

@media (prefers-reduced-motion: reduce) {
	.wp-element-button,
	.wp-element-button::after {
		transition: none;
	}

	.wp-element-button:hover {
		transform: none;
	}
}

/* Links
   =====
   One component. Colour at rest comes from the surface, hover is the same
   everywhere, and the only thing a variant chooses is whether the underline is
   already drawn — which is also what tells a forward link from a back link.

   The underline is two background layers, not text-decoration, because
   text-decoration cannot be wiped in from one side. Forced-colors mode gets a
   real underline back at the bottom of this block.

   A link inside a sentence needs no class: it is styled by being inside a
   sentence, so nobody writing prose has to remember to mark one. That rule
   lives here rather than in theme.json because elements.link reaches every <a>
   on the page — nav items, buttons, whole-card links — and has no way to say
   "only in running text". A link inside a <nav> is navigation, not prose: a tab
   rail and a footer menu are both <li><a>, and neither wants a prose underline.

   Specificity, so the cascade is not luck: the prose selector is (0,1,3) and
   each variant is (0,2,1), which outranks it on class count. theme.json's
   elements.link is (0,1,1) and loses to both. */

:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button),
.is-style-link-standalone a:not(.wp-element-button),
.is-style-link-back a:not(.wp-element-button),
.is-style-link-quiet a:not(.wp-element-button) {
	color: var(--bc-link-content);
	text-decoration: none;
	transition: var(--bc-link-transition);
	padding-bottom: var(--bc-link-underline-offset);
	background-image:
		linear-gradient(var(--bc-link-underline-accent), var(--bc-link-underline-accent)),
		linear-gradient(var(--bc-link-rest-underline), var(--bc-link-rest-underline));
	background-size:
		var(--bc-link-accent-underline-size) var(--bc-link-underline-width),
		var(--bc-link-underline-on) var(--bc-link-underline-width);
	background-position: 0 100%, 0 100%;
	background-repeat: no-repeat;
	/* So a link that wraps carries its underline onto the second line. */
	box-decoration-break: clone;
}

/* The boolean, one line per variant. Every variant states both values rather
   than inheriting one, because a variant inside a <p> also matches the prose
   selector and would otherwise pick up its rest layer. */
:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button) {
	--bc-link-rest-underline: currentColor;
	--bc-link-accent-underline-size: var(--bc-link-underline-off);
}

.is-style-link-standalone a:not(.wp-element-button) {
	--bc-link-rest-underline: transparent;
	--bc-link-accent-underline-size: var(--bc-link-underline-on);
}

.is-style-link-back a:not(.wp-element-button),
.is-style-link-quiet a:not(.wp-element-button) {
	--bc-link-rest-underline: transparent;
	--bc-link-accent-underline-size: var(--bc-link-underline-off);
}

.is-style-link-quiet a:not(.wp-element-button) {
	color: var(--bc-link-quiet-content);
}

/* Hover, identical for all four. The accent underline is drawn left to right
   and the text lights up. It is an animation rather than a transition so that
   the standalone variant — whose underline is already accent green — replays
   the draw instead of changing nothing. */
:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button):hover,
.is-style-link-standalone a:not(.wp-element-button):hover,
.is-style-link-back a:not(.wp-element-button):hover,
.is-style-link-quiet a:not(.wp-element-button):hover {
	color: var(--bc-link-content-hover);
	background-size:
		var(--bc-link-underline-on) var(--bc-link-underline-width),
		var(--bc-link-underline-on) var(--bc-link-underline-width);
	animation: bc-link-wipe var(--bc-link-wipe-duration) var(--bc-link-wipe-ease);
}

@keyframes bc-link-wipe {
	from {
		background-size:
			var(--bc-link-underline-off) var(--bc-link-underline-width),
			var(--bc-link-underline-on) var(--bc-link-underline-width);
	}
}

/* Focus is shared by every link. Buttons carry .wp-element-button and are
   excluded here — they have their own ring, drawn as a shadow so it can sit
   inside the pill. */
a:not(.wp-element-button):focus-visible {
	outline: var(--bc-link-focus-outline-width) solid var(--bc-link-focus-outline-color);
	outline-offset: var(--bc-link-focus-outline-offset);
}

/* Standalone and back — a paragraph that is one link and nothing else.
   A plain block-level flex row, full width. Not inline-flex: vertical margins
   do not apply to inline boxes, so two of these in a row would lose the
   blockGap between them and share a line. Not shrink-wrapped either — core's
   constrained layout centres every child with auto margins marked !important,
   so a fit-content box lands in the middle of the column instead of at the
   start of it. */
.is-style-link-standalone,
.is-style-link-back {
	display: flex;
	justify-content: flex-start;
	align-items: center;
	gap: var(--bc-link-standalone-gap);
	color: var(--bc-link-content);
	font-size: var(--bc-link-standalone-font-size);
	font-weight: var(--bc-link-standalone-font-weight);
	transition: var(--bc-link-standalone-transition);
}

/* The gap widens on the link, not on the paragraph: the paragraph runs the full
   width of the column, and pointing at the empty half of it is not pointing at
   the link. */
.is-style-link-standalone:has(a:hover),
.is-style-link-back:has(a:hover) {
	gap: var(--bc-link-standalone-gap-hover);
}

/* The arrow. A mask, not an <img> and not a text glyph: the paint is
   currentColor, so it inherits the link's colour on either surface and lights
   up with the text on hover. */
.is-style-link-standalone::after,
.is-style-link-back::before {
	content: "";
	display: block;
	flex: none;
	width: var(--bc-link-standalone-arrow-size);
	height: var(--bc-link-standalone-arrow-size);
	background: currentColor;
	transition: var(--bc-link-transition);
}

.is-style-link-standalone:has(a:hover),
.is-style-link-back:has(a:hover) {
	color: var(--bc-link-content-hover);
}

.is-style-link-standalone::after {
	-webkit-mask: var(--bc-link-standalone-arrow) center / contain no-repeat;
	mask: var(--bc-link-standalone-arrow) center / contain no-repeat;
}

.is-style-link-back::before {
	-webkit-mask: var(--bc-link-back-arrow) center / contain no-repeat;
	mask: var(--bc-link-back-arrow) center / contain no-repeat;
}

/* The dark-context rebinding lives in chrome.css, which the theme and the
   static preview both load. Keeping it here meant the preview needed its own
   copy, and the copies drifted. */


@media (prefers-reduced-motion: reduce) {
	.is-style-link-standalone,
	.is-style-link-back,
	:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button),
	.is-style-link-standalone a:not(.wp-element-button),
	.is-style-link-back a:not(.wp-element-button),
	.is-style-link-quiet a:not(.wp-element-button) {
		transition: none;
	}

	:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button):hover,
	.is-style-link-standalone a:not(.wp-element-button):hover,
	.is-style-link-back a:not(.wp-element-button):hover,
	.is-style-link-quiet a:not(.wp-element-button):hover {
		animation: none;
	}
}

/* A painted background is not an underline to a forced-colors user agent, which
   throws backgrounds away. Give those users a real one. */
@media (forced-colors: active) {
	:is(p, li, dd, blockquote, figcaption):not(nav *) a:not(.wp-element-button),
	.is-style-link-standalone a:not(.wp-element-button),
	.is-style-link-back a:not(.wp-element-button),
	.is-style-link-quiet a:not(.wp-element-button) {
		text-decoration: underline;
		text-underline-offset: var(--bc-link-underline-offset);
	}
}

/* Card
   ====
   One component, three sizes, and clickability decided by where the link is.

   SIZE is what you pick: compact, default or banner. Size is the only thing the
   three block styles differ in.

   SURFACE is not picked. A dark section rebinds the card tokens, so the same
   style comes out right on either half of the ladder.

   CLICKABILITY is decided by the content, and deliberately so:

     the heading carries the link  →  the whole card is the hit area, and any
                                      "read more" inside it is an affordance
     the heading is plain text     →  only the links and buttons inside are
                                      clickable, and the card is a container

   That is becom.digital's own rule, not an invention. Its clickable cards are
   an <a> wrapping everything, and the "Lees meer" inside them is a <span> —
   it cannot be a link, because a link cannot nest inside a link. Its event
   cards are an <article> with two real <a> buttons and no card-level link.

   Expressing it as "where the link is" rather than as a toggle means the two
   can never disagree. A card cannot claim to be a destination and have nowhere
   to go, and a card full of buttons cannot silently swallow their clicks. */

.is-style-card,
.is-style-card-compact,
.is-style-card-banner {
	background: var(--bc-card-bg);
	border: var(--bc-size-border) solid var(--bc-card-border);
	color: var(--bc-card-content);
	box-shadow: var(--bc-card-shadow);
	/* Flat on the light half, glass on the dark one — the same rebinding the
	   outline button uses, and the first reader --bc-card-inverse-blur has had. */
	backdrop-filter: blur(var(--bc-card-blur));
	-webkit-backdrop-filter: blur(var(--bc-card-blur));
	/* A card is a closed surface with a radius: anything reaching a rounded
	   corner is clipped by it. Only a clickable card used to do this, as a side
	   effect of its hover ring — so a card with a flush image header clipped
	   when its heading happened to be a link and spilled past the corner when it
	   did not. The ring is drawn inset, so clipping never touches it. */
	overflow: hidden;
}

/* The body of a card that carries a flush media header. The header sits against
   the card's edge, so the padding cannot be on the card — it moves to the body,
   and the card's own rhythm and type rules have to reach one level deeper to
   find the meta, heading and copy that now live here. Exactly the reason the
   documentation's row specimen names its text column: a rule that stops at the
   card's own children stops before anything a media header pushes inward. */
.becom-card-body {
	padding: var(--bc-card-padding);
}

.is-style-card-compact > .becom-card-body {
	padding: var(--bc-card-compact-padding);
}

.is-style-card-banner > .becom-card-body {
	padding: var(--bc-card-banner-padding);
}

/* The two media headers. Both sit flush against the card's edge, above the
   body, and the card's own overflow clips them to its radius.

   The blog card holds a ratio, so its image keeps its shape as the column
   narrows. The event card holds a fixed band, because it carries a date rather
   than a photograph — a date that grew with the column would be absurd. */
.becom-card-image {
	aspect-ratio: var(--bc-card-image-aspect);
}

.becom-card-band {
	min-height: var(--bc-card-band-height);
}

/* A Cover inside a card has no business keeping core's 430px default. */
.wp-block-cover:is(.becom-card-image, .becom-card-band) {
	min-height: unset;
}

.wp-block-cover.becom-card-band {
	min-height: var(--bc-card-band-height);
}

/* Rhythm inside a card, and only when the card stacks. A card laid out as a row
   — an event row, an icon row — puts its children on one line as peers, and a
   vertical gap there pushes the actions off the centre line. is-layout-flex is
   what WordPress marks such a group with.

   Core gives every flow child the global blockGap, which
   is 24px — the page's rhythm, far too loose inside a 24px box. These are
   :not(:first-child) rather than * + * so they outrank it: core's rule is
   (0,1,0) and a bare class ties with it, which would leave the result to
   stylesheet order.

   The values are measured off the source's news card, not chosen. */
:is(.is-style-card, .is-style-card-compact, .becom-card-body):not(.is-layout-flex) > :not(:first-child) {
	margin-block-start: var(--bc-card-gap);
}

:is(.is-style-card, .is-style-card-compact, .becom-card-body):not(.is-layout-flex) > :is(h1, h2, h3, h4, h5, h6):not(:first-child) {
	margin-block-start: var(--bc-card-gap-heading);
}

/* The banner keeps this one step and no other: its lines take the page's rhythm
   through its own blockGap, but the gap before the action is the same decision
   at every size — the text block ends there. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .becom-card-body):not(.is-layout-flex) > :is(.wp-block-buttons, .is-style-link-standalone, .is-style-link-back):not(:first-child) {
	margin-block-start: var(--bc-card-gap-action);
}

/* layout = row also drops the shadow. A card lifts off the page because it is
   one thing among several; a list of rows is one thing, and shadowing every
   line of it smears the stack rather than raising it. becom.digital's own
   event rows carry a border and no shadow for the same reason.

   This is the second thing the row layout decides, after the vertical rhythm
   above. Both hang off is-layout-flex because that is what WordPress marks a
   group laid out as a row with — there is no separate row style to forget. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner).is-layout-flex {
	box-shadow: none;
}

/* A card is a summary. Its heading is 16px, not the page's h3 — three cards in
   a row set at heading size shout at each other and at the section title above
   them.

   **The banner is not in this list.** That rationale is about three cards in a
   row, and a banner is never one of three: it is a full-width panel carrying
   the page's closing statement, so its heading is the page's h2 and its lead is
   the page's lead. It had been taking the news card's ladder, which set a 48px
   display heading at 16px and its lead at 14 — the panel read as a card that
   had been stretched rather than as a band. Only the geometry and the surface
   are the banner's card-ness; the type was never measured for it. */
:is(.is-style-card, .is-style-card-compact, .becom-card-body) > :is(h1, h2, h3, h4, h5, h6) {
	font-size: var(--bc-card-heading-font-size);
	font-weight: var(--bc-card-heading-font-weight);
	line-height: var(--bc-card-heading-line-height);
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .becom-card-body)
	> :is(.is-style-eyebrow-quiet, .is-style-eyebrow-label) {
	font-size: var(--bc-card-meta-font-size);
}

:is(.is-style-card, .is-style-card-compact, .becom-card-body) > :is(p, ul, ol) {
	font-size: var(--bc-card-body-font-size);
	line-height: var(--bc-card-body-line-height);
}

/* ── A card that opens with an icon tile ──
   The tile is what makes it a feature card, so the rule reads the content
   rather than asking for a second block style — the same move clickability
   makes. The source types this card differently from the news card the ladder
   above was measured on: a bigger, bolder heading, and real air under the tile
   instead of the 12px that sits above an ordinary heading. */
:is(.is-style-card, .is-style-card-compact):has(> .is-style-icon-tile)
	> :is(h1, h2, h3, h4, h5, h6) {
	font-size: var(--bc-card-feature-heading-font-size);
	font-weight: var(--bc-card-feature-heading-font-weight);
}

:is(.is-style-card, .is-style-card-compact):not(.is-layout-flex)
	> .is-style-icon-tile + :is(h1, h2, h3, h4, h5, h6):not(:first-child) {
	margin-block-start: var(--bc-card-feature-gap-tile);
}

/* Size is the only difference between the three. */
.is-style-card {
	border-radius: var(--bc-card-radius);
	padding: var(--bc-card-padding);
}

.is-style-card-compact {
	border-radius: var(--bc-card-compact-radius);
	padding: var(--bc-card-compact-padding);
}

.is-style-card-banner {
	border-radius: var(--bc-card-banner-radius);
	padding: var(--bc-card-banner-padding);
}

/* ── Clickable ──
   Everything below applies to any size, which is the point of folding it in:
   as separate block styles, size and clickability could not combine, because
   the editor lets an author pick exactly one. A compact clickable card — an
   event row, an icon row — was not expressible. */

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a) {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	cursor: pointer;
	transition: var(--bc-card-interactive-transition);
}

/* The gradient outline, drawn as an inset mask so it reads as a 1px border
   rather than a fill. Only alpha matters in a mask, so currentColor stands in
   for an opaque layer and no colour literal is needed. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a)::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 2;
	border-radius: inherit;
	padding: var(--bc-card-interactive-ring-width);
	background: var(--bc-card-interactive-ring);
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--bc-duration-card) var(--bc-ease-emphasis);
	-webkit-mask: linear-gradient(currentColor 0 0) content-box, linear-gradient(currentColor 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(currentColor 0 0) content-box, linear-gradient(currentColor 0 0);
	mask-composite: exclude;
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover {
	transform: var(--bc-card-interactive-hover-transform);
	box-shadow: var(--bc-card-interactive-hover-shadow);
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover::before {
	opacity: 1;
}

/* :focus-within, because the thing that takes focus is the link and the thing
   that should show it is the card. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):focus-within {
	box-shadow: var(--bc-card-interactive-focus-shadow);
}

/* One link, stretched over the card. Not a wrapper <a>, which core cannot
   express, and not a second link, which would put two identical destinations
   next to each other in the tab order. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media)
	:is(h1, h2, h3, h4, h5, h6) a {
	text-decoration: none;
	color: inherit;
	background: none;
	transition: var(--bc-link-transition);
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media)
	:is(h1, h2, h3, h4, h5, h6) a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 3;
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):hover
	:is(h1, h2, h3, h4, h5, h6) a {
	color: var(--bc-card-interactive-heading-hover);
}

/* A "read more" inside a clickable card is an affordance, not a second
   destination — it sits under the stretched link and is not separately
   focusable. Anything the author does make a real link stays above it, so a
   card can still carry one genuine secondary action. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a)
	a:not(:is(h1, h2, h3, h4, h5, h6) a) {
	position: relative;
	z-index: 4;
}

/* ── The card's hover is its action's hover ──
   A clickable card is one hit area: the whole surface goes to one place, so the
   thing you are about to press should light up wherever on it you point. The
   source does exactly this, with `group-hover` on every card that is a link —
   the heading's colour, the affordance arrow's slide, the media card's fill.

   **Only on clickable cards.** An event card carries two real buttons and is
   not itself a link; lighting both when the row is hovered would say that one
   of these is about to happen without saying which, which is worse than saying
   nothing. Its buttons keep their own `:hover`, exactly as the source's do.

   The button does not lift here, and neither does its own hover: it is riding a
   card that already lifts 4px, and two lifts at once read as a wobble rather
   than as one thing moving. Rebound rather than overridden, so the button is
   the same button — it is the card that decides its own children do not lift,
   the way it decides their colours. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a) {
	--bc-button-hover-transform: none;
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .wp-element-button {
	filter: var(--bc-button-hover-filter);
}

/* The shine sweeps across, which is the loudest half of a button's hover. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .wp-element-button::after {
	transform: translate(120%);
}

/* Only the outline variant fills — a filled button already has a colour. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .wp-block-button.is-style-outline > .wp-block-button__link {
	background: var(--bc-button-outline-bg-hover);
}

/* The arrow travels with the label, the same 8 → 12 the standalone link makes. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .wp-block-button__link {
	gap: var(--bc-button-icon-gap-hover);
}

/* Links inside a clickable card light up with it too — the underline is drawn,
   the text lights, and a standalone link's gap grows so its arrow travels. The
   rules are the link's own; only the trigger is new. Headings are excluded
   because the heading link has its own colour a few rules above. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover :is(.is-style-link-standalone, .is-style-link-back) {
	gap: var(--bc-link-standalone-gap-hover);
	color: var(--bc-link-content-hover);
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover
	:is(p, li, dd, blockquote, figcaption) a:not(.wp-element-button) {
	color: var(--bc-link-content-hover);
	background-size:
		var(--bc-link-underline-on) var(--bc-link-underline-width),
		var(--bc-link-underline-on) var(--bc-link-underline-width);
	animation: bc-link-wipe var(--bc-link-wipe-duration) var(--bc-link-wipe-ease);
}

/* An image as the first thing in a STACKED card runs to its edges — the
   padding belongs to the body, not to the picture.
   A row's leading image is not a media header. It is a peer on the line, so
   pulling it out by the padding puts it OUTSIDE the card and eats the gap to
   the text beside it — which is exactly what the contact band's portrait did,
   flush against the panel's left border with no air anywhere. `is-layout-flex`
   is what WordPress already puts on a Group laid out as a row, and it is the
   same exclusion the card's vertical rhythm carries, for the same reason. */
.is-style-card:not(.is-layout-flex) > :is(figure, .wp-block-image):first-child {
	margin: calc(var(--bc-card-padding) * -1) calc(var(--bc-card-padding) * -1) var(--bc-card-padding);
	overflow: hidden;
}

.is-style-card-compact:not(.is-layout-flex) > :is(figure, .wp-block-image):first-child {
	margin: calc(var(--bc-card-compact-padding) * -1) calc(var(--bc-card-compact-padding) * -1) var(--bc-card-compact-padding);
	overflow: hidden;
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a) img {
	transition: var(--bc-card-interactive-image-transition);
}

:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover img {
	transform: var(--bc-card-interactive-image-hover);
}

@media (prefers-reduced-motion: reduce) {
	:is(.is-style-card, .is-style-card-compact, .is-style-card-banner),
	:is(.is-style-card, .is-style-card-compact, .is-style-card-banner) img {
		transition: none;
	}

	:is(.is-style-card, .is-style-card-compact, .is-style-card-banner):hover,
	:is(.is-style-card, .is-style-card-compact, .is-style-card-banner):hover img {
		transform: none;
	}
}

/* Icon tile
   =========
   The square that holds an icon — 34 of them on the source, and we had nothing.
   Two fills: a solid brand gradient carrying a white icon, and a tint with a
   ring carrying the colour itself. */

.is-style-icon-tile,
.is-style-icon-tile-tint {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: var(--bc-icon-tile-size);
	height: var(--bc-icon-tile-size);
	border-radius: var(--bc-icon-tile-radius);
}

.is-style-icon-tile {
	background: var(--bc-icon-tile-solid-bg);
	color: var(--bc-icon-tile-solid-content);
	/* The ring is an inset shadow rather than a border so it does not join the
	   box model: a bordered tile is 2px wider than the size token says, and the
	   tint variant already draws its ring this way. */
	box-shadow: inset 0 0 0 var(--bc-size-border) var(--bc-icon-tile-solid-ring),
	            var(--bc-icon-tile-solid-shadow);
	transition: var(--bc-icon-tile-transition);
}

.is-style-icon-tile-tint {
	width: var(--bc-icon-tile-size-sm);
	height: var(--bc-icon-tile-size-sm);
	border-radius: var(--bc-icon-tile-radius-sm);
	background: var(--bc-icon-tile-tint-bg);
	box-shadow: inset 0 0 0 var(--bc-size-border) var(--bc-icon-tile-tint-ring);
	color: var(--bc-icon-tile-tint-content);
}

/* The solid tile is larger, so its icon is too. The tint tile keeps the base
   size it inherits — never "set it explicitly" here: a custom property that
   reads itself resolves to nothing and the icon paints as an empty box. */
/* Each tile names the size of the icon it holds. Never write
   --bc-icon-size: var(--bc-icon-size) — a property that reads itself resolves
   to nothing and the icon paints as an empty box. */
.is-style-icon-tile .becom-icon {
	--bc-icon-size: var(--bc-icon-tile-icon-size);
}

.is-style-icon-tile-tint .becom-icon {
	--bc-icon-size: var(--bc-icon-tile-tint-icon-size);
}

/* The tile cants when the *card* is pointed at, not when the tile is: it is part
   of the card's one hover, the way the heading is.

   And only on a clickable card, like everything else in that hover. This fired
   on any card at first, which put a hover response on the info card — a card
   that goes nowhere and has nothing to press. The source does animate its
   pillar card's tile, but its pillar card is an <article> carrying
   `card-interactive`: it lifts and shows a clickable ring and then does nothing
   when you click it, which is the one state this system will not copy. */
:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .is-style-icon-tile {
	transform: var(--bc-icon-tile-hover-transform);
}

@media (prefers-reduced-motion: reduce) {
	.is-style-icon-tile {
		transition: none;
	}

	:is(.is-style-card, .is-style-card-compact, .is-style-card-banner, .is-style-card-media):has(:is(h1, h2, h3, h4, h5, h6) a):hover .is-style-icon-tile {
		transform: none;
	}
}



/* Card — media
   ===========
   A photograph with the content sitting on it. Built on core/cover, which
   already owns the image, the overlay and the minimum height — so an author
   uses the normal Cover controls and this only supplies the design.

   The scrim is not decoration. Text over an uncontrolled photograph has no
   contrast guarantee at all; the scrim is what makes the guarantee, which is
   why it is part of the component rather than an option on it. */

.is-style-card-media {
	min-height: var(--bc-card-media-min-height);
	border-radius: var(--bc-card-media-radius);
	overflow: hidden;
	/* Cover ships 1em of its own padding, which would sit outside the content
	   column and push the tile 16px in from where the source puts it. The card
	   carries no padding; the column does, exactly as on a card with a media
	   header. */
	padding: 0;
	color: var(--bc-card-media-content);
	border: var(--bc-size-border) solid var(--bc-card-media-border);
	box-shadow: var(--bc-card-shadow);
}

/* Cover paints its own overlay; replace it with the scrim rather than layering
   a second one on top.

   Specificity has to beat core, which sets a black background-color on this
   same element through
   `.wp-block-cover .has-background-dim:not([class*="-background-color"])` —
   (0,3,0). A rule at (0,2,0) loses and the card renders as a black rectangle
   with the photograph invisible underneath it. */
.wp-block-cover.is-style-card-media > .wp-block-cover__background.has-background-dim {
	background-color: transparent;
	background-image: var(--bc-card-media-scrim);
	opacity: 1;
}

.is-style-card-media > .wp-block-cover__image-background {
	transition: var(--bc-card-media-image-transition);
}

.is-style-card-media:hover > .wp-block-cover__image-background {
	transform: var(--bc-card-media-image-hover);
}

/* The content column fills the card, so the tile can sit at the top while the
   text stays at the bottom — which is what the scrim is darkest under.

   Not absolute positioning: core gives .wp-block-cover__inner-container its own
   `position: relative`, so an absolutely positioned tile anchors to the text
   block rather than to the card, and the fixes for that all end in a z-index
   argument with the scrim. A stretched column puts the tile where the source
   puts it and leaves core's layering alone. */
.is-style-card-media > .wp-block-cover__inner-container {
	align-self: stretch;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	padding: var(--bc-card-media-padding);
}

/* The text runs the width of the column; only the tile and the button shrink to
   their content. Stated per child rather than left to `align-items: stretch`,
   because a stretched button fills the card and stops reading as a button. */
.is-style-card-media > .wp-block-cover__inner-container > .wp-block-heading,
.is-style-card-media > .wp-block-cover__inner-container > p {
	align-self: stretch;
}

/* The tile's inset is 16px where the card's padding is 24, so it is pulled the
   8px difference rather than given an inset of its own — one padding, and the
   tile's own offset expressed against it.

   margin-block-end: auto is what holds the text at the bottom of the column. */
.is-style-card-media .is-style-icon-tile {
	--bc-icon-tile-size: var(--bc-card-media-icon-size);
	align-self: flex-start;
	margin-block-end: auto;
	margin-block-start: calc(var(--bc-card-media-icon-inset) - var(--bc-card-media-padding));
	margin-inline-start: calc(var(--bc-card-media-icon-inset) - var(--bc-card-media-padding));
}

/* The rhythm on the photograph. Written :not(:first-child) rather than * + *
   for the same reason the card's is: core's global blockGap rule is (0,1,0) and
   a bare class only ties with it, which would leave the result to stylesheet
   order. */
.is-style-card-media > .wp-block-cover__inner-container > :not(:first-child) {
	margin-block-start: var(--bc-card-media-gap);
}

/* The heading opens the text block wherever it sits in the column, so its top
   margin is the tile's auto gap and not the 8px step. */
.is-style-card-media > .wp-block-cover__inner-container > .wp-block-heading {
	margin-block-start: 0;
	font-size: var(--bc-card-media-heading-font-size);
	font-weight: var(--bc-card-media-heading-font-weight);
	line-height: var(--bc-card-media-heading-line-height);
	letter-spacing: var(--bc-card-media-heading-tracking);
	color: var(--bc-card-media-heading-content);
	text-shadow: var(--bc-card-media-heading-shadow);
}

.is-style-card-media > .wp-block-cover__inner-container > p {
	font-size: var(--bc-card-media-body-font-size);
	line-height: var(--bc-card-media-body-line-height);
	color: var(--bc-card-media-body-content);
	text-shadow: var(--bc-card-media-body-shadow);
}

/* The action ends the text block: 16px, not the card's 32. A media card is a
   poster with one thing to press, so the button belongs to the sentence above
   it rather than sitting off on its own. */
.is-style-card-media > .wp-block-cover__inner-container > .wp-block-buttons {
	margin-block-start: var(--bc-card-media-gap-action);
}

/* The button's wash has to hold against a photograph, where the 6% one measured
   on a flat dark ground disappears. Rebound rather than restyled, so the button
   is the same outline button it is in the hero — it just starts a rung further
   up the glass ladder, and its hover starts a rung up with it. */
.is-style-card-media {
	--bc-button-outline-inverse-bg:       var(--bc-card-media-action-bg);
	--bc-button-outline-inverse-bg-hover: var(--bc-card-media-action-bg-hover);
}

/* The arrow is not drawn here. It travels with the label rather than being part
   of it — a glyph in the button text would be translated, and an <img> would not
   take the button's colour — but that is true of every button that carries an
   icon, not of this card. So the pattern's button says
   `becom-icon--arrow-right becom-button--icon-right` and the rule lives in
   chrome.css with the other two positions.

   This card was the only caller for a while, and the arrow was written into it
   directly, reading the standalone link's arrow token: a button's icon that
   depended on a link's size, in the one stylesheet the documentation page
   cannot load. */

@media (prefers-reduced-motion: reduce) {
	.is-style-card-media > .wp-block-cover__image-background {
		transition: none;
	}

	.is-style-card-media:hover > .wp-block-cover__image-background {
		transform: none;
	}
}

/* A pair of buttons sits close: they are one decision, not two sections. */
.wp-block-buttons {
	gap: var(--bc-button-group-gap);
}

/* Button — compact
   ===============
   The size the event cards use: smaller, tighter, and square-ish rather than a
   pill, because it sits inside a card next to a second action where a full pill
   reads as the page's call to action.

   Applied alongside a variant rather than instead of one, so a compact button
   can still be primary or outline — the two are different axes and the editor's
   single-select style list would not let them combine as siblings. */

.wp-block-button.is-style-compact > .wp-block-button__link {
	border-radius: var(--bc-button-compact-radius);
	padding: var(--bc-button-compact-padding-block) var(--bc-button-compact-padding-inline);
	font-size: var(--bc-button-compact-font-size);
	font-weight: var(--bc-button-compact-font-weight);
	letter-spacing: var(--bc-button-compact-tracking);
}

/* Code
   ====
   A command to copy, and a name inside a sentence. Core's code block ships a
   grey border and a serif-adjacent default that reads as a different site; this
   is the terminal the setup instructions need. The block scrolls sideways
   rather than wrapping, because a wrapped shell command is a broken one when
   somebody copies what they see. */

.wp-block-code {
	background: var(--bc-code-bg);
	color: var(--bc-code-content);
	border: 0;
	border-radius: var(--bc-code-radius);
	padding: var(--bc-code-padding);
	overflow-x: auto;
	font-family: var(--bc-code-font-family);
	font-size: var(--bc-code-font-size);
	line-height: var(--bc-code-line-height);
}

.wp-block-code > code {
	white-space: pre;
	font: inherit;
	background: none;
	color: inherit;
	padding: 0;
}

:where(p, li, td, summary) > code {
	font-family: var(--bc-code-font-family);
	font-size: var(--bc-code-inline-font-size);
	background: var(--bc-code-inline-bg);
	color: var(--bc-code-inline-content);
	border-radius: var(--bc-code-inline-radius);
	padding-inline: var(--bc-code-inline-padding-inline);
	/* A repository address is one unbroken word longer than a phone's column,
	   and a card clips what overflows it. Breaking anywhere is ugly and legible;
	   clipped is neither. */
	overflow-wrap: anywhere;
}
