/*
 * Chiggle Academy — global baseline.
 *
 * Sets the body font, page background, and body text colour from design
 * tokens. Component-specific styles live in homepage.css, dashboard.css,
 * checkout.css, etc.
 *
 * Loaded after variables.css.
 */

/*
 * Universal box-sizing reset (v0.9.88).
 *
 * Without this, every element on the page uses the browser-default
 * `content-box`, where width sizes the CONTENT and padding adds on top.
 * Block-level elements like `.ca-hero` and `.ca-section` are 100% wide
 * (filling parent) — adding L+R padding pushes their box past the viewport,
 * causing horizontal scroll on mobile.
 *
 * `border-box` is the modern default used by Bootstrap, Tailwind, normalize,
 * etc. Width includes padding + border, so an element can be `width: 100%`
 * AND have padding without overflowing its parent. Components that explicitly
 * need content-box can opt back in with their own declaration; vanishingly
 * rare in this codebase.
 *
 * Discovered while debugging homepage horizontal overflow at iPhone 12 Pro
 * (390×844) — 10 of 11 top-level sections overflowed by exactly the L+R
 * padding sum. See CHANGELOG v0.9.88.
 */
*, *::before, *::after {
	box-sizing: border-box;
}

html {
	scroll-behavior: smooth;
}

body {
	font-family: var(--font-body);
	background-color: var(--offwhite);
	color: var(--charcoal);
	line-height: 1.6;
}

h1, h2, h3, h4, h5, h6,
.ast-site-title,
.entry-title {
	font-family: var(--font-display);
	color: var(--navy);
	letter-spacing: -0.02em;
}

/* Brand Kit §04 split (v0.11.38): page/section titles = Nunito
 * (Display & Headings); H3–H6 (card/sub-section titles) and
 * .ast-site-title (the wordmark) stay Poppins (Wordmark &
 * Subheadings) from the rule above. */
h1, h2,
.entry-title {
	font-family: var(--font-heading);
}

a {
	color: var(--navy);
}

a:hover {
	color: var(--gold);
}

/* ═════════════════════════════════════════════════════════
 * FULL-BLEED PAGE WRAPPERS
 *
 * Astra wraps the entire page content in a stack of containers
 * (#page → #content → .ast-container → #primary → main → article →
 * .entry-content), each with its own max-width and padding. For
 * surfaces where our blocks supply their own full-bleed backgrounds
 * (homepage hero, dashboard, course / lesson, checkout), every one
 * of those ancestor containers must be reset to 100% width or the
 * background gets visible margins.
 *
 * The lesson page worked out of the box because TutorLMS renders
 * its own full-width template, bypassing Astra's stack. We
 * replicate that effect for every other surface here using
 * :is() to keep the selector readable.
 *
 * Scoped to specific body classes so inner pages (single posts,
 * default WP pages, etc.) keep Astra's container intact for
 * normal blog-style layouts.
 * ═════════════════════════════════════════════════════════ */

/* v0.9.83 — removed `body.woocommerce-checkout` from this :is() list.
 * Checkout doesn't need full-bleed wrappers — checkout.css provides a
 * proper 720px-centered column. Keeping the checkout body class in this
 * full-bleed reset caused the .entry-content max-width: 720px !important
 * in checkout.css to lose the specificity battle (0,2,1 here beats 0,2,0
 * there even with !important), so billing details + form fields rendered
 * edge-to-edge instead of in the intended 720px column. */
:is(
	body.home,
	body.page,
	body.ca-main-dashboard,
	body.ca-sub-dashboard,
	body.single-courses,
	body.single-lesson,
	body.archive,
	body.tax-course-category,
	body.tax-course-tag,
	body.woocommerce,
	body.woocommerce-account,
	body.woocommerce-cart,
	body.woocommerce-shop,
	body.error404
) :is(
	#page,
	#content,
	#content.site-content,
	.site-content,
	.ast-container,
	.ast-container-fluid,
	.ast-row,
	#primary,
	.content-area,
	main,
	main#main,
	.site-main,
	article,
	article.post,
	article.page,
	.entry-content,
	.ast-no-sidebar .entry-content,
	.ast-separate-container .entry-content
) {
	max-width: none !important;
	width: 100% !important;
	padding-left: 0 !important;
	padding-right: 0 !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* Restore vertical rhythm — the !important padding-reset above
 * also nukes vertical padding, which we want zero on these
 * surfaces because our sections handle their own padding. */
:is(
	body.home,
	body.page,
	body.ca-main-dashboard,
	body.ca-sub-dashboard,
	body.single-courses,
	body.single-lesson,
	body.archive,
	body.tax-course-category,
	body.tax-course-tag,
	body.woocommerce,
	body.woocommerce-checkout,
	body.woocommerce-account,
	body.woocommerce-cart,
	body.woocommerce-shop,
	body.error404
) .entry-content > * {
	margin-top: 0;
	margin-bottom: 0;
}

/* ═════════════════════════════════════════════════════════
 * FULL-BLEED BREAK-OUT
 *
 * If the ancestor-wrapper override above misses any container, our
 * sections might still be visually constrained. The classic
 * `width: 100vw; margin-left: calc(50% - 50vw)` trick forces the
 * element to escape any constrained parent and span the full
 * viewport regardless. `overflow-x: hidden` on body prevents the
 * 100vw-includes-scrollbar gotcha from triggering horizontal scroll.
 * ═════════════════════════════════════════════════════════ */

:is(
	body.home,
	body.page,
	body.ca-main-dashboard,
	body.ca-sub-dashboard,
	body.single-courses,
	body.single-lesson,
	body.woocommerce-checkout,
	body.woocommerce-account,
	body.woocommerce-cart,
	body.woocommerce-shop
) {
	overflow-x: hidden;
}

.ca-hero,
.ca-section,
.ca-stats-bar {
	width: 100vw !important;
	max-width: 100vw !important;
	margin-left: calc(50% - 50vw) !important;
	margin-right: calc(50% - 50vw) !important;
}

/* ═════════════════════════════════════════════════════════
 * PAGE-FRAME CONTAINER (body.ca-framework)
 *
 * Applies a consistent max-width + padding frame to default
 * WordPress / WooCommerce pages that don't have a custom layout
 * (Privacy, Terms, Cart, generic WP pages, 404). Without this,
 * the full-bleed wrapper reset above pushes WP's entry-header
 * and entry-content children flush against the viewport edge —
 * giving a Cart page whose "Cart" H1 sits at x=0 while the empty-
 * cart card stays centred. That is the visual disharmony users
 * reported.
 *
 * The body class is added in inc/hooks-content.php; only pages
 * WITHOUT a bespoke layout get it.
 *
 * Vertical rhythm:
 *   - Top breathing room: 56px from header (matches dashboard hero)
 *   - Bottom breathing room: 80px before footer
 *   - Inter-child gap: 24px (default block spacing)
 *
 * Children with our own full-bleed classes (.ca-hero, .ca-section,
 * .ca-stats-bar) and WordPress alignfull blocks opt out and keep
 * spanning the viewport.
 * ═════════════════════════════════════════════════════════ */

body.ca-framework .entry-header,
body.ca-framework .entry-content > *:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull) {
	max-width: var(--container-max) !important;
	padding-left: var(--container-padding) !important;
	padding-right: var(--container-padding) !important;
	margin-left: auto !important;
	margin-right: auto !important;
	width: 100%;
	box-sizing: border-box;
}

