/*
Theme Name: Ukambas Astra Child
Theme URI: https://ukambas.com
Template: astra
Author: Ukambas
Description: Child theme for the Ukambas website, built on Astra Pro. All Ukambas-specific customization lives here per implementation/M01_WordPress_Foundation.md's Child Theme Creation Guide. Global colors, typography, and layout are configured via the Customizer/Global Styles per implementation/M02_Global_Design_System.md, not hardcoded here.
Version: 0.3.6
Text Domain: ukambas-astra-child
*/

/* ==========================================================================
   Milestone 2 — Global Design System
   docs/03-design/Colors.md + implementation/M02_Global_Design_System.md

   Everything below is custom CSS ONLY where M02 identified Astra Pro has
   no native setting for it: the dark-mode palette (Section 2), the
   active-menu-item underline (Section 5), the card surface (Section 9),
   and Fluent Forms field conformance (Section 8). Colors, typography,
   layout, header, footer, and buttons themselves are configured through
   Astra's own Customizer options, not here.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Dark mode — CSS custom properties (Colors.md Light Mode / Dark Mode
   tables). Light values are the :root default; html[data-theme="dark"] is
   set by dark-mode.js from a saved preference or an explicit toggle.
   The prefers-color-scheme fallback applies only when no explicit
   preference exists yet (:root:not([data-theme])), matching Colors.md's
   "dark mode is a fully equivalent alternative, not an afterthought."
   -------------------------------------------------------------------------- */
:root {
	--ukambas-bg: #FFFFFF;          /* Paper / Neutral 00 */
	--ukambas-bg-subtle: #F7F8FA;   /* Neutral 10 / Mist (Surface) */
	--ukambas-text: #0B0E14;        /* Ink */
	--ukambas-text-secondary: #7A8194; /* Neutral 60 */
	--ukambas-border: #E7E9EE;      /* Neutral 20 */
	--ukambas-accent: #4338CA;      /* Ukambas Indigo */
	--ukambas-accent-hover: #3930AC; /* Indigo, darkened ~15% */
	--ukambas-accent-text: #4338CA; /* Link/focus-outline role, light mode: identical to --ukambas-accent (no split needed here) */
}

html[data-theme="dark"] {
	--ukambas-bg: #0B0E14;          /* Neutral 100 / Ink */
	--ukambas-bg-subtle: #171A21;   /* Neutral 90 */
	--ukambas-text: #FFFFFF;        /* Neutral 00 */
	--ukambas-text-secondary: #B4B9C6; /* Neutral 40 */
	--ukambas-border: #2C3140;      /* Neutral 80 */
	--ukambas-accent: #6D63E8;      /* Surface/background role only (buttons, CTAs, active-nav underline): white text on top needs this to stay dark enough — #837AEB here would drop white-on-button contrast to 3.53:1, verified live via axe-core. Unchanged from M02. */
	--ukambas-accent-hover: #837AEB;
	/* Design System refinement (post-M11): --ukambas-accent (#6D63E8 on
	   #0B0E14, ~4.23:1) fails WCAG 2.1 AA's 4.5:1 for normal TEXT,
	   confirmed live on Solutions/HVAC, Resources, and Resources/
	   Documentation's breadcrumb and contextual links — but #6D63E8 is
	   also reused as the BACKGROUND under white button text (Contact
	   button, every CTA, the Contact form's submit button), where it
	   passes today (4.56:1) precisely because it's dark, not light. A
	   single value cannot satisfy both roles: text-on-#0B0E14 needs a
	   lighter color (>=~0.20 luminance) than a background-under-white-
	   text can tolerate (<=~0.183 luminance) — the ranges don't overlap.
	   Splitting the token by role, reusing only colors already in the
	   codebase, resolves this without changing any button, CTA, or form
	   surface: --ukambas-accent-text carries the link/focus-outline role
	   (#837AEB, ~5.48:1 on #0B0E14) while --ukambas-accent keeps the
	   surface role (#6D63E8, unchanged). */
	--ukambas-accent-text: #837AEB;
}

@media ( prefers-color-scheme: dark ) {
	:root:not( [data-theme] ) {
		--ukambas-bg: #0B0E14;
		--ukambas-bg-subtle: #171A21;
		--ukambas-text: #FFFFFF;
		--ukambas-text-secondary: #B4B9C6;
		--ukambas-border: #2C3140;
		--ukambas-accent: #6D63E8;
		--ukambas-accent-hover: #837AEB;
		--ukambas-accent-text: #837AEB;
	}
}

html[data-theme="dark"] body,
html[data-theme="dark"] {
	background-color: var( --ukambas-bg );
	color: var( --ukambas-text );
}

