/* Work Portfolio Grid block — standalone styles, independent of SDdisplayProjects.css. */

.wpg-block {
	--portfolio-card-gap: 1.5rem;
	--portfolio-heading-color: var(--colD, #656259);
	--portfolio-heading-hover-color: var(--colB, #ba5914);
	--portfolio-body-color: var(--colD, #656259);
	--portfolio-focus-color: var(--colA, #355067);
	--portfolio-focus-width: 2px;

	--portfolio-cols-mobile: 2;
	--portfolio-cols-tablet: 3;
	--portfolio-cols-desktop: 4;

	--portfolio-cta-bg: transparent;

	--portfolio-button-radius: var(--radius-role-button, 0.375rem);
	--portfolio-button-primary-bg: var(--colC, #e0bc1c);
	--portfolio-button-primary-hover-bg: var(--colB, #ba5914);
	--portfolio-button-primary-color: #ffffff;
	--portfolio-button-secondary-color: var(--colA, #355067);
	--portfolio-button-ghost-color: var(--colA, #355067);

	width: 100%;
}

/* Full-bleed regardless of page template. */
.wpg-block.alignfull {
	width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}

/* Wide alignment (editor "Wide" toolbar choice) is no longer given its own
   width formula here — page-width-control.css clamps every .wpg-block the
   same as any other content child, off the shared --boxedWidth/--wideWidth/
   --veryWideWidth tokens driven by the page's shew_page_width tier. Only
   .alignfull (below) still needs a dedicated rule, since full-bleed past
   the viewport edge isn't something the page-tier system does. */

/* -------------------------------------------------
 * Grid + cards
 * ----------------------------------------------- */

.wpg-grid {
	display: grid;
	grid-template-columns: repeat(var(--portfolio-cols-mobile), 1fr);
	gap: var(--portfolio-card-gap);
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Margin-left only, kept as its own #SD rule rather than added to .wpg-grid
   above — that rule also carries the responsive grid-template-columns
   breakpoints below, and giving it an ID would out-specificity those plain
   ".wpg-grid" media-query overrides, freezing every breakpoint at the
   mobile column count. This rule only fights the global
   "#SD UL { margin-left:... }" in SDstandards.css, which was shifting
   every card 20px right of .wpg-block's own (correctly centered) edge. */
#SD .wpg-grid {
	margin-left: 0;
}

@media screen and (min-width: 768px) {
	.wpg-grid {
		grid-template-columns: repeat(var(--portfolio-cols-tablet), 1fr);
	}
}

@media screen and (min-width: 1024px) {
	.wpg-grid {
		grid-template-columns: repeat(var(--portfolio-cols-desktop), 1fr);
	}
}

@media screen and (min-width: 1440px) {
	.wpg-grid {
		grid-template-columns: repeat(var(--portfolio-cols-desktop-lg), 1fr);
	}
}

/* Per-breakpoint reveal-animation toggle (Design Tokens → Portfolio Grid
   Layout). Each band matches the column breakpoint above it exactly, so
   "off" only disables the reveal at the size it was set for. Mirrors the
   prefers-reduced-motion override in motion-effects.css, just scoped to one
   band via the matching wpg-anim-off-* class instead of all breakpoints. */
@media screen and (max-width: 767px) {
	.wpg-anim-off-mobile .wpg-card[data-scroll-behavior="reveal"] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

@media screen and (min-width: 768px) and (max-width: 1023px) {
	.wpg-anim-off-tablet .wpg-card[data-scroll-behavior="reveal"] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

@media screen and (min-width: 1024px) and (max-width: 1439px) {
	.wpg-anim-off-desktop .wpg-card[data-scroll-behavior="reveal"] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

@media screen and (min-width: 1440px) {
	.wpg-anim-off-desktop-lg .wpg-card[data-scroll-behavior="reveal"] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

/* The title is always its own link; the image is a separate, independently
   toggled link (or plain, non-link content). They're siblings either way,
   so the gap lives here rather than inside a single shared link. */
.wpg-card {
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: var(--portfolio-gap-default, 0.5rem);
	/* Grid items default to min-width: auto, which lets the image's
	   intrinsic size blow out the 1fr column track instead of shrinking
	   to it — this is what broke the mobile/tablet column counts. */
	min-width: 0;
}

/* "#SD .entry-content UL > LI" in SDstandards.css (padding-left:1.5em;
   text-indent:-1.5em) is meant for bulleted content lists, but .wpg-card is
   also a UL>LI inside .entry-content, so it inherited the same indent —
   text-indent inherits to .wpg-card-name, pulling the caption left of the
   image above it. ".wpg-grid .wpg-card" (2 classes) out-specificities that
   rule's "UL > LI" (1 class + 2 types) since class count is compared before
   type count. */
#SD .wpg-grid .wpg-card {
	padding-left: 0;
	text-indent: 0;
}
/* Same SDstandards.css UL>LI rule also generates a "•" ::before marker,
   absolutely positioned at the LI's top-left corner (0,0) — independent of
   the padding-left/text-indent reset above, so it still rendered as a black
   dot over the top-left corner of the card image. */
#SD .wpg-grid .wpg-card::before {
	content: none;
}

/* Hide cards from first paint, before scroll-effects.js has run — without
   this, a card can paint visible for a frame (page parse can outrun the
   deferred script) and then flash as the reveal/entry animation takes over.
   Safe to do here (unlike the site-wide motion-effects.css base rule, which
   intentionally never pre-hides for LCP reasons): every wpg-card always gets
   a non-empty data-scroll-effect (shew_wpg_entrance_effect() falls back to
   "fade-up"), so the matching .is-ready / .is-in-view rule in
   motion-effects.css always exists and has higher specificity (3 simple
   selectors vs. 2 here) — it cleanly overrides this the moment JS adds
   either class, whether the card ends up above or below the fold. */
.wpg-card[data-scroll-behavior="reveal"] {
	opacity: 0;
}

/* When Image Is Link is on (shew_pc_image_is_link()), the render helper
   nests both .wpg-card-media and .wpg-card-name inside this single <a> —
   making it, not .wpg-card, the actual two-child flex container. .wpg-card
   itself only has this one child in that case, so its own gap has nothing
   to space. Mirroring the same flex+gap here covers both markup shapes:
   when Image Is Link is off, .wpg-card-link wraps only the name (one
   child), so this gap is a no-op there and .wpg-card's gap does the work
   instead. */
#SD .wpg-card-link {
	display: flex;
	flex-direction: column;
	gap: var(--portfolio-gap-default, 0.5rem);
	text-decoration: none;
	color: inherit;
}

/* Radius + shadow per card type, per state — every value is an explicit
   token (inc/portfolio-card-tokens.php), never assumed in this stylesheet.
   Logo/Project/Website fall back to Default at the token layer when unset,
   so this CSS only needs one set of rules per type, not a cascade. */

.wpg-card-media {
	display: block;
	overflow: hidden;
	aspect-ratio: var(--portfolio-image-ratio-default, auto);
	border-radius: var(--portfolio-radius-default-rest);
	box-shadow: var(--portfolio-shadow-default-rest);
	transition: border-radius 0.2s ease, box-shadow 0.2s ease;
}

#SD .wpg-card-link:hover .wpg-card-media,
#SD .wpg-card-link:focus-visible .wpg-card-media {
	border-radius: var(--portfolio-radius-default-hover);
	box-shadow: var(--portfolio-shadow-default-hover);
}

.wpg-card--logo,
.wpg-card--logo .wpg-card-link {
	gap: var(--portfolio-gap-logo, 0.5rem);
}
.wpg-card--logo .wpg-card-media {
	aspect-ratio: var(--portfolio-image-ratio-logo, auto);
	border-radius: var(--portfolio-radius-logo-rest);
	box-shadow: var(--portfolio-shadow-logo-rest);
}
#SD .wpg-card--logo .wpg-card-link:hover .wpg-card-media,
#SD .wpg-card--logo .wpg-card-link:focus-visible .wpg-card-media {
	border-radius: var(--portfolio-radius-logo-hover);
	box-shadow: var(--portfolio-shadow-logo-hover);
}

.wpg-card--brand,
.wpg-card--brand .wpg-card-link {
	gap: var(--portfolio-gap-brand, 0.5rem);
}
.wpg-card--brand .wpg-card-media {
	aspect-ratio: var(--portfolio-image-ratio-brand, auto);
	border-radius: var(--portfolio-radius-brand-rest);
	box-shadow: var(--portfolio-shadow-brand-rest);
}
#SD .wpg-card--brand .wpg-card-link:hover .wpg-card-media,
#SD .wpg-card--brand .wpg-card-link:focus-visible .wpg-card-media {
	border-radius: var(--portfolio-radius-brand-hover);
	box-shadow: var(--portfolio-shadow-brand-hover);
}

.wpg-card--website,
.wpg-card--website .wpg-card-link {
	gap: var(--portfolio-gap-website, 0.5rem);
}
.wpg-card--website .wpg-card-media {
	aspect-ratio: var(--portfolio-image-ratio-website, auto);
	border-radius: var(--portfolio-radius-website-rest);
	box-shadow: var(--portfolio-shadow-website-rest);
}
/* Layered Reveal frame (shew_csr_render_reveal_frame(), styled/animated by
   displayCaseStudy.css/.js) standing in for the featured image. Fills the
   card's media box when --portfolio-image-ratio-website sets one (height
   100% resolves), otherwise height falls back to auto and the frame's own
   1/1 ratio sizes it. */
.wpg-card-media--reveal .dcs-images--reveal {
	position: relative;
	width: 100%;
	height: 100%;
	aspect-ratio: 1 / 1;
}
#SD .wpg-card--website .wpg-card-link:hover .wpg-card-media,
#SD .wpg-card--website .wpg-card-link:focus-visible .wpg-card-media {
	border-radius: var(--portfolio-radius-website-hover);
	box-shadow: var(--portfolio-shadow-website-hover);
}

/* Video has no .wpg-card-link — the poster is a play trigger, not a
   navigation link, so its hover/focus state is driven by :hover/:focus-visible
   on .wpg-card-video-poster itself rather than a wrapping link. */
.wpg-card--video {
	gap: var(--portfolio-gap-video, 0.5rem);
}
.wpg-card--video .wpg-card-media {
	aspect-ratio: var(--portfolio-image-ratio-video, auto);
	border-radius: var(--portfolio-radius-video-rest);
	box-shadow: var(--portfolio-shadow-video-rest);
}
.wpg-card--video .wpg-card-video-poster:hover .wpg-card-media,
.wpg-card--video .wpg-card-video-poster:focus-visible .wpg-card-media {
	border-radius: var(--portfolio-radius-video-hover);
	box-shadow: var(--portfolio-shadow-video-hover);
}

/* Video play trigger — values ported from the legacy project-selector
   card (assets/css/conditional/templates/projectselector/SDdisplayProjects.css
   .card--video .videoPlay*) so the visual treatment matches what's already
   shipping on /work/?type=video, just renamed into wpg- classes so the two
   systems' CSS never collide. */
.wpg-card-video-poster {
	position: relative;
	cursor: pointer;
}
.wpg-card-video-overlay {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
}
.wpg-card-video-triangle {
	width: 0;
	height: 0;
	border-left: 22px solid currentColor;
	border-top: 14px solid transparent;
	border-bottom: 14px solid transparent;
	opacity: 0.9;
}
.wpg-card-video-embed iframe {
	width: 100%;
	max-width: 100%;
	aspect-ratio: 16 / 9;
	height: auto;
}

/* height: 100% only takes effect when .wpg-card-media has an explicit
   aspect-ratio (a sized ratio); against the default aspect-ratio: auto it
   resolves to auto per spec, so "None" keeps each image's natural height. */
.wpg-card-image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.3s ease;
}

#SD .wpg-card-name {
	display: inline-block;
	font-family: var(--portfolio-title-family-default, inherit);
	font-weight: var(--portfolio-title-weight-default, 600);
	font-size: var(--portfolio-title-size-default, inherit);
	line-height: var(--portfolio-title-line-height-default, inherit);
	letter-spacing: var(--portfolio-title-letter-spacing-default, normal);
	text-transform: var(--portfolio-title-text-transform-default, none);
	color: var(--portfolio-title-color-default, var(--portfolio-heading-color));
	transition: color 0.2s ease;
}

#SD .wpg-card--logo .wpg-card-name {
	font-family: var(--portfolio-title-family-logo, var(--portfolio-title-family-default, inherit));
	font-weight: var(--portfolio-title-weight-logo, var(--portfolio-title-weight-default, 600));
	font-size: var(--portfolio-title-size-logo, var(--portfolio-title-size-default, inherit));
	line-height: var(--portfolio-title-line-height-logo, var(--portfolio-title-line-height-default, inherit));
	letter-spacing: var(--portfolio-title-letter-spacing-logo, var(--portfolio-title-letter-spacing-default, normal));
	text-transform: var(--portfolio-title-text-transform-logo, var(--portfolio-title-text-transform-default, none));
	color: var(--portfolio-title-color-logo, var(--portfolio-title-color-default, var(--portfolio-heading-color)));
}

#SD .wpg-card--brand .wpg-card-name {
	font-family: var(--portfolio-title-family-brand, var(--portfolio-title-family-default, inherit));
	font-weight: var(--portfolio-title-weight-brand, var(--portfolio-title-weight-default, 600));
	font-size: var(--portfolio-title-size-brand, var(--portfolio-title-size-default, inherit));
	line-height: var(--portfolio-title-line-height-brand, var(--portfolio-title-line-height-default, inherit));
	letter-spacing: var(--portfolio-title-letter-spacing-brand, var(--portfolio-title-letter-spacing-default, normal));
	text-transform: var(--portfolio-title-text-transform-brand, var(--portfolio-title-text-transform-default, none));
	color: var(--portfolio-title-color-brand, var(--portfolio-title-color-default, var(--portfolio-heading-color)));
}

#SD .wpg-card--website .wpg-card-name {
	font-family: var(--portfolio-title-family-website, var(--portfolio-title-family-default, inherit));
	font-weight: var(--portfolio-title-weight-website, var(--portfolio-title-weight-default, 600));
	font-size: var(--portfolio-title-size-website, var(--portfolio-title-size-default, inherit));
	line-height: var(--portfolio-title-line-height-website, var(--portfolio-title-line-height-default, inherit));
	letter-spacing: var(--portfolio-title-letter-spacing-website, var(--portfolio-title-letter-spacing-default, normal));
	text-transform: var(--portfolio-title-text-transform-website, var(--portfolio-title-text-transform-default, none));
	color: var(--portfolio-title-color-website, var(--portfolio-title-color-default, var(--portfolio-heading-color)));
}