body.ca-framework .entry-header {
	padding-top: 56px !important;
	padding-bottom: 8px !important;
}

body.ca-framework .entry-content {
	padding-bottom: 80px !important;
	min-height: 320px;
}

body.ca-framework .entry-content > *:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull) {
	margin-top: 24px !important;
}
body.ca-framework .entry-content > *:first-child {
	margin-top: 32px !important;
}

body.ca-framework .entry-title {
	font-family: var(--font-heading); /* Brand §04: page title = Nunito */
	color: var(--navy);
	font-size: clamp(28px, 4vw, 44px);
	font-weight: 700;
	letter-spacing: -0.02em;
	margin: 0 0 8px;
	line-height: 1.15;
}

body.ca-framework .entry-content p,
body.ca-framework .entry-content li {
	font-size: 17px;
	line-height: 1.7;
	color: var(--charcoal);
}

/* ─────────────────────────────────────────────────────────────
 * List indent — v0.13.12 fix.
 *
 * The container-alignment rule above sets `padding-left:
 * var(--container-padding) !important` for every direct child
 * of .entry-content, INCLUDING <ul> and <ol>. Default browser
 * UL/OL padding-left is ~40px; our override drops it to 32px
 * (--container-padding), which puts bullets right at the page
 * edge — bullets appear "too left-aligned" against the
 * surrounding paragraphs.
 *
 * Fix: keep the container-padding (alignment with paragraphs)
 * but ADD enough extra space inside the UL/OL for bullets to
 * sit visually indented from the text column. ~28px additional
 * indent gives bullets ~60px from the page edge — comfortably
 * inside the text block.
 *
 * Nested lists (UL/OL inside an LI) aren't direct children of
 * .entry-content, so the container-padding rule doesn't apply
 * to them. Give them their own indent (32px) for sub-bullets.
 *
 * Applies to: plain <ul>/<ol> from authored content, Gutenberg
 * .wp-block-list, and any nested combination thereof.
 * ───────────────────────────────────────────────────────────── */
/* v0.13.14 — THE ACTUAL FIX.
 *
 * v0.13.12 (+28) and v0.13.13 (+56) both failed silently. Root cause:
 * the container-alignment rule above is
 *   body.ca-framework .entry-content > *:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull)
 * Its four :not(.class) pseudo-classes give it specificity (0,6,1).
 * My list rules were `... .entry-content > .wp-block-list` = (0,3,1)
 * and `... > ul` = (0,2,2). BOTH lower. Both rules use !important, so
 * the !important tie is broken by selector specificity — the container
 * rule won every time, pinning padding-left to var(--container-padding)
 * (32px) and ignoring my override entirely.
 *
 * Fix: give the list rules the SAME :not() chain so they reach
 * specificity ≥ (0,6,1). The ul/ol variants land at (0,6,2), the
 * .wp-block-list variant at (0,7,1) — both beat (0,6,1), and they come
 * later in the file, so they win cleanly. Now the +56 actually applies.
 */
body.ca-framework .entry-content > ul:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull),
body.ca-framework .entry-content > ol:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull),
body.ca-framework .entry-content > .wp-block-list:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull) {
	padding-left: calc(var(--container-padding) + 56px) !important;
}

body.ca-framework .entry-content li {
	margin-bottom: 8px;
	padding-left: 4px;
}

body.ca-framework .entry-content li > ul,
body.ca-framework .entry-content li > ol,
body.ca-framework .entry-content li > .wp-block-list {
	margin-top: 8px !important;
	margin-bottom: 8px !important;
	/* Nested lists are NOT direct children of .entry-content, so the
	 * (0,6,1) container rule never applies to them — a plain (0,3,2)
	 * !important rule wins here without needing the :not() chain. */
	padding-left: 32px !important;
}

/* Definition lists — direct children of .entry-content, so they need
 * the same :not() chain to beat the container rule. */
body.ca-framework .entry-content > dl:not(.ca-hero):not(.ca-section):not(.ca-stats-bar):not(.alignfull) {
	padding-left: calc(var(--container-padding) + 56px) !important;
}
body.ca-framework .entry-content dd {
	margin-left: 32px;
	margin-bottom: 8px;
}

body.ca-framework .entry-content h2 {
	font-family: var(--font-display);
	color: var(--navy);
	font-size: clamp(22px, 2.4vw, 28px);
	font-weight: 700;
	letter-spacing: -0.01em;
	margin-top: 40px !important;
	margin-bottom: 12px !important;
}

