/*
Theme Name:        BlackCloak PCS
Theme URI:         https://my.blackcloak.io
Author:            BlackCloak
Author URI:        https://blackcloak.io
Description:       Block-native (FSE) presentation theme for BlackCloak Private Client Services. Supplies design-token values (--bc-*) consumed by the portable BlackCloak Blocks plugin. Presentation only — reusable functionality lives in the plugin.
Requires at least: 6.6
Tested up to:      7.0
Requires PHP:      8.2
Version:           0.1.0
License:           GNU General Public License v2 or later
License URI:       https://www.gnu.org/licenses/gpl-2.0.html
Text Domain:       blackcloak-pcs
Tags:              full-site-editing, block-patterns, blog, news
*/

/*
 * Styling lives in theme.json (global styles) and patterns. This file carries
 * the theme header and any unavoidable overrides only. Do NOT hard-code brand
 * values here — define them as --bc-* tokens in theme.json (CLAUDE.md §9).
 */

/*
 * Sticky header. bc/site-header sets position:sticky when configured, but it
 * sits inside a template-part wrapper whose box is only the header's own height,
 * so it can't stick. Promote the sticky to that wrapper (a direct child of the
 * tall page wrapper) when the header inside is sticky — no extra markup needed.
 */
.wp-block-template-part:has(> .bc-site-header--sticky) {
	position: sticky;
	top: 0;
	z-index: 30;
}

/*
 * With the cross-site switcher present, the sticky wrapper parks 2.5rem
 * (the switcher's fixed height) above the viewport: the switcher shows at
 * page top, slides away on scroll, and the main bar pins. Mirrors the
 * block's own --sticky:has() rule, which is inert here because the sticky
 * was promoted to this wrapper.
 */
.wp-block-template-part:has(> .bc-site-header--sticky .bc-site-header__switcher) {
	top: -2.5rem;
}

/*
 * The footer always kisses the content above it: the wp-site-blocks flow
 * gap otherwise shows as a page-background strip between a full-bleed
 * closing band (the sand CTAs ending most templates) and the navy footer
 * (the mirror of the contact hero's main rule further down). Unconditional
 * — invisible where a page ends on the plain background, the strip
 * everywhere else. Lives up here so the template-part selectors ascend in
 * specificity (stylelint's no-descending-specificity).
 */
.wp-site-blocks > .wp-block-template-part:has(.bc-site-footer) {
	margin-block-start: 0;
}

/* Keep the sticky header above the admin bar on the front end. */
.admin-bar .wp-block-template-part:has(> .bc-site-header--sticky) {
	top: 32px;
}

.admin-bar
	.wp-block-template-part:has(
		> .bc-site-header--sticky .bc-site-header__switcher
	) {
	top: calc(32px - 2.5rem);
}

/*
 * Inner-page header band: a subtle full-bleed tint behind the breadcrumbs +
 * page/archive title, so content pages open with a refined header zone rather
 * than the bare page surface. The group is alignfull (breaks out of the constrained main)
 * with a constrained inner layout that keeps the copy aligned with the body.
 */