#SD .wpg-card--video .wpg-card-name {
	font-family: var(--portfolio-title-family-video, var(--portfolio-title-family-default, inherit));
	font-weight: var(--portfolio-title-weight-video, var(--portfolio-title-weight-default, 600));
	font-size: var(--portfolio-title-size-video, var(--portfolio-title-size-default, inherit));
	line-height: var(--portfolio-title-line-height-video, var(--portfolio-title-line-height-default, inherit));
	letter-spacing: var(--portfolio-title-letter-spacing-video, var(--portfolio-title-letter-spacing-default, normal));
	text-transform: var(--portfolio-title-text-transform-video, var(--portfolio-title-text-transform-default, none));
	color: var(--portfolio-title-color-video, var(--portfolio-title-color-default, var(--portfolio-heading-color)));
}

/* Client/org name line, video only — sits above the title. No equivalent
   field exists for Logo/Project/Website; their single get_the_title() value
   is the only text on the card. */
.wpg-card-organization {
	display: block;
	margin-top: 0.25rem;
	line-height: 1;
	font-size: 0.875em;
	color: var(--portfolio-body-color);
}

#SD .wpg-card-link:hover .wpg-card-image,
#SD .wpg-card-link:focus-visible .wpg-card-image {
	transform: scale(1.05);
}

