/*---------------- Blockbuilder design tokens (relative only — tenant CSS owns colour/type) ----------------*/
/* Accelerator tokens (Design Studio Advanced pane): what Small/Medium/
   Large SPACING and the two width words MEAN for this site — themeable
   per site via --theme-* (historic literals as fallbacks; an unset theme
   is byte-identical). Blocks store the var reference, so a redefinition
   re-styles every block that ever picked that word — retroactively, by
   design. */
.blk-page								{ --blk-space-xs:var(--theme-space-xs, .5rem); --blk-space-s:var(--theme-space-s, 1rem); --blk-space-m:var(--theme-space-m, 1.75rem); --blk-space-l:var(--theme-space-l, 3rem); --blk-space-xl:var(--theme-space-xl, 5rem);
										  --blk-radius-s:var(--theme-radius-s, 4px); --blk-radius-m:var(--theme-radius-m, 10px); --blk-radius-l:var(--theme-radius-l, 20px);
										  --blk-content:min(var(--theme-content-w, 46rem), 100cqw); --blk-gap:var(--blk-space-m); --blk-rhythm:var(--blk-space-m);
										  container-type:inline-size; }	/* 100cqw = the page column (the viewport on the clean shell) */
/*-- vertical rhythm: siblings breathe; grid/column cells manage their own flow.
   Rhythm rides its OWN var: --blk-gap is also each block's cell/track gap,
   so a child that sets its own Gap inline (a grid, a band tightening its
   contents) shadows the inherited value — margin-top:var(--blk-gap) then
   read the child's INNER gap for the space ABOVE it, and a Gap:None
   wrapper could never make such a child sit flush. Container Gap sets
   BOTH: --blk-gap for the cells, --blk-rhythm for the flow between
   children; self-set cell gaps never leak into the rhythm. --*/
.blk-page .blk + .blk					{ margin-top:var(--blk-rhythm); }
/* No measure cap on text blocks — reading width is the CONTAINER's job
   (Width = Reading); a second route here left text stopping at 46rem
   inside full-width layouts (folder template, 2026-07-24). */
/* heading pairs stay deliberately tight — but they FOLLOW Gap Inside
   downward (min), else a container's rhythm control looks dead on the
   most common pairing (heading + text): flush means flush */
.blk-page .blk-heading + .blk			{ margin-top:min(var(--blk-rhythm), var(--blk-space-s)); }
/* Space After (theme, per heading level / named style): the heading OWNS
   its trailing edge — --blk-sa is its margin and the next block's rhythm
   stands down, so the theme's number is the whole distance whether the
   container flows (margins collapse) or aligns (they add). The Middle /
   Bottom trailing trim further down still wins a tie. Unset keeps the
   pairing rule above. */
.blk-page .blk:is(.blk-heading, .blk-text).-sa	{ margin-bottom:var(--blk-sa); }
.blk-page :is(.blk-heading, .blk-text).-sa + .blk	{ margin-top:0; }
/* An empty choice-bound block (product page: no code, no stock message)
   leaves a hidden .blk-slot so a later choice can swap its content in. The
   rhythm passes over the slot: the next block spaces from the one before it
   exactly as if the slot were absent. */
.blk-page .blk + .blk-slot + .blk		{ margin-top:var(--blk-rhythm); }
.blk-page .blk-heading + .blk-slot + .blk	{ margin-top:min(var(--blk-rhythm), var(--blk-space-s)); }
.blk-page :is(.blk-heading, .blk-text).-sa + .blk-slot + .blk	{ margin-top:0; }
.blk-page .blk-container:is(.-vmid, .-vbot) > :has(+ .blk-slot:last-child)
										{ margin-bottom:0; }
/* Middle/Bottom mean what they say: the stack's trailing margin (a lone
   hero h1's .8em base margin = 20px off-centre at 50px type) must not
   count toward vertical centring — the pane said Middle, so render
   middle. Top alignment keeps the margin: it reads as flow there. */
/* Placement: Overlay — the block leaves the flow and pins to a corner of
   its container (badge over a photo, ribbon, play button). The container
   that HOLDS an overlay becomes the positioning context via :has, so no
   prop is needed on the parent. Offset still nudges from the corner. */
.blk-page .blk-container:has(> .-ovl)	{ position:relative; }
.blk-page .-ovl						{ position:absolute; z-index:2; margin:0 !important;
	/* .blk-container is width:100% for the flow; an overlay sizes to its
	   own content instead (a badge, a ribbon), and a full-width overlay
	   band is said by giving the overlay a Width instead */
										  width:auto; }
.blk-page .-ovl-tl					{ top:0; left:0; }
.blk-page .-ovl-tr					{ top:0; right:0; }
.blk-page .-ovl-bl					{ bottom:0; left:0; }
.blk-page .-ovl-br					{ bottom:0; right:0; }
.blk-page .-ovl-c					{ top:50%; left:50%; translate:-50% -50%; }
/* A literal Gap Inside (None, or a custom length) is EXACT: the rhythm
   owns margin-top between blocks, so a child's OWN bottom margin (a
   heading's .8em) must not add to the gap the operator stated. Scoped to
   the container that asked. */
.blk-page .blk-container.-flush > .blk:not(.-sa)	{ margin-bottom:0; }	/* a themed Space After is deliberate, not a stray base margin */
.blk-page .blk-container.-vmid > :last-child,
.blk-page .blk-container.-vbot > :last-child
										{ margin-bottom:0; }
/* Vertical Alignment = Fill: the children grow to the box's height (an
   equal share each); a grid child then stretches its own row and slots */
.blk-page .blk-container.-vfill > .blk	{ flex:1 1 auto; min-height:0; }
/* a text block's last paragraph carries the theme's 1em bottom margin,
   which collapses through the (paddingless) block and shows as dead
   space at the foot of a padded container or slot — the card case. The
   rhythm margin above the next block supplies the flow spacing. */
.blk-page .blk-text > :last-child		{ margin-bottom:0; }
/* lists keep the paragraph's rhythm below them (the base sheet gives
   them a fraction of it) */
.blk-page .blk-text > ul,
.blk-page .blk-text > ol					{ margin-bottom:1em; }
/* an inline image in text (a bound legacy body holds camera-size photos)
   never outgrows its block */
.blk-page :is(.blk-text, .blk-html) img	{ max-width:100%; height:auto; }
/* iframes in text never outgrow the column. A player pasted at a fixed size
   keeps that width and shape (TextType::sizedFrames inlines both); one with
   no size goes full width at 16:9. A padding-ratio wrapper (inline
   padding-bottom or padding-top) already sizes its iframe, so the ratio
   stands down there. */
.blk-page :is(.blk-text, .blk-html) iframe	{ max-width:100%; }
.blk-page :is(.blk-text, .blk-html) iframe:is([src*="youtube.com/embed"], [src*="youtube-nocookie.com/embed"], [src*="player.vimeo.com"], [src*="dailymotion.com/embed"], [src*="facebook.com/plugins/video"], [src*="fast.wistia"], [src*="loom.com/embed"], [src*="streamable.com"], [src*="rumble.com/embed"])
										{ display:block; width:100%; height:auto; aspect-ratio:16 / 9; }
.blk-page :is(.blk-text, .blk-html) :is([style*="padding-bottom"], [style*="padding-top"]) > iframe
										{ height:100%; aspect-ratio:auto; }
/* a sized player is a block, so its paragraph's alignment reaches it through its margins */
.blk-page :is(.blk-text, .blk-html) :is([style*="text-align:center"], [style*="text-align: center"], [align="center"]) > iframe
										{ margin-inline:auto; }
.blk-page :is(.blk-text, .blk-html) :is([style*="text-align:right"], [style*="text-align: right"], [align="right"]) > iframe
										{ margin-left:auto; }
/* Lists (theme element): every token chains to the base sheet's literal,
   so an unset theme renders as it always has. An icon bullet is the
   .thm-ic idea — a mask painted in the marker colour — hung in the indent;
   unset, its mask is fully transparent and, being out of flow, it costs
   the line nothing. Two vars ride with the icon: -native stands the
   native bullet down, and -k (1) floors the indent at the icon's own
   width, so it never hangs outside the block. A sized plain bullet rides
   the same ::before (the theme's shape mask, -shape-k floor): a bigger
   ::marker glyph would grow the line and ride its baseline. */
.blk-page :is(.blk-text, .blk-html, .blk-sitemap) ul	{ list-style-type:var(--theme-list-icon-native, var(--theme-list-marker, square)); }
.blk-page :is(.blk-text, .blk-html, .blk-sitemap) :is(ul, ol) > li
										{ position:relative; margin-left:var(--theme-list-indent, 1em); font-family:var(--theme-list-font, inherit); line-height:var(--theme-list-line-height, inherit);
	& + li								{ margin-top:var(--theme-list-gap, 0); }
	&::marker							{ color:var(--theme-list-marker-color); }
}
.blk-page :is(.blk-text, .blk-html) ol > li + li	{ margin-top:var(--theme-list-num-gap, var(--theme-list-gap, 0)); }
/* Marker Size is the bullet's: a number that size would tower off the
   text's baseline. Numbers take their own type (the studio's Lists ›
   Numbers); each unset var inherits the item's. */
.blk-page :is(.blk-text, .blk-html) ol > li::marker
										{ color:var(--theme-list-num-color, var(--theme-list-marker-color)); font-family:var(--theme-list-num-font); font-size:var(--theme-list-num-size); font-weight:var(--theme-list-num-bold); font-style:var(--theme-list-num-italic); }
.blk-page :is(.blk-text, .blk-html, .blk-sitemap) ul > li
										{ margin-left:max(var(--theme-list-indent, 1em), (var(--theme-list-marker-size, 1em) + 0.4em) * max(var(--theme-list-icon-k, 0), var(--theme-list-shape-k, 0)));
	&::marker							{ font-size:var(--theme-list-marker-size); }
}
/* A numbered list's indent holds a one-digit number; "10." and "100."
   would hang past the block's edge. Once the list is that long, its
   indent widens to the number, and Indent still wins if set wider. */
.blk-page :is(.blk-text, .blk-html) ol:has(> li:nth-child(10)) > li
										{ margin-left:max(var(--theme-list-indent, 1em), 1.7em); }
.blk-page :is(.blk-text, .blk-html) ol:has(> li:nth-child(100)) > li
										{ margin-left:max(var(--theme-list-indent, 1em), 2.3em); }