.bc-page-header {
	margin-top: 0;
	margin-bottom: var(--bc-space-xl, 4rem);
	padding-block: var(--bc-space-lg, 2.5rem);
	background-color: var(--bc-color-surface-muted, #f0ede6);
	border-bottom: 1px solid var(--bc-color-border, #d9cfbf);
}

/*
 * Align the breadcrumbs + title with the header chrome: their inner column uses
 * the same wide container + inline padding as the site-header bar, so the page
 * title starts exactly where the logo starts (not the narrower content column).
 */
.bc-page-header > * {
	max-width: var(--bc-container-wide, 1200px);
	margin-inline: auto;
	padding-inline: var(--bc-space-lg, 2.5rem);

	/* Match the header bar's box model so the title text starts exactly at the
	   logo (content-box: max-width is the content, padding sits outside it). */
	box-sizing: content-box;
}

.bc-page-header .wp-block-post-title,
.bc-page-header .wp-block-query-title {
	margin-block: var(--bc-space-xs, 0.5rem) 0;
}

/* Post meta line (date + terms) under a single's title. */
.bc-post-meta {
	gap: var(--bc-space-md, 1.5rem);
	margin-block-start: var(--bc-space-xs, 0.5rem);
	font-size: var(--bc-text-sm, 0.875rem);
	color: var(--bc-color-muted, #4d4d51);
}

.bc-post-meta a {
	color: var(--bc-color-link, #414870);
	text-decoration: none;
}

.bc-post-meta a:hover {
	text-decoration: underline;
}

/*
 * A full-bleed band OPENING a page kisses the header: the root flow gap
 * (wp-site-blocks' block-gap margin on main) otherwise shows as a strip of
 * page background between the header and the band (the contact hero; the
 * hero-carousel first-block precedent).
 */
main:has(> .wp-block-bc-event-header.alignfull:first-child),
main:has(> .wp-block-post-content > .bc-section.alignfull:first-child),
main:has(> .wp-block-post-content > .wp-block-bc-hero.alignfull:first-child) {
	margin-block-start: 0;
}

/*
 * Numbered steps (core/list style, functions.php): the toolkit-guide comp's
 * hairline-ruled rows, each opened by a bold zero-padded "01." counter.
 * Ordered lists only; sits with the panel styles conceptually (see the
 * is-style-bc-panel section below) but lives up here so the li selectors
 * precede the higher-specificity archive-card li rules (stylelint's
 * no-descending-specificity — the source-order house pattern). Deliberate
 * trade (the stats-band list-semantics rule): list-style none can drop the
 * "list" container announcement in Safari/VO, but the generated "01."
 * counters ARE exposed as text, so the numbering survives for AT;
 * core/list markup cannot carry role="list".
 */
ol.is-style-bc-steps {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: bc-steps;
}

ol.is-style-bc-steps > li {
	display: flex;
	gap: var(--bc-space-lg, 2.5rem);
	counter-increment: bc-steps;
	margin: 0;
	padding-block: var(--bc-space-md, 1.5rem);
	border-bottom: 1px solid var(--bc-color-border, #d9cfbf);
	font-size: var(--bc-text-md, 1.125rem);
	line-height: 1.5;
}

ol.is-style-bc-steps > li::before {
	content: counter(bc-steps, decimal-leading-zero) ".";
	flex: 0 0 auto;
	font-weight: 700;
}

/*
 * Archive cards: style the core Query/Post Template grid to match the plugin's
 * bc-content-grid cards (flush 16:10 cover, padded copy, hover lift) so archive
 * pages are visually consistent with the homepage and magazine grids.
 */
.bc-archive-grid .wp-block-post-template {
	gap: var(--bc-space-lg, 2.5rem);
}

.bc-archive-grid .wp-block-post-template > li {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--bc-color-surface-deep, #fff);
	border: 1px solid var(--bc-color-border, #d9cfbf);
	border-radius: var(--bc-radius-md, 16px);
	transition:
		transform var(--bc-dur-med, 240ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1)),
		box-shadow var(--bc-dur-med, 240ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1)),
		border-color var(--bc-dur-med, 240ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1));
}

.bc-archive-grid .wp-block-post-template > li:hover {
	transform: translateY(-4px);
	border-color: var(--bc-color-accent, #b2a58f);
	box-shadow: var(--bc-shadow-md, 0 8px 24px rgba(148, 135, 113, 0.2));
}

.bc-archive-grid .wp-block-post-featured-image {
	margin: 0;
	overflow: hidden;
}

.bc-archive-grid .wp-block-post-featured-image img {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	transition: transform 0.4s var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1));
}

.bc-archive-grid
	.wp-block-post-template
	> li:hover
	.wp-block-post-featured-image
	img {
	transform: scale(1.04);
}

.bc-archive-grid .wp-block-post-title {
	margin: 0;
	padding: var(--bc-space-md, 1.5rem) var(--bc-space-md, 1.5rem) 0;
	font-size: var(--bc-text-md, 1.125rem);
}

.bc-archive-grid .wp-block-post-title a {
	color: var(--bc-color-ink, #000);
	text-decoration: none;
}

.bc-archive-grid .wp-block-post-title a:hover {
	color: var(--bc-color-link, #414870);
}

.bc-archive-grid .wp-block-post-excerpt {
	margin: var(--bc-space-xs, 0.5rem) 0 0;
	padding: 0 var(--bc-space-md, 1.5rem) var(--bc-space-md, 1.5rem);
	color: var(--bc-color-muted, #4d4d51);
	font-size: var(--bc-text-sm, 0.875rem);
}

/*
 * Event meta inside an archive card: the block's page-header styling (full-
 * width rules, zero inline padding) is inset to match the card's title/excerpt
 * padding, and the hairline rules are dropped.
 */
.bc-archive-grid .bc-event-meta {
	margin: 0;
	padding: var(--bc-space-xs, 0.5rem) var(--bc-space-md, 1.5rem) 0;
	border-block: 0;
	gap: var(--bc-space-sm, 1rem);
}

@media (prefers-reduced-motion: reduce) {
	.bc-archive-grid .wp-block-post-template > li,
	.bc-archive-grid .wp-block-post-featured-image img {
		transition: none;
	}

	.bc-archive-grid .wp-block-post-template > li:hover {
		transform: none;
	}

	.bc-archive-grid
		.wp-block-post-template
		> li:hover
		.wp-block-post-featured-image
		img {
		transform: none;
	}
}

/*
 * Homepage section rhythm. The page is a flat block list, so every gap defaults
 * to the 24px block gap — no separation between sections. Give the section-
 * starting blocks (the wide headings, the stats band, the CTA) generous top
 * space, while heading→grid stays tight, so sections read as distinct.
 */
.home .wp-block-heading.alignwide,
.home .bc-stats,
.home .bc-cta-band {
	margin-block-start: var(--bc-space-xxl, 6rem);
}

/*
 * A touch more breathing room between a homepage section heading and its grid
 * (the section breaks above the headings stay larger, so hierarchy holds).
 */
.home .wp-block-heading.alignwide + * {
	margin-block-start: 2rem;
}

/*
 * On the homepage the page ends in a full-bleed accent CTA band, so drop the
 * block-gap before the footer and let the band sit flush against it (other
 * pages, which end in body copy, keep their breathing room).
 */
.home .wp-site-blocks > :last-child {
	margin-block-start: 0;
}

/*
 * Interaction polish: a subtle lift on buttons and smooth colour transitions on
 * navigation/footer links, so the whole site feels responsive and premium.
 */
.wp-element-button,
.bc-site-header__cta {
	transition:
		transform var(--bc-dur-fast, 160ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1)),
		box-shadow var(--bc-dur-fast, 160ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1)),
		background-color var(--bc-dur-fast, 160ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1)),
		color var(--bc-dur-fast, 160ms)
			var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1));
}