body.ca-framework .entry-content h3 {
	font-family: var(--font-display);
	color: var(--navy);
	font-size: clamp(18px, 1.8vw, 22px);
	font-weight: 600;
	margin-top: 28px !important;
	margin-bottom: 8px !important;
}

/* WooCommerce shortcode outputs (cart, my-account login form, etc.)
 * render as direct entry-content children. Give them a card-like
 * surface so they don't look like raw form HTML on a flat page. */
body.ca-framework .woocommerce,
body.ca-framework .woocommerce-cart-form,
body.ca-framework .cart-empty,
body.ca-framework .return-to-shop,
body.ca-framework .woocommerce-MyAccount-content,
body.ca-framework .woocommerce-MyAccount-navigation {
	max-width: var(--container-max) !important;
	margin-left: auto !important;
	margin-right: auto !important;
	width: 100%;
	box-sizing: border-box;
}

/* Empty-cart screen — give it a friendly card surface instead of a
 * bare paragraph + button slammed against the viewport edge. */
body.ca-framework.woocommerce-cart .cart-empty {
	background: var(--white);
	border: 1px solid var(--gray-200);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
	padding: 56px 32px !important;
	text-align: center;
	font-size: 18px;
	color: var(--charcoal);
	max-width: 640px !important;
}

body.ca-framework.woocommerce-cart .return-to-shop {
	text-align: center;
	max-width: 640px !important;
	margin-top: 16px !important;
}

body.ca-framework.woocommerce-cart .return-to-shop .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 12px 28px;
	background: var(--gold);
	color: var(--navy);
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 15px;
	border: none;
	border-radius: 999px;
	box-shadow: var(--shadow-md);
	text-decoration: none;
	transition: background 0.15s ease, transform 0.15s ease;
}
body.ca-framework.woocommerce-cart .return-to-shop .button:hover {
	background: var(--gold-hover);
	transform: translateY(-1px);
}

@media (max-width: 768px) {
	body.ca-framework .entry-header {
		padding-top: 40px !important;
	}
	body.ca-framework .entry-content {
		padding-bottom: 56px !important;
	}
	body.ca-framework.woocommerce-cart .cart-empty {
		padding: 40px 20px !important;
	}
}

/* ═════════════════════════════════════════════════════════
 * FEEDBACK FORM (/feedback/)
 * Build plan §2.2.4 — simple form, wp_mail submission.
 * ═════════════════════════════════════════════════════════ */

.ca-feedback-intro {
	max-width: 680px;
	margin: 0 auto 32px;
	text-align: center;
}
.ca-feedback-lead {
	font-size: 18px;
	line-height: 1.65;
	color: var(--charcoal);
}

.ca-feedback-form {
	max-width: 640px;
	margin: 0 auto;
	background: var(--white);
	border: 1px solid var(--gray-200);
	border-radius: var(--radius-lg);
	padding: 32px 28px;
	box-shadow: var(--shadow-sm);
}

.ca-feedback-field {
	margin-bottom: 22px;
}

.ca-feedback-field label {
	display: block;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 14px;
	color: var(--navy);
	margin-bottom: 8px;
	letter-spacing: -0.005em;
}