.blk-page :is(.blk-text, .blk-html, .blk-sitemap) ul > li::before
										{ content:''; position:absolute; --ic:var(--theme-list-marker-size, 1em); left:calc(-1 * var(--ic) - 0.4em); top:calc((1lh - var(--ic)) / 2); width:var(--ic); height:var(--ic); background:var(--theme-list-marker-color, currentColor); -webkit-mask:var(--theme-list-icon, var(--theme-list-sized-mask, linear-gradient(#0000, #0000))) center/contain no-repeat; mask:var(--theme-list-icon, var(--theme-list-sized-mask, linear-gradient(#0000, #0000))) center/contain no-repeat; }
/* grid/column cells sit side by side — no sibling rhythm. Carousel and
   banner TRACK children too: slides ride the track (or stack, in fade/
   banner mode) and the sibling margin pushed every slide after the first
   down by --blk-gap — glaring once fade stacked them. .blk-page prefix +
   last position so it beats BOTH (0,3,0) rules above */
.blk-page .blk-grid > .blk,
.blk-page .blk-columns > .blk,
.blk-page .blk-gallery-grid > .blk,
.blk-page .blk-car-track > .blk,
.blk-page .blk-banner-track > .blk			{ margin-top:0; }

/*---------------- Blockbuilder block primitives ----------------*/
/* Background focal points: inline styles set the --blk-bgpos vars; the
   media query switches to the mobile point — which inline
   background-position could never do. Harmless on blocks without a
   background image. */
.blk-page .blk							{ background-position:var(--blk-bgpos,50% 50%); }
@media (max-width:768px) {
	.blk-page .blk						{ background-position:var(--blk-bgpos-m,var(--blk-bgpos,50% 50%)); }
}
/* Parallax on touch: iOS sizes a fixed-attachment cover against the
   viewport, not the band. Touch screens take the plain cover background;
   !important because the attachment is inline. */
@media (hover:none), (pointer:coarse) {
	.blk-page .blk[style*="background-attachment:fixed"]	{ background-attachment:scroll !important; }
}

/* Show On (device visibility): the renderer stamps data-blk-show on the
   live render only — the editor canvas ghosts instead (block_editor.css).
   display:none removes the box but the node is still a .blk sibling, so
   .blk + .blk rhythm still lands on the next band (a desktop-only header
   above a mobile-only one left an empty slice on the phone; reverse the
   order and there is no predecessor). Zero the gap after a hidden Show On.
   Columns keep their track template until they STACK (640cqw phones /
   900cqw tablets) — Show On hides at 768px VIEWPORT, so a desktop-only
   sidebar slot (the 270px nav column) was display:none while its track
   still reserved space. Collapse the row to 1fr whenever a direct-child
   slot is the one being hidden. Put Show On on the SLOT, not an inner
   block, or the track cannot see it. */
@media (max-width:768px) {
	.blk-page [data-blk-show='desk']	{ display:none !important; }
	.blk-page [data-blk-show='desk'] + .blk,
	.blk-page [data-blk-show='desk'] + .blk-slot + .blk
										{ margin-top:0; }
	.blk-page .blk-columns:has(> [data-blk-show='desk'])	{ grid-template-columns:1fr; }
}
@media (min-width:769px) {
	html:not(.nav-collapsed) .blk-page [data-blk-show='mob'],
	:not(#header) > .blk-page [data-blk-show='mob']
										{ display:none !important; }
	html:not(.nav-collapsed) .blk-page [data-blk-show='mob'] + .blk,
	:not(#header) > .blk-page [data-blk-show='mob'] + .blk,
	:not(#header) > .blk-page [data-blk-show='mob'] + .blk-slot + .blk
										{ margin-top:0; }
	html:not(.nav-collapsed) .blk-page .blk-columns:has(> [data-blk-show='mob']),
	:not(#header) > .blk-page .blk-columns:has(> [data-blk-show='mob'])
										{ grid-template-columns:1fr; }
}
/* The collapsed header form: when the main nav no longer fits on one row
   (nav_fit.js sets .nav-collapsed on <html>, from 769px up), the HEADER
   tree takes its phone Show On — Desktop Only hides, Mobile Only shows.
   Page content and the footer keep the width rule above. A measurement
   pass (.nav-fit-measure) shows the desktop bands again for its length
   without hiding what is on screen, so nothing visible restarts. */
html.nav-collapsed:not(.nav-fit-measure) #header > .blk-page [data-blk-show='desk']
										{ display:none !important; }
html.nav-collapsed:not(.nav-fit-measure) #header > .blk-page [data-blk-show='desk'] + .blk
										{ margin-top:0; }
html.nav-collapsed:not(.nav-fit-measure) #header > .blk-page .blk-columns:has(> [data-blk-show='desk'])
										{ grid-template-columns:1fr; }

/* Pin the box model — tenant stylesheets may or may not carry a global
   border-box reset, and block behaviour must not vary by site. Blocks are
   border-box, width words included: padding stays inside the box, so a
   padded band never pokes past its column or the glass (the honest-box
   ruling — see the Page/Wide/Reading rule below). */
.blk-page .blk							{ box-sizing:border-box; }
/* Responsive columns: --blk-cols is the CAP, --blk-colmin (when set) is
   the drop point. The minmax track floor is EITHER the exact Nth share
   (colmin unset/0 → exactly N columns, the original behaviour) OR the
   minimum width — auto-fill then fits as many as space allows, never
   more than N. The -0.5px guards float rounding at the exact-N width. */
.blk-grid								{ display:grid; gap:var(--blk-gap,1rem);
										  grid-template-columns:repeat(auto-fill, minmax(max(var(--blk-colmin,0px), calc((100% - (var(--blk-cols,2) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,2) - 0.5px)), 1fr)); }
/* Fit Content: one row, each track only as wide as its own content —
   a header cluster, a button pair, a payment-icon strip. The auto-fill
   recipe above cannot express this (its track floor is a percentage
   calc), hence a class rather than another --blk-cols value. Narrow
   containers fall back to wrapping rather than overflowing. */
.blk-grid.-fit							{ grid-template-columns:none; grid-auto-flow:column; grid-auto-columns:minmax(min-content, max-content); justify-content:start; align-items:center; }
/* a sized image's min(width, 100%) cap drops out of shrink-to-fit sizing (a Fit track, an overlay), so the figure states the width itself */
.blk-grid.-fit > .blk-image[style*="--blk-imgmax"],
.blk-page :is(.-ovl > .blk-image, .blk-image.-ovl)[style*="--blk-imgmax"]	{ max-width:var(--blk-imgmax); }
/* The header is exempt: a phone header is always that narrow, and its
   clusters (flag + search, menu + basket) are small by nature. */
@container (max-width:520px) {
	.blk-grid.-fit:not(#header .blk-grid)	{ grid-auto-flow:row; grid-auto-columns:auto; }
}
.blk-columns							{ display:grid; grid-template-columns:var(--blk-cols-template,1fr 1fr); gap:var(--blk-gap,1rem);
	/* tenant-proof (same defence as the img rule above): the legacy
	   Foundation grid in responsive.css carries
	   `[class*=column]+[class*=column]:last-child{float:right}`, and
	   `blk-columns` matches that attribute selector — so the SECOND and
	   last Columns block in any container floated right and shrink-wrapped
	   to its content (Holy Trinity's composed event card, 2026-08-28). */
	float:none; }
/* …and it must WIN: the Foundation selector is (0,3,0) and ours is not,
   so this is !important for the same reason the img rule above is —
   legacy sheets tie or beat block selectors on load order. */
.blk-page .blk-columns					{ float:none !important; }
/* a track's floor is zero, not its content's min-content: a wide table or
   a thumbs strip would otherwise grow its fr track past the row */
.blk-columns > *						{ min-width:0; }
/* Columns stacking — container queries against .blk-page (the page
   column, not the viewport): a narrow band stacks even on wide screens.
   Default stacks on phone widths; -stack-tablet earlier; -stack-never
   opts out entirely. */
@container (max-width:640px) {
	.blk-columns:not(.-stack-never)		{ grid-template-columns:1fr; }
	/* Stacked Order: Right First — an alternating image|text / text|image
	   page stays image,text,image,text once stacked (designers' ask).
	   Order the SECOND track first; two-column rows only need the flip
	   on one child, and deeper tracks keep source order after it. */
	.blk-columns.-stack-swap:not(.-stack-never) > .blk:first-child	{ order:1; }
}
@container (max-width:900px) {
	.blk-columns.-stack-tablet			{ grid-template-columns:1fr; }
	.blk-columns.-stack-tablet.-stack-swap > .blk:first-child		{ order:1; }
}
/* Column Rule: a line drawn in the GAP between tracks, on each item's
   leading edge (::before = left, ::after = top), so tracks never move.
   Weight / style / colour chain to the theme Divider tokens; Rule Length
   is the line's run along the gap, centred on the item. Columns is
   one row (every item but the first); Grid knows its count (-rnN), so
   nth-child exempts the first column and the first row. */
.blk-columns.-rule, .blk-grid.-rule	{ --blk-rule:var(--blk-rule-w, var(--theme-divider-weight, 1px)) var(--blk-rule-style, solid) var(--blk-rule-c, var(--theme-divider-color, #ccc));
	/* the pseudo lives on the ITEM, whose own --blk-gap (a slot's stacked
	   spacing) would otherwise be the one read — pin the track gap here */
	--blk-rule-gap:var(--blk-gap, 1rem);
	> *								{ position:relative; }
	> *::before, > *::after				{ content:""; position:absolute; pointer-events:none; display:none; }
	> *::before							{ top:50%; height:var(--blk-rule-len, 100%); left:calc(var(--blk-rule-gap) / -2); transform:translate(-50%, -50%); border-left:var(--blk-rule); }
	> *::after							{ left:50%; width:var(--blk-rule-len, 100%); top:calc(var(--blk-rule-gap) / -2); transform:translate(-50%, -50%); border-top:var(--blk-rule); }
}
/* Content length: the line spans the item's content box — inset by its
   own padding shorthand (--blk-pad0, emitted beside padding). Reset on
   the item so an ancestor's value never inherits in. */
.blk-columns.-rule-fit, .blk-grid.-rule-fit	{
	> *								{ --blk-pad0:0; }
	> *::before							{ inset:var(--blk-pad0); left:calc(var(--blk-rule-gap) / -2); right:auto; height:auto; transform:translateX(-50%); }
	> *::after							{ inset:var(--blk-pad0); top:calc(var(--blk-rule-gap) / -2); bottom:auto; width:auto; transform:translateY(-50%); }
}
.blk-columns.-rule > * + *::before	{ display:block; }
.blk-grid.-rule:not(.-rule-rows) > *::before	{ display:block; }
.blk-grid.-rule-rows > *::after,
.blk-grid.-rule-both > *::after		{ display:block; }
.blk-grid.-rn1 > *::before,
.blk-grid.-rn2 > :nth-child(2n+1)::before,
.blk-grid.-rn3 > :nth-child(3n+1)::before,
.blk-grid.-rn4 > :nth-child(4n+1)::before,
.blk-grid.-rn5 > :nth-child(5n+1)::before,
.blk-grid.-rn6 > :nth-child(6n+1)::before	{ display:none; }
.blk-grid.-rn1 > :nth-child(-n+1)::after,
.blk-grid.-rn2 > :nth-child(-n+2)::after,
.blk-grid.-rn3 > :nth-child(-n+3)::after,
.blk-grid.-rn4 > :nth-child(-n+4)::after,
.blk-grid.-rn5 > :nth-child(-n+5)::after,
.blk-grid.-rn6 > :nth-child(-n+6)::after	{ display:none; }
/* stacked Columns: the separation is the point, so the rule turns
   horizontal (between the stacked items); Swapped puts the DOM-first
   item second, so the rule moves onto it */
@container (max-width:640px) {
	.blk-columns.-rule:not(.-stack-never) > * + *::before	{ display:none; }
	.blk-columns.-rule:not(.-stack-never) > * + *::after	{ display:block; }
	.blk-columns.-rule.-stack-swap:not(.-stack-never) > :nth-child(2)::after	{ display:none; }
	.blk-columns.-rule.-stack-swap:not(.-stack-never) > :first-child::after	{ display:block; }
}
@container (max-width:900px) {
	.blk-columns.-rule.-stack-tablet > * + *::before	{ display:none; }
	.blk-columns.-rule.-stack-tablet > * + *::after		{ display:block; }
	.blk-columns.-rule.-stack-tablet.-stack-swap > :nth-child(2)::after	{ display:none; }
	.blk-columns.-rule.-stack-tablet.-stack-swap > :first-child::after	{ display:block; }
}
.blk-container							{ margin-inline:auto; width:100%; }
/* inside a parent that sets Horizontal Alignment (flex + align-items),
   the child container must not self-centre: flex auto margins absorb
   free space BEFORE alignment gets a say, so a Reading-width container
   ignored the parent's Left/Right. Alignment-parent decides. */
.blk-page .blk[style*="align-items"] > .blk-container	{ margin-inline:0; }
/* Full Bleed: break out of the page column to the viewport edge (the
   full-width-gallery idea as a container option). 100vw includes the
   scrollbar — pair with overflow-x:hidden on the page shell if a sliver
   of horizontal scroll appears. */
/* Full (Bleed) RETIRED 2026-08-29 (operator: "clean clean clean"): it
   resolved to width:100% in every context — at the top level, where
   .blk-page is already viewport-wide on the clean shell, AND nested inside
   a Page column, where it filled rather than broke out. That made it a
   second way to say Section. The 100vw + negative-margin breakout it was
   invented for was removed in v14 as damaging (Denmead phone footer,
   2026-08-17). A strip that paints to the glass is a Section band with a
   Page inner. */
/* Page / Wide / Reading: HONEST BOXES (operator ruling 2026-08-18 —
   supersedes both the viewport-shrink model and the padding-outside-
   the-column model; both fought the box). The width word IS the box:
   background (colour or image) fills it edge to edge, padding insets
   the content, border-box keeps the padding INSIDE the column so a
   padded Page band on a phone is glass-wide, never overflowing. The
   theme's Side Gutter (--theme-page-pad) is only the DEFAULT
   padding-inline, and on PAGE ALONE (operator, after use 2026-08-19:
   Page is the width that meets the glass; Wide/Reading usually nest
   inside a Page band, where a second default compounded the inset) —
   any explicit Padding on the container is an inline shorthand and
   overrides it wholesale (padding:0 = truly none; 40px 0 MEANS zero
   sides). Full and Section never take the default: Full is deliberate
   glass paint, Section fills its parent and rides the parent's inset.
   A to-the-glass colour strip is still Full wrapping Page. */
.blk-page .blk-container.-page,
.blk-page .blk-container.-reading		{ box-sizing:border-box; }
.blk-page .blk-container.-page			{ max-width:min(var(--theme-page-width, 100cqw), 100cqw); margin-inline:auto; padding-inline:var(--theme-page-pad, 0px); }
/* Background Video (Container): a muted looping layer under the children.
   z-index:0 makes the container its own stacking context, so the -1 video
   paints above the element's OWN background (colour/image = the poster
   while frames load, and what reduced-motion visitors keep) and below
   every child. Same focal vars as background images. */
.blk-container.-hasvid					{ position:relative; z-index:0;
	> .blk-bgvid						{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:var(--blk-bgpos,50% 50%); z-index:-1; pointer-events:none; }
}
@media (max-width:768px) {
	.blk-container.-hasvid > .blk-bgvid	{ object-position:var(--blk-bgpos-m,var(--blk-bgpos,50% 50%)); }
}
/* Extend Behind The Page Header (Trinity pattern, block half): pull the
   band up by the header's height so its media runs to the viewport top.
   The SHELL completes it — default.js measures #header into
   --blk-header-h on :root and site_shell.css stacks the header above
   the slid-under band; a translucent header background lets the media
   show through. Pages with no such band see no change (calc resolves
   to 0). Frontend-only class: the editor canvas has no site header to
   slide under. Scoped to #main-content: the compiled header/footer
   fields are .blk-page trees too, and the flag on a band INSIDE the
   header made it pull ITSELF up by its own height — off-screen, and a
   feedback loop while its height was observed (Ilkley, 2026-08-20).
   The pull engages only when the band actually LEADS with media — a
   direct-child gallery (an empty bound banner renders nothing, so on
   bannerless fleet pages the flag quietly stands down instead of
   tucking the h1 under the header), the band's own background image,
   or a video hero (-hasvid on the band itself or its direct child —
   the video-hero-is-container pattern, Bellevue home), a direct-child
   carousel or embed. Desktop Only (-uh-desk) pulls at the Show On
   desktop width; phones keep the band below the header. */
#main-content .blk-container.-under-header:not(.-uh-desk):is(:has(> .blk-gallery-grid, > .blk-carousel, > .blk-embed, > .-hasvid), .-hasvid, [style*="background-image"])
										{ margin-top:calc(0px - var(--blk-header-h, 0px)); }
@media (min-width:769px) {
	#main-content .blk-container.-under-header.-uh-desk:is(:has(> .blk-gallery-grid, > .blk-carousel, > .blk-embed, > .-hasvid), .-hasvid, [style*="background-image"])
										{ margin-top:calc(0px - var(--blk-header-h, 0px)); }
}

/* Pin While Scrolling (Interactions V2): the vnav pattern — a container
   in a page-body column pins under the sticky header while its row's
   neighbours scroll, and releases when its grid area runs out (native
   sticky containment — no JS). --blk-stick-h is the STICKY header's
   height (default.js; 0 when the header scrolls away, so the pin goes
   to the glass top). On a direct columns child the slot must hug its
   content or its grid area IS the full row and sticky has nowhere to
   move. Live-only class: the editor canvas never traps blocks. */
#main-content .blk-container.-pin-scroll	{ position:sticky; top:calc(var(--blk-stick-h, 0px) + var(--blk-space-s, 12px)); }
.blk-columns > .-pin-scroll				{ align-self:start; }

/* When Pinned (Container, interactions family): the band's inline style
   re-emits background/padding through --blk-bg/--blk-pad vars (fallback
   chain to the --blk-*0 originals), and the pinned header redefines
   them. Solid strips the alpha in CSS — relative color reads the
   ORIGINAL value (a swatch var included), so a palette change keeps
   both states honest; browsers without relative color simply keep the
   translucent band. Compact swaps in the pre-computed 40%-vertical
   shorthand. Only #header.is-stuck arms any of it: no sticky header,
   no editor canvas, no page-body effect. */
/* the solid twin is a pre-computed LITERAL (--blk-bg-stuck from
   ContainerType) — never a relative color: browsers refuse to
   interpolate a transition into rgb(from var(...) ...) and the fade
   wedged at the start value forever (Chrome + Firefox, 2026-08-20) */
#header.is-stuck [data-blk-stuck~="solid"]		{ --blk-bg:var(--blk-bg-stuck); }
#header.is-stuck [data-blk-stuck~="compact"]	{ --blk-pad:var(--blk-pad-stuck); }
/* the classic shrinking header shrinks its LOGO too: sized images in a
   compact band scale to 75% of their own width (ImageType emits the
   --blk-imgw0 pair; unsized images have no pair and are untouched) */
#header.is-stuck [data-blk-stuck~="compact"] .blk-image img
										{ --blk-imgw:calc(var(--blk-imgw0, 100%) * 0.75); }
#header [data-blk-stuck]				{ transition:background-color 0.25s ease, padding 0.25s ease; }
#header [data-blk-stuck] .blk-image img	{ transition:max-width 0.25s ease; }
@media (prefers-reduced-motion: reduce) {
	#header [data-blk-stuck],
	#header [data-blk-stuck] .blk-image img
										{ transition:none; }
}
/* Scroll Cue: the hero "more below" chevron — white over photography with
   a gentle bob (stilled for reduced-motion visitors); blocks.js scrolls
   to whatever follows the container (delegated click) */
.blk-container.-cue						{ position:relative; }
.blk-scroll-cue							{ position:absolute; left:50%; bottom:0.9em; z-index:1; width:2.6em; height:2.6em; margin-left:-1.3em; padding:0; border:0; background:transparent; cursor:pointer; color:#fff;
	svg									{ width:100%; height:100%; filter:drop-shadow(0 1px 3px rgba(0,0,0,0.5)); }
	animation:blk-cue-bob 2.2s ease-in-out infinite;
}
@keyframes blk-cue-bob					{ 0%, 100% { transform:translateY(0); } 50% { transform:translateY(7px); } }
@media (prefers-reduced-motion: reduce) {
	.blk-scroll-cue						{ animation:none; }
}
.blk-heading							{ scroll-margin-top:2rem; }
.blk-image								{ margin:0;
	img									{ display:block; max-width:100%; height:auto; }
	/* Media block, video src: the player sizes to the file's own frame once
	   metadata lands, capped by the figure — same rhythm as an image */
	video								{ display:block; max-width:100%; height:auto; }
	figcaption							{ font-size:0.9em; color:#666; padding-top:0.3em; }
	/* Corners round the figure's box; with a caption underneath, that box
	   ends below the image, so the image wears the same radius itself */
	&:has(> figcaption) > img,
	&:has(> figcaption) > video			{ border-radius:inherit; }
	/* a Max Width image is narrower than its figure, so Corners must
	   round the image itself */
	&[style*="--blk-imgmax"] img,
	&[style*="--blk-imgmax"] video		{ border-radius:inherit; }
}
/* Arc (Media block): the wrapper is the media's exact size; the media clips
   to a pill on a box grown by the overshoot top and bottom, and the
   wrapper's pseudo draws the SAME pill as a bordered box, so a Border on
   the block becomes the line along the arc. Only the pseudo's arc-side
   border paints; its straight edges sit outside the box. */
/* No clip-path: Safari rejects a negative inset(), which the overshoot
   needs. The PILL is taller than the wrapper by the overshoot (d, a
   fraction of the wrapper's height) and rounded; the wrapper's overflow
   cuts its straight edges. Inside it the picture is painted as a cover
   background at the offset that lines it up with the wrapper — top
   d/(1+2d) of the pill, height 1/(1+2d) — so the in-flow <img> only
   holds the size (and the alt text). The ring is a pseudo on the pill's
   padding box, so the border never shifts the picture. Video keeps the
   media element itself inside the pill. */
.blk-arc								{ position:relative; display:block; width:fit-content; max-width:100%; overflow:clip;
	> img								{ opacity:0; }
}
.blk-arc-pill							{ position:absolute; left:0; right:0; top:calc(-100% * var(--blk-arc-d)); bottom:calc(-100% * var(--blk-arc-d)); border-radius:var(--blk-arc-round); overflow:clip; pointer-events:none;
	&::after							{ content:""; position:absolute; inset:0; border-radius:inherit; border:var(--blk-arc-bw,0) solid var(--blk-arc-bc,transparent); }
}
.blk-arc.-left .blk-arc-pill::after		{ border-right-width:0; }
.blk-arc.-right .blk-arc-pill::after	{ border-left-width:0; }
.blk-arc-pic							{ position:absolute; left:0; right:0; top:calc(100% * var(--blk-arc-d) / (1 + 2 * var(--blk-arc-d))); height:calc(100% / (1 + 2 * var(--blk-arc-d))); background:var(--blk-arc-src) var(--blk-bgpos, 50% 50%) / cover no-repeat; }
/* a video cannot be a background: the player itself sits in the pill at
   the same offset (the placeholder tile in edit mode likewise) */
.blk-arc.-video							{ > video, > .blk-video-ph { opacity:0; } }
.blk-arc.-video .blk-arc-pill			{ pointer-events:auto;
	> video, > .blk-video-ph			{ position:absolute; left:0; right:0; top:calc(100% * var(--blk-arc-d) / (1 + 2 * var(--blk-arc-d))); height:calc(100% / (1 + 2 * var(--blk-arc-d))); width:100%; object-fit:cover; }
}
/* Mixed media: a video tile IS an image tile — same figure, same chrome,
   same sort/selection — presenting its poster with a play badge over it.
   The badge stays clickable (blocks.js uses it as a lightbox hit target,
   the only one a poster-less tile has), and the dark plate stands in when
   the video has no poster at all. */
.blk-image.-video						{ position:relative;
	/* poster-tile form only (gallery tiles, and the Media block in edit mode
	   where a live player would swallow the selection click) — a figure that
	   holds a real player letterboxes itself and must not get a plate */
	&:not(:has(video))					{ background:#1a1a1a; }
	&:not(:has(img)):not(:has(video))	{ min-height:8rem; }
	.blk-video-play						{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:52px; height:52px; border-radius:50%; background:rgba(0,0,0,0.6); color:#fff; display:flex; align-items:center; justify-content:center;
		svg								{ width:28px; height:28px; margin-left:3px; }
	}
}
/* tenant-proof: sites commonly declare img{width:100%} (Warwick does, at
   several specificities, loading after this file), and inside a
   fit-content context (container Horizontal Alignment) 100% of a
   shrink-to-fit parent is cyclic → the image collapses to 0 and
   vanishes. Blocks own their image sizing — !important because tenant
   selectors can tie and win on load order; the gallery tile rule below
   re-asserts width:100% the same way for uniform tiles. */
.blk-page .blk-image img:not(figcaption img)	{ width:auto !important; }
/* …and SVGs exported without width/height have NO intrinsic width, so a
   fit-content figure still collapses them to 0 (rasters survive on their
   natural size). Under content alignment the image FIGURE keeps full
   width instead of shrink-wrapping, and the img aligns itself with auto
   margins — same visual result, no intrinsic-size dependence. */
/* Columns excluded: align-items there is Vertical Alignment, and a
   stretched figure grows to the row height */
.blk-page .blk[style*="align-items"]:not(.blk-columns) > .blk-image	{ align-self:stretch; }
/* Track-based blocks have no content width to shrink to — auto-fill and
   the 100% in the track calc both need a definite inline size — so they
   keep the full row under content alignment; so do embeds and players,
   whose frame would fall back to the browser's 300px. A Fit grid's tracks
   and a Hug list's cards are their content, so those shrink and take the
   parent's alignment like any block. */
.blk-page .blk[style*="align-items"] > .blk-grid:not(.-fit),
.blk-page .blk[style*="align-items"] > .blk-columns,
.blk-page .blk[style*="align-items"] > .blk-gallery-grid,
.blk-page .blk[style*="align-items"] > :is(.blk-folder-list, .blk-related-list):not(.-hug),
.blk-page .blk[style*="align-items"] > :is(.blk-embed, .blk-video, .blk-cs-events)	{ align-self:stretch; }
/* horizontal centring of an image keys on the CONTENT alignment the
   operator set, which in a stacked container is align-items. In a ROW
   container align-items is the VERTICAL axis, so these must not fire
   there — valign:center was sliding logos to the middle of their
   column (13.4) */
.blk-page .blk[style*="flex-direction:column"][style*="align-items:center"] > .blk-image img	{ margin-inline:auto; }
.blk-page .blk[style*="flex-direction:column"][style*="align-items:flex-end"] > .blk-image img	{ margin-left:auto; }
/* a card's image figure is capped at its Max Width (the figure is the box), so the figure itself takes the alignment */
.blk-page .blk-card .blk[style*="flex-direction:column"][style*="align-items:center"] > .blk-image[style*="--blk-imgmax"]	{ width:100%; margin-inline:auto; }
.blk-page .blk-card .blk[style*="flex-direction:column"][style*="align-items:flex-end"] > .blk-image[style*="--blk-imgmax"]	{ width:100%; margin-left:auto; margin-right:0; }
/* Divider: wrapper block (padding sits AROUND the line) + inner <hr>
   carrying line/weight/colour/width inline from prepare(). */
/* full width even in shrink-to-fit contexts (halign:center columns): an
   hr has no intrinsic width, so Full/Half rendered ZERO wide there and
   only the explicit Short survived (Denmead home, 2026-08-17) */
.blk-page .blk-divider					{ width:100%; }
.blk-divider hr							{ margin:0; height:0; }
/* CONTENT dividers (the inline editor's hr): the theme's Divider element
   is the default look; the Divider BLOCK's inline styles override
   per-instance. Same token chain both ways — studio default, block
   overrides (operator ruling 2026-08-17, the Table Style pattern). */
.blk-page .blk-text hr,
.blk-page .blk-html hr					{ border:0; height:0; border-top:var(--theme-divider-weight,1px) var(--theme-divider-style,solid) var(--theme-divider-color,#ccc); margin:var(--theme-divider-space,16px) 0; }

/* Inline content icons: <span class="thm-ic" style="--tic:var(--theme-ic-iN)">
   — an atom the inline editors insert from the theme Icons palette
   (icon-before-text rows: the FontAwesome-prefixed contact links no
   vocabulary could say). Painted through a mask, so the icon takes the
   surrounding text size and, unless the theme says otherwise, its colour:
   a named style's Icon Colour (--tic-color, set on the style's rule and
   inherited) wins, then the Body Text Icon Colour, then the text. A
   palette swap rethemes every use already in content. Monochrome by
   design — a multi-colour glyph belongs in an Image block. */
.blk-page .thm-ic						{ display:inline-block; width:1em; height:1em; vertical-align:-0.125em; background:var(--tic-color, var(--theme-icon-color, currentColor)); -webkit-mask:var(--tic) center/contain no-repeat; mask:var(--tic) center/contain no-repeat; margin-right:0.35em; }
/* The hanging icon gutter is an OPT-IN para-style recipe (icon_hang →
   the theme emits it under .thm-ps-pN), never inferred from content
   shape — an implicit :has rule bent Capel's CENTRED footer line
   (operator 2026-08-26). The fixed atom margin above is what makes the
   opted-in gutter exact: atomTidy strips the stored nbsp at frontend
   render, so icon 1em + the style's 0.55em = a deterministic 1.55em. */
/* An icon row: a list item whose leading icon is its marker
   (site_convert fa_icons), so it takes no bullet and no indent. */
.blk-page :is(.blk-text, .blk-html, .blk-cap-html) li.thm-ic-row	{ list-style:none; margin-left:0;
	&::before							{ content:none; }
}

/*-- body grids (site_convert body_grids): a page body is HTML in one Text
   block, so a legacy grid stays in it as body classes. A column takes its
   twelfths per breakpoint — -sN from phones up, -mN from 769px, -lN from
   1025px, each falling back to the size below — and -c centres a narrow
   one. A -flex row sets its items on one line, centred on each other. --*/
.blk-page :is(.blk-text, .blk-html, .blk-cap-html) .thm-row	{ display:flex; flex-wrap:wrap; margin-inline:-0.9375em;
	&.-flex								{ align-items:center; margin-inline:0;
		> :not(.thm-col)				{ flex:0 1 auto; min-width:0; }
		/* button sets side by side: the wrapper's own 30px, between them */
		&:has(> .thm-btn-wrapper)		{ column-gap:30px; }
	}
}
.blk-page :is(.blk-text, .blk-html, .blk-cap-html) .thm-col	{ --cs:initial; --cm:initial; --cl:initial; box-sizing:border-box; min-width:0; padding-inline:0.9375em; width:calc(100% * var(--cs, 12) / 12);	/* initial: a nested column never inherits its parent's twelfths */
	&.-c								{ margin-inline:auto; }
	&.-s1 { --cs:1; } &.-s2 { --cs:2; } &.-s3 { --cs:3; } &.-s4 { --cs:4; } &.-s5 { --cs:5; } &.-s6 { --cs:6; }
	&.-s7 { --cs:7; } &.-s8 { --cs:8; } &.-s9 { --cs:9; } &.-s10 { --cs:10; } &.-s11 { --cs:11; } &.-s12 { --cs:12; }
	&.-m1 { --cm:1; } &.-m2 { --cm:2; } &.-m3 { --cm:3; } &.-m4 { --cm:4; } &.-m5 { --cm:5; } &.-m6 { --cm:6; }
	&.-m7 { --cm:7; } &.-m8 { --cm:8; } &.-m9 { --cm:9; } &.-m10 { --cm:10; } &.-m11 { --cm:11; } &.-m12 { --cm:12; }
	&.-l1 { --cl:1; } &.-l2 { --cl:2; } &.-l3 { --cl:3; } &.-l4 { --cl:4; } &.-l5 { --cl:5; } &.-l6 { --cl:6; }
	&.-l7 { --cl:7; } &.-l8 { --cl:8; } &.-l9 { --cl:9; } &.-l10 { --cl:10; } &.-l11 { --cl:11; } &.-l12 { --cl:12; }
	@media (min-width:769px)			{ width:calc(100% * var(--cm, var(--cs, 12)) / 12); }
	@media (min-width:1025px)			{ width:calc(100% * var(--cl, var(--cm, var(--cs, 12))) / 12); }
}

/* Video: responsive embed — aspect-ratio inline from prepare() */
.blk-video								{ position:relative; overflow:hidden;
	iframe								{ display:block; width:100%; height:100%; border:0; }
}

/* Image Shape: cover-crop to --blk-shape, filling the column so a row of
   shaped images lines up; the focal point steers the crop through the
   --blk-bgpos the banner reads. Gallery tiles keep the gallery's rule. */
.blk-page .blk-image.-shaped > img,
.blk-page .blk-image.-shaped > .blk-arc > img	{ width:100% !important; aspect-ratio:var(--blk-shape); object-fit:cover; object-position:var(--blk-bgpos, 50% 50%); }	/* !important: the tenant-proof width:auto above */
.blk-page .blk-image.-shaped > .blk-arc	{ width:100%; }	/* a shaped image fills the column; its arc wrapper must too */
/* Image Shape = Fill: the picture takes the box it sits in (a stretched
   slot, or a Fill container's share), cover-cropped; the arc wrapper
   follows the figure so the arc runs the full height */
.blk-page .blk-image.-fill				{ height:100%; flex:1 1 auto; min-height:0; }
.blk-page .blk-image.-fill > img,
.blk-page .blk-image.-fill > .blk-arc > img	{ width:100% !important; height:100%; object-fit:cover; object-position:var(--blk-bgpos, 50% 50%); }
.blk-page .blk-image.-fill > .blk-arc	{ width:100%; height:100%; }
/* Max Height: the picture narrows to stand no taller than the cap. A
   shaped picture keeps its column width and crops (or contains) to it. */
.blk-page .blk-image.-maxh > img,
.blk-page .blk-image.-maxh > .blk-arc > img	{ max-height:var(--blk-img-maxh); }
.blk-page .blk-image.-maxh:not(.-shaped, .-fill) > img	{ width:auto !important; max-width:100%; height:auto; }
/* Fit Contain: the whole picture inside the shaped (or filled) box */
.blk-page .blk-image.-contain > img,
.blk-page .blk-image.-contain > .blk-arc > img	{ object-fit:contain; }
/* Image Mask: the picture cover-crops to the SVG's proportions and shows
   through its filled area; the focal point steers the crop as for Shape */
.blk-page .blk-image.-masked > img		{ width:100% !important; aspect-ratio:var(--blk-mask-ar); object-fit:cover; object-position:var(--blk-bgpos, 50% 50%);
										  -webkit-mask-image:var(--blk-mask); -webkit-mask-size:100% 100%; -webkit-mask-repeat:no-repeat; mask-image:var(--blk-mask); mask-size:100% 100%; mask-repeat:no-repeat; }

/* Gallery: grid of Image children; --blk-thumb (aspect + cover-crop) makes
   uniform tiles; lightbox chrome lives in blocks.js */
.blk-gallery-grid							{ display:grid; gap:var(--blk-gap,1rem);
	grid-template-columns:repeat(auto-fill, minmax(max(var(--blk-colmin,0px), calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,3) - 0.5px)), 1fr));
	.blk-image img:not(figcaption img)	{ width:100% !important; aspect-ratio:var(--blk-thumb, auto); object-fit:cover; }
	&[data-gal-lightbox] .blk-image img,
	&[data-gal-lightbox] .blk-image .blk-video-play	{ cursor:zoom-in; }
	/* tile chrome — the gallery's Image Padding/Border/Corners settings,
	   uniform across bound tiles and static Image children. !important:
	   a static child's own appearance renders as INLINE style, which
	   would win per property and break the uniform-tiles ruling — the
	   panel no longer offers per-image appearance in galleries, and this
	   keeps legacy stored values from competing either (2026-07-28) */
	.blk-image							{ padding:var(--blk-tile-pad,0) !important; border:var(--blk-tile-border,none) !important; border-radius:var(--blk-tile-radius,0) !important; box-shadow:var(--blk-tile-shadow,none) !important; overflow:hidden;
		/* a row stretches every tile to its tallest, so an uncaptioned
		   tile's box ends below its image: the image wears the corners */
		> img, > video					{ border-radius:inherit; }
		> figcaption					{ padding-inline:calc(var(--blk-tile-radius, 0px) * 0.3); }
	}
}
/* Thumbnail gallery: main image + strip (bottom, or left like a product
   page). Source figures stay hidden — main is a clone, so caption and
   tile-chrome styling apply to it automatically. */
.blk-gallery-grid.-thumbs				{ display:block;
	.blk-tg-src							{ display:none; }
	.blk-tg-main						{ position:relative;
		.blk-image img					{ width:100% !important; aspect-ratio:auto; object-fit:contain; max-height:70vh; }
	}
	.blk-tg-strip						{ display:flex; justify-content:var(--blk-tg-align, flex-start); gap:8px; margin-top:10px; overflow-x:auto; scrollbar-width:thin; }
	.blk-tg-thumb						{ flex:0 0 auto; width:var(--blk-tg-thumb-w, 64px); height:auto; aspect-ratio:var(--blk-tg-thumb-ar, 1); padding:0; border:2px solid transparent; border-radius:6px; background:none; cursor:pointer; overflow:hidden;
		img								{ width:100%; height:100%; object-fit:cover; display:block; }
		&:hover							{ border-color:#9fb3cd; }
		&.-on							{ border-color:#2b6cb0; }
	}
}
/* Stage Height: every picture whole on a stage of one height */
.blk-gallery-grid.-thumbs[style*="--blk-tg-stage-h"] .blk-tg-main .blk-image img	{ height:var(--blk-tg-stage-h); max-height:none; object-fit:contain; }
.blk-gallery-grid.-thumbs.-thumbs-left	{ display:grid; grid-template-columns:calc(var(--blk-tg-thumb-w, 64px) + 12px) minmax(0,1fr); gap:10px; align-items:start;
	.blk-tg-strip						{ grid-row:1; grid-column:1; flex-direction:column; margin-top:0; overflow-x:hidden; overflow-y:auto; max-height:70vh; }
	.blk-tg-main						{ grid-row:1; grid-column:2; }
}

/* Gallery captions: display is a GALLERY setting; per-image data supplies
   only the text. Over-image: caption on a translucent strip along the
   bottom; -scrim-auto starts dark and blocks.js reclassifies per image
   from the bottom-strip luminance (-cap-light / -cap-dark on the figure —
   the adaptive treatment designers hand-build with custom classes). */
.blk-gallery-grid.-cap-none .blk-image figcaption		{ display:none; }
.blk-gallery-grid.-cap-over .blk-image					{ position:relative;
	figcaption											{ position:absolute; left:var(--blk-cap-inset, 0); right:var(--blk-cap-inset, 0); bottom:var(--blk-cap-inset, 0); margin:0; padding:var(--blk-cap-pad, 0.45em 0.7em); border-radius:var(--blk-cap-radius, 0); font-size:0.85em; line-height:1.35; }
}
.blk-gallery-grid.-cap-over.-scrim-dark .blk-image figcaption,
.blk-gallery-grid.-cap-over.-scrim-auto .blk-image figcaption		{ background:rgba(18,20,24,0.55); color:#fff; }
.blk-gallery-grid.-cap-over.-scrim-light .blk-image figcaption		{ background:rgba(255,255,255,0.72); color:#1f2329; }
.blk-gallery-grid.-cap-over.-scrim-none .blk-image figcaption		{ background:none; color:#fff; }
/* per-figure auto verdicts — after the scrim defaults so they win the tie */
.blk-gallery-grid.-cap-over .blk-image.-cap-dark figcaption		{ background:rgba(18,20,24,0.55); color:#fff; }
.blk-gallery-grid.-cap-over .blk-image.-cap-light figcaption	{ background:rgba(255,255,255,0.72); color:#1f2329; }
/* Where the over-image caption sits (gallery prop caption_pos). Bottom is
   the default and needs no rule. Top anchors the same full-width strip to
   the top edge; Centre floats it instead — the scrim shrinks to a rounded
   backdrop behind the TEXT rather than banding the image. Banner slides
   are .blk-image figures inside the gallery, so both land on them too;
   the scrim/auto rules above still supply the colours. */
.blk-gallery-grid.-cap-over.-cap-top .blk-image figcaption
														{ top:var(--blk-cap-inset, 0); bottom:auto; }
.blk-gallery-grid.-cap-over.-cap-center .blk-image figcaption
														{ top:50%; bottom:auto; left:50%; right:auto; transform:translate(-50%,-50%); width:max-content; max-width:82%; text-align:center; border-radius:var(--blk-cap-radius, 6px); }
/* Caption Colour fills the caption over any contrast strip (Contrast still
   sets its text). Caption Width: Hug fits the words, a measured width boxes
   them; either centres across the image, the Inset keeping only its distance
   from the top or bottom edge. */
.blk-gallery-grid.-cap-over.-cap-bg .blk-image figcaption	{ background:var(--blk-cap-bg); }
.blk-gallery-grid.-cap-over.-cap-text .blk-image figcaption	{ color:var(--blk-cap-color); }
.blk-gallery-grid.-cap-over:is(.-capw-hug, .-capw-len) .blk-image figcaption
														{ left:0; right:0; margin-inline:auto; max-width:calc(100% - 30px); box-sizing:border-box; }
.blk-gallery-grid.-cap-over.-capw-hug .blk-image figcaption	{ width:max-content; }
/* auto margins already centre a Hug / measured caption across; Centre lifts it only */
.blk-gallery-grid.-cap-over.-cap-center:is(.-capw-hug, .-capw-len) .blk-image figcaption	{ transform:translateY(-50%); }
.blk-gallery-grid.-cap-over.-capw-len .blk-image figcaption	{ width:var(--blk-cap-w); }
/* a Description caption is page content, so it reads at body size, not a title caption's 0.85em */
.blk-gallery-grid.-cap-over .blk-image figcaption.blk-cap-html	{ font-size:inherit; }
/* an image in a Description caption is content, sized by its own width: the image-block rules skip it (:not(figcaption img)) */
.blk-page figcaption.blk-cap-html img	{ max-width:100%; height:auto; }
.blk-gallery-grid.-cap-over.-capa-center .blk-image figcaption	{ text-align:center; }
.blk-gallery-grid.-cap-over.-capa-right .blk-image figcaption	{ text-align:right; }
/* a caption is its own box: a Description's lone grid column (the box the
   source drew) fills it rather than narrowing the words inside it */
.blk-page .blk-cap-html .thm-row:has(> .thm-col:only-child)	{ margin-inline:0;
	> .thm-col							{ width:100%; margin-inline:0; padding-inline:0; }
}
/* the caption box is the edge: its content's first and last margins sit inside the padding, not added to it */
.blk-page .blk-cap-html :is(h1, h2, h3, h4, h5, h6, p, ul, ol, div, .thm-row, .thm-col):first-child	{ margin-top:0; }
.blk-page .blk-cap-html :is(h1, h2, h3, h4, h5, h6, p, ul, ol, div, .thm-row, .thm-col):last-child	{ margin-bottom:0; }
/* a Description caption's headings, paragraphs and links wear the caption's text colour */
.blk-gallery-grid.-cap-over .blk-cap-html :is(h1, h2, h3, h4, h5, h6, p, a:not(.thm-btn))
														{ color:inherit; }
/* Banner only: the dots overlay the band's bottom edge, so a bottom caption
   would sit under them. Dots sit at bottom:0.9em and are 0.65em across —
   about 1.6em of band is theirs, and captions render at 0.85em, so 2.2em of
   caption padding (≈1.9em of band) clears them. Keyed on a BUILT dot, so a
   dots-off banner (and a single-slide one) keeps the tighter caption. */
.blk-gallery-grid.-banner:has(.blk-car-dot):not(.-cap-top):not(.-cap-center) figcaption
														{ padding-bottom:2.2em; }

/* Gallery carousel layout: the image list on the carousel track — full
   snap cells, image centred at natural size (contain within 75vh) */
.blk-gallery-grid.-carousel				{ display:block;
	/* slides centre their image vertically — shorter images sit middle
	   of the track, not pinned to the top */
	/* Columns = images per view (default 3, like the grid); 1 restores the
	   classic one-image carousel */
	.blk-car-track > .blk				{ flex:0 0 max(var(--blk-colmin, 0px), calc((100% - (var(--blk-cols, 1) - 1) * var(--blk-gap, 0rem)) / var(--blk-cols, 1))); min-width:0; scroll-snap-align:start; scroll-snap-stop:always; margin:0; display:flex; flex-direction:column; justify-content:center; }
	.blk-image img:not(figcaption img)	{ margin-inline:auto; aspect-ratio:var(--blk-thumb, auto); object-fit:var(--blk-thumb-fit, contain); max-height:75vh; }
}

/* Gallery banner layout: the image list as full-width bands that CROSSFADE
   into one another — a slideshow, not a scrolling track (operator ruling:
   "banners rotate by fading one to another"). Slides stack absolutely and
   only .-on is opaque, so auto-play, arrows and dots all fade alike; the
   markup is .blk-banner / .blk-banner-track precisely so initCarousel (which
   binds .blk-carousel) never scrolls these slides. Slides cover-crop to
   --blk-banner-h around each media row's own focal point (--blk-bgpos,
   50% 50% when the row has none) — one focal per row, no separate mobile
   point (ruling: content on the row). Video rows play muted-looping,
   cropped the same way; blocks.js pauses the ones that are faded out. */
.blk-gallery-grid.-banner				{ display:block;
	.blk-banner							{ position:relative; }
	/* the band height lives on the TRACK now that slides stack: an inset-0
	   slide has no height of its own to give the band. (height, NOT
	   min-height: a Static-source banner's slides are the block's own Image
	   children, each holding a real <img> at width:100% whose natural height
	   — a 4:3 photo across a 1100px band is ~820px — always exceeded the
	   setting, so the band sized to the photo and the Height control did
	   nothing. A bound row is an empty figure carrying a background-image,
	   which is why the same control worked there.) */
	.blk-banner-track					{ position:relative; overflow:hidden; height:var(--blk-banner-h,420px); }
	.blk-banner-track > .blk			{ position:absolute; inset:0; margin:0; opacity:0; transition:opacity .8s ease;
										  background-size:var(--blk-banner-fit, cover); background-repeat:no-repeat; background-position:var(--blk-bgpos,50% 50%); }
	/* no-JS (or pre-bind) fallback: with nothing marked active the band would
	   read blank, so slide 1 shows until blocks.js claims the gallery. Bound
	   slides also carry -on server-side; static children can't, hence this. */
	&:not([data-banner-bound]) .blk-banner-track > .blk:first-child	{ opacity:1; }
	.blk-banner-track > .blk.-on		{ opacity:1; }
	/* …and with the band definite, a static child's image cover-crops into it
	   exactly like a bound row. Width is left to the gallery tile rule's
	   !important 100% (a plain width here would lose to .blk-page's). */
	.blk-banner-track > .blk img:not(figcaption img)	{ height:100%; object-fit:var(--blk-banner-fit, cover); object-position:var(--blk-bgpos,50% 50%); }
	.blk-banner-track > .blk.-video video	{ position:absolute; inset:0; width:100%; height:100%; object-fit:var(--blk-banner-fit, cover); object-position:var(--blk-bgpos,50% 50%); }
	figcaption							{ position:absolute; left:0; right:0; bottom:0; margin:0; padding:12px 16px; color:#fff;
										  background:linear-gradient(transparent,rgba(0,0,0,0.55)); }
	/* dots overlay the band (there is no strip below a full-bleed banner to
	   sit in) and go light-on-dark to read against photography */
	.blk-car-dots						{ position:absolute; left:0; right:0; bottom:0.9em; z-index:1; padding-top:0; }
	.blk-car-dot						{ background:rgba(255,255,255,0.55); box-shadow:0 1px 3px rgba(0,0,0,0.35);
		&.-on							{ background:#fff; }
	}
}
/* a visitor who asked for less motion gets the slideshow without the
   dissolve — navigation still works, it just cuts */
@media (prefers-reduced-motion: reduce) {
	.blk-gallery-grid.-banner .blk-banner-track > .blk	{ transition:none; }
	.blk-carousel.-fade .blk-car-track > .blk-car-slide	{ transition:none; }
}

/* Waterfall: CSS-columns masonry — images keep their heights and flow
   down each column. WYSIWYG: the editor renders it too (editor-only
   children span all columns via column-span in block_editor.css). */
/* columns shorthand takes BOTH: min width + max count — the same colmin
   setting drives waterfall responsiveness natively */
.blk-gallery-grid.-waterfall			{ display:block; columns:var(--blk-colmin,auto) var(--blk-cols,3); column-gap:var(--blk-gap,1rem);
	> .blk								{ break-inside:avoid; margin:0 0 var(--blk-gap,1rem); }
	.blk-image img						{ aspect-ratio:auto; }
}
.blk-lightbox							{ position:fixed; inset:0; z-index:9999; background:rgba(10,12,16,0.92); display:flex; align-items:center; justify-content:center;
	img									{ max-width:92vw; max-height:88vh; display:block; box-shadow:0 8px 40px rgba(0,0,0,0.5); }
	video								{ max-width:92vw; max-height:88vh; display:block; box-shadow:0 8px 40px rgba(0,0,0,0.5); }
	iframe								{ width:min(92vw, 88vh * 16 / 9); aspect-ratio:16 / 9; border:0; display:block; box-shadow:0 8px 40px rgba(0,0,0,0.5); }
	button								{ position:absolute; border:0; background:rgba(255,255,255,0.12); color:#fff; cursor:pointer; border-radius:50%; width:44px; height:44px; display:flex; align-items:center; justify-content:center;
		svg								{ width:22px; height:22px; }
		&:hover							{ background:rgba(255,255,255,0.25); }
	}
	.blk-lb-close						{ top:18px; right:18px; }
	.blk-lb-prev						{ left:18px; top:50%; transform:translateY(-50%); }
	.blk-lb-next						{ right:18px; top:50%; transform:translateY(-50%); }
	.blk-lb-count						{ position:absolute; bottom:16px; left:50%; transform:translateX(-50%); color:rgba(255,255,255,0.8); font-size:13px; }
}

/* Button: call-to-action link. Every look comes from the THEME's button
   tokens (Design Studio Buttons pane + its per-variant panes) with the
   historic literals as fallbacks — an unset theme renders
   byte-identically to before. Typography and shape (font, size, weight,
   transform, tracking, border width, radius) are ONE set for every
   variant; colours are per variant, and Outline / Outline Light / Text
   chain to the Filled / Light pair when unset so a brand recolour
   ripples every variant. Size variants multiply the theme size (a bare
   em there would ignore it). */
/* .thm-video: a body frame box at 16:9 plus 30px, the player or map filling
   it (the legacy .video-container / .map-container; body_video). */
.blk-page :is(.blk-text, .blk-html) .thm-video	{ position:relative; height:0; padding-bottom:56.25%; padding-top:30px; overflow:hidden;
	> :is(iframe, object, embed)		{ position:absolute; top:0; left:0; width:100%; height:100%; }
}
/* .thm-btn-wrapper: an in-body button set on its own line, centred with
   space above and below (the legacy .button-cta-wrapper; cta_class). */
.blk-page :is(.blk-text, .blk-html, .blk-cap-html) .thm-btn-wrapper	{ display:block; text-align:center; margin:30px 0;
	&.-left								{ text-align:left; }
	&.-right							{ text-align:right; }
	&.-mb0								{ margin-bottom:0; }
}
/* .thm-btn: the IN-BODY CTA class (third want: Capel, NF, Crawley all
   carry .button-cta pills in body HTML that our bound bodies rendered
   as text links). A link the inline content marks thm-btn dresses as
   the theme button — same tokens, same variants; site_convert's
   cta_class step rewrites legacy button-cta tokens to it. */
.blk-btn,
.blk-page a.thm-btn						{ display:inline-block; padding:var(--theme-btn-pad-y, 0.65em) var(--theme-btn-pad-x, 1.6em); border:var(--theme-btn-border-width, 2px) var(--theme-btn-border-style, solid) var(--theme-btn-bg, #2d2d2d); border-radius:var(--theme-btn-radius, 6px); background:var(--theme-btn-bg, #2d2d2d); color:var(--theme-btn-text, #fff); font-family:var(--theme-btn-font, inherit); font-size:var(--theme-btn-size, 1em); font-weight:var(--theme-btn-bold, 600); text-transform:var(--theme-btn-transform, inherit); letter-spacing:var(--theme-btn-letter-spacing, inherit); text-decoration:none; line-height:1.3; cursor:pointer;
										  transition:background-color .25s ease, border-color .25s ease, color .25s ease, opacity .25s ease, box-shadow .25s ease;
	/* the admin prefixes the theme sheet, so its Body Link rule arrives as
	   `.template a` (0,1,1) and outranks a bare `.blk-btn` (0,1,0) on the
	   resting colour, weight and underline; nested, the base reads (0,2,1).
	   Elements stay on the base rule (an <input> submit keeps its fill). */
	&:where(a)							{ color:var(--theme-btn-text, #fff); font-weight:var(--theme-btn-bold, 600); text-decoration:none; }
	/* hover: the fade is the default; --theme-btn-hover-fx = 1 (Recolour)
	   stops it and the per-variant hover colours take over, each falling
	   back to the variant's resting colour */
	/* !important, the tenant-proof idiom: the theme's Body Link pane emits
	   `a:hover{text-decoration:underline}`, which outranks the resting
	   `.blk-btn` — unprefixed on the front end (0,1,1) and `.template
	   a:hover` in the admin canvas (0,2,1), so no plain selector here wins
	   in both. A button is not a prose link in any state. The Text variant
	   re-asserts its own underline below, also !important. */
	&:hover								{ opacity:calc(1 - 0.15 * (1 - var(--theme-btn-hover-fx, 0))); background:var(--theme-btn-hover-bg, var(--theme-btn-bg, #2d2d2d)); border-color:var(--theme-btn-hover-bg, var(--theme-btn-bg, #2d2d2d)); color:var(--theme-btn-hover-text, var(--theme-btn-text, #fff)); text-decoration:none !important; }
	&.-light							{ background:var(--theme-btn-light-bg, #fff); border-color:var(--theme-btn-light-text, #2d2d2d); color:var(--theme-btn-light-text, #2d2d2d);
		&:hover							{ background:var(--theme-btn-light-hover-bg, var(--theme-btn-light-bg, #fff)); border-color:var(--theme-btn-light-hover-text, var(--theme-btn-light-text, #2d2d2d)); color:var(--theme-btn-light-hover-text, var(--theme-btn-light-text, #2d2d2d)); }
	}
	&:is(.-outline, .-outline-light)	{ border-width:var(--theme-btn-outline-border-width, var(--theme-btn-border-width, 2px)); }
	&.-outline							{ background:none; border-color:var(--theme-btn-outline-border, var(--theme-btn-bg, #2d2d2d)); color:var(--theme-btn-outline-text, var(--theme-btn-bg, #2d2d2d));
		&:hover							{ background:var(--theme-btn-outline-hover-bg, none); border-color:var(--theme-btn-outline-border, var(--theme-btn-bg, #2d2d2d)); color:var(--theme-btn-outline-hover-text, var(--theme-btn-outline-text, var(--theme-btn-bg, #2d2d2d))); }
	}
	/* white-on-photo CTAs (earned at the THIRD want: Crawley, St Martin's,
	   Holy Trinity hero pills) — Outline in the LIGHT colours by default. */
	&.-outline-light					{ background:none; border-color:var(--theme-btn-outline-light-border, var(--theme-btn-light-bg, #fff)); color:var(--theme-btn-outline-light-text, var(--theme-btn-light-bg, #fff));
		&:hover							{ background:var(--theme-btn-outline-light-hover-bg, none); border-color:var(--theme-btn-outline-light-border, var(--theme-btn-light-bg, #fff)); color:var(--theme-btn-outline-light-hover-text, var(--theme-btn-outline-light-text, var(--theme-btn-light-bg, #fff))); }
	}
	/* Small and Large: the studio's Small / Large Buttons sections, each
	   falling back to the historic ratio of the button size; Small may
	   harden its weight */
	&.-sm								{ padding:var(--theme-btn-sm-pad-y, 0.45em) var(--theme-btn-sm-pad-x, 1.1em); font-size:var(--theme-btn-sm-size, calc(var(--theme-btn-size, 1em) * 0.9)); font-weight:var(--theme-btn-sm-bold, var(--theme-btn-bold, 600)); }
	&.-lg								{ padding:var(--theme-btn-lg-pad-y, 0.85em) var(--theme-btn-lg-pad-x, 2.2em); font-size:var(--theme-btn-lg-size, calc(var(--theme-btn-size, 1em) * 1.15)); }
	/* the underlined-link look: own colour / weight / underline
	   (btn_txt_*; weight falls back to the shared button weight). AFTER
	   the sizes: Small / Large change a text button's type size only — it
	   has no inline box, so its text lines up with the copy around it. */
	&.-text								{ background:none; border-color:transparent; border-inline-width:0; padding-inline:0; color:var(--theme-btn-txt-color, inherit); font-size:var(--theme-btn-txt-size, var(--theme-btn-size, 1em)); font-weight:var(--theme-btn-txt-bold, var(--theme-btn-bold, 600)); text-transform:var(--theme-btn-txt-transform, var(--theme-btn-transform, inherit)); text-decoration:var(--theme-btn-txt-underline, underline);
		&.-sm							{ font-size:var(--theme-btn-sm-size, calc(var(--theme-btn-txt-size, var(--theme-btn-size, 1em)) * 0.9)); }
		&.-lg							{ font-size:var(--theme-btn-lg-size, calc(var(--theme-btn-txt-size, var(--theme-btn-size, 1em)) * 1.15)); }
		&:hover							{ background:none; border-color:transparent; color:var(--theme-btn-txt-hover-color, var(--theme-btn-txt-color, inherit)); text-decoration:var(--theme-btn-txt-underline, underline) !important; }
	}
	/* Width = Full Width (Button block, form Submit): the column's width */
	&.-full								{ display:block; width:100%; box-sizing:border-box; text-align:center; }
}

/* Table block: tabular data in the theme's Table Style; a wide table
   scrolls inside its own box on a narrow screen, never the page */
.blk-table-scroll						{ overflow-x:auto; max-width:100%; }
.blk-table .thm-table					{ min-width:100%; }
.blk-tcell.-left						{ text-align:left; }
.blk-tcell.-center						{ text-align:center; }
.blk-tcell.-right						{ text-align:right; }

/* Carousel: native CSS scroll-snap — swipe/momentum/keyboard from the
   browser; blocks.js adds dots, arrow paging and optional auto-advance.
   Slides are full-width snap cells and hold any blocks. */
.blk-carousel							{ position:relative; }
.blk-car-track							{ display:flex; overflow-x:auto; scroll-snap-type:x mandatory; overscroll-behavior-x:contain; scrollbar-width:none;
	&::-webkit-scrollbar				{ display:none; }
}
/* multi-across (2026-07-27): --blk-cols slides per view (1 = classic full-
   width); the same columns/gap/colmin vocabulary as the grid. Arrows and
   auto-advance page by view width and WRAP — the infinite feel for free. */
.blk-car-track							{ gap:var(--blk-gap, 0px); }
/* Ticker auto-play: a continuous glide — snap would fight the per-frame
   scroll, and the glide IS the navigation, so the nav chrome goes */
.blk-carousel.-ticker .blk-car-track	{ scroll-snap-type:none; }
.blk-carousel.-ticker .blk-car-arrow,
.blk-carousel.-ticker .blk-car-dots		{ display:none; }
/* Fade auto-play (single-column hero slideshows): slides GRID-STACK in one
   cell — in flow, unlike the banner's absolute slides, so the track takes
   the tallest slide's height (composed slides have no fixed band height) —
   and cross-fade by opacity; blocks.js moves the -on class with the same
   engine as the banner. First slide shows until JS binds (no-JS fallback). */
.blk-carousel.-fade .blk-car-track		{ display:grid; overflow:visible; scroll-snap-type:none;
	> .blk-car-slide					{ grid-area:1/1; opacity:0; transition:opacity .8s ease; pointer-events:none; }
	> .blk-car-slide.-on				{ opacity:1; pointer-events:auto; }
}
.blk-carousel.-fade:not([data-car-bound]) .blk-car-track > .blk-car-slide:first-child	{ opacity:1; pointer-events:auto; }
/* fade heroes wear their dots ON the image, banner-style (the strip below
   otherwise breaks the block's bottom edge — and its rounded corners —
   away from the picture), light-on-dark to read against photography */
.blk-carousel.-fade .blk-car-dots		{ position:absolute; left:0; right:0; bottom:0.9em; z-index:1; padding-top:0; }
.blk-carousel.-fade .blk-car-dot		{ background:rgba(255,255,255,0.55); box-shadow:0 1px 3px rgba(0,0,0,0.35);
	&.-on								{ background:#fff; }
}
.blk-car-track > .blk-car-slide			{ flex:0 0 max(var(--blk-colmin, 0px), calc((100% - (var(--blk-cols, 1) - 1) * var(--blk-gap, 0rem)) / var(--blk-cols, 1))); min-width:0; scroll-snap-align:start; scroll-snap-stop:always; margin-top:0; box-sizing:border-box; }
/* chrome chains the studio's Carousel element (--theme-car-*) with the
   historic literals as fallbacks — the Table Style pattern. The glyph keeps
   its share of the box (1.4/2.6 of the historic size), so one Size field
   drives both. */
.blk-car-arrow							{ position:absolute; top:50%; transform:translateY(-50%); z-index:1; width:var(--theme-car-arrow-size, 2.6em); height:var(--theme-car-arrow-size, 2.6em); padding:0; border:0; border-radius:var(--theme-car-arrow-radius, 50%); background:var(--theme-car-arrow-bg, rgba(255,255,255,0.85)); color:var(--theme-car-arrow-color, #333); cursor:pointer; box-shadow:0 1px 4px rgba(0,0,0,0.25); display:flex; align-items:center; justify-content:center;
	svg									{ width:calc(var(--theme-car-arrow-size, 2.6em) * 0.54); height:calc(var(--theme-car-arrow-size, 2.6em) * 0.54); }
	&.-prev								{ left:0.6em; }
	&.-next								{ right:0.6em; }
	&:hover								{ background:var(--theme-car-arrow-hover-bg, #fff); }
}
/* arrows reveal on hover where hover exists; touch devices keep them
   visible (no hover to reveal with) — applies to the carousel track and
   the thumbnail gallery's main image alike. Show Arrows = Always sets the
   resting opacity to 1: a var carrying the NUMBER, since CSS cannot branch
   a media block on a word (the btn_hover_fx flag precedent). */
@media (hover:hover) {
	.blk-car-arrow						{ opacity:var(--theme-car-arrow-always, 0); transition:opacity 0.15s ease; }
	.blk-carousel:hover .blk-car-arrow,
	.blk-banner:hover .blk-car-arrow,
	.blk-tg-main:hover .blk-car-arrow,
	.blk-car-arrow:focus-visible		{ opacity:1; }
}
.blk-car-dots							{ display:flex; justify-content:center; gap:0.55em; padding-top:0.8em; }
.blk-car-dot							{ width:0.65em; height:0.65em; padding:0; border:0; border-radius:50%; background:var(--theme-car-dot-color, #c9c9c9); cursor:pointer; transition:background .15s ease;
	&.-on								{ background:var(--theme-car-dot-on-color, #555); }
}

/* Accordion: native details/summary — zero JS; exclusive-open via the
   shared name attribute. Card tab chrome (2026-08-25, the Phoenix FAQ):
   the ITEM is the card — question row + open answer as one box — via the
   shared --blk-tile-* vars (fallbacks ARE the historic look: 1px #ddd,
   square, transparent). Gap rides a dedicated --blk-acc-gap (never
   --blk-gap — that inherits from ancestor containers); -split switches
   off the joined-stack border collapse. */
.blk-accordion							{ display:flex; flex-direction:column; gap:var(--blk-acc-gap,0px); }
.blk-accordion .blk-accitem + .blk-accitem				{ margin-top:0; }
.blk-accordion:not(.-split) .blk-accitem + .blk-accitem	{ border-top:0; }
details.blk-accitem						{ border:var(--blk-tile-border,1px solid #ddd); border-radius:var(--blk-tile-radius,0); background:var(--blk-tile-bg,transparent); color:var(--blk-tile-color,inherit); box-shadow:var(--blk-tile-shadow,none); padding:var(--blk-tile-pad,0);
	/* slide-open (2026-08-26, the source jQuery-slide look with zero JS):
	   modern engines animate ::details-content height; others snap open
	   exactly as before — progressive enhancement, reduced-motion stilled */
	interpolate-size:allow-keywords;
	&::details-content					{ block-size:0; overflow-y:clip; transition:block-size .28s ease, content-visibility .28s allow-discrete; }
	&[open]::details-content			{ block-size:auto; }
	/* Title Bar Background paints CLOSED items only — an open item joins
	   its content (the North Finchley tab-accordion look) */
	&:not([open]) > summary				{ background:var(--blk-acc-title-bg,transparent); }
	summary								{ padding:0.8em 1em; cursor:pointer; list-style:none; display:flex; align-items:center; gap:0.6em;
		&:not([class*="thm-ps-"])		{ font-weight:600; }	/* a default: a named Title Style decides its own weight */
		&::before						{ content:''; width:0.55em; height:0.55em; border-right:2px solid currentColor; border-bottom:2px solid currentColor; transform:rotate(-45deg); transition:transform .18s ease; flex:0 0 auto; }
		&::-webkit-details-marker		{ display:none; }
	}
	&[open] > summary::before			{ transform:rotate(45deg); }
	.blk-accitem-body					{ padding:0.3em 1em 1em; }
}
/* Look: Rows — flush items between divider lines (the theme Divider,
   or the item Border when set); the title and answer sit on the text edge */
.blk-accordion.-rows details.blk-accitem	{ border:0; border-bottom:var(--blk-tile-border, var(--theme-divider-weight,1px) var(--theme-divider-style,solid) var(--theme-divider-color,#ddd)); border-radius:0; box-shadow:none;
	&:first-child						{ border-top:var(--blk-tile-border, var(--theme-divider-weight,1px) var(--theme-divider-style,solid) var(--theme-divider-color,#ddd)); }
	summary								{ padding-inline:0; }
	.blk-accitem-body					{ padding-inline:0; }
}
/* icon variants (Card tab): Right moves the glyph to a ::after pushed to
   the far edge; Plus swaps the chevron for +/− text glyphs. */
.blk-accordion.-ic-right details.blk-accitem summary::before			{ content:none; }
.blk-accordion.-ic-right details.blk-accitem summary::after				{ content:''; width:0.55em; height:0.55em; border-right:2px solid currentColor; border-bottom:2px solid currentColor; transform:rotate(-45deg); transition:transform .18s ease; flex:0 0 auto; margin-left:auto; }
.blk-accordion.-ic-right details.blk-accitem[open] > summary::after		{ transform:rotate(45deg); }
.blk-accordion.-ic-plus details.blk-accitem summary::before				{ content:'+'; width:auto; height:auto; border:0; transform:none; font-size:1.2em; line-height:1; font-weight:400; }
.blk-accordion.-ic-plus details.blk-accitem[open] > summary::before		{ content:'−'; transform:none; }
.blk-accordion.-ic-plus.-ic-right details.blk-accitem summary::after	{ content:'+'; width:auto; height:auto; border:0; transform:none; font-size:1.2em; line-height:1; font-weight:400; }
.blk-accordion.-ic-plus.-ic-right details.blk-accitem[open] > summary::after	{ content:'−'; transform:none; }
/* Caret: the small filled dropdown triangle (North Finchley) — down when
   closed, flipped when open */
.blk-accordion.-ic-caret details.blk-accitem summary::before,
.blk-accordion.-ic-caret.-ic-right details.blk-accitem summary::after	{ content:''; width:0; height:0; border:0; border-left:5px solid transparent; border-right:5px solid transparent; border-top:6px solid currentColor; transform:none; transition:transform .18s ease; }
.blk-accordion.-ic-caret details.blk-accitem[open] > summary::before,
.blk-accordion.-ic-caret.-ic-right details.blk-accitem[open] > summary::after	{ transform:rotate(180deg); }
.blk-accordion.-ic-caret.-ic-right details.blk-accitem summary::before	{ content:none; }
@media (prefers-reduced-motion: reduce) {
	details.blk-accitem summary::before,
	details.blk-accitem::details-content,
	.blk-accordion.-ic-right details.blk-accitem summary::after			{ transition:none; }
}

/* Tabs: bar + one panel. Critical layout owned under .blk-page — tenants
   style tab bars; we keep flex, gaps, and panel stack intact. */
.blk-page .blk-tabs						{ display:block; }
.blk-page .blk-tabs-bar					{ display:flex; flex-wrap:wrap; gap:0.25em 0.5em; margin:0 0 1em; padding:0; border-bottom:1px solid #ddd; list-style:none; }
.blk-page .blk-tabs-btn					{ appearance:none; -webkit-appearance:none; font:inherit; cursor:pointer; margin:0 0 -1px; padding:0.55em 0.95em; border:1px solid transparent; border-bottom-color:#ddd; border-radius:4px 4px 0 0; background:transparent; color:inherit;
	&.-on								{ border-color:#ddd; border-bottom-color:#fff; background:#fff; font-weight:600; }
}
.blk-page .blk-tabs > .blk-tab			{ margin-top:0; }
.blk-page .blk-tabs > .blk-tab[hidden]	{ display:none !important; }

/*---------------- Phase 4 — product / folder module blocks ----------------*/
/* Product price: size segments match .blk-btn; strike RRP/orig when on offer.
   Tenant CSS owns brand colour; we only set layout + offer chrome. */
.blk-page .blk-prod-price				{ line-height:1.3;
	&.-sm .price						{ font-size:0.9em; }
	&.-lg .price						{ font-size:1.35em; font-weight:600; }
	.price								{ font-size:1.15em; font-weight:600; }
	.price-orig .amount					{ text-decoration:line-through; opacity:0.7; margin-right:0.5em; }
	.price-rrp .amount					{ text-decoration:line-through; opacity:0.55; font-size:0.9em; }
	.price-pack							{ margin-left:0.35em; font-size:0.6em; font-weight:400; opacity:0.75; }
	.price-saving						{ color:var(--theme-offer-text, #c62828); font-size:0.9em; }
	.price-both							{ display:flex; flex-wrap:wrap; gap:0.35em 1em; }
	.vat-status,.vat-label				{ font-size:0.85em; opacity:0.75; }
}
/* Buy: a themed <button>, an optional quantity stepper, and the form's own
   error and live lines. Nested price/variants/options keep form flow. */
.blk-page .blk-prod-buy					{
	.shop-wrapper,.blk-prod-actions		{ display:flex; flex-wrap:wrap; align-items:center; gap:0.6em; }
	.blk-prod-qty-preview				{ width:3.2em; text-align:center; padding:0.45em 0.3em; border:1px solid #ccc; border-radius:4px; box-sizing:border-box; }
	.blk-qty-step						{ display:inline-flex; align-items:stretch; border:var(--theme-field-border, 1px) solid var(--theme-field-border-color, #c1c1c1); border-radius:var(--theme-field-radius, 4px); background:var(--theme-field-bg, Field); }
	.blk-qty-btn						{ appearance:none; border:0; background:none; color:inherit; font:inherit; width:2.2em; cursor:pointer; }
	.blk-qty-input						{ width:3em; border:0; background:none; color:var(--theme-field-text, FieldText); text-align:center; font:inherit; -moz-appearance:textfield;
		&::-webkit-inner-spin-button, &::-webkit-outer-spin-button	{ -webkit-appearance:none; margin:0; }
	}
	.blk + .blk							{ margin-top:var(--blk-space-s); }
}
/* Add buttons (Add To Basket, card quick-add): the state labels share one
   grid cell, so the button keeps the widest label's width in every state. */
.blk-page :is(.blk-prod-buy, .blk-card-buy)	{
	button.js-add						{ position:relative; display:inline-grid; align-items:center; justify-items:center;
		&.-full							{ display:grid; }
	}
	.blk-add-label						{ grid-area:1/1; }
	.blk-add-label.-off					{ visibility:hidden; }
	.blk-add-tick						{ display:inline-block; width:0.8em; height:0.45em; margin-right:0.4em; border:solid currentColor; border-width:0 0 2px 2px; transform:translateY(-0.15em) rotate(-45deg); }
	.blk-prod-error						{ margin:0.5em 0 0; color:var(--theme-error, #b3261e); font-size:0.9em; }
	.sr-only							{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
}
[x-cloak]								{ display:none !important; }
/* Variants: leave the attribute chrome to product.css when loaded; baseline only. */
.blk-page .blk-prod-variants			{
	.variant-block						{ margin:0; }
	.variant-block dd					{ margin:0 0 0.6em; }
	/* a text option (no colour or picture swatch) is a chip that shows its words, in the Form Fields look */
	input.radio-swatch + label:not([style*="background"])
										{ width:auto; min-width:40px; height:auto; min-height:40px; padding:0.4em 0.8em; box-sizing:border-box; vertical-align:top; margin:0 5px 5px 0; text-align:center; line-height:1.3;
										  border:var(--theme-field-border, 1px) solid var(--theme-field-border-color, #bbb); border-radius:var(--theme-field-radius, 0); background:var(--theme-field-bg, #fff); color:var(--theme-field-text, inherit);
		div								{ display:block; }
	}
	input.radio-swatch:checked + label:not([style*="background"])
										{ border-color:var(--theme-field-focus-color, currentColor); box-shadow:0 0 0 1px var(--theme-field-focus-color, currentColor); }
}
/* Product Badge: a disc in the accent colour by default; the Badges studio
   element sets shape, size and a colour pair per kind. Empty = invisible. */
.blk-page .blk-prod-badge				{ line-height:1;
	&:not(:has(.blk-badge), .blk-empty)	{ display:none; }
	.blk-badge							{ display:inline-flex; align-items:center; justify-content:center; min-width:var(--theme-badge-size, 70px); min-height:var(--theme-badge-min-h, var(--theme-badge-size, 70px)); padding:var(--theme-badge-pad, 0.3em); box-sizing:border-box; border-radius:var(--theme-badge-shape, 50%); text-align:center; font-weight:700; font-size:0.85em; text-transform:lowercase;
										  background:var(--theme-badge-offer-bg, var(--theme-btn-bg, #e8a23a)); color:var(--theme-badge-offer-text, var(--theme-btn-text, #fff)); }
	&.-new .blk-badge					{ background:var(--theme-badge-new-bg, var(--theme-btn-bg, #2d6a4f)); color:var(--theme-badge-new-text, var(--theme-btn-text, #fff)); }
	&.-sold_out .blk-badge				{ background:var(--theme-badge-sold-bg, #555); color:var(--theme-badge-sold-text, #fff); }
}
/*---------------- Popup (CTA dialog) ----------------*/
/* The SHELL is the fixed viewport layer (overlay + placement); the .blk
   inside is the dialog box, whose look comes entirely from the standard
   Appearance props. z-index sits above sticky headers — tenants pin
   theirs in the low hundreds; --blk-popup-z lets a site go higher. */
.blk-popup-shell						{ position:fixed; inset:0; z-index:var(--blk-popup-z,9000); display:flex; padding:16px; pointer-events:none;
	&[hidden]							{ display:none; }
	&.-overlay							{ background:rgba(0,0,0,0.45); pointer-events:auto; }
	&.-centre							{ align-items:center; justify-content:center; }
	&.-corner							{ align-items:flex-end; justify-content:flex-end; }
	&.-bar								{ align-items:flex-end; justify-content:center; padding:0; }
	> .blk-popup						{ pointer-events:auto; position:relative; width:min(520px, 100%); max-height:calc(100vh - 32px); overflow-y:auto;
		/* the box's OWN look is Appearance-driven; these are only the
		   defaults a bare popup needs to read as a dialog at all */
		background:var(--blk-popup-bg,#fff); border-radius:var(--theme-radius-m,10px); box-shadow:0 10px 40px rgba(0,0,0,0.28); padding:24px;
	}
	&.-bar > .blk-popup					{ width:100%; max-width:none; border-radius:0; }
}
/* entrance: a plain fade/rise unless the block carries its own reveal fx */
.blk-popup-shell:not([hidden]) > .blk-popup	{ animation:blk-popup-in .28s ease-out; }
@keyframes blk-popup-in					{ from { opacity:0; transform:translateY(12px); } }
@media (prefers-reduced-motion: reduce) {
	.blk-popup-shell > .blk-popup		{ animation:none; }
}
.blk-popup-close						{ position:absolute; top:8px; right:8px; z-index:2; width:32px; height:32px; display:flex; align-items:center; justify-content:center; border:0; border-radius:50%; background:rgba(255,255,255,0.85); color:#374151; cursor:pointer; padding:0;
	svg									{ width:17px; height:17px; }
	&:hover								{ background:#fff; color:#111; }
}

/* House table style: the studio's Table Style tokens with the historic
   matrix literals as fallbacks — consumers (price matrix, delivery
   options, future Table block) wear .thm-table or these matrix classes */
table.thm-table							{ width:100%; border-collapse:collapse; border:var(--theme-tbl-border-width,1px) var(--theme-tbl-border-style,solid) var(--theme-tbl-border-color,#e5e5e5); background:#fff; color:inherit;
	th,td								{ padding:var(--theme-tbl-cell-pad,0.55em) 0.75em; border:var(--theme-tbl-border-width,1px) var(--theme-tbl-border-style,solid) var(--theme-tbl-border-color,#e5e5e5); text-align:left; }
	th									{ font-weight:var(--theme-tbl-head-bold,600); background:var(--theme-tbl-head-bg-color,#f7f7f7); color:var(--theme-tbl-head-color,inherit); }
	tbody tr:nth-child(even) td			{ background:var(--theme-tbl-stripe-color,transparent); }
}
/* Matrix: defensive table baseline — tenants restyle tables hard. A product
   without breaks keeps an empty, hidden wrapper. */
.blk-page .blk-prod-matrix				{
	&:not(:has(table), .blk-empty)		{ display:none; }
	table								{ width:100%; border-collapse:collapse; border:var(--theme-tbl-border-width,1px) var(--theme-tbl-border-style,solid) var(--theme-tbl-border-color,#e5e5e5); background:#fff; color:inherit; font:inherit; }
	th,td								{ padding:var(--theme-tbl-cell-pad,0.55em) 0.75em; border:var(--theme-tbl-border-width,1px) var(--theme-tbl-border-style,solid) var(--theme-tbl-border-color,#e5e5e5); text-align:left; }
	th									{ font-weight:var(--theme-tbl-head-bold,600); background:var(--theme-tbl-head-bg-color,#f7f7f7); color:var(--theme-tbl-head-color,inherit); }
	tbody tr:nth-child(even) td			{ background:var(--theme-tbl-stripe-color,transparent); }
	tr.no-qty,tr.not-on-offer			{ display:none; }
	&.-compact th,&.-compact td			{ padding:0.3em 0.5em; font-size:0.92em; }
	/* offer column empty when not on offer — hide c3 */
	.price-break:not(.on-offer) .c3,
	.price-break:not(.on-offer) th.c3	{ display:none; }
}
/* ChurchSuite events: house cards over the vendor's headless embed —
   same responsive column recipe, cards ARE .blk-card (Card tab chrome
   applies). The <template> children are inert until Alpine stamps them. */
.blk-page .blk-cs-grid					{ display:grid; gap:var(--blk-gap,1.5rem);
										  grid-template-columns:repeat(auto-fill, minmax(max(var(--blk-colmin,14rem), calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1.5rem)) / var(--blk-cols,3) - 0.5px)), 1fr)); }
.blk-page .blk-cs-card					{ text-decoration:none; color:var(--blk-tile-color,inherit); }
.blk-page .blk-cs-card .blk-card-snippet	{ padding-bottom:0.85em; }

/* Card lists (folder_list / related_list): gallery-grid column machinery +
   shared .blk-card chrome via --blk-tile-* (fallbacks ARE the default look).
   colmin DEFAULTS to 14rem here (the card carousel's floor): with 0px, any
   shrink-to-fit ancestor makes the width indefinite, the percentage share
   resolves to auto, and auto-fill collapses to ONE column (Denmead home,
   2026-08-17 — the list needed an explicit colmin just to be 3-across).
   At normal widths the Nth share exceeds 14rem, so exact-N is unchanged. */
.blk-page .blk-folder-list,
.blk-page .blk-related-list				{ display:grid; gap:var(--blk-gap,1rem);
										  grid-template-columns:repeat(auto-fill, minmax(max(var(--blk-colmin,14rem), calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,3) - 0.5px)), 1fr)); }
/* border-box: cards are NOT .blk (which gets it globally) — content-box
   made each card's border add outside the carousel flex-basis, so the
   last card's right border clipped past the track (operator 2026-07-28) */
.blk-page .blk-card						{ display:flex; flex-direction:column; gap:0.5em; box-sizing:border-box; padding:var(--blk-tile-pad,0); border:var(--blk-tile-border,1px solid #e8e8e8); border-radius:var(--blk-tile-radius,0); box-shadow:var(--blk-tile-shadow,none); overflow:hidden; background:var(--blk-tile-bg,#fff); color:var(--blk-tile-color,inherit); transition:box-shadow .15s ease, background-color .15s ease;
	&:hover								{ box-shadow:var(--blk-tile-shadow,0 4px 14px rgba(0,0,0,0.1)); filter:brightness(0.99); }
}
/* Card tab Hover cell (2026-08-25): '' = the lift above. Tint mixes the
   card bg toward the card TEXT colour (literal #333 fallback — 'inherit'
   would void the color-mix) so dark-on-light darkens and light-on-brand
   lightens; both alternates cancel the default lift/brightness. */
.blk-page .-hov-none .blk-card:hover	{ box-shadow:var(--blk-tile-shadow,none); filter:none; }
.blk-page .-hov-tint .blk-card:hover	{ box-shadow:var(--blk-tile-shadow,none); filter:none;
										  background:color-mix(in srgb, var(--blk-tile-bg,#fff) 86%, var(--blk-tile-color,#333)); }
/* Card tab Selected (Show Current Page, the pill-nav want): the marked
   card takes the Selected pair, falling back to the ordinary tile look.
   Hover effects stand down on it (after the hover rules — the tie must
   break this way): the state is a statement, not an invitation. */
.blk-page .blk-card.-sel				{ background:var(--blk-tile-sel-bg,var(--blk-tile-bg,#fff)); color:var(--blk-tile-sel-color,var(--blk-tile-color,inherit));
	&:hover								{ box-shadow:var(--blk-tile-shadow,none); filter:none; background:var(--blk-tile-sel-bg,var(--blk-tile-bg,#fff)); }
}
/* Imageless items in a CUSTOM row card: an image-only first column
   collapses so the text spans the full row (the source-list look —
   North Finchley's dateless first news item reserved a dead 230px
   track). Curated cards already skip the figure per item. */
/* :not(:has(…)), never :empty (whitespace text nodes defeat it) and
   never :has(:not(:has(…))) — :has cannot nest inside :has, the whole
   selector silently drops. This reads: a -no-img card's columns whose
   FIRST column contains no block. */
.blk-page .blk-card.-no-img .blk-columns:not(:has(> .blk-container:first-child .blk))	{ grid-template-columns:1fr;
	> .blk-container:first-child		{ display:none; }
}
/* …and the same when the image sits in the LAST column (image-right rows) */
.blk-page .blk-card.-no-img .blk-columns:not(:has(> .blk-container:last-child .blk))	{ grid-template-columns:1fr;
	> .blk-container:last-child			{ display:none; }
}
/* Last Row: Centred (fixed column counts). Grid cannot centre a partial
   row, so the list becomes a flex wrap whose BASIS is the grid rule's own
   track width — the same cards land on each row at every width, and the
   short row centres under them. flex-shrink stays 1 so a track narrower
   than its content still behaves; grow stays 0 so a short row keeps card
   width instead of stretching to fill. */
/* Last Row: Avoid (Grid, Page List, Related List). The block emits the
   column counts that leave no short row as --blk-e1..e5 (its own count,
   then the smaller divisors of its tile count; unused slots read 1). Each
   --ev-tN is that count's exact share WHEN the count fits at the minimum
   column width, and the full width when it does not — the clamp is a 0 /
   100% switch on "container width minus the width N columns need". The
   track floor is the smallest share on offer, i.e. the largest count that
   fits, and auto-fill then lands exactly that many columns. */
.blk-page .blk-grid.-even,
.blk-page .blk-folder-list.-even,
.blk-page .blk-related-list.-even		{ --ev-min:var(--blk-colmin, 14rem); --ev-gap:var(--blk-gap, 1rem);
	--ev-t1:max(calc((100% - (var(--blk-e1, 1) - 1) * var(--ev-gap)) / var(--blk-e1, 1) - 0.5px), calc(100% - clamp(0px, (100% - (var(--blk-e1, 1) * var(--ev-min) + (var(--blk-e1, 1) - 1) * var(--ev-gap))) * 9999, 100%)));
	--ev-t2:max(calc((100% - (var(--blk-e2, 1) - 1) * var(--ev-gap)) / var(--blk-e2, 1) - 0.5px), calc(100% - clamp(0px, (100% - (var(--blk-e2, 1) * var(--ev-min) + (var(--blk-e2, 1) - 1) * var(--ev-gap))) * 9999, 100%)));
	--ev-t3:max(calc((100% - (var(--blk-e3, 1) - 1) * var(--ev-gap)) / var(--blk-e3, 1) - 0.5px), calc(100% - clamp(0px, (100% - (var(--blk-e3, 1) * var(--ev-min) + (var(--blk-e3, 1) - 1) * var(--ev-gap))) * 9999, 100%)));
	--ev-t4:max(calc((100% - (var(--blk-e4, 1) - 1) * var(--ev-gap)) / var(--blk-e4, 1) - 0.5px), calc(100% - clamp(0px, (100% - (var(--blk-e4, 1) * var(--ev-min) + (var(--blk-e4, 1) - 1) * var(--ev-gap))) * 9999, 100%)));
	--ev-t5:max(calc((100% - (var(--blk-e5, 1) - 1) * var(--ev-gap)) / var(--blk-e5, 1) - 0.5px), calc(100% - clamp(0px, (100% - (var(--blk-e5, 1) * var(--ev-min) + (var(--blk-e5, 1) - 1) * var(--ev-gap))) * 9999, 100%)));
	grid-template-columns:repeat(auto-fill, minmax(min(var(--ev-t1), var(--ev-t2), var(--ev-t3), var(--ev-t4), var(--ev-t5)), 1fr));
}
.blk-page .blk-folder-list.-row-c,
.blk-page .blk-related-list.-row-c		{ display:flex; flex-wrap:wrap; justify-content:center;
	> .blk-card							{ flex:0 1 max(var(--blk-colmin,14rem), calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,3) - 0.5px)); min-width:0; }
}
/* Item Width Hug (Flow mode): pill rows — each card as wide as its
   content, wrapping; gap still reads from the grid rule above. */
.blk-page .blk-folder-list.-hug,
.blk-page .blk-related-list.-hug		{ display:flex; flex-wrap:wrap;
	> .blk-card							{ flex:0 0 auto; }
	&.-hug-c							{ justify-content:center; }
}
.blk-page .blk-card-img					{ margin:0; aspect-ratio:var(--blk-card-aspect,4/3); overflow:hidden; background:#f3f3f3;
	img									{ display:block; width:100% !important; height:100%; max-width:none; object-fit:cover; }
}
/* Image Shape: Natural — no box height to fill and nothing to crop to, so
   the cover rule stands down and each picture keeps its own height. The
   server sends a width-constrained file for this mode (CardList). */
.blk-page .-img-nat .blk-card-img,
.blk-page .-img-nat .blk-card .blk-image	{ aspect-ratio:auto;
	img									{ height:auto; object-fit:unset; }
}
/* Image Fit: Contain — the whole picture inside the shape's box, the box's
   own fill beside it; the server sends a fit-within file for this mode */
.blk-page .-img-contain .blk-card-img img,
.blk-page .-img-contain .blk-card .blk-image img	{ object-fit:contain; }
.blk-page .-img-contain .blk-card .blk-container.-item-img	{ background-size:contain !important; background-repeat:no-repeat; background-position:center; }	/* !important: the item image arrives as an inline background */
/* Image Shape: Circle — the square crop (--blk-card-aspect:1/1) drawn fully round */
.blk-page .-img-circle .blk-card-img,
.blk-page .-img-circle .blk-card .blk-image,
.blk-page .-img-circle .blk-card .blk-container.-item-img	{ border-radius:50%; }
/* a container painted with the item's image follows a CHOSEN shape only (no
   fallback): Landscape and Natural leave composed cards at the height their
   own content and Minimum Height give them */
.blk-page .blk-card .blk-container.-item-img	{ aspect-ratio:var(--blk-card-aspect); }
/* flex:1 — the link must FILL the card: composed templates pin their
   bottom band with margin-top:auto INSIDE the link (the frontend repeat
   pass wraps card content in it; edit mode doesn't), and auto margins
   need the free space to live in the same flex context
   (operator 2026-07-29: pinned in edit, not on the front). */
.blk-page .blk-card-link				{ display:flex; flex-direction:column; gap:0.5em; flex:1 1 auto; text-decoration:none; color:inherit; font-weight:inherit; }	/* the theme's Links element (colour, bold, underline) styles prose links, not a card's wrapper */
/* a text link folded into its card's link (Block\Service\CardPageLink) keeps
   the look of a link — the theme's Links element, or the browser's own */
.blk-page .blk-card-page-link			{ color:var(--theme-link-color, LinkText); font-weight:var(--theme-link-bold, inherit); text-decoration:var(--theme-link-underline, underline); }
.blk-page .blk-card-link:hover .blk-card-page-link
										{ color:var(--theme-link-hover-color, var(--theme-link-color, LinkText)); text-decoration:var(--theme-link-hover-underline, var(--theme-link-underline, underline)); }
.blk-page .blk-card-title				{ padding:0 0.75em; }
.blk-page .blk-card-title:not([class*="thm-ps-"])	{ font-weight:600; }	/* the chrome's weight is a default: a named Title Style decides its own */
.blk-page .blk-card-snippet				{ font-size:0.92em; opacity:0.85; padding:0 0.75em 0.85em; line-height:1.4; }
.blk-page .blk-card-price				{ padding:0 0.75em; margin-top:auto; font-weight:600;
	.price-amount						{ font-size:inherit; font-weight:inherit; }	/* a quick-add card carries .item-product for productBuy; the product page's price size is not the card's */
	.price-was							{ margin-left:0.5em; font-weight:400; opacity:0.6; text-decoration:line-through; }
}
.blk-page .blk-card-buy					{ padding:0.5em 0.75em 0.85em; text-align:var(--blk-card-buy-align,left); }
/* COMPOSED cards (repeater card template): generic blocks inherit the
   curated card's look by POSITION — the fallback renders the original
   hand-written markup, the template renders real blocks, and without
   these the two drifted (bottom-pinned price/buy, 4:3 crop, card type
   scale — operator 2026-07-29). */
.blk-page .blk-card .blk				{ margin:0; }
/* COMPOSED cards own their rhythm outright: the chrome's 0.5em flex gap
   exists for the curated image/title/snippet units, but between Card
   Items blocks it is an uncancellable 8px that surfaces under overlay
   compositions (the Denmead caption strip sat proud of the card bottom
   by exactly this gap, 2026-08-17). Composers space with padding. */
.blk-page .blk-card:has(> .blk),
.blk-page .blk-card-link:has(> .blk)	{ gap:0; }
/* Sides: Alternate — every second card mirrors its Columns. RTL swaps the
   tracks without rewriting the inline template; each track reads LTR. */
.blk-page .-card-alt .blk-card:nth-child(even) > .blk-columns,
.blk-page .-card-alt .blk-card:nth-child(even) > .blk-card-link > .blk-columns
										{ direction:rtl;
	> *									{ direction:ltr; }
}
.blk-page .blk-card .blk-heading		{ padding:0 0.75rem; }
/* the card's text colour is a default: a named Style carries its own colour and must win */
.blk-page .blk-card .blk-heading:not([class*="thm-ps-"])	{ color:inherit; }
/* compact title default — a named Style on the heading must win (custom
   row cards match source list typography through the theme, never CSS) */
.blk-page .blk-card .blk-heading:not([class*="thm-ps-"])	{ font-size:1em; font-weight:600; line-height:inherit; }
/* rem gutter, not em: a heading and text in one card column must share
   a left edge whatever the title's named-style size */
.blk-page .blk-card .blk-text			{ padding:0 0.75rem; }
/* the small faded card text is a default: a Text block with a named Style keeps the style's size and full colour */
.blk-page .blk-card .blk-text:not([class*="thm-ps-"])	{ font-size:0.92em; opacity:0.85; line-height:1.4; }
.blk-page .blk-card .blk-image			{ margin:0; aspect-ratio:var(--blk-card-aspect,4/3); overflow:hidden; background:#f3f3f3; max-width:min(var(--blk-imgmax, 100%), 100%);
	/* the figure is the box: a Max Width sizes it, not the image inside */
	img									{ display:block; width:100% !important; height:100%; max-width:none !important; object-fit:cover; }
}
/* List Image on Hover (legacy pg_image is_list_image=9, carried into the
   curated card): the hover image stacks over the base and fades in on
   pointer-over or keyboard focus. Touch has no hover — base image stands. */
.blk-page .blk-card-img.-has-hover		{ position:relative;
	img.-hover							{ position:absolute; inset:0; opacity:0; transition:opacity 0.25s ease; }
}
.blk-page .blk-card:hover .blk-card-img.-has-hover img.-hover,
.blk-page .blk-card:focus-within .blk-card-img.-has-hover img.-hover
										{ opacity:1; }
@media (prefers-reduced-motion:reduce) {
	.blk-page .blk-card-img.-has-hover img.-hover	{ transition:none; }
}

/* Caption placement (Captions prop): dresses the card's TITLE — the item
   title block of a composed card (its -bind-item-* role class), or the
   built-in card's .blk-card-title. 'over' anchors the
   title as a scrim bar on the card bottom; 'hover' hides it below the
   crop (chrome overflow:hidden) and slides it up on pointer-over or
   keyboard focus. Touch has no hover — the bar stays visible; reduced
   motion drops the slide. Overlay modes pair with image+title cards.
   The caption owns its box: its paddings are !important because the item
   title block carries a Padding prop of its own for the Under look. */
.blk-page [class*="-cap-"] .blk-card	{ position:relative; }
.blk-page .-cap-over :is(.blk-card-title, [class*="-bind-item-"][class*="title"]),
.blk-page .-cap-hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ position:absolute; left:var(--blk-cap-inset, 0); right:var(--blk-cap-inset, 0); bottom:var(--blk-cap-inset, 0); box-sizing:content-box; margin:0; padding:var(--blk-cap-pad, 0.7em 0.75em) !important; border-radius:var(--blk-cap-radius, 0); background:var(--blk-cap-bg, rgba(0,0,0,0.45)); text-align:center; }
/* the overlay's own colours are defaults: a named Title Style (thm-ps-N) carries its colour and must win */
.blk-page .-cap-over :is(.blk-card-title, [class*="-bind-item-"][class*="title"]):not([class*="thm-ps-"]),
.blk-page .-cap-hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"]):not([class*="thm-ps-"])
										{ color:#fff; }
.blk-page .-cap-hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ transform:translateY(101%); transition:transform 0.25s ease; }
.blk-page .-cap-hover .blk-card:hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"]),
.blk-page .-cap-hover .blk-card:focus-within :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ transform:translateY(0); }
@media (hover:none) {
	.blk-page .-cap-hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ transform:none; }
}
@media (prefers-reduced-motion:reduce) {
	.blk-page .-cap-hover :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ transition:none; transform:none; }
}

/* Read More (a snippet's or short body's closing words): the Body Link
   colour, or a named style's own look when Read More Style sets one */
.blk-page .blk-snip-more:not([class*="thm-ps-"])	{ color:var(--theme-link-color, inherit); font-weight:var(--theme-link-bold, inherit); }
.blk-page a.blk-snip-more				{ text-decoration:var(--theme-link-underline, underline); }

/* Caption chrome (earned: Ilkley sub-line + Bellevue pill looks).
   Pill hugs the title (left/right auto-margins centre it without a
   transform, so the hover slide composes); position cells move the
   OVERLAY caption — centre and bottom-left are On Image only (the
   captionClass whitelist gates them). The second line is the list's
   --blk-cap-more string, emitted only in an overlay mode; the built-in
   card carries it as a .blk-card-more span instead. */
.blk-page .-cap-pill :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ left:0; right:0; bottom:0; width:max-content; max-width:85%; margin:0 auto var(--blk-cap-inset, 0.75em); padding:var(--blk-cap-pad, 0.45em 1.2em) !important; border-radius:var(--blk-cap-radius, 999px); background:var(--blk-cap-bg, rgba(255,255,255,0.92)); }
.blk-page .-cap-pill :is(.blk-card-title, [class*="-bind-item-"][class*="title"]):not([class*="thm-ps-"])
										{ color:#1f2329; }
.blk-page .-capp-center :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ bottom:50%; translate:0 50%; margin-bottom:0; }
.blk-page .-capp-bl :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ margin-left:var(--blk-cap-inset, 0.75em); margin-right:auto; margin-bottom:var(--blk-cap-inset, 0.75em); text-align:left; }
.blk-page .-capp-bl:not(.-cap-pill) :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ left:0; right:auto; max-width:85%; }
/* Bottom Left + Pill = the flush-left lozenge (the Bellevue source
   look): anchored to the card's left edge, rounded on its free end
   only, lifted clear of the bottom — a floating pill with a margin
   reads tentative where the flush anchor reads designed. */
.blk-page .-cap-pill.-capp-bl :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ margin-left:0; margin-bottom:var(--blk-cap-inset, 1.1em); padding:var(--blk-cap-pad, 0.5em 1.4em 0.5em 1em) !important; border-radius:var(--blk-cap-radius, 0 999px 999px 0); }
/* Inset Left = the caption inside the bottom-left corner (earned: the
   3bs designers' common look — "completely within the card"): the
   source's fixed 30px margin (the same on its 409px and 624px tiles) and
   three quarters of the card's width. With Pill, the source's 40px corners
   and 15/20px padding. Ahead of the Panel rule, which fills the image
   whatever the position. */
.blk-page .-capp-bli :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ left:0; right:auto; width:75%; max-width:none; box-sizing:border-box; margin:0 0 var(--blk-cap-inset, 30px) var(--blk-cap-inset, 30px); text-align:left; }
.blk-page .-cap-pill.-capp-bli :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ padding:var(--blk-cap-pad, 15px 15px 15px 20px) !important; border-radius:var(--blk-cap-radius, 40px); }
/* Panel = the inset tint wash (earned: North Finchley's Navy inset
   tiles). The caption box fills the image behind a proportional margin
   (the source's fixed 30px ≈ 8% of its tile — proportional holds across
   column counts); padding, the subtle 3% rounding and the Caption
   Colour tint are the source's own numbers, with the bar's dark scrim
   as the unset fallback. Position cells keep their meaning INSIDE the
   panel: Bottom (default) sits the text at the panel's foot, Centre
   centres it, Bottom Left also left-aligns (text-align rides the
   earlier -capp-bl rule; inset/translate here override its geometry). */
.blk-page .-cap-panel :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ inset:var(--blk-cap-inset, 8%); translate:none; width:auto; max-width:none; margin:0; padding:var(--blk-cap-pad, 15px) !important; border-radius:var(--blk-cap-radius, 3%); background:var(--blk-cap-bg, rgba(0,0,0,0.45));
										  display:flex; flex-direction:column; justify-content:flex-end; }
.blk-page .-cap-panel.-capp-center :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ justify-content:center; }
/* Caption Width: Full spans the image less its inset; Hug is as wide as
   the words (centred, or held left by the left positions). A Panel always
   fills, so neither applies to it. */
.blk-page .-capw-full:not(.-cap-panel) :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ left:var(--blk-cap-inset, 0); right:var(--blk-cap-inset, 0); width:auto; max-width:none; margin-left:0; margin-right:0; }
.blk-page .-capw-hug:not(.-cap-panel) :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ width:max-content; max-width:85%; }
.blk-page .-capw-hug:not(.-cap-panel, .-capp-bl, .-capp-bli) :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ margin-left:auto; margin-right:auto; }
.blk-page .-capw-len:not(.-cap-panel) :is(.blk-card-title, [class*="-bind-item-"][class*="title"])
										{ left:var(--blk-cap-inset, 0); right:var(--blk-cap-inset, 0); width:var(--blk-cap-w); max-width:calc(100% - 2 * var(--blk-cap-inset, 0px)); box-sizing:border-box; margin-left:auto; margin-right:auto; }
.blk-card-more,
.blk-page [class*="-cap-"] .blk-card [class*="-bind-item-"][class*="title"]::after
										{ display:block; font-size:0.78em; font-weight:400; opacity:0.85; margin-top:0.2em; }
.blk-page [class*="-cap-"] .blk-card [class*="-bind-item-"][class*="title"]::after
										{ content:var(--blk-cap-more,none); }
/* Second Line Style: the chosen named style's vars; each one the style
   leaves unset follows Body, never the title it hangs from */
.blk-page .-cap-more-ps .blk-card-more,
.blk-page .-cap-more-ps .blk-card [class*="-bind-item-"][class*="title"]::after
										{ font-family:var(--blk-cmore-font, var(--theme-text-font, inherit)); font-size:var(--blk-cmore-size, var(--theme-text-size, 1rem)); font-weight:var(--blk-cmore-weight, normal); font-style:var(--blk-cmore-italic, normal);
										  text-transform:var(--blk-cmore-transform, none); letter-spacing:var(--blk-cmore-spacing, normal); color:var(--blk-cmore-color, inherit); opacity:1; }

/* grouped bottom bands (pinned container) keep the card rhythm */
.blk-page .blk-card .blk-container		{ display:flex; flex-direction:column; gap:0.5em; }
/* a card row whose blocks all rendered nothing (no price, no buy button) takes no room; a styled strip or spacer stays */
.blk-page .blk-card .blk-container:empty:not([style*="background"], [style*="min-height"])	{ display:none; }
/* Bottom-pinning is NOT css magic: the Buy Button block owns an
   'Align To Card Bottom' option that emits margin-top:auto INLINE —
   identical in edit/preview/frontend by construction. Price styling
   keys on the ROLE class the renderer stamps on item-bound blocks
   (-bind-item-price), never on where the block sits — the sibling
   heuristic died the moment price moved into columns. */
.blk-page .blk-card .-bind-item-price	{ font-size:1em; font-weight:600; opacity:1; }
/* Page List carousel: cards become snap cells on the shared track — width
   from the SAME columns/colmin vars the grid uses, so both layouts read one
   set of settings. -car kills the grid display on the block itself. */
.blk-page .blk-folder-list.-car			{ display:block; }
.blk-carousel.-cards .blk-car-track		{ gap:var(--blk-gap,1rem);
	> .blk-card							{ flex:0 0 max(var(--blk-colmin,14rem), calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,3))); min-width:0; scroll-snap-align:start; margin-top:0; }
}

/* Keep Loading: the sentinel spans the whole row (grid or flex wrap); its
   Show More button centres under the cards once auto-loading stops */
.blk-page .blk-list-more				{ grid-column:1 / -1; flex:0 0 100%; text-align:center;
	> .blk-btn[hidden]					{ display:none; }
}

/* File downloads: list or grid of download links. */
.blk-page .blk-file-list				{
	&.-list								{ display:flex; flex-direction:column; gap:var(--blk-gap,0.5rem); }
	&.-grid								{ display:grid; gap:var(--blk-gap,1rem);
										  grid-template-columns:repeat(auto-fill, minmax(max(10rem, calc((100% - (var(--blk-cols,3) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,3) - 0.5px)), 1fr)); }
	.blk-file-row						{ display:flex; align-items:center; gap:0.75em; text-decoration:none; box-sizing:border-box; }
	.blk-file-row:not(.blk-btn)			{ padding:var(--blk-tile-pad, 0.65em 0.85em); border:var(--blk-tile-border, 1px solid #e8e8e8); border-radius:var(--blk-tile-radius, 6px); color:var(--blk-tile-color, inherit); background:var(--blk-tile-bg, #fff);
		&:hover							{ filter:brightness(0.97); }
	}
	.blk-file-icon .thm-ic				{ width:1.4em; height:1.4em; margin:0; }
	/* Look: Pill — as wide as its words, fully rounded; Button — the theme
	   button (.blk-btn), its own colours and corners */
	&.-pill								{ align-items:flex-start;
		.blk-file-row:not(.blk-btn)		{ width:max-content; max-width:100%; border-radius:var(--blk-tile-radius, 999px); padding:var(--blk-tile-pad, 0.45em 1.2em); }
		.blk-file-icon					{ width:1.4em; height:1.4em; }
	}
	&.-button							{ align-items:flex-start;
		.blk-file-row					{ width:max-content; max-width:100%; }
		.blk-file-icon					{ width:1.2em; height:1.2em; }
		.blk-file-size					{ opacity:0.85; }
	}
	.blk-file-icon						{ flex:0 0 auto; width:2.2em; height:2.2em; display:flex; align-items:center; justify-content:center;
		img								{ max-width:100%; max-height:100%; display:block; }
	}
	.blk-file-ext						{ display:inline-block; font-size:0.65em; font-weight:700; letter-spacing:0.04em; padding:0.25em 0.4em; border-radius:3px; background:#eee; color:#555; }
	.blk-file-body						{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:0.15em; }
	.blk-file-title						{ font-weight:600; }
	.blk-file-desc						{ font-size:0.9em; opacity:0.8; }
	.blk-file-size						{ flex:0 0 auto; font-size:0.85em; opacity:0.7; white-space:nowrap; }
}
/* AV gallery: responsive columns of players. */
.blk-page .blk-av-list					{ display:grid; gap:var(--blk-gap,1rem);
										  grid-template-columns:repeat(auto-fill, minmax(max(12rem, calc((100% - (var(--blk-cols,2) - 1) * var(--blk-gap,1rem)) / var(--blk-cols,2) - 0.5px)), 1fr)); }
.blk-page .blk-av-item					{ display:flex; flex-direction:column; gap:0.45em; }
.blk-page .blk-av-player				{ position:relative; aspect-ratio:16/9; background:#111; border-radius:4px; overflow:hidden;
	iframe,video						{ display:block; width:100% !important; height:100%; border:0; max-width:none; object-fit:contain; }
	&.-audio							{ aspect-ratio:auto; background:transparent;
		audio							{ width:100%; }
	}
}
.blk-page .blk-av-ph					{ position:relative; aspect-ratio:16/9; background:#1a1a1a; border-radius:4px; overflow:hidden; display:flex; align-items:center; justify-content:center;
	img									{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; opacity:0.85; }
}
.blk-page .blk-av-title					{ font-weight:600; font-size:0.95em; }

/* Form block fills its container — constrain width by wrapping it in the
   layout, never a form-level max-width (operator 2026-08-18). */
.blk-page .blk-form-ref					{ width:100%; }
.blk-page .blk-form						{ display:flex; flex-direction:column; gap:var(--blk-gap,var(--blk-space-s,1rem)); width:100%; }
.blk-page .blk-form-fields				{ display:flex; flex-direction:column; gap:var(--blk-gap,var(--blk-space-s,1rem)); }
/* fields are .blk siblings — the page rhythm margin would STACK on the
   flex gap (spacing read as bigger than tempo, operator 2026-07-27) */
.blk-page .blk-form-fields > .blk		{ margin-top:0; }
.blk-page .blk-ffield,
.blk-page .blk-fcaptcha					{ display:flex; flex-direction:column; gap:0.35rem;
	.blk-ffield-label:not([class*="thm-ps-"])	{ font-weight:600; }
	.input-block						{ display:block; }
	input:not([type="radio"]):not([type="checkbox"]),
	select, textarea					{ width:100%; max-width:100%; box-sizing:border-box; }
	/* tenant contact-form CSS commonly grids/floats label rows — checks and
	   radios OWN their layout: tick then text, left, whatever the theme says
	   (operator screenshots 2026-07-27, twice — hence the heavy hand) */
	.blk-ffield-check,
	.blk-ffield-radio					{ display:flex !important; align-items:center; justify-content:flex-start !important; gap:0.5em; font-weight:400; text-align:left !important; width:100%; float:none !important;
		input							{ flex:0 0 auto; width:auto !important; margin:0 !important; float:none !important; position:static !important; }
		.blk-ffield-label, span			{ flex:0 1 auto; width:auto !important; text-align:left !important; float:none !important; position:static !important; margin:0 !important; }
	}
	.blk-ffield-radios					{ display:flex; flex-direction:column; gap:0.35em; }
	.blk-prod-custom					{ display:flex; flex-direction:column; gap:var(--blk-gap,var(--blk-space-s,1rem)); }
	.blk-prod-custom-title				{ margin:0; font-weight:600; }
	.blk-prod-custom-note				{ margin:0; }
	.blk-swatch							{ flex:0 0 auto; display:inline-block; font-style:normal; width:1.4em; height:1.4em; border:1px solid currentColor; border-radius:50%; background-size:cover; background-position:center; }
}
/* Form Fields (theme element): every field reads --theme-field-*, each
   chained to the base sheet's field (default.css) so an unset theme is
   unchanged. Ticks, radios and file pickers keep the browser's controls.
   Height is a floor for one-line fields and drop-downs; a message box
   keeps its lines. Focus Colour drives the border and glow; the theme
   sheet stands the browser's ring down only once it is set. */
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) :is(input:not([type="radio"], [type="checkbox"], [type="file"], [type="hidden"]), select, textarea)
										{ border:var(--theme-field-border, 1px) solid var(--theme-field-border-color, #c1c1c1); border-radius:var(--theme-field-radius, 0); background-color:var(--theme-field-bg, Field); color:var(--theme-field-text, FieldText); }
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) input:not([type="radio"], [type="checkbox"], [type="file"], [type="hidden"])
										{ min-height:var(--theme-field-height, 0); padding:var(--theme-field-pad-y, 4px) var(--theme-field-pad-x, 4px); }
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) select
										{ min-height:var(--theme-field-height, 0); padding:var(--theme-field-pad-y, 3px) calc(var(--theme-field-pad-x, 3px) + 15px) var(--theme-field-pad-y, 3px) var(--theme-field-pad-x, 3px); }
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) textarea
										{ padding:var(--theme-field-pad-y, 3px) var(--theme-field-pad-x, 3px); }
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) :is(input, textarea)::placeholder
										{ color:var(--theme-field-placeholder, #888); }
.blk-page :is(.blk-ffield, .blk-prod-variants, .blk-prod-custom) :is(input:not([type="radio"], [type="checkbox"], [type="file"], [type="hidden"]), select, textarea):focus
										{ border-color:var(--theme-field-focus-color, var(--theme-field-border-color, #c1c1c1)); box-shadow:0 0 7px var(--theme-field-focus-color, #7993a3); }
/* Bot Check: the ALTCHA widget sits as a bare tick + text row in the
   form's own type — inputs take the tenant theme, not block tokens */
.blk-page .blk-fcaptcha altcha-widget	{ font:inherit; color:inherit; --altcha-max-width:100%; --altcha-padding:0; --altcha-border-width:0; --altcha-color-base:transparent; --altcha-color-base-content:currentColor; }
/* Honeypot: off-screen, never display:none (some bots skip hidden fields —
   off-screen looks fillable to them, invisible to humans; tabindex -1
   keeps keyboards out) */
.blk-page .blk-hp						{ position:absolute !important; left:-9999px !important; top:auto; width:1px; height:1px; overflow:hidden; }
/* Address finder (postcode field): its rows stack at the form's field gap;
   the found address echoes in small print */
.blk-page .blk-ffield .address-finder	{ display:flex; flex-direction:column; gap:var(--blk-gap,0.75em);
	.af-found							{ font-size:0.9em; opacity:0.8; padding:0 0.2em; }
}
/* Unit suffix (the KG box): input + dark unit cell share one row */
.blk-page .blk-ffield .input-block.-unit	{ display:flex; align-items:stretch;
	input								{ flex:1 1 auto; min-width:0; border-top-right-radius:0; border-bottom-right-radius:0; }
	.blk-ffield-unit					{ flex:0 0 auto; display:flex; align-items:center; padding:0 0.9em; background:#2d2d2d; color:#fff; font-weight:700; font-size:0.85em; letter-spacing:0.04em; border-radius:0 6px 6px 0; }
}
/* Section title inside a form ('Your Details', 'Address' groupings) */
.blk-page .blk-ffield-title				{ margin:0.75em 0 0; font-size:0.82em; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; opacity:0.8; }
/* Labels Left: each field a two-column row — the label in a column of the
   form's Label Width, the input beside it; ticks, the bot check and the
   submit line up with the inputs. Phones stack as Above. */
@media (min-width:769px) {
	.blk-page .blk-form.-labels-left	{
		.blk-ffield:not(:has(> .blk-ffield-check))	{ display:grid; grid-template-columns:var(--blk-flbl-w, 180px) minmax(0, 1fr); column-gap:1em; align-items:center;
			> *							{ grid-column:2; }
			> .blk-ffield-label			{ grid-column:1; margin:0; }
			&:has(textarea, .blk-ffield-radios, .address-finder)	{ align-items:start;
				> .blk-ffield-label		{ padding-top:0.6em; }
			}
		}
		.blk-ffield:has(> .blk-ffield-check),
		.blk-fcaptcha,
		.blk-fsubmit					{ margin-left:calc(var(--blk-flbl-w, 180px) + 1em); }
	}
}
/* Floating labels (form Labels = Floating): label starts inside the input
   and floats to a small line at the top edge on focus/content — the
   modern-form look, done with :has() so the label can stay before the
   input in source order. Only rows the template marked -float (text-ish
   + textarea); selects/checks/radios/titles keep above-labels. */
.blk-page .blk-form.-labels-float .blk-ffield.-float	{ position:relative;
	.blk-ffield-label					{ position:absolute; top:0.62em; left:0.8em; z-index:1; opacity:0.55; pointer-events:none;
										  transition:top .15s ease, font-size .15s ease, opacity .15s ease; }
	.blk-ffield-label:not([class*="thm-ps-"])	{ font-weight:400; }
	input, textarea						{ padding-top:1.35em; }
	/* the label plays the placeholder's role at rest — a real placeholder
	   would double up under it; it appears once the label floats away */
	input::placeholder, textarea::placeholder			{ color:transparent; }
	&:has(input:focus) input::placeholder,
	&:has(textarea:focus) textarea::placeholder			{ color:inherit; opacity:0.4; }
	&:has(input:focus) .blk-ffield-label,
	&:has(textarea:focus) .blk-ffield-label,
	&:has(input:not(:placeholder-shown)) .blk-ffield-label,
	&:has(textarea:not(:placeholder-shown)) .blk-ffield-label
										{ top:0.25em; font-size:0.72em; opacity:0.75; }
}
/* Inside labels (form Labels = Inside): the label is the input's
   placeholder, so the visible label line goes; it stays for screen readers */
.blk-page .blk-form.-labels-inside .blk-ffield.-inside > .blk-ffield-label
										{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.blk-page .blk-ffield.-inside select:has(> option[value=""]:checked)	{ color:var(--theme-field-placeholder, #888); }
.blk-page .blk-ffield.-inside select option							{ color:var(--theme-field-text, FieldText); }
.blk-page .blk-fsubmit					{ margin-top:0.25rem; }
.blk-page .blk-form-msg					{ padding:0.85em 1em; border-radius:6px; background:#eef7ee; color:#1a5c1a;
	&.-error							{ background:#fdecec; color:#8a1f1f; }
	&.-ok								{ background:#eef7ee; color:#1a5c1a; }
}

/* Directory blocks: baseline only — tenant CSS owns the legacy inner
   classes (directory-tel1, directory-email, directory-social). */
.blk-page .blk-dir-contact				{ line-height:1.6;
	.directory-contact					{ font-weight:600; }
	ul.directory-social					{ list-style:none; margin:0.5em 0 0; padding:0; display:flex; flex-wrap:wrap; gap:0.35em 1em; }
}
/* columns inside a card (price | buy footer pattern): compact by default.
   Literal 0.5em, not var(--blk-gap,…): the list's row gap cascades into
   the card, so the fallback would leak it. An EXPLICIT Gap/Vertical
   Alignment on the columns wins — ColumnsType emits both inline. */
.blk-page .blk-card .blk-columns		{ gap:0.5em; align-items:center; }

/*---------------- interactions (V1 2026-08-03) ----------------*/
/* Click actions: the carrier advertises itself; the action runs in
   blocks.js (delegated). Editor canvases never carry these attrs. */
[data-blk-act]							{ cursor:pointer; }

/* Reveal: .blk-rvl-pre (initial state) is JS-APPLIED, never static — a
   visitor whose JS fails sees every block. .blk-in plays the entrance
   (once, or per visit under data-blk-rvl-rpt). A block with an inline
   Offset transform keeps it (inline wins): reveal degrades to its opacity
   half there, by design. Strength (data-blk-amt) multiplies every motion
   distance through --blk-rvl-amt; the pure fades have no distance and
   ignore it. Flip caps shy of 90° — past edge-on it reads mirrored. */
/* the head gate (AssetCatalog reveal-gate) holds reveal blocks back from the
   first paint until blocks.js arms them */
.blk-rvl-wait [data-blk-rvl]:not([data-rvl-armed])	{ opacity:0; }
/* the pre state snaps on (blocks.js rvlPre) */
.blk-rvl-snap							{ transition:none !important; }
.blk-rvl-pre							{ opacity:0; transition:opacity .6s ease-out, transform .6s ease-out; will-change:opacity, transform; }
.blk-rvl-pre[data-blk-amt=subtle]		{ --blk-rvl-amt:.35; }
.blk-rvl-pre[data-blk-amt=strong]		{ --blk-rvl-amt:2.5; }
.blk-rvl-pre[data-blk-rvl=fade_out]		{ opacity:1; }
.blk-rvl-pre[data-blk-rvl=fade_up]		{ transform:translateY(calc(28px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=fade_down]	{ transform:translateY(calc(-28px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=slide_up]		{ opacity:1; transform:translateY(calc(44px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=slide_down]	{ opacity:1; transform:translateY(calc(-44px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=slide_left]	{ opacity:1; transform:translateX(calc(44px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=slide_right]	{ opacity:1; transform:translateX(calc(-44px * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=scale]		{ transform:scale(calc(1 - .14 * var(--blk-rvl-amt,1))); }
.blk-rvl-pre[data-blk-rvl=rotate]		{ transform:rotate(calc(-8deg * var(--blk-rvl-amt,1))) scale(calc(1 - .06 * var(--blk-rvl-amt,1))); }
/* flip's angle meets its cap near Normal, so Strength also moves the
   viewpoint: Subtle turns flatter, Strong turns closer */
.blk-rvl-pre[data-blk-rvl=flip]			{ transform:perspective(calc(800px / var(--blk-rvl-amt,1))) rotateY(min(calc(85deg * var(--blk-rvl-amt,1)), 89deg)); }
.blk-rvl-pre[data-blk-rvl=bounce]		{ transform:scale(max(.4, calc(1 - .3 * var(--blk-rvl-amt,1)))); }
.blk-rvl-pre.blk-in						{ opacity:1; transform:none; will-change:auto; }
.blk-rvl-pre.blk-in[data-blk-rvl=fade_out]	{ opacity:0; }
/* the keyframes' fill would pin transform once the entrance is over and
   swallow an On Hover move, so .blk-rvl-done drops the animation (its last
   frame is the resting state, nothing jumps) */
.blk-rvl-pre.blk-in:not(.blk-rvl-done)[data-blk-rvl=bounce]	{ transition:none; animation:blk-rvl-bounce .65s cubic-bezier(.34,1.56,.64,1) both; }
@keyframes blk-rvl-bounce				{ 0% { opacity:0; transform:scale(max(.4, calc(1 - .3 * var(--blk-rvl-amt,1)))); } 60% { opacity:1; transform:scale(calc(1 + .06 * var(--blk-rvl-amt,1))); } 80% { transform:scale(.98); } 100% { opacity:1; transform:scale(1); } }
/* V2 pacing tokens (Delay / Speed on the On Reveal row). A One By One
   group's Delay is its children's gap, timed in blocks.js (data-rvl-td,
   !important), which wins over these. */
.blk-rvl-pre[data-blk-rvl-delay=short]	{ transition-delay:.15s; animation-delay:.15s; }
.blk-rvl-pre[data-blk-rvl-delay=medium]	{ transition-delay:.4s; animation-delay:.4s; }
.blk-rvl-pre[data-blk-rvl-delay=long]	{ transition-delay:.8s; animation-delay:.8s; }
.blk-rvl-pre[data-blk-rvl-dur=fast]		{ transition-duration:.35s; animation-duration:.4s; }
.blk-rvl-pre[data-blk-rvl-dur=slow]		{ transition-duration:1.1s; animation-duration:1s; }

/* Ambient (V2): a quiet infinite loop while the block is idle. Waits
   for the block's entrance (a not-yet-revealed block must keep its
   offset pre state — animation would override the transform), then
   floats or breathes through the strength multiplier. */
[data-blk-amb-amt=subtle]				{ --blk-amb-amt:.55; }
[data-blk-amb-amt=strong]				{ --blk-amb-amt:1.7; }
[data-blk-amb=float]:not(.blk-rvl-pre),
.blk-rvl-pre.blk-in[data-blk-amb=float]	{ animation:blk-amb-float 4.5s ease-in-out 1s infinite; }
[data-blk-amb=pulse]:not(.blk-rvl-pre),
.blk-rvl-pre.blk-in[data-blk-amb=pulse]	{ animation:blk-amb-pulse 3.6s ease-in-out 1s infinite; }
@keyframes blk-amb-float				{ 0%, 100% { transform:translateY(0); } 50% { transform:translateY(calc(-7px * var(--blk-amb-amt,1))); } }
@keyframes blk-amb-pulse				{ 0%, 100% { transform:scale(1); } 50% { transform:scale(calc(1 + .035 * var(--blk-amb-amt,1))); } }

/* Linked pattern placement: the pattern's blocks are the placement's own
   siblings on the page; on the canvas they sit inert under a label */
.blk-pattern-ref:not(.-edit)			{ display:contents; }
.blk-pattern-ref.-edit					{ position:relative; outline:1px dashed #8fa8c8; outline-offset:2px;
	.blk-pattern-ref-label				{ position:absolute; top:-0.9em; left:0.5em; z-index:2; padding:0.1em 0.5em; font:600 11px/1.4 system-ui, sans-serif; color:#fff; background:#5a7aa6; border-radius:3px; }
	.blk-pattern-ref-body				{ display:flex; flex-direction:column; gap:var(--blk-gap, 1rem); }
}
/* Hover colours (Container): the background as an inset shadow — painted
   over the background image, under the content — and the text colour
   carried into headings and links */
.blk-container.-hovc					{ transition:box-shadow .25s ease, color .25s ease; }
.blk-container.-hovc[style*="--blk-hov-bg"]:hover	{ box-shadow:inset 0 0 0 100vmax var(--blk-hov-bg); }
/* a Shadow is inline, so with one set the hover layer must out-rank it and carry it along */
.blk-container.-hovc[style*="--blk-hov-bg"][style*="--blk-shadow"]:hover	{ box-shadow:inset 0 0 0 100vmax var(--blk-hov-bg), var(--blk-shadow) !important; }
.blk-page .blk-container.-hovc[style*="--blk-hov-c"]:hover,
.blk-page .blk-container.-hovc[style*="--blk-hov-c"]:hover :is(h1, h2, h3, h4, h5, h6, p, li, a:not(.blk-btn), .blk-text, .blk-heading)
										{ color:var(--blk-hov-c); transition:color .25s ease; }
/* Hover: a reversible nudge, pure CSS. Strength (data-blk-hov-amt)
   multiplies through --blk-hov-amt; flip stays a full turn — a partial
   flip holds edge-on and reads broken, so strength doesn't apply. */
/* The hover pace is held off while an entrance is pending or playing: the
   reveal's own transition (.blk-rvl-pre, its Speed and Delay) must time the
   entrance, and blocks.js marks .blk-rvl-done once it has arrived. */
[data-blk-hov]:not(.blk-rvl-pre),
[data-blk-hov].blk-rvl-done				{ transition:opacity .25s ease, transform .25s ease; }
[data-blk-hov-amt=subtle]				{ --blk-hov-amt:.35; }
[data-blk-hov-amt=strong]				{ --blk-hov-amt:2.5; }
[data-blk-hov=fade]:hover				{ opacity:max(.25, calc(1 - .35 * var(--blk-hov-amt,1))); }
[data-blk-hov=up]:hover					{ transform:translateY(calc(-6px * var(--blk-hov-amt,1))); }
[data-blk-hov=down]:hover				{ transform:translateY(calc(6px * var(--blk-hov-amt,1))); }
[data-blk-hov=left]:hover				{ transform:translateX(calc(-6px * var(--blk-hov-amt,1))); }
[data-blk-hov=right]:hover				{ transform:translateX(calc(6px * var(--blk-hov-amt,1))); }
[data-blk-hov=scale]:hover				{ transform:scale(calc(1 + .05 * var(--blk-hov-amt,1))); }
[data-blk-hov=rotate]:hover				{ transform:rotate(calc(3deg * var(--blk-hov-amt,1))); }
[data-blk-hov=flip]:hover				{ transform:perspective(800px) rotateY(180deg); }
[data-blk-hov=bounce]:hover				{ animation:blk-hov-bounce .5s ease; }
@keyframes blk-hov-bounce				{ 0%, 100% { transform:none; } 30% { transform:translateY(calc(-8px * var(--blk-hov-amt,1))); } 55% { transform:translateY(2px); } 75% { transform:translateY(calc(-4px * var(--blk-hov-amt,1))); } }

/* Group hover (V2, Applies To = Images Inside): the card pattern —
   hover the block, the effect plays on the images within; the block
   itself stays still (the reset outranks the self rules by attribute
   count). Images crop at their figure so a zoom stays inside the
   card. Scale zooms IN for images — the classic card treatment.
   Bounce/flip are self-only effects and do nothing in this mode. */
[data-blk-hov][data-blk-hov-t=img]:hover		{ transform:none; opacity:1; animation:none; }
/* A repeated card (.blk-card) names its own transition for the lift, at
   (0,2,0) — over both the hover and the reveal rules, which would leave a
   card's entrance and its hover move snapping instead of easing. These
   re-state the card's pair beside each.
   A card composed as one root block wears that block's On Hover on the
   wrapper (BlockRenderer), which owns the border, radius and clip; the
   root block stands down so the effect plays once, on the whole card. */
.blk-page .blk-card[data-blk-hov]		{ transition:opacity .25s ease, transform .25s ease, box-shadow .15s ease, background-color .15s ease; }
.blk-page .blk-card.blk-rvl-pre			{ transition:opacity .6s ease-out, transform .6s ease-out, box-shadow .15s ease, background-color .15s ease; }
.blk-page .blk-card.blk-rvl-pre[data-blk-rvl-dur=fast]	{ transition-duration:.35s, .35s, .15s, .15s; }
.blk-page .blk-card.blk-rvl-pre[data-blk-rvl-dur=slow]	{ transition-duration:1.1s, 1.1s, .15s, .15s; }
/* entrance over (blocks.js): the hover lift is back to its own pace */
.blk-page .blk-card[data-blk-hov].blk-rvl-done	{ transition-duration:.25s, .25s, .15s, .15s; }
.blk-page .blk-card[data-blk-hov] > [data-blk-hov]:hover,
.blk-page .blk-card[data-blk-hov] > .blk-card-link > [data-blk-hov]:hover
										{ transform:none; opacity:1; animation:none; }
[data-blk-hov-t=img] .blk-image					{ overflow:hidden; }
[data-blk-hov-t=img] img						{ transition:opacity .25s ease, transform .25s ease; }
[data-blk-hov=fade][data-blk-hov-t=img]:hover img	{ opacity:max(.25, calc(1 - .35 * var(--blk-hov-amt,1))); }
[data-blk-hov=up][data-blk-hov-t=img]:hover img		{ transform:translateY(calc(-6px * var(--blk-hov-amt,1))); }
[data-blk-hov=down][data-blk-hov-t=img]:hover img	{ transform:translateY(calc(6px * var(--blk-hov-amt,1))); }
[data-blk-hov=left][data-blk-hov-t=img]:hover img	{ transform:translateX(calc(-6px * var(--blk-hov-amt,1))); }
[data-blk-hov=right][data-blk-hov-t=img]:hover img	{ transform:translateX(calc(6px * var(--blk-hov-amt,1))); }
[data-blk-hov=scale][data-blk-hov-t=img]:hover img	{ transform:scale(calc(1 + .07 * var(--blk-hov-amt,1))); }
[data-blk-hov=rotate][data-blk-hov-t=img]:hover img	{ transform:rotate(calc(2deg * var(--blk-hov-amt,1))) scale(1.03); }

/* !important: the hover pace and the card's pair are stated at higher
   specificity than these bare hooks */
@media (prefers-reduced-motion: reduce) {
	[data-blk-hov], .blk-rvl-pre, [data-blk-amb], [data-blk-hov-t=img] img
										{ transition:none !important; animation:none !important; }
	[data-blk-hov]:hover, [data-blk-hov-t=img]:hover img
										{ transform:none; opacity:1; }
}

/* breadcrumb: the legacy .path class carries default.css's 12px bottom
   margin — inside a block the rhythm system owns spacing (default.css
   itself stays untouched: unflagged sites' legacy widget still needs it) */
.blk-page .blk-breadcrumb .path			{ margin:0; }
/* Sitemap block: top-level sections flow in Columns (one on phones). It
   shares the theme's Lists dress with text (the :is() rules above);
   Markers None strips it back to plain indented links. */
.blk-page .blk-sitemap a					{ text-decoration:none; }
/* Flow: Flat — one even list: no indent per level, and the columns break
   between any two rows rather than only between sections */
.blk-page div.blk-sitemap.-flat			{
	ul ul								{ padding-left:0; margin:0; }
	li									{ break-inside:avoid; }
	&:not(.-markers) li					{ margin-left:0; }	/* with Theme Bullets every row keeps the bullet's indent */
	> ul > li							{ break-inside:auto; }
}
.blk-page .blk-sitemap > ul				{ column-count:var(--blk-sm-cols, 2); column-gap:var(--blk-space-m, 2em); margin-top:0;
	> li								{ break-inside:avoid; }
	> li > a:not([class*="thm-ps-"])	{ font-weight:700; }
}
/* an item too tall for a column starts at the foot of one and its first
   line opens the next, so an absolute marker would straddle the break.
   The marker rides the first line instead: its margin box is exactly
   one line, centred on it as the absolute one is. */
.blk-page .blk-sitemap ul > li::before	{ position:static; display:inline-block; vertical-align:top; margin:calc((1lh - var(--ic)) / 2) 0.4em calc((1lh - var(--ic)) / 2) calc(-1 * var(--ic) - 0.4em); }
.blk-page .blk-sitemap:not(.-markers) ul	{ list-style:none; padding-left:0; }
.blk-page .blk-sitemap:not(.-markers) ul ul	{ padding-left:1em; }
.blk-page .blk-sitemap:not(.-markers) ul > li	{ margin-left:0;
	&::before							{ content:none; }
}
@media (max-width:768px) {
	.blk-page .blk-sitemap > ul			{ column-count:1; }
}
/* Embed block: full-width iframe panel; the editor tile is inert */
.blk-page .blk-embed iframe				{ display:block; width:100%; border:0; }
/* Widget links follow the SURROUNDING text, not the site link token:
   a widget's injected content is foreign — the page's link colour is
   tuned to the page's own surfaces, never to whatever band the widget
   lands in (North Finchley's verse reference: periwinkle on gold ≈
   2.9:1, failing AA; inherited #444 ≈ 6.3:1). A provider stylesheet
   that sets its own colour still wins. */
.blk-page .blk-widget a					{ color:inherit; }
.blk-embed-ph							{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; background:#eef1f5; border:1px dashed #c3cad4; border-radius:6px; color:#5f6b7a;
	svg									{ width:34px; height:34px; }
	img									{ width:40px; height:40px; }
}
.blk-embed-host							{ font-weight:600; font-size:14px; }
.blk-embed-note							{ font-size:12px; color:#8a94a3; }
.blk-embed-note.-warn					{ max-width:34em; color:#b45309; font-size:13px; text-align:center; }

/* A block that SETS its text colour carries its links with it — a navy
   band's links read in the band colour, never the theme link purple.
   The attribute match is exact: ';color:' / leading 'color:' cannot match
   'background-color:'. Blocks without an explicit colour keep theme links.
   BUTTONS are excluded: .blk-btn carries its own bg/text PAIR from the theme
   tokens, and this rule ties (0,3,1) with .blk-btn.-light but lands later in
   the file — so without the :not() a Light button in a coloured band inherited
   the band's colour and went white-on-white (Wylam hero, 2026-08-28).
   A link inside a Use Light Links band takes the theme's light set
   instead (template.css); the :where() keeps the specificity unchanged. */
.blk-page .blk[style^="color:"] a:not(.blk-btn):not(.thm-btn):where(:not(.-light-links a)),
.blk-page .blk[style*=";color:"] a:not(.blk-btn):not(.thm-btn):where(:not(.-light-links a)),
.blk-page .blk[style^="color:"] .blk-card-page-link:where(:not(.-light-links .blk-card-page-link)),
.blk-page .blk[style*=";color:"] .blk-card-page-link:where(:not(.-light-links .blk-card-page-link))
										{ color:inherit; }

/* Site Component (frontend): furniture obeys the BLOCK colour context —
   links inherit the block's text colour instead of the theme link colour,
   so a utility-bar cluster on a dark band reads in the band's colour with
   no tenant CSS. Scoped to the component block only: links in ordinary
   text blocks keep the theme link colour. */
.blk-page .blk-component a,
.blk-page .blk-component a:visited		{ color:inherit; }
.blk-page .blk-component #user-pane li	{ color:inherit; }

/* Search (theme element): both form factors read --theme-search-*, each
   token falling back to the look it had.
   The Search Box rule names #p-search: the base sheet styles it as
   `#search #p-search` — two ids, which no class chain outranks — and would
   otherwise hold it at 80px with a white-on-white icon. The magnifier is a
   mask on the form, not the input's background image, so it takes a colour. */
.blk-page .blk-component #search			{ position:relative; display:inline-block; max-width:100%;
	&::after							{ content:''; position:absolute; right:12px; top:50%; width:var(--theme-search-icon-size, 1.05em); height:var(--theme-search-icon-size, 1.05em); translate:0 -50%; pointer-events:none; background:var(--theme-search-icon-color, #8a8f98); -webkit-mask:url(/media/icons/search.svg) center/contain no-repeat; mask:url(/media/icons/search.svg) center/contain no-repeat; }
}
.blk-page .blk-component #search #p-search
										{ width:min(var(--theme-search-width, 330px), 86cqw); margin:0; padding:10px max(38px, var(--theme-search-icon-size, 0px) + 22px) 10px 12px; border:var(--theme-search-border, 1px) solid var(--theme-search-border-color, #d9d9d9); border-radius:var(--theme-search-radius, 0); background:var(--theme-search-bg, #fff); color:var(--theme-search-text, #1f2329); font:inherit; font-size:1em; line-height:1.3; box-sizing:border-box; }
/* the placeholder follows Text Colour, so it stays legible on a dark
   field; unset lands on the browsers' own mid-grey */
.blk-page .blk-component #search #p-search::placeholder,
.blk-page .blk-component #search-toggle input[type="text"]::placeholder
										{ color:color-mix(in srgb, var(--theme-search-text, #757575) 60%, transparent); opacity:1; }
.blk-page .blk-component #search #p-search:focus-visible,
.blk-page .blk-component #search-toggle input[type="text"]:focus-visible
										{ outline:2px solid var(--theme-search-focus-color, color-mix(in srgb, currentColor 30%, transparent)); outline-offset:1px; box-shadow:0 0 7px var(--theme-search-focus-color, #7993a3); }
/* Search (Icon): the compact form factor both church conversions
   wanted — a currentColor magnifier <label>; clicking it focuses the
   input (native label behaviour, zero JS) and :focus-within expands
   the field; blur collapses it. Enter submits as the open box does. */
.blk-page .blk-component #search-toggle	{ display:flex; align-items:center; }
.blk-page .blk-component #search-toggle label
										{ display:inline-flex; cursor:pointer; padding:0.3em; color:var(--theme-search-icon-color, inherit); }
.blk-page .blk-component #search-toggle svg
										{ width:var(--theme-search-toggle-icon-size, var(--theme-search-icon-size, 1.35em)); height:var(--theme-search-toggle-icon-size, var(--theme-search-icon-size, 1.35em)); }
.blk-page .blk-component #search-toggle .visually-hidden
										{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.blk-page .blk-component #search-toggle input[type="text"]
										{ width:0; padding:10px 0; margin:0; opacity:0; border:var(--theme-search-border, 1px) solid transparent; border-radius:var(--theme-search-radius, 0); background:var(--theme-search-bg, #fff); font-size:1em; box-sizing:border-box; transition:width 0.25s ease, opacity 0.2s ease, padding 0.25s ease; }
.blk-page .blk-component #search-toggle:focus-within input[type="text"]
										{ width:min(var(--theme-search-width, 240px), 60cqw); padding:10px 12px; opacity:1; border-color:var(--theme-search-border-color, #d9d9d9); color:var(--theme-search-text, #1f2329); }
@media (prefers-reduced-motion:reduce) {
	.blk-page .blk-component #search-toggle input[type="text"]	{ transition:none; }
}
/* outer spacing is the BLOCK's job (gap/padding props) — trim the
   furniture's own stray outer margins so component gaps read evenly */
.blk-page .blk-component > :first-child	{ margin-top:0; }
.blk-page .blk-component > :last-child	{ margin-bottom:0; }
/* Mobile Menu Button: bare glyph, the block box IS the button — hug the
   icon on BOTH axes so Background / rounding / padding read as its
   chrome (full rounding = a circle). align-self beats the grid/flex
   default stretch, which pulled the button row-tall into a lozenge
   beside a taller cell (operator screenshot 2026-08-19). */
.blk-page .blk-component:has(> #menu-icon-wrapper)	{ width:fit-content; height:fit-content; }
/* a container's Horizontal Alignment is its inline align-items; the
   button's own centring must yield to it or the setting has no effect */
.blk-page :not([style*="align-items"]) > .blk-component:has(> #menu-icon-wrapper)	{ align-self:center; }
.blk-page .blk-component #menu-icon		{ display:flex; cursor:pointer; }
/* the studio's Mobile Menu › Menu Button box (Background / Padding / Shape
   / Border), unless the block paints a background of its own — then the
   block box is the button */
.blk-page .blk-component:not([style*="background"]) > #menu-icon-wrapper #menu-icon
										{ padding:var(--theme-hb-btn-pad, 0); background:var(--theme-hb-btn-bg, transparent); border-radius:var(--theme-hb-btn-shape, 0); border:var(--theme-hb-btn-border, 0px) solid var(--theme-hb-btn-border-color, currentColor); }
.blk-page .blk-component .hamb-icon-svg	{ display:block; width:var(--theme-hb-btn-size, 1.5em); height:var(--theme-hb-btn-size, 1.5em); }
/* the studio's Mobile Menu › Menu Button colour, unless the block has a
   Text Colour of its own (the set-prop-wins rule) */
.blk-page .blk-component:not([style^="color:"]):not([style*=";color:"]) > #menu-icon-wrapper
										{ color:var(--theme-hb-btn-color); }
.blk-page .blk-component ul				{ margin:0; padding-left:0; }

/* Social Links block. Each <a> is the SPOT, a CSS box; --g is the network's
   glyph as a mask image. The theme's Social Icons element tunes it, and
   every token falls back to the historic look — a disc in the block's Text
   Colour with the glyph knocked out so the band shows through.
   --theme-social-style is a NUMBER: 1 solid, 0 outline, -1 glyph only. It
   drives three things at once, since CSS cannot branch on a word: the
   spot's opacity (negatives clamp to 0), the ring an outline wears by
   default ((1 - s*s) * 2px is 2px only at 0), and the glyph's default
   paint — transparent on a solid spot (the knockout), the spot colour once
   the spot is not filled. Spot and glyph are SIBLING layers: a mask hides
   descendants too, so the glyph's fill cannot live inside the masked spot. */
.blk-social								{ --soc-s:var(--theme-social-style, 1); --soc-g:calc(var(--theme-social-scale, 100) * 1%); }
/* the spot colour, per icon: the block's Text Colour, else the theme Spot
   Colour blended to the network's brand colour by Brand Colours (0% / 100%) */
.blk-social a							{ --soc-c0:var(--blk-social-c, color-mix(in srgb, var(--soc-brand, var(--theme-social-spot-color, currentColor)) var(--theme-social-brand, 0%), var(--theme-social-spot-color, currentColor))); }
.blk-social ul							{ display:flex; flex-wrap:wrap; gap:var(--theme-social-gap, 12px); margin:0; padding:0; list-style:none; }
.blk-social li							{ margin:0; line-height:0; }
/* (0,2,1)/(0,3,1): the admin canvas ships the theme link colour as
   `.template a` / `.template a:hover`, the front end as bare `a` — the
   spot takes the block's Text Colour in both */
.blk-page .blk-social a,
.blk-page .blk-social a:hover			{ --soc-c:var(--soc-hc, var(--soc-c0)); position:relative; display:block; box-sizing:border-box; width:var(--blk-social-size, 36px); height:var(--blk-social-size, 36px); border:var(--theme-social-border, calc((1 - var(--soc-s) * var(--soc-s)) * 2px)) solid var(--soc-c); border-radius:var(--theme-social-shape, 50%); color:inherit; forced-color-adjust:none; print-color-adjust:exact;
	&::before,
	.blk-social-spot					{ content:''; position:absolute; inset:0; border-radius:inherit; }
	.blk-social-spot					{ background:var(--soc-c); opacity:var(--soc-s); transition:background-color .25s ease; -webkit-mask:var(--g) center/var(--soc-g) no-repeat, linear-gradient(#000 0 0); mask:var(--g) center/var(--soc-g) no-repeat, linear-gradient(#000 0 0); -webkit-mask-composite:xor; mask-composite:exclude; }
	&::before							{ background:var(--soc-hg, var(--theme-social-glyph-color, color-mix(in srgb, var(--soc-c) calc((1 - max(var(--soc-s), 0)) * 100%), transparent))); transition:background-color .25s ease; -webkit-mask:var(--g) center/var(--soc-g) no-repeat; mask:var(--g) center/var(--soc-g) no-repeat; }
}
/* Hover (the theme's Social Icons): per icon, in the house easing. The
   hover colours are --soc-hc / --soc-hg, which only exist under :hover —
   an unset theme colour leaves them invalid, so the resting colour shows.
   Each effect is its own property's var; None arms none of them. */
.blk-page .blk-social a					{ transition:transform .25s ease, opacity .25s ease, border-color .25s ease; }
.blk-page .blk-social a:hover			{ --soc-hc:var(--theme-social-hover-spot-color); --soc-hg:var(--theme-social-hover-glyph-color); transform:var(--theme-social-hover-tf, none); opacity:var(--theme-social-hover-op, 1); animation:var(--theme-social-hover-anim, none); }
@media (prefers-reduced-motion: reduce) {
	.blk-page .blk-social a:hover		{ transform:none; animation:none; }
}
/* a header / footer compiled before the glyph masks carries an inline
   <svg> disc per link until its next publish: it fills the spot box and
   takes the text colour */
.blk-social a > svg						{ display:block; width:100%; height:100%; fill:currentColor; }
.blk-social-ph							{ padding:8px 12px; border:1px dashed #c3cad4; border-radius:6px; color:#8a94a3; font-size:13px; }

/* per-media tile scale (logo normalising): the figure carries
   --blk-img-scale ('NN%'); the modern `scale` property takes the
   percentage directly. Attribute-scoped — no identity transform on
   every image. Bound tiles and static Media children both emit it. */
.blk-page .blk-image[style*="--blk-img-scale"] > img,
.blk-page .blk-image[style*="--blk-img-scale"] > .blk-arc > img	{ scale: var(--blk-img-scale); transform-origin:center; }

/* ---- Calendar block ------------------------------------------------ */
/* --theme-cal-* names follow the field keys (cssVars / Table Style). */
.blk-page .blk-cal						{ container-type:inline-size; --cal-line:var(--theme-cal-line-color,#e5e5e5); --cal-today:var(--theme-cal-today-color,var(--theme-role-primary,#4a6fa5)); --cal-weekend:var(--theme-cal-weekend-bg,#fafafa); --cal-radius:var(--theme-cal-chip-radius,4px);
	[x-cloak]							{ display:none; }
}
.blk-page .blk-cal-head					{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin:0 0 12px; }
.blk-page .blk-cal-arrow				{ display:inline-flex; align-items:center; justify-content:center; width:2em; height:2em; border-radius:50%; text-decoration:none; color:inherit;
	svg									{ width:1.15em; height:1.15em; display:block; } }
.blk-page .blk-cal-arrow:hover			{ background:var(--cal-weekend); }
/* the title IS the dropdown: a select wearing the heading, the chevron its only chrome (default.css styles bare selects as form fields) */
.blk-page .blk-cal-head select.blk-cal-title	{ appearance:none; -webkit-appearance:none; -moz-appearance:none; width:auto; display:inline-block; border:0; border-radius:0; background:transparent; color:var(--cal-today); font:inherit; font-size:1.05em; font-weight:600; line-height:1.2; margin:0; padding:0 1.3em 0 .2em; cursor:pointer; outline:0; box-shadow:none;
	background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234a6fa5' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>"); background-repeat:no-repeat; background-position:right .2em center; background-size:.7em; }
.blk-page .blk-cal-head select.blk-cal-title:focus	{ outline:0; border:0; box-shadow:none; }
.blk-page .blk-cal-head select.blk-cal-title:focus-visible	{ outline:2px solid var(--cal-today); outline-offset:2px; }
/* the List view has no month to move: arrows and the range dropdown hide, the pills stay */
.blk-page .blk-cal.-list .blk-cal-arrow, .blk-page .blk-cal.-list .blk-cal-jump	{ display:none; }
/* a meta line: icon in the gutter, text wraps aligned with its own first line */
.blk-page .blk-cal-meta					{ display:grid; grid-template-columns:1em 1fr; column-gap:.45em; align-items:start; min-width:0;
	.blk-cal-ico						{ width:1em; height:1em; margin-top:.12em; opacity:.75; }
	a									{ color:inherit; } }
/* Month | List: the back-end radio pills */
.blk-page .blk-cal-views				{ display:inline-flex; margin-left:auto; padding:3px; border-radius:999px; background:var(--cal-weekend); border:1px solid var(--cal-line); }
.blk-page .blk-cal-pill-opt				{ padding:.25em .9em; border-radius:999px; text-decoration:none; color:inherit; font-size:.85em; line-height:1.4; }
.blk-page .blk-cal-pill-opt[aria-pressed="true"]	{ background:var(--cal-today); color:#fff; }
.blk-page .blk-cal .sr-only				{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.blk-page .blk-cal-legend				{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:12px; }
.blk-page .blk-cal-pill					{ display:inline-flex; align-items:center; gap:6px; border:1px solid var(--cal-line); border-radius:999px; padding:2px 10px; background:transparent; color:inherit; font:inherit; font-size:.85em; line-height:1.2; cursor:pointer; }
.blk-page .blk-cal-pill[aria-pressed="false"]	{ opacity:.45; text-decoration:line-through; }
.blk-page .blk-cal-dot					{ display:inline-block; width:.6em; height:.6em; border-radius:50%; background:var(--src,currentColor); flex:none; }
/* the event mark: a short vertical bar in the source colour (Apple's current grammar) */
.blk-page .blk-cal-mark					{ display:inline-block; width:3px; height:1em; border-radius:2px; background:var(--src,currentColor); flex:none; align-self:center; margin-right:.2em; }
.blk-page .blk-cal-body					{ display:grid; grid-template-columns:1fr 0; gap:0; transition:grid-template-columns .25s ease, gap .25s ease; }
.blk-page .blk-cal-grid					{ border-left:1px solid var(--cal-line); border-top:1px solid var(--cal-line); }
.blk-page .blk-cal-weekdays				{ display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); font-size:.8em; text-transform:uppercase; letter-spacing:.04em; opacity:.7;
	> div								{ padding:4px 6px; border-right:1px solid var(--cal-line); border-bottom:1px solid var(--cal-line); min-width:0; }
}
.blk-page .blk-cal-week					{ display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); grid-auto-rows:min-content; min-height:6.5rem; border-bottom:1px solid var(--cal-line);
	/* column lines run the full row height, and the weekend tint fills its two columns, however tall the row — backgrounds, not per-child borders */
	background-image:linear-gradient(to right, var(--cal-line) 1px, transparent 1px);
	background-size:calc(100% / 7) 100%; background-repeat:repeat-x; }
.blk-page .blk-cal-day					{ cursor:pointer; }
.blk-page .blk-cal-hit					{ display:block; }
/* the weekend tint rides the day's own hit target, so Sunday-start weeks tint the right two days */
.blk-page .blk-cal-day.-weekend .blk-cal-hit	{ background:var(--cal-weekend); }
.blk-page .blk-cal-day:hover .blk-cal-hit	{ background:rgba(0,0,0,.035); }
/* the event whose popover is open */
.blk-page .blk-cal-chip.-open, .blk-page .blk-cal-bar.-open, .blk-page .blk-cal-item.-open, .blk-page .blk-cal-card.-open,
.blk-page .blk-cal-chip:focus-visible, .blk-page .blk-cal-bar:focus-visible, .blk-page .blk-cal-item:focus-visible, .blk-page .blk-cal-card:focus-visible	{ outline:2px solid var(--cal-today); outline-offset:1px; }
.blk-page .blk-cal-day[aria-selected="true"] .blk-cal-num	{ background:color-mix(in srgb, var(--cal-today) 16%, transparent); }
.blk-page .blk-cal-day.-today[aria-selected="true"] .blk-cal-num	{ background:var(--cal-today); }
/* children sit on the week grid by grid-column; the cell keeps role + dataset */
.blk-page .blk-cal-day					{ grid-row:1 / span calc(var(--lanes) + 2); display:contents; }
.blk-page .blk-cal-day > *				{ grid-column:inherit; }
.blk-page .blk-cal-num					{ grid-row:1; justify-self:end; margin:4px 5px 0 0; width:1.75em; height:1.75em; border:0; border-radius:50%; background:transparent; color:inherit; font:inherit; font-size:.72em; padding:0; line-height:1.75em; text-align:center; cursor:pointer; }
.blk-page .blk-cal-num:focus, .blk-page .blk-cal-num:focus-visible	{ outline:0; }
.blk-page .blk-cal-day.-today .blk-cal-num	{ background:var(--cal-today); color:#fff; font-weight:600; }
.blk-page .blk-cal-day.-out .blk-cal-num	{ opacity:.35; }
.blk-page .blk-cal-month-label			{ grid-row:1; justify-self:start; align-self:center; margin:6px 0 0 6px; font-size:.65em; text-transform:uppercase; letter-spacing:.04em; opacity:.7; }
.blk-page .blk-cal-chips				{ display:flex; flex-direction:column; gap:5px; padding:2px 4px 6px; min-width:0; overflow:hidden; }
/* an entry: title over time, the mark running both lines */
.blk-page .blk-cal-chip, .blk-page .blk-cal-more	{ display:flex; align-items:stretch; gap:5px; border:0; background:transparent; color:inherit; font:inherit; font-size:.68em; line-height:1.25; text-align:left; padding:0 2px; border-radius:var(--cal-radius); cursor:pointer; min-width:0;
	.blk-cal-mark						{ height:auto; align-self:stretch; margin:1px 0; }
	.blk-cal-chip-text					{ display:flex; flex-direction:column; min-width:0; }
	.blk-cal-chip-title					{ overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
	.blk-cal-time						{ font-size:.9em; opacity:.6; }
}
.blk-page .blk-cal-chip:hover, .blk-page .blk-cal-bar:hover	{ filter:brightness(.92); }
.blk-page .blk-cal-more					{ opacity:.7; cursor:pointer; }
.blk-page .blk-cal-bar					{ margin:1px 2px; padding:1px 6px; border:0; border-radius:var(--cal-radius); background:var(--src); color:#fff; font:inherit; font-size:.68em; line-height:1.25; text-align:left; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; cursor:pointer; z-index:1; }
.blk-page .blk-cal-bar.-cl				{ border-radius:0 var(--cal-radius) var(--cal-radius) 0; margin-left:0; }
.blk-page .blk-cal-bar.-cr				{ border-radius:var(--cal-radius) 0 0 var(--cal-radius); margin-right:0; }
.blk-page .-cancelled					{ text-decoration:line-through; opacity:.6; }
.blk-page .blk-cal-dots					{ display:none; }
.blk-page .blk-cal-pane					{ border:1px solid var(--cal-line); border-radius:var(--cal-radius); padding:12px; font-size:.9em; overflow:hidden; opacity:0; visibility:hidden; transform:translateX(24px); transition:opacity .25s ease, transform .25s ease, visibility 0s linear .25s; }
.blk-page .blk-cal.-pane .blk-cal-pane	{ opacity:1; visibility:visible; transform:none; transition:opacity .25s ease .05s, transform .25s ease .05s, visibility 0s; }
.blk-page .blk-cal-pane-head			{ display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
/* pane row: the mark runs the row's full height; time, title and place each on their own line */
.blk-page .blk-cal-item					{ display:grid; grid-template-columns:auto 1fr; gap:1px 10px; align-items:start; width:100%; border:0; border-top:1px solid var(--cal-line); background:transparent; color:inherit; font:inherit; font-size:.95em; line-height:1.25; text-align:left; padding:8px 0; cursor:pointer;
	.blk-cal-mark						{ grid-row:1 / span 3; align-self:stretch; height:auto; margin:2px 0; }
	.blk-cal-item-title					{ grid-column:2; font-weight:600; }
	.blk-cal-item-when, .blk-cal-item-where	{ grid-column:2; font-size:.85em; opacity:.7; }
}
.blk-page .blk-cal-pop					{ position:fixed; inset:auto 16px 16px 16px; width:auto; height:auto; max-width:480px; margin:0 auto; border:0; background:#fff; color:#222; border-radius:8px; box-shadow:0 12px 40px rgba(0,0,0,.25); padding:0; z-index:1000; font-size:1em; line-height:1.4; max-height:calc(100vh - 32px); box-sizing:border-box; display:flex; flex-direction:column; overflow:hidden;
	.blk-cal-pop-scroll					{ overflow:auto; overscroll-behavior:contain; padding:20px 20px 18px; min-height:0; }
	/* a poster banner: full width, its own proportions up to a cap, cropped only past that */
	.blk-cal-pop-img					{ display:block; width:calc(100% + 40px); height:auto; max-height:260px; object-fit:cover; margin:-20px -20px 16px; border-radius:8px 8px 0 0; }
	.blk-cal-pop-title					{ margin:0 28px .5em 0; font-size:1.15em; font-weight:600; line-height:1.3; }
	.blk-cal-pop-meta					{ display:flex; flex-direction:column; gap:.25em; margin-bottom:.9em; font-size:.85em; opacity:.75; }
	.blk-cal-pop-desc					{ margin:0 0 .6em; }
	.blk-cal-pop-url, .blk-cal-pop-att	{ margin:.4em 0 0; font-size:.9em; } }
/* one close control for the pane and the popover: a quiet grey disc, none of the theme button's chrome */
.blk-page .blk-cal-close				{ width:1.7em; height:1.7em; border:0; border-radius:50%; background:rgba(0,0,0,.08); color:#444; font:inherit; font-size:1em; line-height:1.7em; text-align:center; padding:0; box-shadow:none; cursor:pointer; flex:none; }
.blk-page .blk-cal-close:hover			{ background:rgba(0,0,0,.14); }
.blk-page .blk-cal-close:focus-visible	{ outline:2px solid var(--cal-today); outline-offset:1px; }
.blk-page .blk-cal-pop-close			{ position:absolute; top:10px; right:10px; background:rgba(255,255,255,.85); z-index:1; }
.blk-page .blk-cal-pop-close:hover		{ background:#fff; }
.blk-page .blk-cal-list-date			{ margin:1.2em 0 .4em; }
.blk-page .blk-cal-cards				{ display:grid; gap:14px; margin-bottom:1.4em;
	/* borderless and unpainted by default — the shared card chrome's white is a tile default, not a row's; the Card tab's border and background still win through their vars */
	> .blk-card							{ border:var(--blk-tile-border,0); padding:var(--blk-tile-pad,2px 0); background:var(--blk-tile-bg,transparent); box-shadow:var(--blk-tile-shadow,none); }
}
/* a list card: the mark is its own column and runs the card's height; title, then time and place */
.blk-page .blk-cal-card					{ text-align:left; color:inherit; font:inherit; font-size:inherit; line-height:1.25; cursor:pointer; display:grid; grid-template-columns:auto 1fr; column-gap:10px; align-items:stretch;
	> .blk-cal-mark						{ align-self:stretch; height:auto; margin:2px 0; width:3px; }
	.blk-cal-card-body					{ display:flex; flex-direction:column; gap:.3em; min-width:0; }
	.blk-card-title						{ padding:0;
		&:not([class*="thm-ps-"])		{ font-weight:600; }
	}
	.blk-card-snippet					{ font-size:.85em; opacity:.7; padding:0; display:flex; flex-direction:column; gap:.15em; } }
.blk-page .blk-cal-tag					{ display:inline-block; font-size:.75em; padding:0 6px; border-radius:999px; background:var(--cal-weekend); margin-left:6px; }
.blk-page .blk-cal-showmore				{ text-align:center; margin:.4em 0 0; }
.blk-page .blk-cal-errors				{ color:#b00; font-size:.85em; }

/* desktop: the day pane beside the grid (Outlook) */
@container (min-width:900px) {
	.blk-page .blk-cal.-pane .blk-cal-body	{ grid-template-columns:1fr 300px; gap:16px; }
	.blk-page .blk-cal-pop				{ inset:50% auto auto 50%; transform:translate(-50%,-50%); }
}
/* phone: dots under the day number, the selected day's list beneath (Apple) */
@container (max-width:640px) {
	.blk-page .blk-cal-week				{ min-height:0; }
	.blk-page .blk-cal-bar, .blk-page .blk-cal-chips	{ display:none; }
	.blk-page .blk-cal-dots				{ display:flex; gap:2px; justify-content:center; padding:0 0 6px; grid-row:2;
		.blk-cal-dot					{ width:.45em; height:.45em; }
		.-more							{ background:none; font-size:.6em; line-height:1; }
	}
	.blk-page .blk-cal-num				{ justify-self:center; margin:4px auto 0; }
	.blk-page .blk-cal-day				{ grid-row:1 / span 2; }
	.blk-page .blk-cal-body				{ grid-template-columns:1fr; grid-template-rows:auto 0; }
	.blk-page .blk-cal.-pane .blk-cal-body	{ grid-template-columns:1fr; grid-template-rows:auto auto; }
	.blk-page .blk-cal-pane				{ border:0; border-top:1px solid var(--cal-line); border-radius:0; padding:12px 0; transform:translateY(12px); }
	.blk-page .blk-cal-head select.blk-cal-title	{ font-size:1.2em; }
	.blk-page .blk-cal-views			{ margin-left:0; }
	.blk-page .blk-cal-month-label		{ display:none; }
}

/*---------------- Forum block ----------------*/
/* Tokens map once on the root; rows, cards and the menu read them. The compose dialogs
   render in #alpine-modal-root, outside the block, so their rules repeat there. */
.blk-page .blk-forum					{ container-type:inline-size; --forum-line:var(--theme-cal-line-color,#e5e5e5); --forum-muted:color-mix(in srgb, currentColor 60%, transparent); --forum-accent:var(--theme-role-primary,#4a6fa5); --forum-chip:var(--theme-cal-weekend-bg,#f4f4f4); --forum-radius:var(--blk-radius-s);
	[x-cloak]							{ display:none; }
	button.blk-btn						{ appearance:none; -webkit-appearance:none; margin:0; cursor:pointer; }
	:is(ol,ul) > li						{ margin:0; }
	.sr-only							{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
}
.blk-page .blk-forum-row,
.blk-page .blk-forum-thread,
.blk-page .blk-forum-latest,
.blk-page .blk-forum-post				{ border:var(--blk-tile-border,1px solid var(--forum-line)); border-radius:var(--blk-tile-radius,var(--forum-radius)); background:var(--blk-tile-bg,transparent); color:var(--blk-tile-color,inherit); box-shadow:var(--blk-tile-shadow,none); padding:var(--blk-tile-pad,.6em .8em); }
.blk-page :is(.blk-forum-row, .blk-forum-thread, .blk-forum-latest, .blk-forum-post) + :is(.blk-forum-row, .blk-forum-thread, .blk-forum-latest, .blk-forum-post)
										{ margin-top:.5em; }
.blk-page .blk-forum-head				{ margin:0 0 .8em; }
.blk-page .blk-forum-head h2,
.blk-page .blk-forum-cat h2,
.blk-page .blk-forum-thread h3,
.blk-page .blk-forum-latest h3			{ margin:0 0 .3em; font-size:1.05em; line-height:1.3; font-weight:600; }
.blk-page .blk-forum-head > p			{ margin:.2em 0 .6em; color:var(--forum-muted); }
.blk-page .blk-forum-by					{ margin:0; }
.blk-page .blk-forum-by time,
.blk-page .blk-forum-ago,
.blk-page .blk-forum-permalink,
.blk-page .blk-forum-count,
.blk-page .blk-forum-empty,
.blk-page .blk-forum-missing,
.blk-page .blk-forum-note,
.blk-page .blk-forum-snippet			{ color:var(--forum-muted); }
.blk-page .blk-forum-permalink			{ text-decoration:none; }
.blk-page .blk-forum-author				{ font-weight:600; }
.blk-page .blk-forum-note.-error		{ color:var(--forum-accent); }
.blk-page .blk-forum-trail ol			{ display:flex; flex-wrap:wrap; gap:.35em; list-style:none; margin:0 0 .8em; padding:0; }
.blk-page .blk-forum-trail li + li::before
										{ content:'/'; margin-right:.35em; color:var(--forum-muted); }
.blk-page .blk-forum-trail [aria-current]
										{ font-weight:600; }
.blk-page .blk-forum-cat				{ margin:0 0 1.2em; }
.blk-page .blk-forum-row				{ display:flex; flex-wrap:wrap; align-items:baseline; gap:.2em .8em; text-decoration:none; }
.blk-page .blk-forum-row-name			{ font-weight:600; }
.blk-page .blk-forum-row-desc			{ flex:1 1 100%; color:var(--forum-muted); }
.blk-page .blk-forum-thread			{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:flex-start; gap:.4em .8em; }
.blk-page .blk-forum-thread-main		{ flex:1 1 auto; min-width:0; }
.blk-page .blk-forum-post,
.blk-page .blk-forum-latest				{ display:flex; flex-direction:column; gap:.4em; }
.blk-page .blk-forum-latest > *			{ margin:0; }
.blk-page .blk-forum-thread.-sticky,
.blk-page .blk-forum-post.-op,
.blk-page .blk-forum-post.-focused		{ border-inline-start:3px solid var(--forum-accent); }
.blk-page .blk-forum-post.-op			{ background:var(--blk-tile-bg,color-mix(in srgb, var(--forum-chip) 45%, transparent)); }
.blk-page .blk-forum-post.-ancestor		{ background:color-mix(in srgb, var(--forum-chip) 70%, transparent); }
.blk-page .blk-forum-stats				{ display:flex; flex-wrap:wrap; gap:.35em .8em; margin:0; color:var(--forum-muted); font-size:.85em; }
.blk-page .blk-forum-chips,
.blk-page .blk-forum-badges				{ display:flex; flex-wrap:wrap; gap:.35em; list-style:none; margin:.35em 0 0; padding:0; }
.blk-page .blk-forum-chips a,
.blk-page .blk-forum-badge				{ display:inline-block; border-radius:999px; background:var(--forum-chip); padding:.1em .6em; font-size:.85em; text-decoration:none; }
.blk-page .blk-forum-search				{ margin:0 0 .8em;
	> summary							{ width:fit-content; cursor:pointer; color:var(--forum-muted); }
	&[open] > summary					{ margin-bottom:.5em; }
}
.blk-page .blk-forum-filters			{ display:flex; flex-wrap:wrap; gap:.75em; align-items:flex-end; }
.blk-page .blk-forum-field				{ display:flex; flex-direction:column; gap:.2em; flex:1 1 10em; min-width:0; }
.blk-page .blk-forum-field > span		{ font-size:.85em; color:var(--forum-muted); }
.blk-page .blk-forum-field :is(input,select,textarea)
										{ width:100%; box-sizing:border-box; border:var(--theme-field-border,1px) solid var(--theme-field-border-color,#c1c1c1); border-radius:var(--theme-field-radius,0); background-color:var(--theme-field-bg,Field); color:var(--theme-field-text,FieldText); min-height:var(--theme-field-height,0); padding:var(--theme-field-pad-y,4px) var(--theme-field-pad-x,4px); }
.blk-page .blk-forum-field :is(input,select,textarea):focus
										{ border-color:var(--theme-field-focus-color,var(--theme-field-border-color,#c1c1c1)); box-shadow:0 0 7px var(--theme-field-focus-color,#7993a3); outline:0; }
.blk-page .blk-forum .blk-forum-md		{ line-height:1.5; overflow-wrap:anywhere;
	p									{ margin:0 0 .6em; }
	blockquote							{ margin:.4em 0; padding:.2em .8em; border-left:3px solid var(--forum-line); color:var(--forum-muted); }
	pre									{ overflow-x:auto; background:var(--forum-chip); border-radius:var(--forum-radius); padding:.6em .8em; }
	code								{ background:var(--forum-chip); border-radius:var(--forum-radius); padding:0 .25em; }
	pre code							{ background:none; padding:0; }
	ul,
	ol									{ margin:.4em 0; padding-left:1.4em; }
	table								{ width:100%; border-collapse:collapse; }
	th,
	td									{ border:1px solid var(--forum-line); padding:.3em .5em; text-align:left; }
	&.-clip								{ display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:6; overflow:hidden; }
	&.-clip.-open						{ display:block; -webkit-line-clamp:unset; overflow:visible; }
}
.blk-page .blk-forum-gallery			{ display:flex; flex-wrap:wrap; gap:.5em; list-style:none; margin:.6em 0 0; padding:0; }
.blk-page .blk-forum-gallery img		{ flex:1 1 8em; max-width:100%; height:auto; border-radius:var(--forum-radius); }
.blk-page .blk-forum-post-head,
.blk-page .blk-forum-foot				{ display:flex; flex-wrap:wrap; align-items:center; gap:.3em .8em; }
.blk-page .blk-forum-foot:not(:has(*))	{ display:none; }
.blk-page .blk-forum-mod				{ position:relative; margin-left:auto; }
.blk-page .blk-forum-menu				{ z-index:5; width:max-content; list-style:none; margin:0; padding:.25em 0; background:var(--theme-role-surface,#fff); border:1px solid var(--forum-line); border-radius:var(--forum-radius); box-shadow:var(--theme-shadow-medium,0 4px 14px rgba(0,0,0,0.16)); }
.blk-page .blk-forum-menu button		{ display:block; width:100%; appearance:none; -webkit-appearance:none; margin:0; padding:.4em .8em; border:0; background:transparent; color:inherit; font:inherit; text-align:start; cursor:pointer; }
.blk-page .blk-forum-menu button.-danger
										{ font-weight:700; }
.blk-page .blk-forum-menu button:hover,
.blk-page .blk-forum-menu button:focus-visible
										{ background:var(--forum-chip); }
.blk-page .blk-forum-more				{ margin:.6em 0 0; }
/* The reply view's context strip grows by --forum-pull while the post is pulled down. */
.blk-page .blk-forum-context			{ position:relative; display:flex; align-items:flex-end; justify-content:center; box-sizing:border-box; min-height:calc(2.4em + var(--forum-pull, 0px)); margin:0 0 .5em; padding:.5em; border:1px dashed var(--forum-line); border-radius:var(--forum-radius); color:var(--forum-muted); font-size:.9em; transition:min-height .2s ease;
	&.-pulling							{ transition:none; }
	&.-ready, &.-loading				{ color:var(--forum-accent); border-color:currentColor; }
	&:has(.blk-forum-context-load:focus) .blk-forum-context-hint
										{ display:none; }
}
.blk-page .blk-forum-context-hint::before
										{ content:'\2191'; display:inline-block; margin-right:.4em; transition:transform .2s ease; }
.blk-page .blk-forum-context.-ready .blk-forum-context-hint::before
										{ transform:rotate(180deg); }
.blk-page .blk-forum-context-load		{ appearance:none; -webkit-appearance:none; margin:0; padding:0; border:0; background:none; color:var(--forum-accent); font:inherit; text-decoration:underline; cursor:pointer;
	&:not(:focus)						{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
}
#alpine-modal-root .blk-forum-editor	{ margin:0 0 .6em; }
#alpine-modal-root .blk-forum-editor-bar
										{ display:flex; flex-wrap:wrap; gap:.25em; margin:0 0 .4em; }
#alpine-modal-root .blk-forum-tool		{ appearance:none; -webkit-appearance:none; min-width:2.2em; margin:0; padding:.25em .6em; border:1px solid var(--theme-field-border-color,#c1c1c1); border-radius:var(--theme-field-radius,4px); background:var(--theme-field-bg,#fff); color:inherit; font:inherit; font-size:.9em; line-height:1.4; cursor:pointer;
	&:hover,
	&.-on								{ background:var(--theme-cal-weekend-bg,#f4f4f4); }
}
#alpine-modal-root .blk-forum-editor-input
										{ width:100%; box-sizing:border-box; min-height:8em; border:var(--theme-field-border,1px) solid var(--theme-field-border-color,#c1c1c1); border-radius:var(--theme-field-radius,0); background-color:var(--theme-field-bg,Field); color:var(--theme-field-text,FieldText); padding:var(--theme-field-pad-y,4px) var(--theme-field-pad-x,4px); }
#alpine-modal-root .blk-forum-editor-input:focus
										{ border-color:var(--theme-field-focus-color,var(--theme-field-border-color,#c1c1c1)); box-shadow:0 0 7px var(--theme-field-focus-color,#7993a3); outline:0; }
#alpine-modal-root .blk-forum-quote		{ margin:0 0 .8em; padding:.6em .8em; border-left:3px solid var(--theme-cal-line-color,#e5e5e5); background:var(--theme-cal-weekend-bg,#f4f4f4); border-radius:var(--blk-radius-s,4px); }
#alpine-modal-root .blk-forum-md		{ line-height:1.5; overflow-wrap:anywhere; }
#alpine-modal-root .blk-forum-note,
#alpine-modal-root .blk-forum-ago		{ color:color-mix(in srgb, currentColor 60%, transparent); }
#alpine-modal-root .blk-forum-note.-error
										{ color:var(--theme-role-primary,#4a6fa5); }
#alpine-modal-root .blk-forum-by		{ margin:0 0 .3em; }
@container (max-width:640px) {
	.blk-page .blk-forum-thread			{ flex-direction:column; }
	.blk-page .blk-forum-stats,
	.blk-page .blk-forum-foot			{ width:100%; }
	.blk-page .blk-forum-mod			{ margin-left:0; }
}