html[data-theme="dark"] h1,
html[data-theme="dark"] h2,
html[data-theme="dark"] h3,
html[data-theme="dark"] h4,
html[data-theme="dark"] h5,
html[data-theme="dark"] h6 {
	color: var( --ukambas-text );
}

/* Design System refinement (post-DSR01): Astra's own
   ".ast-site-identity .site-title a { color: var(--ast-global-color-2); }"
   (specificity 0,0,2,1) beats "html[data-theme="dark"] a" (0,0,1,2)
   regardless of color mode — confirmed via CSS.getMatchedStylesForNode
   — leaving the header's site title/logo link at its light-mode Ink
   color (#0B0E14) against the dark-mode #0B0E14 background, effectively
   invisible at rest and when focused. The site title is a wordmark/
   heading element, not an inline content link, so it uses the same
   --ukambas-text token every other heading already uses in dark mode,
   not the link-accent token. Matched with equal structure so this rule
   wins on real specificity. */
html[data-theme="dark"] .ast-site-identity .site-title a {
	color: var( --ukambas-text );
}

html[data-theme="dark"] a {
	color: var( --ukambas-accent-text );
}

/* ST05: Astra Pro's own header-builder rule,
   ".ast-builder-menu-mobile .main-navigation .main-header-menu
   .menu-item > .menu-link { color: var(--ast-global-color-3); }"
   (specificity 0,0,5,0) beats the generic "html[data-theme="dark"] a"
   rule above (0,0,1,2) regardless of color mode — confirmed via
   CSS.getMatchedStylesForNode, the same category of specificity
   conflict already documented for the site title above, just on a
   different element (and a less obvious selector — found live, not
   assumed from the shorter ".main-header-menu .menu-link" selector,
   which is NOT the one actually winning). --ast-global-color-3 is the
   approved Ink text color, correct for light mode; in dark mode it
   renders Ink text against the Ink header background, making every
   primary nav link invisible. Matched with equal selector structure
   (plus the dark-mode attribute) so this rule wins.

   The desktop nav is colored by a second, separate Astra Pro rule,
   ".ast-builder-menu-1 .menu-item > .menu-link" (specificity 0,0,3,0)
   — a different selector from the mobile one above, found live via the
   same CSS.getMatchedStylesForNode method; both are needed since Astra
   renders desktop and mobile nav as two separate DOM trees with
   different wrapper classes, only one visible at a time per viewport. */
html[data-theme="dark"] .ast-builder-menu-mobile .main-navigation .main-header-menu .menu-item > .menu-link,
html[data-theme="dark"] .ast-builder-menu-1 .menu-item > .menu-link {
	color: var( --ukambas-accent-text );
}

/* No separate hover/focus shade exists for the text role (only
   #837AEB was approved for this token, avoiding a third invented
   color) — hover/focus text color no longer shifts in dark mode, but
   focus remains visibly indicated by the outline rules below, which
   also use --ukambas-accent-text. */
html[data-theme="dark"] a:hover,
html[data-theme="dark"] a:focus {
	color: var( --ukambas-accent-text );
}

html[data-theme="dark"] .site-header,
html[data-theme="dark"] .site-footer,
html[data-theme="dark"] .site-above-footer-wrap,
html[data-theme="dark"] .site-primary-footer-wrap,
html[data-theme="dark"] .site-below-footer-wrap,
html[data-theme="dark"] .main-header-bar {
	background-color: var( --ukambas-bg );
	border-color: var( --ukambas-border );
}

/* The footer's own menu links and the Core Message paragraph don't
   inherit color from these wrapper rules (Astra scopes their color via
   its own dynamic CSS, independent of ancestor background), so dark
   mode needs to say so explicitly — found via a real Lighthouse
   contrast audit: without this, dark mode left footer text and links
   at their light-mode colors against the now-dark background above,
   an unreadable combination (in one case, 1.05:1 contrast). */
html[data-theme="dark"] .site-above-footer-wrap a,
html[data-theme="dark"] .site-primary-footer-wrap p,
html[data-theme="dark"] .site-below-footer-wrap {
	color: var( --ukambas-text );
}

html[data-theme="dark"] .wp-block-button:not( .is-style-outline ) .wp-block-button__link,
html[data-theme="dark"] .ast-button,
html[data-theme="dark"] div.ast-custom-button {
	background-color: var( --ukambas-accent );
}

html[data-theme="dark"] .wp-block-button:not( .is-style-outline ) .wp-block-button__link:hover {
	background-color: var( --ukambas-accent-hover );
}