#SD .wpg-card-link:hover .wpg-card-name,
#SD .wpg-card-link:focus-visible .wpg-card-name {
	color: var(--portfolio-heading-hover-color);
}

/* No discrete button remains on the card, so the link itself needs a clear
   keyboard focus indicator. */
#SD .wpg-card-link:focus-visible {
	/* Longhand, not the `outline: <w> solid <c>` shorthand — combining two
	   var() refs in that shorthand fails to resolve in testing (width/color
	   silently fall back to the browser default ring). Longhands resolve
	   each var() independently. */
	outline-width: var(--portfolio-focus-width);
	outline-style: solid;
	outline-color: var(--portfolio-focus-color);
	outline-offset: 4px;
	border-radius: var(--portfolio-radius-default-rest);
}

/* -------------------------------------------------
 * Entrance animation — cards opt into the global token-driven reveal system
 * (assets/js/global/scroll-effects.js + assets/css/global/motion-effects.css)
 * via data-scroll-behavior/data-scroll-effect on each <li>. Timing/easing
 * come entirely from Design Tokens → Motion; nothing block-specific here.
 * ----------------------------------------------- */

/* -------------------------------------------------
 * CTA — sibling of .wpg-grid, never a list item
 * ----------------------------------------------- */

.wpg-cta {
	width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
	margin-top: var(--wpg-cta-margin-top, var(--portfolio-card-gap));
	margin-bottom: var(--wpg-cta-margin-bottom, var(--portfolio-card-gap));
	background: var(--wpg-cta-bg, var(--portfolio-cta-bg));
	text-align: center;
}

/* Inner content stays boxed to the standard content width and centered —
   only the background (.wpg-cta above) bleeds to the full viewport. */
.wpg-cta-inner {
	max-width: var(--contentWidth, var(--maxWidth, 1200px));
	margin-left: auto;
	margin-right: auto;
	padding: var(--wpg-cta-padding, 0);
}

.wpg-cta-headline {
	margin: 0 0 0.5rem;
	font-family: var(--wpg-cta-headline-family, inherit);
	font-weight: var(--wpg-cta-headline-weight, 700);
	font-size: var(--wpg-cta-headline-size, 1.25rem);
	line-height: var(--wpg-cta-headline-line-height, inherit);
	letter-spacing: var(--wpg-cta-headline-letter-spacing, normal);
	text-transform: var(--wpg-cta-headline-text-transform, none);
	color: var(--wpg-cta-headline-color, var(--portfolio-heading-color));
}

.wpg-cta-body {
	margin: 0 0 1rem;
	font-family: var(--wpg-cta-body-family, inherit);
	font-weight: var(--wpg-cta-body-weight, inherit);
	font-size: var(--wpg-cta-body-size, inherit);
	line-height: var(--wpg-cta-body-line-height, inherit);
	letter-spacing: var(--wpg-cta-body-letter-spacing, normal);
	text-transform: var(--wpg-cta-body-text-transform, none);
	color: var(--wpg-cta-body-color, var(--portfolio-body-color));
}

#SD .wpg-cta-button {
	display: inline-block;
	padding: 0.6em 1.4em;
	border-radius: var(--portfolio-button-radius);
	font-weight: 600;
	text-decoration: none;
}

#SD .wpg-cta-button--primary {
	background: var(--portfolio-button-primary-bg);
	color: var(--portfolio-button-primary-color);
}

#SD .wpg-cta-button--primary:hover {
	background: var(--portfolio-button-primary-hover-bg);
}

#SD .wpg-cta-button--secondary {
	background: transparent;
	color: var(--portfolio-button-secondary-color);
	border: 2px solid var(--portfolio-button-secondary-color);
}

#SD .wpg-cta-button--ghost {
	background: transparent;
	color: var(--portfolio-button-ghost-color);
	text-decoration: underline;
}

#SD .wpg-cta-button:focus-visible {
	outline-width: var(--portfolio-focus-width);
	outline-style: solid;
	outline-color: var(--portfolio-focus-color);
	outline-offset: 2px;
}