.ca-feedback-form input[type="text"],
.ca-feedback-form select,
.ca-feedback-form textarea {
	width: 100%;
	font-family: var(--font-body);
	font-size: 15px;
	color: var(--charcoal);
	background: var(--white);
	border: 1.5px solid var(--gray-200);
	border-radius: 12px;
	padding: 12px 16px;
	box-sizing: border-box;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.ca-feedback-form select {
	min-height: 48px;
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1L6 6L11 1' stroke='%23122B69' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
	background-repeat: no-repeat;
	background-position: right 16px center;
	background-size: 12px 8px;
	padding-right: 44px;
}

.ca-feedback-form input[type="text"] {
	min-height: 48px;
}

.ca-feedback-form textarea {
	resize: vertical;
	min-height: 160px;
	line-height: 1.55;
}

.ca-feedback-form input:focus,
.ca-feedback-form select:focus,
.ca-feedback-form textarea:focus {
	border-color: var(--gold);
	box-shadow: 0 0 0 3px rgba(255, 155, 3, 0.18);
	outline: none;
}

.ca-feedback-hint {
	margin-top: 6px;
	color: var(--gray-500);
	font-size: 13px;
	line-height: 1.5;
}

.ca-feedback-form button[type="submit"] {
	margin-top: 8px;
}

.ca-feedback-notice {
	padding: 14px 18px;
	border-radius: 12px;
	font-size: 14px;
	line-height: 1.5;
	margin: 0 0 22px;
	border: 1px solid transparent;
}
.ca-feedback-notice-success {
	background: color-mix(in srgb, var(--green) 8%, transparent);
	border-color: color-mix(in srgb, var(--green) 25%, transparent);
	color: var(--green-dark);
}
.ca-feedback-notice-error {
	background: color-mix(in srgb, var(--coral) 8%, transparent);
	border-color: color-mix(in srgb, var(--coral) 30%, transparent);
	color: var(--error-dark);
}
.ca-feedback-notice-info {
	background: color-mix(in srgb, var(--sky) 8%, transparent);
	border-color: color-mix(in srgb, var(--sky) 25%, transparent);
	color: var(--sky-dark);
}
.ca-feedback-notice a {
	color: inherit;
	text-decoration: underline;
}

.ca-feedback-footer {
	max-width: 640px;
	margin: 28px auto 0;
	color: var(--gray-500);
	font-size: 14px;
	font-style: italic;
	text-align: center;
}

@media (max-width: 480px) {
	.ca-feedback-form { padding: 24px 20px; }
}

/* ═════════════════════════════════════════════════════════════════
 * STICKY MOBILE CTA — v0.9.55
 *
 * Pinned bottom CTA bar for anonymous visitors at ≤900px. Lives in
 * global.css so it can render on any page where the wp_footer hook in
 * inc/hooks-homepage.php injects the markup. Currently fires on:
 *   - homepage (/)
 *   - /templates/
 *   - /llm-prompts/
 *
 * Class is `.ca-sticky-cta` (was `.ca-home-sticky-cta` in v0.9.51–54).
 * ═════════════════════════════════════════════════════════════════ */
.ca-sticky-cta {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	background: var(--white);
	border-top: 1px solid var(--gray-200);
	box-shadow: 0 -4px 16px rgba(18, 43, 105, 0.12);
	padding: 12px 20px;
	display: none;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	z-index: 50;
}
.ca-sticky-cta-info {
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.ca-sticky-cta-price {
	font-family: var(--font-display);
	color: var(--navy);
	font-weight: 800;
	font-size: 19px;
	line-height: 1;
}
.ca-sticky-cta-meta {
	color: var(--charcoal);
	font-size: 11.5px;
	opacity: 0.75;
}

/* ═════════════════════════════════════════════════════════════════
 * ACCESSIBILITY UTILITIES — v0.9.60
 *
 * Screen-reader-text: hides content visually while keeping it
 * accessible to screen readers. Used for form labels, button labels
 * where icons-only would lack a textual name, etc. Mirrors WP core's
 * definition so it's available even if the parent theme drops it.
 *
 * Skip-link: keyboard users get a "Skip to main content" link that
 * jumps past the header nav. Hidden until focused.
 * ═════════════════════════════════════════════════════════════════ */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	-webkit-clip-path: inset(50%);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}
.screen-reader-text:focus {
	background-color: var(--white);
	clip: auto !important;
	-webkit-clip-path: none;
	clip-path: none;
	color: var(--navy);
	display: block;
	font-size: 0.875rem;
	font-weight: 700;
	height: auto;
	left: 5px;
	line-height: normal;
	padding: 15px 23px 14px;
	text-decoration: none;
	top: 5px;
	width: auto;
	z-index: 100000;
	border-radius: 8px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Skip-to-main-content link — first tab-stop for keyboard users.
 * Hidden until focused, then floats top-left with gold border. */
.ca-skip-link {
	position: absolute;
	top: -100px;
	left: 8px;
	background: var(--gold);
	color: var(--navy);
	font-family: var(--font-display);
	font-weight: 700;
	padding: 12px 22px;
	border-radius: 8px;
	text-decoration: none;
	z-index: 100000;
	transition: top 0.15s ease;
	box-shadow: 0 8px 24px rgba(18, 43, 105, 0.18);
}
.ca-skip-link:focus {
	top: 8px;
	outline: 2px solid var(--navy);
	outline-offset: 3px;
}

/* Universal focus-visible enhancement — every interactive element gets
 * a visible focus ring for keyboard users. Browser default outline is
 * suppressed elsewhere; this adds it back in a brand-consistent way
 * for any element that lacks a more specific :focus-visible rule. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 2px;
	border-radius: 4px;
}

@media (max-width: 900px) {
	.ca-sticky-cta { display: flex; }
	/* Bottom padding on the pages where the sticky CTA lives so the
	 * bar doesn't crop the final ~60px of page content. Homepage
	 * already has its own `.ca-cta-final` padding rule. */
	body.page-id-81 .entry-content,
	body.page-id-399 .entry-content {
		padding-bottom: 100px;
	}
}

/* ═════════════════════════════════════════════════════════════════
 * 404 PAGE — v0.9.58
 *
 * Branded replacement for Astra's bare "This page doesn't seem to
 * exist" template. Navy gradient hero + brand-pattern texture + four
 * coloured destination cards + search box. Mirrors the visual
 * language we established for the homepage hero / final CTA / outcome
 * cards so this page reads as part of the site, not an error screen.
 *
 * Template at theme root (`404.php`).
 * ═════════════════════════════════════════════════════════════════ */
/* Astra's `.ast-container` defaults to `display: flex; flex-direction: row`
 * which makes our full-width 404 section size to its content instead of
 * the viewport. Force block flow on body.error404 so the section spans
 * full width. Same fix we applied for body.single-courses in v0.9.51. */
body.error404 .ast-container {
	display: block !important;
}

.ca-404 {
	background:
		linear-gradient(140deg, #0d1f4a 0%, var(--navy) 50%, #1a3a8a 100%);
	color: var(--white);
	padding: 100px 32px 120px;
	position: relative;
	overflow: hidden;
	min-height: 70vh;
	width: 100%;
}
.ca-404::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image: url('../img/brand-pattern-navy.png');
	background-size: 380px auto;
	background-repeat: repeat;
	opacity: 0.05;
	mix-blend-mode: screen;
	pointer-events: none;
}
.ca-404::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(circle at 14% 22%, rgba(255, 155, 3, 0.18) 0%, transparent 55%),
		radial-gradient(circle at 86% 78%, rgba(74, 144, 217, 0.12) 0%, transparent 55%);
	pointer-events: none;
}
.ca-404-inner {
	max-width: 920px;
	margin: 0 auto;
	position: relative;
	z-index: 1;
	text-align: center;
}
.ca-404-eyebrow {
	display: inline-block;
	padding: 6px 16px;
	background: rgba(255, 155, 3, 0.14);
	border: 1px solid rgba(255, 155, 3, 0.4);
	border-radius: 999px;
	color: var(--gold);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 11.5px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	margin-bottom: 24px;
}
.ca-404-title {
	font-family: var(--font-display);
	color: var(--white);
	font-weight: 800;
	font-size: clamp(36px, 5.4vw, 60px);
	line-height: 1.05;
	letter-spacing: -0.024em;
	margin: 0 0 18px;
}
.ca-404-lead {
	font-size: clamp(16px, 1.4vw, 18px);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.82);
	max-width: 620px;
	margin: 0 auto 44px;
}

/* Destination cards — 4-up at desktop, 2-up at tablet, 1-up at mobile.
 * Per-tone left accent + coloured icon disc. Hover: lift + arrow slides. */
