/* Block: News (acf/news)
   ---------------------------------------------------------------------------
   News cards on a Slate band, each card one link to its source. Phone first:
   one card per row (Latest: a one-up carousel), Latest three-up from 768,
   the Archive two-up from 768 and three-up from 992. Notes:
   docs/news-block.md.

   Comp references (Figma file 9eBn6GzkM1aHMg59Ck62cP):
     desktop 1512  Home "News-worthy Notes" 30:2 (band 6593-7570), the News
                   page grid 4059:186 / 187 / 202 and Load More 4059:215
     phone 402     Home 127:505 (band 7036-7929). The News page has no phone
                   comp: its phone and tablet layouts are extrapolated.

   The card box is the comp's hover panel (4059:169: Linen at 10% over Slate,
   416 x 720), so the panel IS the card: 24px above the photo, 21px either
   side, and ~105px under the last line on desktop. The list is pulled out by
   the side padding, so the photos still line up with the container. Rows sit
   62px apart box to box, the comp's row 1 -> 2 spacing; the comp puts row 3
   only 86px under row 2's text, which would leave a hovered row-2 card's
   panel 3px from row 3's photo (docs/news-block.md).

   Vertical gaps are the comp's ink-to-ink distances converted to line boxes
   with the fonts' measured metrics (Richmond Display ascent .91, descent .25,
   cap .679; Rig Sans ascent .94/.96, descent .27, cap .70; as acf/feature).

   Block stylesheets print BEFORE reset.min.css, style.css and the global
   styles (header.md, "CSS order trap"), so every rule here wins on
   specificity, never on order.
--------------------------------------------------------------------------- */