/* -------------------------------------------------
 * Anchor Tile — featured brand/website treatment, rendered ahead of the
 * regular grid (which posts are anchors is chosen per-block via
 * wpg_anchor_posts; anchor content lives on the post in
 * group_anchor_content_fields.json, palette/type pulled live from the
 * post's own content blocks — see inc/helpers/anchor-tile-render.php /
 * Notion: "Anchor Tile Spec"). This is
 * a first pass: alternating image/text sides by position. Exact staggered
 * offset mechanics are still open per that spec's own "not yet nailed
 * down" note — expect a follow-up design pass once there's real content
 * to look at.
 * ----------------------------------------------- */

.wpg-anchor-grid {
	display: flex;
	flex-direction: column;
	gap: var(--wpg-anchor-grid-gap, calc(var(--portfolio-card-gap) * 2));
	list-style: none;
	margin: 0 0 calc(var(--portfolio-card-gap) * 2);
	padding: 1.5rem 0 0;
}

/* Optional intro copy (wpg_introduction ACF field) rendered above the Anchor
   Tile section. Shares the .wpg-anchor-maxwidth-* width classes below (same
   ACF field, wpg_anchor_max_width) so its measure always matches whatever
   the anchor section is constrained to. */
.wpg-introduction {
	margin: 0 0 calc(var(--portfolio-card-gap) * 2);
}
.wpg-introduction > *:last-child {
	margin-bottom: 0;
}

/* Optional per-block override (wpg_anchor_max_width ACF field) — constrains
   only the Anchor Tile section, independent of the page's own width setting
   and of the CTA/card-grid siblings. Not present when the field is left on
   "Default", in which case the anchor grid simply inherits the full width of
   its .wpg-block parent as before. Uses the same --boxedWidth/--wideWidth/
   --veryWideWidth tokens as page-width-control.css so the choices stay
   consistent with the site-wide width tiers. */
.wpg-anchor-maxwidth-boxed,
.wpg-anchor-maxwidth-wide,
.wpg-anchor-maxwidth-very_wide {
	margin-right: auto;
}
/* ID-scoped like the "#SD .wpg-grid" override above (line 61) — needed to
   out-specificity the global "#SD UL { margin-left:... }" reset in
   SDstandards.css, which otherwise pins every UL 20px right of its
   container regardless of margin-left:auto set at plain-class specificity. */
#SD .wpg-anchor-maxwidth-boxed,
#SD .wpg-anchor-maxwidth-wide,
#SD .wpg-anchor-maxwidth-very_wide {
	margin-left: auto;
}
/* .wpg-anchor-grid itself is also a UL inside .entry-content, so it's
   additionally hit by "#SD .entry-content UL { margin-left:0 }" — that
   selector carries an extra type selector (UL) on top of the same id+class
   count as the rule above, which out-specificities it and silently zeroed
   margin-left back to 0, leaving the whole anchor section flush left
   instead of centered. Compounding .wpg-anchor-grid onto the class selector
   here (two classes on one element, same id) beats that extra type
   selector regardless of type count. */
#SD .wpg-anchor-grid.wpg-anchor-maxwidth-boxed,
#SD .wpg-anchor-grid.wpg-anchor-maxwidth-wide,
#SD .wpg-anchor-grid.wpg-anchor-maxwidth-very_wide {
	margin-left: auto;
}
.wpg-anchor-maxwidth-boxed {
	max-width: var(--boxedWidth);
}
.wpg-anchor-maxwidth-wide {
	max-width: var(--wideWidth);
}
.wpg-anchor-maxwidth-very_wide {
	max-width: var(--veryWideWidth);
}
.wpg-anchor-maxwidth-full {
	max-width: none;
}

/* Same "#SD .entry-content UL > LI" text-indent/padding-left inheritance
   bug as .wpg-grid .wpg-card above (SDstandards.css's bulleted-list style
   leaking onto this UL>LI) — here it was invisible while the whole card
   was one <a>, but clips/shifts the new standalone button's text now that
   .wpg-anchor-button actually renders text-indent visibly. */
#SD .wpg-anchor-grid .wpg-anchor {
	padding-left: 0;
	text-indent: 0;
}
/* Same "•" ::before marker as .wpg-card above — independent of the
   padding-left/text-indent reset, rendered as a black dot over the
   top-left corner of the primary image. */
#SD .wpg-anchor-grid .wpg-anchor::before {
	content: none;
}

.wpg-anchor {
	position: relative;
	margin: 0;
}

/* Signed-in-only edit link — sits directly under the card's main button
   (the #SD prefix on the base rule, not just :hover/:focus-visible,
   matches the specificity of the theme's default link-color rule so the
   white text actually wins instead of rendering as illegible dark-on-dark). */
#SD .wpg-anchor-edit {
	display: inline-block;
	grid-column: 1 / -1;
	justify-self: start;
	margin-top: 0.4rem;
	padding: 0.3em 0.75em;
	font-family: "Space Mono", monospace;
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: #fff;
	background: rgba(0, 0, 0, 0.7);
	border-radius: var(--portfolio-radius-default-rest);
	text-decoration: none;
}
#SD .wpg-anchor-edit:hover,
#SD .wpg-anchor-edit:focus-visible {
	background: #000;
	color: #fff;
}

#SD .wpg-anchor-inner {
	display: grid;
	grid-template-columns: 0.75fr 1fr;
	gap: calc(var(--portfolio-card-gap) * 2.5);
	align-items: start;
}

/* Alternates which side the image sits on without duplicating markup —
   flips reading direction on the grid container, then flips it back on
   every direct child so text content still reads left-to-right. */
.wpg-anchor--even .wpg-anchor-inner {
	direction: rtl;
}
.wpg-anchor--even .wpg-anchor-inner > * {
	direction: ltr;
}

.wpg-anchor-media {
	display: flex;
	flex-direction: column;
	gap: var(--portfolio-card-gap);
	max-width: 85%;
}
.wpg-anchor--even .wpg-anchor-media {
	margin-left: auto;
}

.wpg-anchor-image--primary {
	display: block;
	width: 100%;
	/* Caps the image's own proportions so it can't tower over a short quote/
	   overview regardless of the source photo's native crop — a literal "no
	   more than N% taller than the text column" isn't something CSS can do
	   (text length varies card to card, so it'd need JS to measure and
	   resize on every load/breakpoint/reveal). This ratio is the tunable
	   knob instead: raise toward 1/1 for a shorter image, lower toward 4/5
	   or below for more of the original portrait crop. */
	aspect-ratio: var(--wpg-anchor-image-ratio, 1 / 1);
	height: auto;
	object-fit: cover;
	border-radius: var(--portfolio-radius-default-rest);
	box-shadow: var(--portfolio-shadow-default-rest);
}