/*
 * Design button system (docs/design-system.md — Primary, Large is the page
 * default). Fill/label colours + pill radius + Hahmlet Medium come from
 * theme.json elements.button; the metrics and states live here.
 */
.wp-element-button {
	/* border-box so min-height is the TOTAL 52px pill height (content-box
	   made buttons 52 + 32px padding = 84px tall — a live-verify catch). */
	box-sizing: border-box;
	min-height: 52px;
	padding: 16px 32px;
	font-size: var(--bc-text-md, 1.125rem);
	line-height: 1.1;
}

.wp-element-button:hover,
.bc-site-header__cta:hover {
	transform: translateY(-2px);
	box-shadow: var(--bc-shadow-md, 0 8px 24px rgba(148, 135, 113, 0.2));
}

.wp-element-button:hover {
	background-color: var(--bc-color-gold-4, #c4b7a1);
	color: var(--bc-color-navy-1, #151722);
}

/* Secondary (core outline style): transparent, navy outline; brass fill on hover. */
.is-style-outline .wp-element-button,
.is-style-outline.wp-element-button {
	padding: 16px 24px;
	background-color: transparent;
	border: 1px solid var(--bc-color-navy-2, #1f2338);
	color: var(--bc-color-navy-3, #2a2f4d);
}

.is-style-outline .wp-element-button:hover,
.is-style-outline.wp-element-button:hover {
	background-color: var(--bc-color-gold-5, #d9cfbf);
	border-color: var(--bc-color-gold-2, #948771);
	color: var(--bc-color-navy-2, #1f2338);
}

/* Disabled (WCAG-exempt pair per the design spec). Must sit after the hover
   rules so a disabled control never lifts — the lower specificity is
   deliberate cascade order, not an accident. */
/* stylelint-disable-next-line no-descending-specificity */
.wp-element-button:disabled,
.wp-element-button[aria-disabled='true'] {
	background-color: var(--bc-color-neutral-6, #cbcbcd);
	color: #fff;
	transform: none;
	box-shadow: none;
	cursor: default;
}

/* stylelint-disable no-descending-specificity -- independent components; order is cascade-neutral here. */
.bc-mega-menu a,
.bc-site-footer a,
.bc-breadcrumbs a {
	transition: color var(--bc-dur-fast, 160ms)
		var(--bc-ease, cubic-bezier(0.2, 0.8, 0.2, 1));
}
/* stylelint-enable no-descending-specificity */

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

	.wp-element-button:hover,
	.bc-site-header__cta:hover {
		transform: none;
	}
}

/*
 * Intro statement (design spec §4 + hi-fi addendum #2): the two-tone display
 * paragraph — Hahmlet Light at the H3 scale, muted base copy with key
 * phrases (<strong>) in full ink. Registered as a core/paragraph block style
 * in functions.php.
 */
.is-style-bc-intro {
	/* Hi-fi: an 824px centred column, text left-aligned (52ch at this scale
	   computed to ~1100px — far wider than the comp). */
	max-width: 51.5rem;
	margin-inline: auto;
	font-family: var(--bc-font-heading, "Hahmlet", georgia, serif);
	font-size: var(--bc-text-xl, 2rem);
	font-weight: 300;
	line-height: 1.5;
	letter-spacing: -0.02em;
	color: var(--bc-color-muted, #4d4d51);
}

.is-style-bc-intro strong,
.is-style-bc-intro b {
	font-weight: 300;
	color: var(--bc-color-ink, #000);
}

/*
 * Eyebrow kicker (core/paragraph style, functions.php): gold uppercase
 * letterspaced label above headings — the Family Offices comp's
 * "CLIENT SUCCESS STORIES". Brass as TEXT rides the AA-safe token.
 */
.is-style-bc-eyebrow {
	font-family: var(--bc-font-body, "Red Hat Text", system-ui, sans-serif);
	font-size: var(--bc-text-sm, 0.875rem);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--bc-color-accent-text, #6f6349);
}

/*
 * Ink kicker (core/paragraph style, functions.php): the success-story
 * comp's "THE PROBLEM" / "THE RESULT" section label — the section-divider
 * label voice (uppercase semibold, 6% tracking) in full ink, as an
 * authorable paragraph.
 */
.is-style-bc-kicker {
	font-family: var(--bc-font-body, "Red Hat Text", system-ui, sans-serif);
	font-size: var(--bc-text-base, 1rem);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--bc-color-ink, #000);
}

/*
 * Sand panel (core/group style, functions.php): the success-story comp's
 * "BlackCloak Steps In" box — a surface-muted rounded card; its opening
 * heading sits on a hairline rule. In-column reusable panel primitive.
 */
.is-style-bc-panel {
	box-sizing: border-box;
	padding: var(--bc-space-lg, 2.5rem);
	border-radius: var(--bc-radius-lg, 24px);
	background-color: var(--bc-color-surface-muted, #f0ede6);
}

.is-style-bc-panel > :is(h1, h2, h3, h4, h5, h6):first-child {
	margin-block: 0 var(--bc-space-md, 1.5rem);
	padding-block-end: var(--bc-space-md, 1.5rem);
	border-bottom: 1px solid var(--bc-color-border, #d9cfbf);
	font-family: var(--bc-font-body, "Red Hat Text", system-ui, sans-serif);
	font-size: var(--bc-text-lg, 1.5rem);
	font-weight: 500;
	letter-spacing: -0.01em;
	line-height: 1.3;
}

/*
 * A panel holding a numbered-steps list (the toolkit-guide comp's "Step by
 * step" box) takes the SERIF section-heading voice instead of the
 * success-story panel's body face — self-scoping via :has(), so the
 * existing panels are untouched and authors register nothing extra.
 */
.is-style-bc-panel:has(> ol.is-style-bc-steps)
	> :is(h1, h2, h3, h4, h5, h6):first-child {
	font-family: var(--bc-font-heading, "Hahmlet", georgia, serif);
	font-size: var(--bc-text-xl, 2rem);
	font-weight: 300;
	letter-spacing: -0.02em;
}


/*
 * Front-page rhythm (hi-fi §y-offsets): each section-opening H2 gets the
 * design's ~128px of air above and ~64px before its content. Scoped to
 * direct post-content children so headings inside white bc/section bands
 * (which carry their own padding) are untouched.
 */
.home .wp-block-post-content > h2.wp-block-heading {
	margin-block-start: var(--bc-space-3xl, 8rem);
	margin-block-end: var(--bc-space-xl, 4rem);
}

/*
 * Cross-document View Transitions (the motion language, docs/17): pages
 * soft-crossfade into each other on same-origin navigation. Native and
 * progressive — Chrome 126+/Safari 18.2+ animate, everything else
 * navigates normally. The at-rule itself is unconditional (it cannot
 * reliably nest in @media across engines); reduced motion instead zeroes
 * the pseudo-element animations, so the swap is instant.
 */
@view-transition {
	navigation: auto;
}

::view-transition-old(root) {
	animation-duration: 200ms;
}

::view-transition-new(root) {
	animation-duration: 250ms;
}

@media screen and (prefers-reduced-motion: reduce) {
	::view-transition-old(root),
	::view-transition-new(root) {
		animation-duration: 0s;
	}
}