/* Astra Pro's own stylesheet declares
   ".wp-block-buttons .wp-block-button.is-style-outline >
   .wp-block-button__link:not(.has-text-color) { color: #0B0E14; }" — a
   higher-specificity selector than a plain
   ".wp-block-button.is-style-outline .wp-block-button__link" rule, so it
   wins regardless of dark mode, leaving Secondary/outline button text at
   its light-mode Ink color. Found via a real axe-core scan of the
   Platform page (the first page with an outline button actually rendered
   in dark mode) — Ink-on-Neutral-90 measured at 1.1:1 contrast, and
   would have been true on the Homepage's two outline buttons as well,
   undetected because Milestone 4's QA didn't run a full dark-mode scan.
   Matched here with equal structure so this rule wins on real specificity. */
html[data-theme="dark"] .wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link:not( .has-text-color ),
html[data-theme="dark"] .wp-block-button.is-style-outline .wp-block-button__link {
	color: var( --ukambas-text );
	border-color: var( --ukambas-border );
}

/* Respect the OS/browser reduced-motion preference for the theme switch
   itself, per docs/03-design/Animations.md's Accessibility Considerations. */
html {
	transition: background-color 0.15s ease, color 0.15s ease;
}
@media ( prefers-reduced-motion: reduce ) {
	html {
		transition: none;
	}
}

/* --------------------------------------------------------------------------
   Editor color palette utility classes (found missing during Milestone 4's
   Visual QA — see M04_Homepage_Visual_QA.md Section 9).

   WordPress only auto-generates the .has-{slug}-color / -background-color /
   -border-color CSS for a theme.json "settings.color.palette" entry
   (WP_Theme_JSON reads theme.json exclusively). Astra is a classic theme
   with no theme.json, so add_theme_support('editor-color-palette') in
   functions.php registers the *names* for the block editor's swatches but
   produces no matching frontend CSS at all — every block using
   has-neutral-10-background-color (the CTA Block's tinted surface) was
   silently rendering with no background whatsoever. This is the direct,
   necessary fix: one rule per registered palette entry, values matching
   functions.php's ukambas_editor_color_palette() exactly.
   -------------------------------------------------------------------------- */