/* Row of 2-4 secondary images below the primary image, always square,
   same gap and corner radius tokens as everything else in this block
   (--portfolio-card-gap, --portfolio-radius-default-rest) rather than
   bespoke values — replaces the old single overlapping-corner treatment. */
.wpg-anchor-secondary-row {
	display: flex;
	gap: var(--portfolio-card-gap);
}
.wpg-anchor-secondary-item {
	flex: 1 1 0;
	min-width: 0;
	/* Square via a padding-top spacer on ::before, not aspect-ratio and not
	   padding-top on this element itself. Two separate bugs ruled those out:
	   (1) aspect-ratio on a flex item whose width comes from flex-grow
	   (flex-basis:0) fails to resolve height on some Safari/WebKit versions
	   and the item collapses to zero height — confirmed on-device (images
	   loaded but never appeared, iPad Safari specifically; never reproduced
	   in newer WebKit builds). (2) padding-top:% placed directly on this
	   flex item resolves against the ROW's width (a percentage always
	   resolves against the containing block, i.e. the parent — never the
	   item's own flex-resolved width), producing a tall rectangle instead
	   of a square. Nesting the spacer one layer deeper in ::before fixes
	   that: ::before's containing block is THIS element (already correctly
	   sized by flex-grow), so its padding-top:100% finally measures against
	   the right width, and this element's own auto height then just wraps
	   that pseudo box — no circular dependency either direction. */
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--portfolio-radius-default-rest);
	box-shadow: var(--portfolio-shadow-default-rest);
}
.wpg-anchor-secondary-item::before {
	content: "";
	display: block;
	padding-top: 100%;
}
.wpg-anchor-image--secondary {
	display: block;
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Optional Screen Capture image (anchor_screen_capture), rendered below the
   primary/secondary images — a rectangular site screenshot rather than the
   square secondary treatment, so it keeps its own aspect ratio instead of
   the ::before-spacer square trick above. */
.wpg-anchor-screen-capture {
	display: block;
	width: 100%;
	border-radius: var(--portfolio-radius-default-rest);
	box-shadow: var(--portfolio-shadow-default-rest);
	overflow: hidden;
}
.wpg-anchor-screen-capture img {
	display: block;
	width: 100%;
	height: auto;
}
.wpg-anchor-visual-variant .wpg-anchor-swatches,
.wpg-anchor-visual-variant .wpg-anchor-colorwheel,
.wpg-anchor-visual-variant .wpg-anchor-type {
	margin-top: 0;
	max-width: 100%;
}
.wpg-anchor-visual-variant .wpg-anchor-colorwheel {
	display: flex;
	justify-content: center;
}
.wpg-anchor-visual-variant .wpg-anchor-colorwheel .color-wheel-wrap {
	justify-content: center;
}
.wpg-anchor-visual-variant .wpg-anchor-colorwheel .color-wheel {
	max-width: 100%;
}

/* --wpg-anchor-hang is the single source of truth for the left text edge
   shared by the title, the overview, the quote's wrapped lines, the name,
   and the title/org line — all indented flush to it. The quote's opening
   mark is the only thing allowed to sit left of that edge (in the negative
   text-indent it alone uses), so the whole card body reads as one
   hanging-indent column instead of independently-aligned pieces.

   Implemented as a 2-column grid (hang column + text column) rather than
   matching padding-left on every child individually — a repeated
   padding-left value only *looks* like one shared edge; it's actually N
   separate declarations that happen to agree, and any one of them losing
   that declaration (a Type Role inline style, a specificity fight, a future
   edit) silently knocks that element's edge out of line with the rest,
   which is exactly the "left alignment strays" symptom seen on tablet.
   A grid column is a single layout fact every child is placed into, so
   there's nothing per-child left to drift. */
.wpg-anchor-body {
	/* rem, not em — an em-based value resolves against each element's own
	   font-size (title/overview/quote/meta all differ), which throws the
	   shared edge off by a few px between them. rem stays a fixed physical
	   offset everywhere it's used, so it lines up exactly. */
	/* Hang = the quote-mark circle + its gap, so the circle (the only thing
	   left of this edge) sits fully in the hang column. */
	--wpg-anchor-mark-size: 2rem;
	--wpg-anchor-mark-gap: 0.625rem;
	--wpg-anchor-hang: calc(var(--wpg-anchor-mark-size) + var(--wpg-anchor-mark-gap));
	--wpg-anchor-body-gap: 0.75rem;
	display: grid;
	grid-template-columns: var(--wpg-anchor-hang) 1fr;
	column-gap: 0;
	row-gap: var(--wpg-anchor-body-gap);
	align-items: start;
}

/* font-family/weight/size/line-height/letter-spacing/text-transform/color
   each read their own --wpg-anchor-{element}-{prop} custom property,
   emitted inline only when a Type Role is picked (Design Tokens →
   Portfolio → Anchor Portfolio Pieces, shew_wpg_render_anchor_card()) —
   same var(--x, fallback) pattern as the CTA roles (.wpg-cta-headline/
   .wpg-cta-body above). Falls back to the original hardcoded look when no
   role is picked, so this is a no-op until someone actually chooses one. */
#SD .wpg-anchor-name {
	font-family: var(--wpg-anchor-title-family, inherit);
	font-weight: var(--wpg-anchor-title-weight, 700);
	font-size: var(--wpg-anchor-title-size, 1.25rem);
	line-height: var(--wpg-anchor-title-line-height, inherit);
	letter-spacing: var(--wpg-anchor-title-letter-spacing, normal);
	text-transform: var(--wpg-anchor-title-text-transform, none);
	color: var(--wpg-anchor-title-color, var(--portfolio-heading-color));
	display: block;
	grid-column: 2;
}

.wpg-anchor-overview {
	font-family: var(--wpg-anchor-overview-family, inherit);
	font-weight: var(--wpg-anchor-overview-weight, inherit);
	font-size: var(--wpg-anchor-overview-size, 0.95rem);
	line-height: var(--wpg-anchor-overview-line-height, 1.5);
	letter-spacing: var(--wpg-anchor-overview-letter-spacing, normal);
	text-transform: var(--wpg-anchor-overview-text-transform, none);
	color: var(--wpg-anchor-overview-color, var(--portfolio-body-color));
	display: block;
	grid-column: 2;
}

/* WYSIWYG output wraps anchor_overview in its own <p>, which otherwise
   carries the theme's default paragraph bottom margin on top of the
   .wpg-anchor-body gap below it — stacking two sources of space. Zeroed
   here so --wpg-anchor-overview-quote-gap is the only thing controlling
   that spacing. */
.wpg-anchor-overview p {
	margin: 0;
}