.ca-404-cards {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 16px;
	margin-bottom: 48px;
	text-align: left;
}
.ca-404-card {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 22px 22px 20px;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 16px;
	text-decoration: none !important;
	color: var(--white);
	position: relative;
	overflow: hidden;
	transition: transform 0.25s cubic-bezier(0.22, 0.61, 0.36, 1),
	            background 0.2s ease,
	            border-color 0.2s ease;
}
/* Top-edge accent strip per tone */
.ca-404-card::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: var(--gold);
	opacity: 0.8;
}
.ca-404-card-gold::before  { background: var(--gold); }
.ca-404-card-sky::before   { background: var(--sky); }
.ca-404-card-teal::before  { background: var(--teal); }
.ca-404-card-coral::before { background: var(--coral); }

.ca-404-card:hover,
.ca-404-card:focus-visible {
	transform: translateY(-4px);
	background: rgba(255, 255, 255, 0.10);
	border-color: rgba(255, 255, 255, 0.2);
	outline: none;
}
.ca-404-card-icon {
	width: 48px;
	height: 48px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 12px;
	margin-bottom: 6px;
	transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.ca-404-card-gold  .ca-404-card-icon { background: rgba(255, 155,   3, 0.18); color: var(--gold);  }
.ca-404-card-sky   .ca-404-card-icon { background: rgba( 74, 144, 217, 0.18); color: var(--sky);   }
.ca-404-card-teal  .ca-404-card-icon { background: rgba( 28, 124, 140, 0.20); color: var(--teal);  }
.ca-404-card-coral .ca-404-card-icon { background: rgba(255, 107, 107, 0.20); color: var(--coral); }
.ca-404-card:hover .ca-404-card-icon { transform: scale(1.08) rotate(-3deg); }

.ca-404-card-title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 17px;
	color: var(--white);
	letter-spacing: -0.005em;
}
.ca-404-card-desc {
	font-size: 13.5px;
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.7);
	flex-grow: 1;
}
.ca-404-card-arrow {
	color: var(--gold);
	margin-top: 6px;
	transition: transform 0.25s ease;
}
.ca-404-card:hover .ca-404-card-arrow { transform: translateX(6px); }

/* Search row */
.ca-404-search {
	max-width: 520px;
	margin: 0 auto;
}
.ca-404-search-label {
	font-family: var(--font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.75);  /* a11y: 0.55 → 0.75 on navy (4.30 → 7.0) */
	margin-bottom: 14px;
}
.ca-404-search form {
	display: flex;
	background: var(--white);
	border-radius: 999px;
	padding: 4px 4px 4px 22px;
	box-shadow: 0 12px 28px rgba(0, 0, 0, 0.22);
}
.ca-404-search input[type="search"] {
	flex: 1;
	border: none;
	outline: none;
	background: transparent;
	font-family: var(--font-body);
	font-size: 15px;
	color: var(--charcoal);
	padding: 12px 4px;
}
.ca-404-search input[type="search"]::placeholder {
	color: rgba(45, 45, 45, 0.5);
}
.ca-404-search button {
	border: none;
	background: var(--gold);
	color: var(--navy);
	width: 44px;
	height: 44px;
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	flex-shrink: 0;
	transition: background 0.2s ease, transform 0.2s ease;
}
.ca-404-search button:hover,
.ca-404-search button:focus-visible {
	background: var(--gold-light);
	transform: scale(1.06);
	outline: none;
}

/* Hide the stock Astra 404 section if any of it leaks through */
body.error404 .error-404.not-found,
body.error404 .ast-404-layout-1,
body.error404 .ast-404-search {
	display: none !important;
}

@media (max-width: 1024px) {
	.ca-404-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
	.ca-404 { padding: 72px 22px 88px; }
	.ca-404-title { font-size: clamp(28px, 8vw, 36px); }
	.ca-404-lead { font-size: 15px; margin-bottom: 32px; }
	.ca-404-cards { grid-template-columns: 1fr; gap: 12px; margin-bottom: 36px; }
	.ca-404-card { padding: 18px 18px 16px; }
	.ca-404-card-icon { width: 42px; height: 42px; margin-bottom: 4px; }
	.ca-404-search form { padding-left: 18px; }
}

/* ═════════════════════════════════════════════════════════════════
 * COOKIE CONSENT BANNER — v0.9.64
 *
 * Complianz GDPR Free renders its banner with generic blue/grey
 * defaults. We override to match the brand: navy/gold palette,
 * Poppins for the title, gold pill for Accept, navy-outline pills
 * for Deny / View preferences / Save preferences. Top gold accent
 * strip mirrors the wc-blocks notice pattern (checkout.css).
 *
 * Collision with `.ca-sticky-cta` (also fixed bottom, z-index 50):
 * when the banner is visible (.cmplz-show), the sticky-CTA hides
 * via :has(). Once consent is given, Complianz removes .cmplz-show
 * and the sticky-CTA returns. Modern browsers only — :has() ships
 * everywhere we care about (Chrome 105+, Safari 15.4+, FF 121+).
 * ═════════════════════════════════════════════════════════════════ */
.cmplz-cookiebanner {
	background: var(--white) !important;
	border-radius: var(--radius-md) !important;
	border-top: 4px solid var(--gold) !important;
	box-shadow: var(--shadow-lg) !important;
	font-family: var(--font-body) !important;
	color: var(--charcoal) !important;
	padding: 18px 22px !important;
	max-width: 440px !important;
}
.cmplz-cookiebanner .cmplz-title {
	font-family: var(--font-display) !important;
	font-weight: 700 !important;
	font-size: 17px !important;
	color: var(--navy) !important;
	letter-spacing: -0.01em !important;
}
.cmplz-cookiebanner .cmplz-message,
.cmplz-cookiebanner .cmplz-message p {
	font-family: var(--font-body) !important;
	font-size: 13.5px !important;
	line-height: 1.55 !important;
	color: var(--charcoal) !important;
}
.cmplz-cookiebanner .cmplz-message a {
	color: var(--navy) !important;
	text-decoration: underline !important;
	text-underline-offset: 2px !important;
}
.cmplz-cookiebanner .cmplz-message a:hover {
	color: var(--gold) !important;
}
.cmplz-cookiebanner .cmplz-divider {
	background: var(--gray-200) !important;
	height: 1px !important;
	margin: 12px 0 !important;
}
.cmplz-cookiebanner .cmplz-category summary {
	font-family: var(--font-display) !important;
	font-weight: 600 !important;
	color: var(--navy) !important;
	font-size: 13.5px !important;
}
.cmplz-cookiebanner .cmplz-category .cmplz-description {
	font-size: 12.5px !important;
	color: var(--charcoal) !important;
}
.cmplz-cookiebanner .cmplz-links a,
.cmplz-cookiebanner .cmplz-documents a {
	color: var(--navy) !important;
	font-size: 12px !important;
	text-decoration: underline !important;
	text-underline-offset: 2px !important;
}
.cmplz-cookiebanner .cmplz-links a:hover,
.cmplz-cookiebanner .cmplz-documents a:hover {
	color: var(--gold) !important;
}