.has-ink-color { color: #0B0E14; }
.has-ink-background-color { background-color: #0B0E14; }
.has-ink-border-color { border-color: #0B0E14; }

.has-ukambas-indigo-color { color: #4338CA; }
.has-ukambas-indigo-background-color { background-color: #4338CA; }
.has-ukambas-indigo-border-color { border-color: #4338CA; }

.has-paper-color { color: #FFFFFF; }
.has-paper-background-color { background-color: #FFFFFF; }
.has-paper-border-color { border-color: #FFFFFF; }

.has-slate-color { color: #475569; }
.has-slate-background-color { background-color: #475569; }
.has-slate-border-color { border-color: #475569; }

.has-neutral-20-color { color: #E7E9EE; }
.has-neutral-20-background-color { background-color: #E7E9EE; }
.has-neutral-20-border-color { border-color: #E7E9EE; }

.has-neutral-40-color { color: #B4B9C6; }
.has-neutral-40-background-color { background-color: #B4B9C6; }
.has-neutral-40-border-color { border-color: #B4B9C6; }

.has-neutral-60-color { color: #7A8194; }
.has-neutral-60-background-color { background-color: #7A8194; }
.has-neutral-60-border-color { border-color: #7A8194; }

.has-neutral-80-color { color: #2C3140; }
.has-neutral-80-background-color { background-color: #2C3140; }
.has-neutral-80-border-color { border-color: #2C3140; }

.has-success-color { color: #1E8E5A; }
.has-success-background-color { background-color: #1E8E5A; }
.has-success-border-color { border-color: #1E8E5A; }

.has-caution-color { color: #B7791F; }
.has-caution-background-color { background-color: #B7791F; }
.has-caution-border-color { border-color: #B7791F; }

.has-risk-color { color: #C0362C; }
.has-risk-background-color { background-color: #C0362C; }
.has-risk-border-color { border-color: #C0362C; }

.has-info-color { color: #2563A6; }
.has-info-background-color { background-color: #2563A6; }
.has-info-border-color { border-color: #2563A6; }

/* Neutral 10 and Neutral 90 are the two palette entries that also carry a
   specific structural role (Colors.md's "Subtle section background"),
   so — unlike the purely semantic/decorative colors above, which stay
   fixed regardless of mode — these use the same CSS custom properties as
   everything else's dark-mode surface, so a block using this swatch
   flips correctly instead of staying a light-mode gray on a dark page. */
.has-neutral-10-color { color: var( --ukambas-bg-subtle ); }
.has-neutral-10-background-color { background-color: var( --ukambas-bg-subtle ); }
.has-neutral-10-border-color { border-color: var( --ukambas-bg-subtle ); }

/* --------------------------------------------------------------------------
   Focus indicators (found missing during Milestone 4's Visual QA — see
   M04_Homepage_Visual_QA.md Section 9). Nothing in Milestone 1-3 actually
   defined a branded focus style; every interactive element was relying on
   Astra Pro's own generic default ("a:focus-visible { outline-style:
   dotted; outline-color: inherit; }") — visible, but not the Ukambas
   Indigo outline Colors.md's Accessibility Requirements and Components.md's
   button focus spec call for. "html body" raises this rule's specificity
   just enough to win over Astra's equal-specificity rule regardless of
   which stylesheet happens to load second; verified against real focus
   state (not a mid-transition read — Astra's own hover/focus color
   transitions briefly blend old and new outline-color, which reads as a
   false negative if checked before that transition settles).
   -------------------------------------------------------------------------- */
html body a:focus,
html body button:focus,
html body input:focus,
html body select:focus,
html body textarea:focus,
html body .wp-block-button__link:focus,
html body .main-header-menu a:focus {
	outline: 2px solid var( --ukambas-accent-text );
	outline-offset: 3px;
}

/* The header's Contact button (Astra Pro's Header Builder button
   component) renders as .ast-custom-button-link inside
   .ast-builder-button-wrap — a more specific selector
   (.ast-builder-button-wrap .ast-custom-button-link:focus) than the
   generic "a:focus" above, in Astra Pro's own stylesheet. Matched with
   equal specificity here so this rule — not Astra's dotted default —
   wins, verified via real Tab-key navigation to this exact button. */
html body .ast-builder-button-wrap .ast-custom-button-link:focus {
	outline: 2px solid var( --ukambas-accent-text );
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   Header — active menu-item indicator (M02 Section 5). Astra's default
   "current menu item" treatment does not match Components.md's spec: a
   weight change plus a small Indigo underline, never a background fill.
   -------------------------------------------------------------------------- */
.main-header-menu .current-menu-item > .menu-link,
.main-header-menu .current_page_item > .menu-link {
	font-weight: 600;
	box-shadow: inset 0 -2px 0 0 var( --ukambas-accent );
	background-color: transparent;
}

/* --------------------------------------------------------------------------
   Cards (M02 Section 9) — flat, borderless, shadowless surface. No native
   Astra Pro control produces this exact combination. Reusable by any
   Gutenberg pattern built from Milestone 3 onward.
   -------------------------------------------------------------------------- */
.ukambas-card {
	background-color: var( --ukambas-bg-subtle );
	border: none;
	border-radius: 8px;
	box-shadow: none;
	padding: 2rem; /* 32px — within Components.md's 24-32px "generous" range */
}

/* Makes an entire live UKB – Content-Type Card the click target (M08),
   per M03's "Live (clickable)" card state — the label text alone should
   not be the only way to activate the card. */
.ukambas-card-link {
	display: block;
	color: inherit;
}

/* Astra Pro's ".ast-single-post .entry-content a, .ast-comment-content
   a:not(...)" rule (0,0,2,1 specificity, confirmed via CSS.getMatched
   StylesForNode) was beating a plain .ukambas-card-link and underlining
   the live Documentation card's heading and body text — the one visual
   difference from the five (correctly non-underlined) Coming Soon
   cards, found live via M08 QA. Matched/exceeded here so this wins. */
.wp-block-group.ukambas-card a.ukambas-card-link {
	text-decoration: none;
}

/* html[data-theme="dark"] a (M04) carries higher specificity
   (0,0,1,2) than the plain .ukambas-card-link class alone (0,0,1,0)
   and was winning, painting the live Documentation card's text the
   dark-mode accent color at 3.4:1 against the card background — found
   live via M08 QA. Matched with equal structure so this rule wins. */
html[data-theme="dark"] .ukambas-card-link {
	color: inherit;
}

/* --------------------------------------------------------------------------
   Forms (M02 Section 8) — Fluent Forms conformance to Components.md.
   Scoped to Fluent Forms' own top-level ".fluentform" wrapper class so
   nothing outside an actual form is affected. Visual-only, per M02
   Section 8; Milestone 9 places the real fields this will style.
   -------------------------------------------------------------------------- */
.fluentform input:not( [type="submit"] ):not( [type="checkbox"] ):not( [type="radio"] ),
.fluentform select,
.fluentform textarea {
	border: 1px solid var( --ukambas-border );
	border-radius: 8px;
	background-color: transparent;
	color: var( --ukambas-text );
}

/* Fluent Forms' own ".ff-default .ff-el-form-control{color:var(--
   fluentform-secondary)}" rule (0,0,2,0 specificity, confirmed via
   CSS.getMatchedStylesForNode) beats the plain ".fluentform select" /
   ".fluentform textarea" rule above (0,0,1,1) — every select and
   textarea (industry, optional note, message) rendered at a fixed
   gray failing dark-mode contrast (3.16:1), found live via M09 QA.
   The equivalent "input:not()..." selector above happens to already
   out-specify Fluent's rule (three :not() pseudo-classes), which is
   why text/email fields were unaffected. Matched/exceeded here. */
.fluentform.ff-default .ff-el-form-control {
	color: var( --ukambas-text );
}

.fluentform input:not( [type="submit"] ):not( [type="checkbox"] ):not( [type="radio"] ):focus,
.fluentform select:focus,
.fluentform textarea:focus {
	border-color: var( --ukambas-accent );
	outline: 2px solid var( --ukambas-accent-text );
	outline-offset: 1px;
}

.fluentform .ff-el-input--label label {
	font-size: 0.875rem;
	color: var( --ukambas-text );
}

.fluentform .error,
.fluentform .ff-el-is-error input,
.fluentform .ff-el-is-error select,
.fluentform .ff-el-is-error textarea {
	border-color: #C0362C; /* Risk */
}

/* Chrome/Edge force a white input background via the UA-only
   ":-webkit-autofill" state once a field name has been autofilled/
   remembered once, overriding "background-color: transparent" above
   entirely (a UA mechanism, not a specificity issue) — leaving
   var(--ukambas-text)'s light color invisible on that forced white
   background in dark mode. Found live on the Contact form's "Optional
   note" field post-launch. -webkit-text-fill-color must be used
   instead of color (autofill also ignores plain color), and the huge
   transition delay is the standard technique to prevent Chrome's own
   yellow autofill flash from appearing before this rule applies. */
.fluentform input:-webkit-autofill,
.fluentform input:-webkit-autofill:hover,
.fluentform input:-webkit-autofill:focus,
.fluentform select:-webkit-autofill,
.fluentform textarea:-webkit-autofill,
.fluentform textarea:-webkit-autofill:hover,
.fluentform textarea:-webkit-autofill:focus {
	-webkit-text-fill-color: var( --ukambas-text );
	-webkit-box-shadow: 0 0 0px 1000px transparent inset;
	transition: background-color 9999s ease-in-out 0s;
}

.fluentform .error {
	color: #C0362C; /* Risk */
	font-size: 0.875rem;
}

/* ==========================================================================
   Milestone 9 — Contact Implementation
   implementation/M09_Contact_Implementation.md

   Submit button — Fluent Forms renders a plain <button>, not a
   .wp-block-button__link, so it inherits none of Milestone 2's Global
   (Primary) Button styling automatically. Values below are copied
   from that button's own computed style (getComputedStyle, verified
   live) so the form's call to action matches every other Primary
   button on the site exactly.
   ========================================================================== */
.fluentform .ff-btn-submit {
	background-color: var( --ukambas-accent );
	color: #FFFFFF;
	padding: 15px 30px;
	border-radius: 4px;
	border: none;
	font-weight: 500;
	font-size: 16px;
	font-family: inherit;
	cursor: pointer;
}

.fluentform .ff-btn-submit:hover {
	background-color: var( --ukambas-accent-hover );
}

.fluentform .ff-btn-submit:focus {
	outline: 2px solid var( --ukambas-accent-text );
	outline-offset: 3px;
}

/* Path toggle (Request Early Access / General Inquiry) — styled as the
   two clearly-labeled tabs Wireframes.md's Contact mockup shows,
   layered on top of Fluent Forms' own native radio-button markup
   (kept in the DOM, not replaced) so every native keyboard behavior
   (Tab into the group, Arrow keys to switch, immediate selection)
   keeps working with zero custom key-handling code. Fluent Forms
   itself already toggles a "ff_item_selected" class on the checked
   option's wrapper on change — the active/inactive tab look below is
   pure CSS reacting to that class, no JS needed for the visual state. */
.ukambas-path-toggle .ff-el-input--content {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 0.5rem;
}

.ukambas-path-toggle .ff-el-form-check {
	margin: 0;
}

.ukambas-path-toggle .ff-el-form-check-label {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.625rem 1.25rem;
	border: 2px solid var( --ukambas-border );
	border-radius: 999px;
	cursor: pointer;
	font-weight: 500;
	color: var( --ukambas-text );
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.ukambas-path-toggle .ff-el-form-check.ff_item_selected .ff-el-form-check-label {
	background-color: var( --ukambas-accent );
	border-color: var( --ukambas-accent );
	color: #FFFFFF;
}

.ukambas-path-toggle .ff-el-form-check-label:focus-within {
	outline: 2px solid var( --ukambas-accent-text );
	outline-offset: 2px;
}

/* Conditional field-set crossfade, per docs/03-design/Animations.md's
   "brief crossfade" micro-interaction. Fluent Forms shows a
   conditionally-visible group via an inline style="display:block"
   (which always beats a plain CSS rule, inline styles win regardless
   of specificity) and hides it by falling back to its own base rule
   ".fluentform .has-conditions{display:none}" (confirmed via
   CSS.getMatchedStylesForNode) — neither can transition on its own,
   so !important is used here specifically to take over the hidden
   state's display and let opacity/max-height actually animate. */
.fluentform .ff-el-group.has-conditions {
	transition: opacity 0.25s ease, max-height 0.25s ease, margin-bottom 0.25s ease;
	max-height: 620px;
	opacity: 1;
	overflow: hidden;
}

.fluentform .ff-el-group.has-conditions.ff_excluded {
	display: block !important;
	opacity: 0 !important;
	max-height: 0 !important;
	margin-bottom: 0 !important;
	pointer-events: none;
}

@media ( prefers-reduced-motion: reduce ) {
	.fluentform .ff-el-group.has-conditions,
	.ukambas-path-toggle .ff-el-form-check-label {
		transition: none;
	}
}

/* --------------------------------------------------------------------------
   Footer (M02 Section 6) — generous top padding separating the footer
   from the page's final content section. Fixed during Milestone 4's
   Visual QA: this selector was ".ast-above-footer-wrap" since Milestone
   2, which doesn't exist in Astra's rendered markup (the real class is
   "site-above-footer-wrap", no "ast-" prefix) — the padding was never
   actually applied.
   -------------------------------------------------------------------------- */
.site-above-footer-wrap {
	padding-top: 6rem; /* 96px */
}

/* ==========================================================================
   Milestone 3 — Gutenberg Pattern Library
   implementation/M03_Gutenberg_Pattern_Library.md

   Custom CSS only where Astra Pro/Gutenberg core has no native
   equivalent: the Display font-size's responsive step-down (Gutenberg's
   editor-font-sizes are fixed, non-responsive values without a
   theme.json) and the Content-Type Card's "Coming Soon" badge (no core
   Badge block exists).
   ========================================================================== */

/* UKB – Hero – Homepage: Display headline steps down moderately on
   mobile, per M03 Section 5, without ever dropping below the site's
   largest text. Astra's own mobile breakpoint (768px) is reused rather
   than introducing a new one. */
@media ( max-width: 768px ) {
	.has-display-font-size {
		font-size: 2.25rem;
	}
}

/* UKB – Content-Type Card / Content-Type Grid: "Coming Soon" badge.
   Caution-toned per Components.md's Badges; communicated by visible
   text, never color alone. */
.ukambas-badge {
	display: inline-block;
	font-size: 0.75rem;
	font-weight: 600;
	padding: 0.25rem 0.625rem;
	border-radius: 999px;
	margin: 0;
}

.ukambas-badge-caution {
	/* #B7791F (the base Caution token) measures 3.31:1 against this
	   badge's own #FDF3E3 tint — below the 4.5:1 WCAG AA floor. Darkened
	   to the same hue's #8A5A17 (5.37:1), found live on the Resources
	   Hub (M08 QA) — the first page to actually render this badge. */
	color: #8A5A17;
	background-color: #FDF3E3; /* Caution, lightened for a badge-appropriate tint */
}

html[data-theme="dark"] .ukambas-badge-caution {
	/* The same #B7791F text measures 3.92:1 against this rgba overlay on
	   the dark card background — also below 4.5:1. Lightened to #E0A94D
	   (6.77:1) rather than reusing the light-mode #8A5A17, which would
	   fail worse (2.42:1) on a dark background. */
	color: #E0A94D;
	background-color: rgba( 183, 121, 31, 0.16 );
}

/* ==========================================================================
   Milestone 4 — Homepage Implementation
   implementation/M04_Homepage_Implementation.md

   Pending-illustration placeholder. A bare Image block with no src
   renders nothing at all on the front end (confirmed against WordPress
   core's render_block_core_image, which requires a literal <img> with a
   src to output anything) — invisible, not merely unstyled, which both
   fails M04 Section 9's "reserve dimensions to avoid layout shift"
   requirement and makes a Feature Block's two-column layout look
   broken rather than obviously pending. Each placeholder therefore
   uses a flat, neutral-tinted inline SVG as its src (not a photograph,
   not stock imagery — a solid rectangle at the illustration's intended
   dimensions) plus a dashed border, so the empty slot is visible,
   reserves its space, and is unmistakably a placeholder rather than a
   finished asset.
   -------------------------------------------------------------------------- */
.ukambas-pending-asset img {
	border: 1px dashed var( --ukambas-border );
	border-radius: 8px;
}

/* ==========================================================================
   AS01.2 — Icon Set Implementation
   implementation/AS01_1_Icon_Set_QA_Review.md,
   implementation/AS01_Asset_Implementation_Plan.md

   Every icon inherits color via currentColor (Icons.md's SVG Standards),
   so no icon needs its own color rule beyond what it inherits from its
   surrounding context — these rules only handle sizing, spacing, and
   the one icon-only control's state-based visibility.
   -------------------------------------------------------------------------- */
.ukambas-icon {
	display: inline-block;
	vertical-align: middle;
	flex-shrink: 0;
}

/* Capability Card / Documentation card icon: standalone, above the
   card's own heading — per the Asset Implementation Plan's insertion
   point ("positioned before the card's existing heading text"). */
.ukambas-card-icon {
	display: block;
	margin-bottom: 0.75rem;
	color: var( --ukambas-accent-text );
}

/* Coming Soon badge icon: inline with the badge's own small text,
   inheriting the badge's already-contrast-checked text color rather
   than the card icon's accent color, so it never introduces a new
   color pairing beyond what M08 QA already verified for this badge. */
.ukambas-badge-icon {
	margin-right: 0.25rem;
	color: inherit;
}

/* Site-wide dark-mode toggle button (AS01.2, repositioned in AS01.7).
   Matches the existing "html body button:focus" rule above for its
   focus outline automatically, since it is a plain <button> with no
   more specific selector overriding that.

   AS01.7: rendered via 'astra_header_after' (inc/icons.php), which
   fires outside the <header> element entirely, not inside any Astra
   Header Builder flex zone — deliberately, since that zone doesn't
   exist at all on Hostinger staging (see
   implementation/AS01_7_Toggle_Remediation_Report.md). "position:
   fixed" is what makes this work: it positions the button relative to
   the viewport, not to whatever element happens to be its DOM parent,
   so it visually sits in the header's top-right corner regardless of
   where in the document it actually renders, and stays there through
   scroll exactly like the sticky header above it — without needing to
   be a flex child of that header at all.

   Coordinates measured directly (not guessed) against the actual
   rendered header at each breakpoint: desktop header height 81px,
   mobile header height 80px. The 923px breakpoint below is Astra's own
   exact desktop/mobile header switch point on this site, found by
   testing every width from 920-925px directly (920-922px = mobile
   header visible, 923px+ = desktop header visible) — matched exactly
   here so the toggle's position never falls in a dead zone between
   Astra's own switch and this rule's. */
.ukambas-theme-toggle {
	position: fixed;
	top: 20px;
	right: 24px;
	z-index: 999;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	padding: 0.5rem;
	cursor: pointer;
	color: var( --ukambas-text );
	line-height: 0;
}

/* Mobile: the desktop rule's "right: 24px" position would sit
   directly on top of the mobile menu trigger. Measured directly (not
   guessed) after first trying to fit the toggle into either the
   title-to-Contact gap or the Contact-to-trigger gap: with the toggle
   no longer competing for space in that flex row (see the AS01.7 hook
   change above), the Contact button itself now expands to fill the
   freed space, leaving only ~20px between Contact's right edge and
   the mobile trigger's left edge at both 375px and 390px — too narrow
   for an accessible tap target without crowding either neighbor.
   Rather than force a cramped fit, the toggle is placed just below
   the mobile header instead: "top" is set to the mobile header's own
   measured 80px height plus an 8px gap, "right: 16px" keeps it in the
   same top-right visual region without any collision risk at any
   width in this range. Uses Astra's own exact 923px header breakpoint
   (measured above, not an assumed round number). */
@media ( max-width: 922px ) {
	.ukambas-theme-toggle {
		top: 88px;
		right: 16px;
		padding: 0.375rem;
		background-color: var( --ukambas-bg );
		border-radius: 999px;
		box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.15 );
	}
}

/* Both icons are always rendered (see inc/icons.php); only the one
   matching the *target* state a click would switch to is shown —
   Moon while in light mode ("switch to dark"), Sun while in dark mode
   ("switch to light") — matching the Asset Implementation Plan's Alt
   Text Mapping and dark-mode.js's aria-label logic exactly. */
.ukambas-theme-toggle-icon--sun {
	display: none;
}

html[data-theme="dark"] .ukambas-theme-toggle-icon--sun {
	display: inline-flex;
}

html[data-theme="dark"] .ukambas-theme-toggle-icon--moon {
	display: none;
}

/* Mobile header fix, originally from AS01.2 (Product Owner review):
   when the toggle was still rendered as a flex child of this zone
   (see the AS01.7 change note above — it no longer is), its added
   width pushed the site title's flex-basis:0% zone below its natural
   ~118px unwrapped width at 375-390px, wrapping "Ukambas" onto two
   lines. Scoped entirely to #ast-mobile-header — a separate DOM tree
   from #ast-desktop-header, per Astra's own header markup, so desktop
   is completely unaffected.

   Retained as-is after AS01.7's toggle repositioning: the toggle no
   longer occupies this flex row at all (it renders via
   'astra_header_after', outside <header> entirely, and is positioned
   with "position: fixed" above), so the specific wrapping cause this
   guards against can no longer recur from the toggle specifically —
   but the "Ukambas" nowrap guarantee costs nothing to keep as a
   standing protection, and the Contact-button-only flex-wrap/
   flex-shrink rules are harmless no-ops on a now-single-child row
   rather than something that needed removing. Not re-tested for
   removal in AS01.7 — kept rather than risk an unnecessary,
   unverified change to already-working CSS. */
#ast-mobile-header .site-title a {
	white-space: nowrap;
}

#ast-mobile-header .ast-header-button-1 {
	flex-wrap: nowrap;
}

#ast-mobile-header .ast-header-button-1 > * {
	flex-shrink: 0;
}

/* AS01.7 Pre-Launch Remediation — Contact header CTA (Item 22). Appended
   by inc/header-cta.php as the final <li> of the existing primary/
   mobile_menu nav menu rather than an Astra Pro Header Builder button
   (not available on staging — see the Section 20 investigation in
   implementation/AS01_7_Staging_Execution_Report_Phase_A.md). Styled
   here to read as a distinct CTA, not a plain nav link. --ukambas-accent/
   --ukambas-accent-hover already flip automatically between light and
   dark mode at :root (see the top of this file), so the background
   color needs no separate override — but the TEXT color does (see the
   dark-mode-specific override block below). */
.main-header-menu .ukambas-nav-cta > .menu-link {
	display: inline-flex;
	align-items: center;
	background-color: var( --ukambas-accent );
	color: #FFFFFF;
	border-radius: 999px;
	padding: 0.5rem 1.25rem;
	margin-left: 0.5rem;
}

.main-header-menu .ukambas-nav-cta > .menu-link:hover,
.main-header-menu .ukambas-nav-cta > .menu-link:focus {
	background-color: var( --ukambas-accent-hover );
	color: #FFFFFF;
}

/* Found live via axe-core, not assumed: in dark mode, Astra Pro's own
   "html[data-theme="dark"] .ast-builder-menu-1 .menu-item > .menu-link"
   rule (specificity 0,4,1 — an ID-free but 4-class-plus-attribute
   selector) beat the plain rule above (0,3,0), leaving the CTA's text
   at --ukambas-accent-text (#837AEB) against the --ukambas-accent
   (#6D63E8) background — 1.29:1 contrast, since both tokens are close
   in luminance by design (Design System note above). The same
   specificity-conflict category already documented for the site title
   (this file, ~line 96) and the primary nav links (~line 115), just on
   this new CTA element. Fixed the same way: an ID-anchored selector,
   which always outranks a class-and-attribute-only selector regardless
   of source order. */
html[data-theme="dark"] #ast-hf-menu-1 .ukambas-nav-cta > .menu-link,
html[data-theme="dark"] #ast-hf-mobile-menu .ukambas-nav-cta > .menu-link {
	color: #FFFFFF;
}

/* Mobile (off-canvas) menu: items stack vertically, so the desktop
   pill's "margin-left" spacing doesn't apply — replaced with a small
   top margin to separate it from the plain-text links above it, and
   centered so it still reads as a distinct CTA row rather than another
   list item. Uses the same 922px breakpoint as the toggle above. */
@media ( max-width: 922px ) {
	.main-header-menu .ukambas-nav-cta {
		margin-top: 0.5rem;
	}

	.main-header-menu .ukambas-nav-cta > .menu-link {
		display: flex;
		justify-content: center;
		margin-left: 0;
	}
}

/* Found live via document.styleSheets matching (not assumed): inside the
   mobile off-canvas menu specifically, two more Astra core rules beat
   the two plain-class rules above —
   ".ast-header-break-point .main-navigation ul .menu-item .menu-link"
   (padding: 0 20px; width: 100%; a bottom border) and
   ".ast-builder-menu-mobile .main-navigation .main-header-menu
   .menu-link" (background-color: var(--ast-global-color-4)) — both
   specificity (0,4,x), beating the (0,3,0) rules above the same way the
   dark-mode text color was beaten. Anchored to the mobile menu's own ID
   (#ast-hf-mobile-menu), which always outranks any number of classes,
   for the properties Astra was overriding: background, padding, width,
   border. Desktop (#ast-hf-menu-1) already renders correctly without
   this — scoped to mobile only, on purpose. */
#ast-hf-mobile-menu .ukambas-nav-cta > .menu-link {
	background-color: var( --ukambas-accent );
	color: #FFFFFF;
	padding: 0.5rem 1.25rem;
	width: auto;
	border: none;
}