/* Dedicated token for the space between the overview and the quote that
   follows it, independent of --wpg-anchor-body-gap (which still governs
   title→overview and quote→button spacing). Expressed as extra margin-top
   on top of the body gap so the token value is the true total spacing:
   defaults to --wpg-anchor-body-gap itself, i.e. no visual change until
   overridden. */
.wpg-anchor-overview + .wpg-anchor-quote-content {
	margin-top: calc(var(--wpg-anchor-overview-quote-gap, var(--wpg-anchor-body-gap, 0.75rem)) - var(--wpg-anchor-body-gap, 0.75rem));
}

.wpg-anchor-quote-content {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	min-width: 0;
	grid-column: 2;
}

.wpg-anchor-quote {
	font-family: var(--wpg-anchor-quote-family, inherit);
	font-weight: var(--wpg-anchor-quote-weight, inherit);
	font-style: var(--wpg-anchor-quote-style, italic);
	font-size: var(--wpg-anchor-quote-size, 1.1rem);
	line-height: var(--wpg-anchor-quote-line-height, 1.5);
	letter-spacing: var(--wpg-anchor-quote-letter-spacing, normal);
	text-transform: var(--wpg-anchor-quote-text-transform, none);
	color: var(--wpg-anchor-quote-color, inherit);
	display: block;
	position: relative;
}

/* Opening mark lives in its own element (anchor-tile-render.php) and is
   pulled fully out of flow rather than faked with text-indent — text-indent
   only shifts the *line box*, so it still counts toward line-wrap width and
   in some engines drags the following character(s) with it (the "T" that
   went red along with the mark). An absolutely positioned mark has no width
   as far as the quote text is concerned, so the actual first letter sits
   flush on the shared edge like every other element in the card. */
/* Mark sits in a circle badge (same treatment as the Testimonial Cards
   Single style's mark, testimonialCards.css) out in the hang column, left
   of the shared text edge — the quote text, title, overview and photo all
   start on that edge; only the circle hangs. Circle background / foreground / Type
   Role (family, weight, style only) come from Design Tokens → Portfolio →
   Anchor Portfolio Pieces → Base (inc/anchor-portfolio-tokens.php). */
.wpg-anchor-quote-mark {
	position: absolute;
	left: calc(-1 * var(--wpg-anchor-hang));
	top: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--wpg-anchor-mark-size);
	height: var(--wpg-anchor-mark-size);
	/* The glyph sits in the top of its em box — nudged down so it reads
	   centered in the circle rather than riding its upper edge. */
	padding-top: 0.35em;
	box-sizing: border-box;
	border-radius: 50%;
	background: var(--wpg-anchor-mark-bg, var(--colF));
	color: var(--wpg-anchor-mark-color, #ffffff);
	font-family: var(--wpg-anchor-mark-family, inherit);
	font-weight: var(--wpg-anchor-mark-weight, 700);
	font-style: var(--wpg-anchor-mark-style, normal);
	font-size: 1.5rem;
	line-height: 1;
}

/* Face circle sits to the left of the name/title-org text, both starting
   flush at --wpg-anchor-hang like the quote's wrapped lines do. */
.wpg-anchor-quote-meta {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-family: var(--wpg-anchor-quote-meta-family, inherit);
	font-weight: var(--wpg-anchor-quote-meta-weight, inherit);
	font-size: var(--wpg-anchor-quote-meta-size, 0.875em);
	line-height: var(--wpg-anchor-quote-meta-line-height, inherit);
	letter-spacing: var(--wpg-anchor-quote-meta-letter-spacing, normal);
	text-transform: var(--wpg-anchor-quote-meta-text-transform, none);
	color: var(--wpg-anchor-quote-meta-color, var(--portfolio-body-color));
}

.wpg-anchor-quote-face {
	flex: 0 0 auto;
	width: 3rem;
	height: 3rem;
	border-radius: 50%;
	overflow: hidden;
}

.wpg-anchor-quote-face img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.wpg-anchor-quote-meta-text {
	display: flex;
	flex-direction: column;
	gap: 0.15em;
	min-width: 0;
}

.wpg-anchor-person {
	font-weight: 600;
}

.wpg-anchor-title-org {
	opacity: 0.8;
}

.wpg-anchor-button {
	grid-column: 2;
	justify-self: start;
	margin-top: 0.5rem;
	text-decoration: none;
}

/* Dedicated token for the space between the quote and the button that
   follows it (only applies when a quote is present — .wpg-anchor-button
   otherwise keeps its plain 0.5rem margin-top above). Same
   flex-gap-plus-margin-top technique as the overview→quote gap above:
   total spacing = the token value, defaulting to the current
   body-gap + 0.5rem (1.25rem) so nothing shifts until overridden. */
.wpg-anchor-quote-content + .wpg-anchor-button {
	margin-top: calc(var(--wpg-anchor-quote-button-gap, calc(var(--wpg-anchor-body-gap, 0.75rem) + 0.5rem)) - var(--wpg-anchor-body-gap, 0.75rem));
}

#SD .wpg-anchor-button:focus-visible {
	outline-width: var(--portfolio-focus-width);
	outline-style: solid;
	outline-color: var(--portfolio-focus-color);
	outline-offset: 4px;
	border-radius: var(--portfolio-radius-default-rest);
}