/* Buttons — gold primary, navy ghosts */
.cmplz-cookiebanner .cmplz-btn {
	font-family: var(--font-body) !important;
	font-weight: 600 !important;
	font-size: 14px !important;
	border-radius: 999px !important;
	padding: 10px 22px !important;
	transition: transform 120ms ease, background-color 120ms ease, color 120ms ease, border-color 120ms ease, box-shadow 120ms ease !important;
}
.cmplz-cookiebanner .cmplz-accept {
	background: var(--gold) !important;
	color: var(--navy) !important;
	border: 1px solid var(--gold) !important;
	box-shadow: 0 2px 8px rgba(255, 155, 3, 0.28) !important;
}
.cmplz-cookiebanner .cmplz-accept:hover {
	background: var(--gold-hover) !important;
	border-color: var(--gold-hover) !important;
	transform: translateY(-1px);
}
.cmplz-cookiebanner .cmplz-deny,
.cmplz-cookiebanner .cmplz-view-preferences,
.cmplz-cookiebanner .cmplz-save-preferences,
.cmplz-cookiebanner a.cmplz-manage-options {
	background: var(--white) !important;
	color: var(--navy) !important;
	border: 1px solid var(--navy) !important;
}
.cmplz-cookiebanner .cmplz-deny:hover,
.cmplz-cookiebanner .cmplz-view-preferences:hover,
.cmplz-cookiebanner .cmplz-save-preferences:hover,
.cmplz-cookiebanner a.cmplz-manage-options:hover {
	background: var(--navy) !important;
	color: var(--white) !important;
	transform: translateY(-1px);
}

/* Close (X) button */
.cmplz-cookiebanner .cmplz-close {
	color: var(--navy) !important;
	opacity: 0.65;
	transition: opacity 120ms ease, color 120ms ease;
}
.cmplz-cookiebanner .cmplz-close:hover {
	color: var(--gold) !important;
	opacity: 1;
}

/* Toggle switches in category list — gold when active */
.cmplz-cookiebanner .cmplz-category .cmplz-slider:has(input:checked),
.cmplz-cookiebanner .cmplz-toggle .cmplz-slider:has(input:checked) {
	background: var(--gold) !important;
}

/* Email anti-spam decoy on the Complianz DOCUMENT pages (cookie policies +
 * the US opt-out / Privacy Choices page). Complianz writes the contact email as
 *   hello@<span class="cmplz-fmail-domain">ex.com</span>chiggle.academy
 * and relies on its own front-end stylesheet to hide the decoy span so humans
 * see "hello@chiggle.academy" while scrapers harvest the poisoned address. That
 * Complianz stylesheet is NOT enqueued on these document pages here, so the
 * email rendered as the broken, unusable "hello@ex.comchiggle.academy". Hiding
 * the decoy in our always-loaded global CSS restores the correct address for
 * sighted + screen-reader users (display:none is dropped from the a11y tree),
 * while keeping the anti-harvest poison in the raw markup. (Audit 2026-05-29.) */
.cmplz-fmail-domain { display: none !important; }

/* Banner cleanup (audit 2026-05-29). This site uses only Functional +
 * Statistics cookies (uses_ad_cookies=no, no preference cookies), and is a
 * plain GDPR/CCPA banner — not an IAB-TCF setup. Complianz's banner template
 * still emits the Marketing + Preferences category toggles, the TCF
 * vendor/purposes links, and an unconfigured document-links block that render
 * literal {vendor_count}/{title} tokens on dead href="#" anchors. The banner
 * config also carries these categories at show:0 (forward-compatible), but this
 * build renders them anyway, so we hide them here. Result: the preferences
 * panel shows only Functional + Statistics, matching the Privacy Policy. */
.cmplz-cookiebanner .cmplz-category.cmplz-marketing,
.cmplz-cookiebanner .cmplz-category.cmplz-preferences,
.cmplz-cookiebanner .cmplz-documents,
.cmplz-cookiebanner li:has(> .cmplz-manage-vendors),
.cmplz-cookiebanner li:has(> .cmplz-read-more-purposes) {
	display: none !important;
}

/* Astra's default footer "copyright" bar. The site ships a custom branded
 * footer (.ca-footer, inc/hooks-footer.php); Astra's builder copyright row
 * otherwise double-renders on default-template pages (e.g. Contact,
 * How-we-make) as "© 2026 Chiggle Academy | Powered by Astra" — wrong rights
 * holder + an unwanted theme credit. Hide Astra's below-footer everywhere; our
 * .ca-footer is the canonical footer. (Audit 2026-05-29.) */
.site-below-footer-wrap {
	display: none !important;
}

/* Re-consent (revoke / manage) bottom-left tab Complianz renders post-consent */
.cmplz-cookiebanner-anchor,
#cmplz-manage-consent,
.cmplz-show-banner {
	background: var(--navy) !important;
	color: var(--white) !important;
	border-radius: 999px !important;
	font-family: var(--font-body) !important;
	font-size: 12.5px !important;
}
.cmplz-cookiebanner-anchor:hover,
#cmplz-manage-consent:hover,
.cmplz-show-banner:hover {
	background: var(--gold) !important;
	color: var(--navy) !important;
}