.news--section {
	/* --- Phone (402, Home 127:505) --- */
	--news-fg: var(--wp--preset--color--black, #000);
	/* Buttons and focus rings: Deep Sea, 5.7:1 on Slate (the comp's Load
	   More and All News outlines). */
	--news-ink: var(--wp--preset--color--deep-sea, #1b2632);
	--news-bg: var(--wp--preset--color--slate, #81a5a2);
	/* The hover / focus panel (4059:169): Linen at 10% over Slate, #8AA9A5.
	   Slightly LIGHTER than the Slate, as drawn. */
	--news-panel: rgba(215, 208, 199, 0.1);

	/* .theme-container's 15px phone gutter, plus this, is the comp's 44. */
	--news-inset: 28px;
	--news-pad-top: 30px;        /* band top -> heading cap 37 */
	--news-pad-bottom: 35px;     /* last summary ink -> band end 67 */
	--news-gap-header: 40px;     /* heading (2 lines) -> button 48 below its ink */
	--news-gap-cards: 33px;      /* button -> card box; the photo 57 below the button */
	--news-more-gap: 32px;       /* last card box -> Load More */

	--news-card-pad-top: 24px;
	--news-card-pad-x: 21px;
	--news-card-pad-bottom: 24px;
	/* Photo to photo (76 at 1512). Never under twice the card's side padding,
	   so the gap between card boxes never goes negative. */
	--news-gap-x: clamp(42px, 5.03vw, 76px);
	--news-gap-y: 24px;          /* card box to card box */

	--news-media-radius: var(--lwh-media-radius, 60px);
	--news-gap-media: 42px;      /* photo -> title cap 49 (phone comp) */
	--news-gap-title: 38px;      /* title cap -> date cap 85 */
	--news-gap-date: 19px;       /* date cap -> summary cap 45 */
	--news-cta-gap: 24px;        /* the last line -> "Read full article" (2026-10-17) */
	--news-title-size: var(--wp--preset--font-size--h-3, 48px);

	position: relative;
	/* Over the pinned hero, like the panels and bands around it. */
	z-index: 1;
	padding-top: var(--news-pad-top);
	padding-bottom: var(--news-pad-bottom);
	background-color: var(--news-bg);
	color: var(--news-fg);
}

.news--section.archive-mod {
	--news-pad-top: 36px;        /* no comp: 60 from the intro's text to the photo */
	--news-pad-bottom: 60px;
}

.news--container.theme-container {
	padding-left: calc(var(--theme-content-padding) + var(--news-inset));
	padding-right: calc(var(--theme-content-padding) + var(--news-inset));
}

/* --- The News page: one Slate panel ------------------------------------------
   On the News page the archive follows the Slate intro panel ("The Dome
   Daily"), and the comp draws them as one panel (4059:94 runs on into
   4059:168). The intro's bottom padding and its eyebrow-led tail are
   dropped, so the gap from its text to the cards is this block's alone; the
   two Slates meet with no rounded top in between (style.css cancels the
   blockGap margin). Where :has() is unsupported the gap is just larger. */
.intro--section:has(+ .news--section) {
	--intro-pad-bottom: 0px;
	--intro-lead-tail: 0px;
	/* intro.css clips the panel to its rounded corners (Phase 7 audit H-4).
	   With no bottom padding here, the clip would cut the last line while
	   the reveal brings it up from 24px below; the Slate runs on into the
	   cards, so nothing needs clipping. */
	overflow: visible;
}

/* --- Heading and button (InnerBlocks) ---------------------------------------
   Both DOM shapes: the front end prints the InnerBlocks straight into
   .news--header (the ACF wrapper is opted out so [data-reveal-group] staggers
   them); the editor still wraps them in .acf-innerblocks-container. */

.news--header {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.news--header > .acf-innerblocks-container {
	display: contents;
}

:is(.news--header, .news--header > .acf-innerblocks-container) > * {
	max-width: 100%;
	margin-top: 0;
	margin-bottom: 0;
}

:is(.news--header, .news--header > .acf-innerblocks-container) > * + * {
	margin-top: var(--news-gap-header);
}

/* Phones: the button centred under the heading (127:505). (0,3,0) over core's
   justification classes and the layout's generated container class. */
:is(.news--header, .news--header > .acf-innerblocks-container) > .wp-block-buttons {
	align-self: stretch;
	justify-content: center;
}

.news--header + .news--cards {
	margin-top: var(--news-gap-cards);
}

/* --- Buttons: All News (core/button) and Load More ---------------------------
   A flat Deep Sea outline and label on Slate (4059:215), not the Sunset label,
   which would read 1.9:1 here. Hover and keyboard focus fill it Deep Sea with
   a Slate label: our call, the comps show no hover. The intro's light panels
   do the same. */

.news--section .wp-block-button__link {
	border-color: var(--news-ink);
	background-color: transparent;
	background-image: none;
	color: var(--news-ink);
	-webkit-background-clip: border-box;
	background-clip: border-box;
}

.news--section .wp-block-button__link:hover,
.news--section .wp-block-button__link:focus-visible {
	background-color: var(--news-ink);
	background-image: none;
	color: var(--news-bg);
}

/* buttons.css rings in Linen, 1.8:1 on Slate. */
.news--section .wp-block-button__link:focus-visible {
	outline: 2px solid var(--news-ink);
	outline-offset: 3px;
}

/* Load More shows only where js/news.js can drive it: lwh-js is set by the
   inline head script (functions.php) before first paint. Without it every
   card shows (below) and so no button is needed. */
.news--more-wrap {
	display: none;
	justify-content: center;
	margin-top: var(--news-more-gap);
}

html.lwh-js .news--more-wrap {
	display: flex;
}

/* --- The list ---------------------------------------------------------------- */

.news--cards {
	position: relative;
}

.news--list {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	column-gap: calc(var(--news-gap-x) - 2 * var(--news-card-pad-x));
	row-gap: var(--news-gap-y);
	/* Pulled out by the card's side padding, so the photos line up with the
	   container while the panel reaches past them. */
	margin: 0 calc(-1 * var(--news-card-pad-x));
	padding: 0;
	list-style: none;
}

.news--item {
	display: flex;
	min-width: 0;
	margin: 0;
	padding: 0;
}

/* Load More, the first batch (2026-10-16, Phase 7 audit NW-1, NW-5): a whole
   number of rows for the columns the list has, so no card is left alone above
   the button. Six one up (phones), eight two up (768-991), nine three up
   (992+), the numbers in news.php's $steps. These rules hold the page until
   js/news.js takes over: it then marks every card past what shows
   `is-later-mod` and drops `is-paged-mod` from the list, keeping the count a
   whole number of rows as the window crosses a tier. Only under html.lwh-js,
   so with JS off every card shows. Classes, never the hidden attribute:
   reset.min.css has [hidden]{display:none !important}, which nothing could
   undo for a no-JS visitor. */
html.lwh-js .news--list.is-paged-mod > .news--item:nth-child(n + 7),
html.lwh-js .news--item.is-later-mod {
	display: none;
}

/* Two up the first batch is eight, three up nine. The button hides, before
   js/news.js runs, from the tier whose first batch already shows every card
   (news.php prints the class when there are seven to nine items). */
@media (min-width: 768px) {
	html.lwh-js .news--list.is-paged-mod > .news--item:nth-child(-n + 8) {
		display: flex;
	}

	html.lwh-js .news--more-wrap.is-done-md-mod {
		display: none;
	}
}

@media (min-width: 992px) {
	html.lwh-js .news--list.is-paged-mod > .news--item:nth-child(-n + 9) {
		display: flex;
	}

	html.lwh-js .news--more-wrap.is-done-lg-mod {
		display: none;
	}
}

/* --- The card ------------------------------------------------------------------
   One link holding the photo, title, date and summary. The box is the comp's
   hover panel, so the panel, the click target and the focus ring are all the
   same rectangle. Grid items stretch, so every card in a row is as tall as
   the tallest and their panels line up. */

.news--card {
	/* The containing block for its own .screen-reader-text (position:
	   absolute). Without it the hidden source note of carousel slides 2 and
	   3 is placed against .news--cards, outside the scrolling track, at its
	   static x of 400 and 758px, and widened a 402px phone page to 759. */
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	box-sizing: border-box;
	padding: var(--news-card-pad-top) var(--news-card-pad-x) var(--news-card-pad-bottom);
	color: inherit;
	text-decoration: none;
	background-color: transparent;
	transition: background-color 0.2s ease;
	/* Keyboard focus scrolls a card into view; without this, Shift+Tab left
	   its top under the sticky header (96px of a 700px card at 1512; Phase 7
	   audit NW-3). --theme-menu-height is the pinned header (menubar.css). */
	scroll-margin-top: calc(var(--theme-menu-height, 46px) + 16px);
}

.news--card:focus-visible {
	background-color: var(--news-panel);
}

/* Hover only where there is a real hover: on a touch screen a tap left the
   panel lit after the card opened its link in a new tab (audit NW-6). */
@media (hover: hover) {
	.news--card:hover {
		background-color: var(--news-panel);
	}
}

/* Keyboard focus only: clear the ring a click could leave first, then add the
   theme's on :focus-visible (equal specificity, so the order matters). Inset,
   so the carousel's scroll box can't clip it on phones. */
.news--card:focus {
	outline: none;
}

.news--card:focus-visible {
	outline: 2px solid var(--news-ink);
	outline-offset: -2px;
}

.news--media {
	position: relative;
	overflow: hidden;
	/* width: 100% is not optional with aspect-ratio: without a definite inline
	   size Chrome can run the ratio backwards (image-band-block.md). */
	width: 100%;
	aspect-ratio: 1 / 1;
	flex: none;
	background-color: rgba(0, 0, 0, 0.08);
}

.news--img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The one rounded corner, by column (4059:180-182): top-left, bottom-left,
   top-right, the same on every row. One column (phones, and the carousel)
   keeps the desktop order card by card; the Archive's two columns use the
   outer corners, top-left then top-right (below). */
.news--item:nth-child(3n + 1) .news--media {
	border-top-left-radius: var(--news-media-radius);
}

.news--item:nth-child(3n + 2) .news--media {
	border-bottom-left-radius: var(--news-media-radius);
}

.news--item:nth-child(3n + 3) .news--media {
	border-top-right-radius: var(--news-media-radius);
}

/* Type. (0,2,0): the global styles' :root :where(h2/h3) is (0,1,0) and prints
   after this file. */
.news--card .news--title {
	margin: var(--news-gap-media) 0 0;
	color: inherit;
	font-family: var(--wp--preset--font-family--display, serif);
	font-size: var(--news-title-size);
	font-weight: 300;
	line-height: 1;
	letter-spacing: 0;
	overflow-wrap: break-word;
}

.news--card .news--date {
	margin: var(--news-gap-title) 0 0;
	font-family: var(--wp--preset--font-family--sans, sans-serif);
	font-size: var(--wp--preset--font-size--eyebrow, 18px);
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.news--card .news--summary {
	margin: var(--news-gap-date) 0 0;
	font-size: var(--wp--preset--font-size--body, 20px);
	font-weight: 300;
	line-height: 29px;
}

/* "Read full article ›" (2026-10-17, Dapper's review DR-8; the comps draw
   none). In the date's type, Rig Sans Bold 18 with 0.1em tracking, uppercase,
   in the card's black (7.8:1 on Slate), so the card's two small caps lines
   echo each other. margin-top: auto sends it to the foot of the card and
   takes up whatever a shorter card has spare: the cards in a row (and the
   carousel's slides) stretch to the tallest, so the line sits level across
   them. The gap above it is padding, so the tallest card keeps it too. From
   992 it fits the card's existing room under the last line (see
   --news-cta-gap there); below 992 the card had only its 24px padding there,
   so it grows by the gap and the line. */
.news--card .news--cta {
	display: block;
	margin-top: auto;
	padding-top: var(--news-cta-gap);
	font-family: var(--wp--preset--font-family--sans, sans-serif);
	font-size: var(--wp--preset--font-size--eyebrow, 18px);
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.news--cta-end {
	white-space: nowrap;
}

/* The carousel chevron at 1em, its centre on the capitals' (the chevron's ink
   is centred in its box, 9px above the box's foot; the caps' centre is 0.35em
   above the baseline). With the tracking's trailing 0.1em, 0.3em from the
   last letter. */
.news--cta-chevron {
	display: inline-block;
	width: 1em;
	height: 1em;
	margin-left: 0.2em;
	vertical-align: -0.15em;
}

/* --- Carousel (Latest below 768) -----------------------------------------------
   A plain scroll-snap track, so it swipes with JS off; js/carousel.js (shared
   with acf/image-band and acf/feature) adds the arrows, the wrap-around, ←/→
   and the live region, and moves focus with the slide when a card's link has
   it (docs/news-block.md). */

.news--section.is-carousel-mod .news--list {
	display: flex;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.news--section.is-carousel-mod .news--list::-webkit-scrollbar {
	display: none;
}

.news--section.is-carousel-mod .news--item {
	flex: 0 0 100%;
	scroll-snap-align: start;
}

/* A square over the first photo's box, so the pill can sit in its corner at
   any width: 18px in from the right and 21 up from the bottom (127:505). */
.news--nav-frame {
	position: absolute;
	top: var(--news-card-pad-top);
	left: 0;
	right: 0;
	aspect-ratio: 1 / 1;
	pointer-events: none;
}

/* The arrow pill: the band's and the feature's geometry (100.4 x 48, the small
   clipped corner), repeated here because their stylesheets load only with
   them. White over the photo, not the comp's Linen, after the client's
   2026-09-01 ruling on the band's pill (turnover.md). */
.news--nav {
	position: absolute;
	right: 18px;
	bottom: 21px;
	z-index: 2;
	display: flex;
	align-items: center;
	gap: 17.6px;
	width: max-content;
	padding: 9.8px 14px;
	border: 1px solid #fff;
	border-radius: var(--lwh-clip-corner-sm, 10px) var(--lwh-clip-corner-sm, 10px) 0 var(--lwh-clip-corner-sm, 10px);
	/* Deep Sea at 45% under the white, as the band's and the feature's pills
	   (2026-10-15, Phase 7 audit AM-1): 3:1 or better over the photos. */
	background-color: rgba(27, 38, 50, 0.45);
	color: #fff;
	pointer-events: auto;
}

.news--arrow {
	position: relative;
	display: block;
	width: 26.4px;
	height: 26.4px;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	cursor: pointer;
}

/* The tap target (2026-10-15, Phase 7 audit F1): an invisible box takes each
   26.4px arrow out to its half of the pill, 50.2 x 48, as on the band's and
   the feature's pills. Nothing changes on screen. */
.news--arrow::before {
	content: "";
	position: absolute;
	top: -10.8px;
	bottom: -10.8px;
	left: -15px;
	right: -8.8px;
}

.news--arrow.is-next::before {
	left: -8.8px;
	right: -15px;
}

.news--arrow[disabled] {
	opacity: 0.35;
	cursor: default;
}

.news--arrow:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 4px;
	border-radius: 2px;
}

.news--chevron {
	display: block;
	width: 100%;
	height: 100%;
}

.news--arrow.is-prev .news--chevron {
	transform: rotate(180deg);
}

/* --- Editor -------------------------------------------------------------- */

.news--placeholder {
	margin: 30px 0 0;
	padding: 40px 30px;
	border: 1px dashed currentColor;
	text-align: center;
	opacity: 0.7;
}

/* --- Tablet (768) ------------------------------------------------------------
   Latest: the comp's desktop row, three up, with the heading beside the
   button. The carousel's pill goes; the list is a grid again, so the shared
   controller finds nothing to scroll and leaves the keys alone. Three-up
   cards are 199-268px wide here, so their titles follow h4's fluid size
   (35-41px; it reaches the comp's 48 at 1290).
   Archive: two up, at the phone card's size or larger (320-431px), with the
   comp's 48px titles. */

@media (min-width: 768px) {
	.news--section {
		--news-pad-top: 60px;
		--news-pad-bottom: 60px;
		--news-gap-cards: 41px;
		--news-gap-y: 40px;
		--news-gap-media: 27px;      /* photo -> title cap 34 (desktop comps) */
		--news-more-gap: 32px;
	}

	.news--section.archive-mod {
		--news-pad-top: 60px;
	}

	.news--header {
		flex-direction: row;
		align-items: flex-start;
		justify-content: space-between;
		gap: 24px;
	}

	/* Beside the heading: the button's top 10px below the heading's line box
	   (30:2: cap 6680, button 6683-6742). */
	:is(.news--header, .news--header > .acf-innerblocks-container) > * + * {
		margin-top: 0;
	}

	:is(.news--header, .news--header > .acf-innerblocks-container) > .wp-block-buttons {
		flex: none;
		align-self: flex-start;
		justify-content: flex-end;
		margin-top: 10px;
	}

	.news--section.latest-mod .news--list,
	.news--section.is-carousel-mod .news--list {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		overflow: visible;
		scroll-snap-type: none;
	}

	.news--section.latest-mod {
		--news-title-size: var(--wp--preset--font-size--h-4, 48px);
	}

	.news--nav-frame {
		display: none;
	}

	.news--section.archive-mod .news--list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* Two columns: the outer corners, top-left then top-right. */
	.news--section.archive-mod .news--item:nth-child(n) .news--media {
		border-radius: 0;
	}

	.news--section.archive-mod .news--item:nth-child(odd) .news--media {
		border-top-left-radius: var(--news-media-radius);
	}

	.news--section.archive-mod .news--item:nth-child(even) .news--media {
		border-top-right-radius: var(--news-media-radius);
	}
}

/* --- Desktop (992) -------------------------------------------------------------
   Both modes three up in .theme-container (146 -> 1366 at 1512, where the
   comps put the cards at 109-1383 on Home and 119-1393 on News; the gutter
   decision every block shares, figma-comps.md): 356px photos at 1512 against
   the comp's 374, with the comp's 76px between them. */

@media (min-width: 992px) {
	.news--section {
		--news-inset: 0px;
		--news-pad-top: 80px;        /* 30:2: band top -> heading cap 87 */
		--news-pad-bottom: 67px;     /* 30:2: panel bottom -> band end */
		--news-gap-y: 62px;          /* 4059:169 -> row 2: panel to panel */
		/* 4059:169: the panel runs 105px under the last line box (113 under
		   its baseline). Since 2026-10-17 "Read full article" sits in that
		   space: the gap, its 25.2px line, and the card's 24px bottom padding
		   (its top padding's) add up to the same 105, so no card grows. */
		--news-card-pad-bottom: 24px;
		--news-cta-gap: calc(105px - 25.2px - 24px);
		--news-more-gap: 19px;       /* row 3's panel -> Load More (4059:215) */
		--news-title-size: var(--wp--preset--font-size--h-4, 48px);
	}

	/* 4059:51: the intro's one-line paragraph to the first panel (photo at
	   1281 under an intro at 778, as the comp). */
	.news--section.archive-mod {
		--news-pad-top: 85px;
		--news-pad-bottom: 64px;     /* Load More -> band end */
	}

	.news--section.archive-mod .news--list {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.news--section.archive-mod .news--item:nth-child(n) .news--media {
		border-radius: 0;
	}

	.news--section.archive-mod .news--item:nth-child(3n + 1) .news--media {
		border-top-left-radius: var(--news-media-radius);
	}

	.news--section.archive-mod .news--item:nth-child(3n + 2) .news--media {
		border-bottom-left-radius: var(--news-media-radius);
	}

	.news--section.archive-mod .news--item:nth-child(3n + 3) .news--media {
		border-top-right-radius: var(--news-media-radius);
	}
}

@media (prefers-reduced-motion: reduce) {
	.news--card {
		transition: none;
	}
}