/* Palette variant */
.wpg-anchor-swatches {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-top: 0.5rem;
}
.wpg-anchor-swatch {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.25rem;
}
.wpg-anchor-swatch-chip {
	display: block;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: var(--wpg-anchor-swatch-color, #ccc);
}
.wpg-anchor-swatch-caption {
	font-family: "Space Mono", monospace;
	font-size: 0.7rem;
	text-align: center;
}

/* Palette variant — Radial mode. Reuses the Project - Color block's own
 * .color-wheel-wrap/.color-wheel markup and animation (createColorWheel(),
 * inc/projectLibrary.php; scroll-reveal handled by the same site-wide
 * IntersectionObserver as everywhere else) — only overriding size for the
 * anchor card's small scale. Chosen via Design Tokens → Portfolio →
 * Anchor Portfolio Pieces → Brands → Color Display. */
.wpg-anchor-colorwheel {
	display: block;
	margin-top: 0.5rem;
}
.wpg-anchor-colorwheel .color-wheel-wrap {
	display: flex;
	justify-content: flex-start;
}
.wpg-anchor-colorwheel .color-wheel {
	width: 100%;
	max-width: 140px;
	height: auto;
	overflow: visible;
}

/* Same per-wedge reveal as the full-size block (colors.css) — duplicated
 * rather than shared across files since colors.css only loads on pages
 * that actually contain a Project - Color block, which this portfolio
 * grid page doesn't. Same --color-wheel-duration/--slice-delay tokens
 * (Design Tokens → Color Treatments), so both stay in sync. */
.wpg-anchor-colorwheel .color-wheel-wrap .color-wheel path {
	opacity: 0;
	transform: scale(0.5);
	transform-origin: 250px 250px;
	transition:
		opacity  var(--color-wheel-duration, 0.5s) cubic-bezier(0.22, 1, 0.36, 1) var(--slice-delay, 0ms),
		transform calc(var(--color-wheel-duration, 0.5s) + 0.1s) cubic-bezier(0.22, 1, 0.36, 1) var(--slice-delay, 0ms);
}
.wpg-anchor-colorwheel .color-wheel-wrap.is-in-view .color-wheel path {
	opacity: 1;
	transform: scale(1);
}
@media (prefers-reduced-motion: reduce) {
	.wpg-anchor-colorwheel .color-wheel-wrap .color-wheel path {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* Type variant — actual letterform/font-name SVG artwork pulled from the
 * post's own project-typography block (inc/helpers/anchor-tile-render.php,
 * shew_anchor_brand_system_from_blocks()), not CSS-drawn "Aa" glyphs — that
 * block stores per-typeface artwork, no plain-text typeface name to label
 * a CSS specimen with. */
.wpg-anchor-type {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	margin-top: 0.5rem;
	align-items: flex-end;
}
.wpg-anchor-type-item {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.25rem;
}
.wpg-anchor-type-specimen {
	display: block;
	width: 2.5rem;
	height: 2.5rem;
	object-fit: contain;
}
.wpg-anchor-type-label {
	display: block;
	height: 0.85rem;
	width: auto;
	object-fit: contain;
}

@media screen and (max-width: 767px) {
	#SD .wpg-anchor-inner,
	#SD .wpg-anchor--even .wpg-anchor-inner {
		grid-template-columns: 1fr;
		direction: ltr;
	}
	.wpg-anchor-media,
	.wpg-anchor--even .wpg-anchor-media {
		max-width: 100%;
		margin-left: 0;
	}

	/* Secondaries sit beside the primary image, not below it, once the
	   card itself has already dropped to a single stacked column — keeps
	   the media block from getting too tall on small screens.

	   Both a flex and a grid version of "primary width -> square height ->
	   stretch the secondary column to match" were tested live and both
	   collapsed to 0 — browsers don't reliably resolve that circular
	   dependency (secondary column's size depends on primary's computed
	   height, which a naive read of the box model says depends on
	   secondary's width). Broken here by fixing --wpg-anchor-mobile-split
	   (the primary image's share of the width) as the one independent
	   value, then deriving the whole container's height from it via
	   aspect-ratio — a plain box calculation, not a cross-item layout
	   dependency. Every child then sizes off that already-known height. */
	.wpg-anchor-media {
		--wpg-anchor-mobile-split: 0.65;
		display: flex;
		flex-direction: row;
		gap: var(--portfolio-card-gap);
		aspect-ratio: 1 / var(--wpg-anchor-mobile-split);
	}
	.wpg-anchor-image--primary {
		flex: 0 0 calc(var(--wpg-anchor-mobile-split) * 100%);
		width: calc(var(--wpg-anchor-mobile-split) * 100%);
		height: 100%;
	}
	.wpg-anchor-secondary-row {
		flex: 1 1 auto;
		height: 100%;
		flex-direction: column;
		align-items: flex-start;
	}
	/* flex:1 1 0 divides the row's now-definite height evenly among however
	   many items there are, then aspect-ratio derives each item's WIDTH from
	   that already-resolved height — the opposite direction from the base
	   (row-layout) rule above, which derives height FROM a flex-resolved
	   width and needed the padding-top-square fallback instead. This
	   direction (height known -> width needed) doesn't hit that same
	   collapse bug since the height is definite before aspect-ratio ever
	   runs, so aspect-ratio itself is restored here rather than inheriting
	   the row-layout padding-top hack, which can't derive height-from-width
	   in reverse. */
	.wpg-anchor-secondary-item {
		position: static;
		flex: 1 1 0;
		aspect-ratio: 1 / 1;
	}
	.wpg-anchor-secondary-item::before {
		content: none;
	}
	.wpg-anchor-image--secondary {
		position: static;
	}

	/* .wpg-anchor-media becomes a row flex above (primary + secondary-row
	   side by side) — the Screen Capture image isn't part of that split, so
	   it's forced onto its own full-width line below rather than becoming a
	   third flex item squeezed into the same row. */
	.wpg-anchor-screen-capture {
		flex: 1 1 100%;
		margin-top: var(--portfolio-card-gap);
	}
}

/* -------------------------------------------------
 * Rhythm layout (wpg_layout = rhythm) — see shew_wpg_rhythm_plan() in
 * inc/helpers/work-portfolio-grid-render.php for the row cycle. Each <li>
 * carries its own --wpg-col / --wpg-row / --wpg-ratio; those are only read
 * at 1024px+, so smaller screens get the normal tablet/mobile .wpg-grid.
 * Approved from the "Brands grid lab" mockup, 2026-10-01.
 * ----------------------------------------------- */

/* Larger captions at every width — the title-size tokens are :root vars
   (inc/portfolio-card-tokens.php), so overriding them here scopes the
   change to Rhythm grids without touching the per-type #SD rules.
   The *-token vars come from Design Tokens → Portfolio → Rhythm Grid
   (inc/rhythm-grid-tokens.php), only emitted when picked — the fallbacks
   here are the approved defaults. */
.wpg-grid--rhythm {
	--wpg-rhythm-gap: var(--wpg-rhythm-gap-token, clamp(1.25rem, 2vw, 2rem));
	--wpg-rhythm-caption: var(--wpg-rhythm-caption-token, clamp(1.125rem, calc(0.6vw + 0.9rem), 1.5rem));
	--wpg-rhythm-caption-lh: var(--wpg-rhythm-caption-lh-token, 1.2);
	/* Titles are links, so they use the standard site link colors (#SD A in
	   SDstandards.css: Color A, --colHover on hover). */
	--portfolio-title-color-default: var(--colA);
	--portfolio-title-color-brand: var(--colA);
	--portfolio-title-color-website: var(--colA);
	--portfolio-title-color-logo: var(--colA);
	--portfolio-title-color-video: var(--colA);
	--portfolio-heading-hover-color: var(--colHover, var(--colC));
	--portfolio-title-size-default: var(--wpg-rhythm-caption);
	--portfolio-title-size-brand: var(--wpg-rhythm-caption);
	--portfolio-title-size-website: var(--wpg-rhythm-caption);
	--portfolio-title-size-logo: var(--wpg-rhythm-caption);
	--portfolio-title-size-video: var(--wpg-rhythm-caption);
	--portfolio-title-line-height-default: var(--wpg-rhythm-caption-lh);
	--portfolio-title-line-height-brand: var(--wpg-rhythm-caption-lh);
	--portfolio-title-line-height-website: var(--wpg-rhythm-caption-lh);
	--portfolio-title-line-height-logo: var(--wpg-rhythm-caption-lh);
	--portfolio-title-line-height-video: var(--wpg-rhythm-caption-lh);
}

@media screen and (min-width: 1024px) {
	.wpg-grid.wpg-grid--rhythm {
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--wpg-rhythm-gap);
		row-gap: calc(var(--wpg-rhythm-gap) * 1.5);
		align-items: start;
	}
	/* Width cap so tiles don't keep growing on large screens — at 1368px the
	   biggest (6-column) tile tops out around 670px. #SD to beat the
	   "#SD .wpg-grid { margin-left: 0 }" reset above. */
	#SD .wpg-grid.wpg-grid--rhythm {
		max-width: var(--wpg-rhythm-max-width, 1368px);
		margin-left: auto;
		margin-right: auto;
	}
	.wpg-grid--rhythm > li {
		grid-column: var(--wpg-col, auto);
		grid-row: var(--wpg-row, auto);
	}
	/* Pair: the 4:3 and 4:5 cards differ in height — bottoms (captions)
	   align, leaving open space above the shorter one. */
	.wpg-grid--rhythm > [data-wpg-slot="pair"] {
		align-self: end;
	}
	/* Beats the per-type .wpg-card--brand .wpg-card-media ratio rules. */
	.wpg-grid--rhythm .wpg-card .wpg-card-media {
		aspect-ratio: var(--wpg-ratio, 1 / 1);
	}
}