/* Collision fix: hide sticky CTA while banner is on-screen */
body:has(.cmplz-cookiebanner.cmplz-show) .ca-sticky-cta {
	display: none !important;
}

@media (max-width: 600px) {
	.cmplz-cookiebanner {
		left: 12px !important;
		right: 12px !important;
		max-width: calc(100vw - 24px) !important;
		padding: 16px 18px !important;
	}
	.cmplz-cookiebanner .cmplz-btn {
		padding: 9px 18px !important;
		font-size: 13.5px !important;
	}
}

/* ═════════════════════════════════════════════════════════
 * REDUCED-MOTION SUPPORT (v0.9.79 a11y)
 *
 * Respects the OS-level "Reduce motion" preference (macOS / iOS /
 * Windows / Android all expose it). Users who set this — including
 * many with vestibular-disorder, motion-sensitivity, or focus
 * conditions — get our site with all animations + transitions
 * shortened to ~0.01s (effectively instant), the smooth-scroll
 * behaviour disabled, and animations stopped after one cycle.
 *
 * The `!important` is necessary because most of our component CSS
 * sets `transition: ...` or `animation: ...` without media-query
 * guards. Rather than patch every rule individually (~50+ across
 * the design system), a single global override at the end of
 * global.css covers the whole codebase.
 *
 * Cookie banner CSS (above) and Complianz CSS plus TutorLMS-injected
 * transitions all get respected because of !important specificity.
 *
 * WCAG 2.1 SC 2.3.3 (Animation from Interactions, Level AAA) calls
 * for honouring prefers-reduced-motion. We're at AAA on this axis.
 * ═════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
	html {
		scroll-behavior: auto;
	}
}

/* ═════════════════════════════════════════════════════════
 * PRINT STYLESHEET (v0.9.79)
 *
 * Specifically tuned for `/certificate/` (the Founder Certificate
 * archive + single certificate page) — when a learner Cmd/Ctrl-P's
 * or saves as PDF, they should get a clean certificate filling the
 * page with no site chrome.
 *
 * Generally improves print output for every page too: drops the
 * header / footer / sticky-CTA / cookie banner / admin bar / nav
 * scrim, forces colour preservation, sets sensible page margins.
 * ═════════════════════════════════════════════════════════ */
@media print {
	/* Page setup — A4 default, letter works similarly */
	@page {
		margin: 18mm 14mm;
		size: auto;
	}

	/* Preserve brand colours when printed — Chrome/Edge default to
	 * "Color: Off" to save ink. WCAG-aware. */
	*,
	*::before,
	*::after {
		-webkit-print-color-adjust: exact !important;
		print-color-adjust: exact !important;
	}

	/* Hide everything that isn't certificate / page content.
	 *
	 * The wildcard `[class*="cmplz-"]` MUST exclude `<body>` and `<html>`.
	 * Complianz adds a body class (`cmplz-consent-given` etc.) to indicate
	 * consent state — without the `:not(body):not(html)` guard, the wildcard
	 * matches the whole <body> and hides the entire document, producing a
	 * blank print / PDF. Fixed v0.11.79 (the cert-print-blank bug). */
	.ca-header,
	.ca-footer,
	.ca-sticky-cta,
	.ca-nav-scrim,
	.ca-promo-bar,            /* launch-offer announcement bar (top of every page) */
	.cmplz-cookiebanner,
	.cmplz-cookiebanner-container,
	#wpadminbar,
	#tutor-dashboard-footer-mobile,
	.ca-skip-link,
	#ca-signin-modal,
	/* Hide cookie consent dim layer (NOT the body itself, even though
	 * it carries cmplz-* state classes — see header comment above). */
	[class*="cmplz-"]:not(.cmplz-document):not(body):not(html) {
		display: none !important;
	}

	/* Wider, breathing room for content body */
	body {
		background: white !important;
		color: black !important;
		font-size: 11pt;
		line-height: 1.5;
	}

	/* Headings keep brand colours, slightly smaller for print */
	h1, h2, h3, h4 {
		color: var(--navy) !important;
		page-break-after: avoid;
	}

	/* Prevent awkward breaks inside cards / lists / images */
	.ca-outcome-card,
	.ca-feat-card,
	.ca-faq-item,
	.ca-tpl-card,
	.ca-prompt-card,
	img, svg, figure {
		page-break-inside: avoid;
		break-inside: avoid;
	}

	/* Show absolute URL after link text (so printed copy is useful) */
	a[href]::after {
		content: " (" attr(href) ")";
		font-size: 0.85em;
		color: #444;
		font-weight: normal;
	}
	/* …but not for site-internal anchor links, hash-only links, or
	 * obvious-URL link text */
	a[href^="#"]::after,
	a[href^="javascript:"]::after,
	a.ca-btn::after,
	.ca-nav a::after,
	nav a::after {
		content: "";
	}

	/* Body removes the offwhite page tint */
	body {
		background-color: white !important;
	}

	/* /certificate/ archive page — center it, no padding overflow */
	body.post-type-archive-certificate main,
	body.single-certificate main,
	body.page-template-certificate main {
		max-width: 700px;
		margin: 0 auto;
		padding: 0;
	}

	/* Skip-link should never print */
	.screen-reader-text { display: none !important; }
}

/* ═════════════════════════════════════════════════════════
 * LEARNER NOTICE BANNERS (v0.11.66)
 *
 *   .ca-lapse-banner  (inc/hooks-membership-lapse.php) — shown to a
 *     lapsed member on the dashboard and, prepended via the_content,
 *     on the /templates/ + /llm-prompts/ library pages.
 *   .ca-cert-nudge    (inc/hooks-cert-nudge.php) — dashboard-only
 *     nudge to set the name printed on the Founder Certificate.
 *
 * Moved here from dashboard.css in v0.11.66: the lapse banner now
 * renders on standalone pages where dashboard.css is not enqueued,
 * and global.css loads everywhere. The dashboard hide-rule
 * exemptions for both classes stay in dashboard.css.
 * ═════════════════════════════════════════════════════════ */