/* Title Type Role's font-style (Rhythm Grid tokens) — the per-type title
   rules above have no style property of their own. */
#SD .wpg-grid--rhythm .wpg-card-name {
	font-style: var(--wpg-rhythm-title-style, normal);
}

/* Open cells */
#SD .wpg-grid .wpg-breather {
	padding-left: 0;
	text-indent: 0;
	margin: 0;
	min-width: 0;
}
#SD .wpg-grid .wpg-breather::before {
	content: none;
}
.wpg-breather--quote {
	grid-column: 1 / -1;
	align-self: center;
}
/* Cell Background token — a filled panel that stretches to the row height,
   quote centered inside. No background picked: plain text, no padding. */
#SD .wpg-grid .wpg-breather--quote {
	display: flex;
	align-items: center;
	padding: var(--wpg-breather-padding, 0);
	background: var(--wpg-breather-bg, transparent);
	border-radius: var(--portfolio-radius-default-rest, 0);
}
/* Below 1024px a full-width quote would strand the card before it alone
   on its row — dense flow lets the next card backfill that gap. */
@media screen and (max-width: 1023px) {
	.wpg-grid--rhythm {
		grid-auto-flow: row dense;
	}
}
@media screen and (min-width: 1024px) {
	.wpg-grid--rhythm > .wpg-breather--quote {
		grid-column: var(--wpg-col, auto);
	}
	/* Filled panels fill the row; plain quotes stay centered beside the tiles. */
	.wpg-grid--rhythm > .wpg-breather--quote {
		align-self: var(--wpg-breather-align, center);
	}
}

.wpg-breather-figure {
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: 0.875rem;
	max-width: 36rem;
}
#SD .wpg-breather-quote {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	/* --wpg-breather-quote-* = Rhythm Grid Quote role, else the anchor
	   Quote role (inc/rhythm-grid-tokens.php). Size only comes from a
	   Rhythm-specific role; otherwise it matches the captions. */
	font-family: var(--wpg-breather-quote-family, var(--font-primary, inherit));
	font-weight: var(--wpg-breather-quote-weight, 400);
	font-style: var(--wpg-breather-quote-style, normal);
	font-size: var(--wpg-breather-quote-size, var(--wpg-rhythm-caption));
	text-transform: var(--wpg-breather-quote-text-transform, none);
	line-height: var(--wpg-breather-quote-line-height, 1.35);
	letter-spacing: var(--wpg-breather-quote-letter-spacing, normal);
	color: var(--wpg-breather-quote-color, var(--colA, #355067));
}
/* Quotation mark in a circle hanging left of the text — same treatment and
   sizes as the anchor quote's .wpg-anchor-quote-mark. Quote and name line
   share the indented edge; only the circle sits in the hang. Circle/glyph
   colors: Rhythm Grid tokens, else the anchor's --wpg-anchor-mark-*. */
.wpg-breather-figure {
	--wpg-breather-mark-size: 2rem;
	--wpg-breather-hang: calc(var(--wpg-breather-mark-size) + 0.625rem);
	position: relative;
	padding-left: var(--wpg-breather-hang);
}
/* Positioned against the blockquote itself (the theme already gives
   blockquote position: relative), pulled left into the hang. */
#SD .wpg-breather-quote {
	position: relative;
}
#SD .wpg-breather-quote::before {
	content: "\201C";
	position: absolute;
	left: calc(-1 * var(--wpg-breather-hang));
	top: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--wpg-breather-mark-size);
	height: var(--wpg-breather-mark-size);
	padding-top: 0.35em;
	box-sizing: border-box;
	border-radius: 50%;
	background: var(--wpg-breather-mark-bg, var(--wpg-anchor-mark-bg, var(--colF)));
	color: var(--wpg-breather-mark-color, var(--wpg-anchor-mark-color, #ffffff));
	font-family: var(--wpg-breather-mark-family, inherit);
	font-weight: var(--wpg-breather-mark-weight, 700);
	font-style: var(--wpg-breather-mark-style, normal);
	font-size: 1.5rem;
	line-height: 1;
}
#SD .wpg-breather-quote p {
	margin: 0;
	text-wrap: pretty;
}
/* --wpg-breather-meta-* = Rhythm Grid Name / Organization role, else the
   anchor Quote Name / Organization / Title role. */
.wpg-breather-meta {
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
	font-family: var(--wpg-breather-meta-family, inherit);
	font-weight: var(--wpg-breather-meta-weight, 400);
	font-style: var(--wpg-breather-meta-style, normal);
	font-size: var(--wpg-breather-meta-size, var(--text-role-small-size, 0.9375rem));
	line-height: var(--wpg-breather-meta-line-height, 1.35);
	letter-spacing: var(--wpg-breather-meta-letter-spacing, normal);
	text-transform: var(--wpg-breather-meta-text-transform, none);
	color: var(--wpg-breather-meta-color, var(--portfolio-body-color));
}
.wpg-breather-name {
	font-weight: 600;
	color: var(--wpg-breather-meta-color, var(--colA, #355067));
}