/* Wrapper used only when the lapse banner is prepended to a
 * standalone page's the_content — gives it the centred column + top
 * breathing room the dashboard context already provides. */
.ca-lapse-banner-pagewrap {
	max-width: 1080px;
	margin: 0 auto;
	padding: 32px 24px 0;
}

.ca-lapse-banner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 18px;
	margin: 0 0 24px;
	padding: 22px 26px;
	background: var(--gold-pale);
	border: 1px solid var(--gold);
	border-radius: var(--radius-lg);
}
.ca-lapse-banner-body {
	flex: 1 1 320px;
}
.ca-lapse-banner-title {
	margin: 0 0 6px;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.15rem;
	color: var(--navy);
	letter-spacing: -0.01em;
}
.ca-lapse-banner-text {
	margin: 0;
	font-size: 0.9rem;
	line-height: 1.55;
	color: var(--charcoal);
}
.ca-lapse-banner-cta {
	flex: 0 0 auto;
	padding: 12px 24px;
	border-radius: var(--radius-sm);
	background: var(--gold);
	color: var(--navy);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9rem;
	text-decoration: none !important;
	white-space: nowrap;
	transition: background-color 0.15s ease;
}
.ca-lapse-banner-cta:hover,
.ca-lapse-banner-cta:focus-visible {
	background: var(--gold-hover);
}

/* Certificate-name nudge — calmer treatment than the lapse banner:
 * a white card with a gold left-accent, vs the gold-pale fill. */
.ca-cert-nudge {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 18px;
	margin: 0 0 24px;
	padding: 20px 24px;
	background: var(--white);
	border: 1px solid var(--gold);
	border-left: 4px solid var(--gold);
	border-radius: var(--radius-lg);
}
.ca-cert-nudge-body {
	flex: 1 1 320px;
}
.ca-cert-nudge-title {
	margin: 0 0 5px;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.05rem;
	color: var(--navy);
	letter-spacing: -0.01em;
}
.ca-cert-nudge-text {
	margin: 0;
	font-size: 0.88rem;
	line-height: 1.55;
	color: var(--charcoal);
}
.ca-cert-nudge-actions {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 14px;
}
.ca-cert-nudge-cta {
	padding: 11px 22px;
	border-radius: var(--radius-sm);
	background: var(--gold);
	color: var(--navy);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.88rem;
	text-decoration: none !important;
	white-space: nowrap;
	transition: background-color 0.15s ease;
}
.ca-cert-nudge-cta:hover,
.ca-cert-nudge-cta:focus-visible {
	background: var(--gold-hover);
}
.ca-cert-nudge-dismiss {
	font-size: 0.85rem;
	color: var(--charcoal);
	text-decoration: underline;
	white-space: nowrap;
}

@media (max-width: 640px) {
	.ca-lapse-banner,
	.ca-cert-nudge {
		padding: 18px;
	}
	.ca-lapse-banner-cta {
		width: 100%;
		text-align: center;
	}
	.ca-cert-nudge-actions {
		width: 100%;
	}
	.ca-cert-nudge-cta {
		flex: 1;
		text-align: center;
	}
	.ca-lapse-banner-pagewrap {
		padding: 24px 16px 0;
	}
}

/* ═════════════════════════════════════════════════════════
 * PWA INSTALL AFFORDANCE (v0.11.69)
 *
 *   .ca-pwa-install      — the dismissible bottom install banner
 *                          (inc/hooks-pwa.php), shown to logged-in
 *                          learners on mobile.
 *   #ca-pwa-footer-link  — the evergreen footer "Install the app" link
 *                          (inc/hooks-footer.php).
 * ═════════════════════════════════════════════════════════ */

.ca-pwa-install {
	position: fixed;
	left: 12px;
	right: 12px;
	bottom: 12px;
	z-index: 60;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 14px;
	padding: 13px 14px 13px 18px;
	background: var(--navy);
	color: var(--white);
	border-radius: var(--radius-lg);
	box-shadow: 0 8px 28px rgba(18, 43, 105, 0.34);
}
.ca-pwa-install[hidden] {
	display: none;
}
.ca-pwa-install-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}
.ca-pwa-install-text strong {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.95rem;
}
.ca-pwa-install-sub {
	font-size: 0.8rem;
	line-height: 1.4;
	color: rgba(255, 255, 255, 0.82);
}
.ca-pwa-install-actions {
	display: flex;
	align-items: center;
	gap: 6px;
	flex-shrink: 0;
}
.ca-pwa-install-btn {
	background: var(--gold);
	color: var(--navy);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.85rem;
	border: none;
	border-radius: var(--radius-sm);
	padding: 9px 16px;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.15s ease;
}
.ca-pwa-install-btn[hidden] {
	display: none;
}
.ca-pwa-install-btn:hover,
.ca-pwa-install-btn:focus-visible {
	background: var(--gold-hover);
}
.ca-pwa-install-dismiss {
	background: transparent;
	border: none;
	color: rgba(255, 255, 255, 0.7);
	font-size: 0.95rem;
	line-height: 1;
	padding: 8px;
	cursor: pointer;
}
.ca-pwa-install-dismiss:hover,
.ca-pwa-install-dismiss:focus-visible {
	color: var(--white);
}

/* The banner is a mobile affordance — the goal is home-screen install on
 * phones. Hidden on desktop; the footer link still covers desktop. */
@media (min-width: 901px) {
	.ca-pwa-install {
		display: none !important;
	}
}

/* Yield to the cookie-consent banner (both are bottom-anchored). */
body:has(.cmplz-cookiebanner.cmplz-show) .ca-pwa-install {
	display: none !important;
}

/* Lift clear of TutorLMS's mobile dashboard footer nav when present. */
body:has(#tutor-dashboard-footer-mobile) .ca-pwa-install {
	bottom: 80px;
}

/* Footer "Install the app" link — hidden once the app is installed. */
#ca-pwa-footer-link[hidden] {
	display: none;
}
