/*
 * Shared components — Easy Quran Classes.
 * Reusable classes so page composition (Elementor containers) never repeats
 * one-off CSS. See DESIGN.md §16–19 for the source rules.
 */

/* ---------- Base / resets scoped to our content ---------- */

body {
	background: var(--eqc-cream-100);
	color: var(--eqc-text);
	font-family: var(--eqc-font-body);
	font-size: var(--eqc-fs-body);
	line-height: 1.62;
}

h1, h2, h3 {
	font-family: var(--eqc-font-display);
	color: var(--eqc-heading);
	font-weight: 400;
	line-height: 1.08;
}

h1 { font-size: var(--eqc-fs-h1); }
h2 { font-size: var(--eqc-fs-h2); }
h3 { font-size: var(--eqc-fs-h3); line-height: 1.18; }
h4 { font-size: var(--eqc-fs-h4); font-weight: 600; font-family: var(--eqc-font-body); }

a { color: inherit; }

img { display: block; max-width: 100%; height: auto; }

/*
 * Hello Elementor's own reset.css hardcodes a bright pink (#cc3366)
 * button:hover/:focus background/border as its "unstyled button" default.
 * Every plain <button> we write (FAQ toggle, nav toggle, form buttons
 * added later) inherits it unless explicitly reset, since we never touch
 * the parent theme itself. Neutralize once, here, rather than re-fixing
 * it on each new button component.
 */
button:hover,
button:focus,
[type="button"]:hover,
[type="button"]:focus {
	background-color: transparent;
	border-color: transparent;
	/* Hello's same rule also sets color:#fff (meant to read against its
	   pink background); reset to inherit or it leaves white-on-transparent
	   text once the pink is removed. */
	color: inherit;
}

/* Decorative SVG must never be announced to assistive tech. */
[data-eqc-decorative="true"] {
	pointer-events: none;
}

/*
 * Icon sprite references (inc/icon-sprite.php + eqc_icon()) are bare
 * <svg><use></svg> elements with no width/height attribute, so without an
 * explicit size a browser renders them at the SVG replaced-element default
 * (300x150) — this rule is load-bearing, not cosmetic.
 */
.eqc-icon {
	width: 1.25em;
	height: 1.25em;
	display: inline-block;
	flex: none;
	vertical-align: -0.15em;
	overflow: visible;
}

/*
 * Elementor's own base widget CSS sets `position: relative` on every
 * `.elementor-widget-html` wrapper. Our eqc_html() snippets often contain
 * `position: absolute` children (badges, avatars) that are meant to
 * anchor to an ANCESTOR container (e.g. .eqc-card--testimonial), not to
 * this wrapper — which also collapses to near-zero height, so the
 * intended offset ends up measured from the wrong box entirely. Reset it
 * site-wide; nothing here relies on the wrapper itself being a
 * positioning context.
 */
.elementor-widget-html { position: static; }

/* ---------- Layout ---------- */

.eqc-section {
	padding-block: var(--eqc-section-space);
}

.eqc-section--tight { padding-block: calc(var(--eqc-section-space) * 0.55); }

.eqc-section--cream { background: var(--eqc-cream-100); }
.eqc-section--surface { background: var(--eqc-surface); }

/* The content column is the reference's own 85.6% band, held once --eqc-u
   reaches its ceiling so the design stops growing past ~2100px. No inline
   padding: the 85.6% box IS the column the reference measures, so padding
   here would inset the content a second time. */
.eqc-container {
	width: min(calc(1119 * var(--eqc-u)), calc(100% - 2 * var(--eqc-gutter)));
	margin-inline: auto;
	padding: 0;
	box-sizing: border-box;
	/* Elementor's kit sets a flat 20px container gap, the only spacing in the
	   vertical stack that never scaled with the design. */
	row-gap: calc(22 * var(--eqc-u));
}

.eqc-container--narrow { max-width: var(--eqc-content-narrow); }
.eqc-container--text { max-width: var(--eqc-text-max); }

.eqc-stack { display: flex; flex-direction: column; gap: var(--eqc-stack-gap); }

/* ---------- Eyebrow / section heading ---------- */

/* One shape for every section tag site-wide, at a consistent font size. The
   explicit min-block-size keeps a tag that carries an icon exactly as tall
   as one that doesn't. */
/* Section tags carry the site's cartouche, not a rounded rectangle (client,
   2026-09-17), everywhere on the site.

   Drawn with BORDER-IMAGE, which is the only mechanism that can hold the end
   caps at a fixed size while the middle grows with the label. The earlier
   version masked the frame at `100% 100%` and stretched the caps with the tag,
   so a long label produced a visibly different shape from a short one -- the
   distortion the client asked to be rid of. Here the slice takes 36 of the
   image's 260 units from each end; those regions are painted at a fixed width
   and only region 5, two straight horizontal lines, is stretched. Stretching a
   straight line is invisible, which is the whole trick.

   The cap keeps its aspect because its drawn width tracks the tag's height:
   36/54 of it, the slice's own proportions in the image. Height is therefore
   the one thing that must stay constant site-wide, and it is -- every tag uses
   --eqc-eyebrow-h and no variant overrides it.

   `fill` on border-image-slice is what paints the middle region, and the image
   carries the pricing-banner contour as its fill, so the background IS the
   banner shape rather than a rounded rectangle behind it. Frame and banner
   share their anchor points (only the arc radii differ), so the two contours
   agree.

   The drawing lives in assets/svg/eyebrow-frame.svg, whose own comment marks
   which units are cap and which are stretchable middle. Its colours are
   literal copies of --eqc-surface and --eqc-gold-600: a border-image cannot
   recolour an external SVG (`currentColor` resolves inside that document).

   CONTROLS (client, Round 20: "the corners must keep the same shape, the
   length adjustable"). Set any of these on a tag or a wrapper; none of them
   can change the caps' shape, only their overall scale or the middle's length:
     --eqc-eyebrow-h      overall size. Caps scale uniformly with it. Keep one
                          value site-wide (tokens.css) so all tags match.
     --eqc-eyebrow-pad    space between the label and each cap -- lengthens
                          or shortens the straight middle only. Default 0.9em.
     --eqc-eyebrow-min-w  minimum overall length, e.g. to make a row of short
                          tags the same length. Default: fits the label.
   Proof that length never touches the caps: tests/visual/eyebrow-caps.mjs
   compares the cap pixels of the shortest and longest tag on a page. */
.eqc-eyebrow {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	font-size: var(--eqc-fs-eyebrow);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--eqc-bronze-600);
	background: none;
	/* One height for every tag on the site. The cap width below is derived
	   from it, so a variant that changed the height would change the cap's
	   shape too.
	   Floored at 3em of the label's own type (Round 20): --eqc-eyebrow-h is
	   --eqc-u based and bottoms out at 30.8px below a 915px viewport, which
	   pressed the frame into a flat band around 13px capitals -- the ogee tips
	   shrank to slivers and the label ran into them. 3em keeps the frame's
	   proportion to its own text constant; on desktop the token still wins. */
	--_eyebrow-h: max(var(--eqc-eyebrow-h), 3em);
	block-size: var(--_eyebrow-h);
	min-block-size: var(--_eyebrow-h);
	box-sizing: border-box;
	border-style: solid;
	border-color: transparent;
	/* Top/bottom 0 so the caps paint at the tag's full height; left/right hold
	   the cap at the slice's own 36:54 ratio. */
	border-width: 0 calc(var(--_eyebrow-h) * 36 / 54);
	border-image-source: url('../svg/eyebrow-frame.svg');
	border-image-slice: 0 36 fill;
	border-image-repeat: stretch;
	/* Inline padding sits inside the flat middle band. With none, the label
	   began where the cap ends and read as touching the tip -- the "squeezed"
	   look the client flagged. Vertical padding stays 0: the height is fixed. */
	padding: 0 var(--eqc-eyebrow-pad, 0.9em);
	min-inline-size: var(--eqc-eyebrow-min-w, auto);
	position: relative;
}

/* A section tag must hug its text. .eqc-section-heading is a flex column
   with the default `align-items: stretch`, so this inline-flex pill is
   otherwise stretched to the column's full width wherever the heading is
   NOT centred — measured 557px on /faq/ and 440px on /courses/ without this
   rule. --center re-centres it; the base case never had a rule at all. */
.eqc-section-heading .eqc-eyebrow { align-self: flex-start; }
.eqc-section-heading--center .eqc-eyebrow { align-self: center; }

.eqc-heading-rule {
	display: block;
	width: clamp(64px, 8vw, 120px);
	height: 1px;
	margin-block: 0.9em;
	background: linear-gradient(90deg, var(--eqc-gold-500), transparent);
	border: 0;
}

/* Ornate section-heading rule — one self-contained inline SVG asset
 * (divider-section.svg: hairline + diamond terminals + rosette medallion),
 * used under every H2 site-wide. This class is fully self-contained and
 * must not also carry the base `.eqc-heading-rule` class: that class's
 * `height:1px; background:linear-gradient(...)` would paint a full-width
 * flat gold bar with a tiny flower stranded near the left edge instead of
 * the centered line-diamond-rosette-diamond-line motif intended.
 * eqc_section_heading_el() does not emit the base class alongside this one,
 * and this rule is written to be correct regardless of what else is
 * applied alongside it.
 */
.eqc-heading-rule--ornate {
	display: flex;
	justify-content: flex-start;
	width: 100%;
	height: auto;
	background: none;
	margin-block: 0.4em;
	color: var(--eqc-gold-500);
	opacity: 0;
	transform: scale(0.85);
	transition: opacity var(--eqc-motion-slow) var(--eqc-ease-standard),
		transform var(--eqc-motion-slow) var(--eqc-ease-standard);
}
.eqc-section-heading--center .eqc-heading-rule--ornate { justify-content: center; }
/* A divider must never be wider than the wrapper it is placed in. This was
   a bare clamp() with no relation to its container, so every divider without
   an explicit width override rendered at 240px -- inside a 183px teacher card
   that overflowed the card edge by 57px and read as a rule running across the
   gap into the next card. width:100% sizes it to the slot; the clamp stays as
   the ceiling for the wide, free-standing rules. */
.eqc-divider-svg { width: 100%; max-width: clamp(180px, 22vw, 240px); height: auto; flex: none; }
html.eqc-js .is-visible .eqc-heading-rule--ornate { opacity: 1; transform: scale(1); }
html:not(.eqc-js) .eqc-heading-rule--ornate { opacity: 1; transform: scale(1); }

/* ---------- Buttons ----------
 * Two call sites share one visual language:
 * 1. Raw `<a class="eqc-btn eqc-btn--variant">` in header.php/footer.php.
 * 2. Elementor's native Button widget elsewhere, kept for in-editor
 *    text/link editability. Elementor's
 *    `_css_classes` control lands on the widget's OUTER wrapper div, not
 *    the inner <a class="elementor-button">, so every rule below also
 *    targets ".elementor-widget-button.eqc-btn(--variant) .elementor-button"
 *    to re-skin the real link — this is the one deliberate override of
 *    Elementor's own button chrome (DESIGN.md §19: child-theme CSS is the
 *    approved place for reusable styling Elementor Free can't express).
 *
 * Every selector below is element-qualified (`a.eqc-btn`/`button.eqc-btn`),
 * never the bare class. A bare `.eqc-btn` also matches the Elementor wrapper
 * `<div class="eqc-btn ... elementor-widget-button">`, which then paints full
 * pill chrome (height, padding-inline, border, background) of its own on top
 * of the inner `.elementor-button` anchor's copy — two overlapping pills of
 * different sizes, worst on hover/press since the transform applies to both.
 * Element-qualifying makes it impossible for a `<div>` wrapper to match, so
 * the wrapper stays pure invisible layout and only the real link is painted.
 */

a.eqc-btn, button.eqc-btn,
.elementor-widget-button.eqc-btn .elementor-button {
	/* max(), not a media query: the 44px tap floor applies at every width. */
	--_h: max(48px, calc(58 * var(--eqc-u)));
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: calc(10 * var(--eqc-u));
	height: var(--_h);
	width: auto;
	padding-inline: calc(40 * var(--eqc-u));
	/* A floor, not a width: a short label ("View All Teachers") otherwise
	   shrink-wraps to a pill noticeably narrower than the long-label buttons
	   beside it elsewhere on the page, so the same control reads as two
	   different components. --sm opts out (it is sized for card footers). */
	min-inline-size: calc(190 * var(--eqc-u));
	border-radius: var(--eqc-radius-pill);
	font-family: var(--eqc-font-body);
	font-size: var(--eqc-fs-button);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	border: 1px solid transparent;
	cursor: pointer;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard),
		background-color var(--eqc-motion-base) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-base) var(--eqc-ease-standard);
}

/* The outer Elementor wrapper itself is layout-only — never chrome — and
   stays a plain inline shrink-wrap box (not stretched to the container's
   cross-axis) so it adds no block-level width/margin of its own around the
   link. */
.elementor-widget-button.eqc-btn {
	display: inline-block;
	align-self: center;
	width: auto;
	max-width: 100%;
}
/* Button groups that are explicitly left-aligned (e.g. a hero text column)
   opt back in by wrapping native buttons in a container with this class. */
.eqc-align-start > .elementor-widget-button.eqc-btn { align-self: flex-start; }
/* A button that must fill its container (e.g. a card footer) opts in here;
   the wrapper stretches and the inner anchor (below) fills it in turn. */

a.eqc-btn:hover, button.eqc-btn:hover,
.elementor-widget-button.eqc-btn .elementor-button:hover {
	transform: translateY(-2px);
	box-shadow: 0 10px 22px rgba(20, 35, 27, 0.16);
}
a.eqc-btn:active, button.eqc-btn:active,
.elementor-widget-button.eqc-btn .elementor-button:active {
	transform: translateY(0);
	box-shadow: none;
}
a.eqc-btn:focus-visible, button.eqc-btn:focus-visible,
.elementor-widget-button.eqc-btn .elementor-button:focus-visible {
	outline: 3px solid var(--eqc-gold-500);
	outline-offset: 2px;
}

a.eqc-btn--primary, button.eqc-btn--primary,
.elementor-widget-button.eqc-btn--primary .elementor-button {
	background: var(--eqc-green-800);
	color: var(--eqc-white);
}
a.eqc-btn--primary:hover, button.eqc-btn--primary:hover,
.elementor-widget-button.eqc-btn--primary .elementor-button:hover { background: var(--eqc-green-700); }

a.eqc-btn--bronze, button.eqc-btn--bronze,
.elementor-widget-button.eqc-btn--bronze .elementor-button {
	background: var(--eqc-bronze-700);
	color: var(--eqc-white);
}
a.eqc-btn--bronze:hover, button.eqc-btn--bronze:hover,
.elementor-widget-button.eqc-btn--bronze .elementor-button:hover { background: var(--eqc-bronze-600); }

a.eqc-btn--secondary, button.eqc-btn--secondary,
.elementor-widget-button.eqc-btn--secondary .elementor-button {
	background: transparent;
	color: var(--eqc-green-800);
	border-color: var(--eqc-border-strong);
}
a.eqc-btn--secondary:hover, button.eqc-btn--secondary:hover,
.elementor-widget-button.eqc-btn--secondary .elementor-button:hover { background: var(--eqc-surface); }

.eqc-footer-cta a.eqc-btn--secondary,
.eqc-footer-cta .elementor-widget-button.eqc-btn--secondary .elementor-button {
	color: var(--eqc-cream-100);
	border-color: rgba(247, 243, 236, 0.4);
}
.eqc-footer-cta a.eqc-btn--secondary:hover,
.eqc-footer-cta .elementor-widget-button.eqc-btn--secondary .elementor-button:hover { background: rgba(255, 255, 255, 0.08); }

/* WhatsApp buttons take the brand green as their permanent rest state, not
   only on hover/focus/press, so this rule does not need `:hover`/
   `:focus-visible`/`:active` qualifiers to apply. Selectors carry
   element+class weight to match the `a.eqc-btn--secondary` rules they
   override, and the `.eqc-footer-cta` variant is listed explicitly because
   it sets its own background at higher specificity. #25D366 is WhatsApp's
   own green, kept because the point is instant brand recognition — but the
   label on it is DARK, not white. White on #25D366 measures 1.98:1, which
   fails WCAG 1.4.3 at any size, and `font-weight` is not a contrast
   exemption. --eqc-heading on the same green measures 8.23:1. */
a.eqc-btn--whatsapp,
.eqc-footer-cta a.eqc-btn--whatsapp {
	background: var(--eqc-whatsapp-green);
	border-color: var(--eqc-whatsapp-green-dark);
	color: var(--eqc-heading);
	font-weight: 700;
}
a.eqc-btn--whatsapp .eqc-icon { color: var(--eqc-heading); }
/* A visible hover effect still applies on top of the permanent green — a
   modest darken to the brand's own border shade, so the state change reads
   as "pressed" without breaking brand recognition. */
a.eqc-btn--whatsapp:hover,
a.eqc-btn--whatsapp:focus-visible,
a.eqc-btn--whatsapp:active,
.eqc-footer-cta a.eqc-btn--whatsapp:hover,
.eqc-footer-cta a.eqc-btn--whatsapp:focus-visible {
	background: var(--eqc-whatsapp-green-dark);
}

.eqc-btn-group {
	display: flex;
	flex-wrap: wrap;
	gap: calc(13 * var(--eqc-u));
	align-items: center;
}
/* A lone CTA button inside a centred (narrow) column centres too — used by
   the home + courses "View All FAQs" buttons. */
.eqc-container--narrow .eqc-btn-group { justify-content: center; }
/* The hero's "Book Free Trial" / "Chat on WhatsApp" pair, and the About
   section's "Book a Free Trial" / "Call Any Time" pair, would otherwise
   render at different widths because the button box shrink-wraps its own
   (differently long) label + icon. Both pairs are built with
   eqc_icon_button() (a plain `<a class="eqc-btn">` inside a plain
   `.elementor-widget-html` wrapper, no widget-specific classes on the
   wrapper itself), so one rule covers both sections. */
.eqc-hero-text .eqc-btn-group > .elementor-widget-html,
.eqc-about-text .eqc-btn-group > .elementor-widget-html {
	flex: 1 1 0;
	min-width: 0;
	/* Without this cap, the equal-width rule stretches both buttons across
	   the full column on wide screens, compounding the padding above into
	   an oversized pair. Capped so they stay a sensible button width and
	   simply centre with extra gap instead of stretching further.
	   !important because Elementor's own core CSS sets max-width on
	   .elementor-widget at equal-or-higher specificity and loads after this
	   stylesheet — confirmed via computed style (240px in this rule, 100%
	   on the actual element) before reaching for !important; a lone button
	   in a group (career page's single "Apply Now" CTA) has flex-grow:1
	   with nothing to share the row with, so it would otherwise stretch to
	   the column's full width uncapped. */
	max-inline-size: 280px !important;
}
.eqc-hero-text .eqc-btn-group > .elementor-widget-html a.eqc-btn,
.eqc-about-text .eqc-btn-group > .elementor-widget-html a.eqc-btn {
	width: 100%;
	/* The wrapper's cap above is the authority for this pair, and it must be:
	   the shared button floor is fluid and overtakes a fixed cap on a wide
	   screen, which pushed each button past the wrapper it is supposed to
	   fill and broke the pair's equal widths. */
	min-inline-size: 0;
}

/* Below the width where two labels can share a row without either one
   shrinking past its own text ("Chat on WhatsApp" needs 205px, but the
   equal-width rule above caps each item to half the group — at 390px
   that's 155px, so the label would spill past the pill's rounded edge;
   measured live, not assumed), stack the pair into one full-width button
   per row instead. 28rem (448px) is the measured point where 205px + 183px
   content + the group's own gap first fits two across, not a device
   guess. `!important` throughout: Elementor bakes each container's own
   `flex_direction: row` setting as generated per-element CSS, confirmed
   via computed style to still win here without it — the same fight
   `.eqc-nav-drawer-cta`/`.eqc-header-cta` above already document and solve
   the same way. */
/* Short labels for narrow screens. Both are real text in the markup and the
   anchor carries an aria-label with the FULL wording, so the accessible name
   never shrinks with the visual one -- see eqc_btn_label() in
   tools/elementor-helpers.php. Only buttons that share a row have a short form;
   a button standing alone has one label and is unaffected by any of this. */
.eqc-btn-label-short { display: none; }
@media (max-width: 28rem) {
	.eqc-btn-label-full { display: none; }
	.eqc-btn-label-short { display: inline; }
}

@media (max-width: 28rem) {
	.eqc-btn-group { flex-direction: column !important; align-items: stretch !important; }
	.eqc-btn-group > * { width: 100% !important; max-inline-size: none !important; }
	/* --compact opts a PAIR out of that stack (client, 2026-09-17): with the
	   short labels above, "Free Trial" and "WhatsApp" fit across 390px and even
	   320px, which is the whole point of shortening them. The stack remains the
	   default because it is still right for any pair that keeps long wording.
	   `!important` for the same reason the rule above needs it -- Elementor
	   bakes each container's own flex_direction as per-element CSS. */
	.eqc-btn-group--compact { flex-direction: row !important; align-items: center !important; flex-wrap: nowrap !important; }
	.eqc-btn-group--compact > * { width: auto !important; flex: 1 1 0 !important; min-inline-size: 0 !important; }
	.eqc-btn-group--compact .eqc-btn {
		width: 100%;
		justify-content: center;
		/* The pair splits the row evenly, so the label has to be allowed to
		   shrink rather than force the button wider than its half. */
		min-inline-size: 0;
		padding-inline: calc(10 * var(--eqc-u));
		white-space: nowrap;
	}
	/* Specificity match for the hero/about 240px cap above
	   (`.eqc-hero-text .eqc-btn-group > .elementor-widget-html`, 3 classes)
	   — a lower-specificity `!important` here loses to it even inside this
	   media query, confirmed via computed style still reading 240px without
	   this. */
	.eqc-hero-text .eqc-btn-group > .elementor-widget-html,
	.eqc-about-text .eqc-btn-group > .elementor-widget-html { max-inline-size: none !important; }
	.eqc-btn-group .eqc-btn { width: 100%; justify-content: center; }
}

/* ---------- Cards ---------- */

.eqc-card {
	background: var(--eqc-surface);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-card);
	box-shadow: var(--eqc-shadow-card);
	padding: clamp(1.25rem, 1rem + 1vw, 2rem);
	/* Flex column so `.eqc-card__foot { margin-top: auto }` (below) can pin
	   a divider/CTA to the same baseline across a row regardless of how
	   much copy sits above it — the general fix for cards whose footer
	   rule/arrow drifted up or down depending on content length. */
	display: flex;
	flex-direction: column;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-base) var(--eqc-ease-standard);
}

.eqc-card:hover {
	transform: translateY(-5px);
	box-shadow: var(--eqc-shadow-card-hover);
}
/* No one-word last line in card copy (client, Round 20: "Meet the teacher
   and confirm it feels / right."). `pretty` only moves a word or two down
   to keep the last line from being a single word, so long copy keeps its
   natural measure. Browsers without it wrap as before. */
.eqc-card p,
.eqc-trust-tile p { text-wrap: pretty; }

/* Shared "pin to card bottom" convention — apply to whatever a card's last
   row is (a divider + CTA, a facts box, tag chips) so it lands on the same
   baseline as its siblings in a grid row no matter how long the copy above
   it runs. */
.eqc-card__foot { margin-top: auto; }

.eqc-grid {
	display: grid;
	gap: var(--eqc-grid-gap);
}

/* When a grid item is an Elementor HTML widget (eqc_html()) rather than a
   Container, `.eqc-card` sits ONE LEVEL INSIDE the actual grid cell, so CSS
   Grid's implicit row-stretch never reaches it — the card just shrink-wraps
   its own content instead of matching its row siblings (the uneven "How It
   Works" / pathway step cards). Stretching the widget wrapper itself into a
   flex container fixes every such row site-wide. */
.eqc-grid > .elementor-widget-html { display: flex; }
.eqc-grid > .elementor-widget-html > .eqc-card { flex: 1 1 auto; width: 100%; }

/* Course/teacher grids: an explicit 3/2/1 column count (not auto-fit),
   matching DESIGN.md §16. auto-fit packs 4-5 narrow cards per row instead of
   the intended 3, breaking the grid's symmetry. */
.eqc-grid--courses,
.eqc-grid--teachers { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 61.25rem) {
	.eqc-grid--courses { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 36rem) {
	.eqc-grid--courses { grid-template-columns: 1fr; }
}
/* Below the 3-up width the teachers grid becomes a snap-scrolling row, the
   same swipe-through behaviour the reviews carousel gives. */
@media (max-width: 75rem) {
	.eqc-grid--teachers {
		grid-template-columns: none;
		grid-auto-flow: column;
		grid-auto-columns: calc((100% - var(--eqc-grid-gap)) / 2);
		gap: var(--eqc-grid-gap);
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		padding-bottom: 0.5rem;
		/* The native scrollbar is hidden; it clashes with the reviews
		   carousel's dot strip (initTeacherRows() in eqc.js builds a
		   matching .eqc-slider-dots row right after this element). */
		scrollbar-width: none;
	}
	.eqc-grid--teachers::-webkit-scrollbar { display: none; }
	.eqc-grid--teachers > * { scroll-snap-align: center; }
}
@media (max-width: 36rem) {
	.eqc-grid--teachers { grid-auto-columns: 100%; }
}
/* Explicit column counts, not auto-fit — every card/panel grid resolves to a
   symmetric layout at every width (DESIGN.md rule: 6->3x2, 4->2x2, 3->3x1;
   1-up + side-scroll on phones) rather than leaving a 3+1 / 2+1 orphan row.
   --pricing is re-set to repeat(4,1fr) further down.

   Scope note: this guarantee only holds for the grids whose child count is
   FIXED by a page builder (courses 6, pricing 4, teachers 6, trust 4). The
   blog grid is fed by however many posts are published, so a partial last row
   is normal there and expected — a 3-up archive is the intended shape, not an
   orphan to design out. If a trust/step row ever grows past 4, revisit that
   count too rather than assuming this comment still covers it. */
.eqc-grid--pricing { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.eqc-grid--blog { grid-template-columns: repeat(3, 1fr); }
/* Two columns only while each gets at least 15rem, and never more than two.
   It used to be a fixed repeat(2) until a 36rem VIEWPORT, but this grid also
   sits in the narrow container (/teachers/ "What Students Can Expect"),
   where between 600 and 1024px each tile was 178-200px: two-word titles
   broke in half and the copy ran to six lines (client, Round 20). Measured,
   the tiles read cleanly from ~250px up. The inner max() is the two-column
   cap: a column is never narrower than half the row, so four tiles cannot
   become 3+1 on a wide screen. Phones need no media query -- two 15rem
   columns never fit there. */
.eqc-grid--2col {
	/* -1px: an exact half rounds to just over it at some widths (546px at 1280
	   dropped to one column); one pixel cannot make room for a third. */
	grid-template-columns: repeat(auto-fit, minmax(min(100%, max(15rem, (100% - var(--eqc-grid-gap)) / 2 - 1px)), 1fr));
}
.eqc-grid--trust { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 61.25rem) {
	.eqc-grid--blog,
	.eqc-grid--trust { grid-template-columns: repeat(2, 1fr); }
}
/* A group of THREE (course-detail "How Classes Run", the kids pathway) is
   three equal columns, not three cards in a four-column grid with an empty
   fourth (client, Round 20), and not a 2+1 with a hole at tablet width. It
   stacks to one column only when a third of the row gets too narrow to read a
   paragraph in. Doubled class: outranks the 4- and 2-column rules above and
   the odd-count rule below whatever their order. */
.eqc-grid--trust.eqc-grid--trust:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 48rem) {
	.eqc-grid--trust.eqc-grid--trust:has(> :nth-child(3):last-child) { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 36rem) {
	.eqc-grid--blog { grid-template-columns: 1fr; }
	/* .eqc-grid--trust is NOT in the list above: the client asked for a group
	   of four tags to stay a symmetrical 2x2 on phones rather than becoming a
	   1x4 column. Blog keeps collapsing -- a post card carries an image and an
	   excerpt. (2col collapses by its own minimum width, above.)

	   ONLY an even-sized group goes two-up. Most of these groups hold four
	   tiles, but /online-quran-classes-for-kids/ and the course-detail pages
	   hold THREE, and three items in two columns leaves a visible hole in the
	   bottom-right -- the opposite of the symmetry being asked for. The
	   quantity query reads "the last child sits at an even position", i.e. the
	   group has an even number of them; an odd group falls back to one column.
	   Without :has() support the selector never matches and every group is one
	   column, which is exactly the old behaviour -- a safe degradation. */
	.eqc-grid--trust:not(:has(> :last-child:nth-child(even))) { grid-template-columns: 1fr; }
	/* Two-up, a tile has to survive a ~150px column, and as an icon-beside-text
	   flex row it did not: a flex item will not shrink below its longest word,
	   so this pushed /online-quran-classes-for-kids/ to 330px at a 320px
	   viewport (caught by the sweep's overflow check, not by eye). Stacking the
	   icon hands the copy the tile's whole width, and min-inline-size:0 lets it
	   take it -- `auto` is a flex item's default minimum and is what blocks the
	   shrink. Scoped to the two-column case; a single-column tile has room for
	   the icon beside its text and keeps it. */
	.eqc-grid--trust:has(> :last-child:nth-child(even)) .eqc-trust-tile {
		flex-direction: column;
		gap: calc(6 * var(--eqc-u));
		padding: 0.9em 0.85em;
		min-inline-size: 0;
	}
	.eqc-grid--trust .eqc-trust-tile > * { min-inline-size: 0; overflow-wrap: break-word; }
}

/* Numbered index badge — shared by course cards, "How It Works" steps
   (10-home.php) and the "Beginner Pathway" steps (12-courses.php). Base
   styling applies wherever the markup is used, and .eqc-card--course
   layers the extra rosette-ring treatment on top. */
.eqc-card-index {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.9em;
	height: 2.9em;
	border-radius: 50%;
	border: 1px solid var(--eqc-border-strong);
	color: var(--eqc-bronze-700);
	font-family: var(--eqc-font-display);
	font-size: 1.1rem;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-card:hover .eqc-card-index { transform: rotate(-8deg) scale(1.05); }
.eqc-card--course { position: relative; overflow: hidden; }
/* Faint rosette ring behind the number, echoing the scalloped badge shape
   of the course card design — see the note above .eqc-corner-motif for why
   this ships as a mask rather than an <img>. */
.eqc-card--course .eqc-card-index { border: 0; color: var(--eqc-gold-700); }
.eqc-card--course .eqc-card-index::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: var(--eqc-gold-500);
	-webkit-mask-image: url('../svg/seal-outline.svg');
	mask-image: url('../svg/seal-outline.svg');
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	z-index: 0;
}
/* Explicit z-index (not just DOM order) on both layers: a positioned
   pseudo-element and a positioned real child are otherwise stacked by tree
   order, which would paint this "behind" decoration on TOP of the number
   it's meant to sit under. */
.eqc-card-index-num { position: relative; z-index: 1; }
/* Faint corner-motif watermark on every course card, matching the small
   gold arabesque fragment visible in the top-right of each reference card.
   z-index:0 + real children boosted to z-index:1 keeps it strictly behind
   card content regardless of DOM order (see note above). */
.eqc-card--course::after {
	content: '';
	position: absolute;
	top: 0;
	right: 0;
	width: 92px;
	height: 92px;
	background-color: var(--eqc-gold-500);
	opacity: 0.07;
	-webkit-mask-image: url('../svg/corner-motif.svg');
	mask-image: url('../svg/corner-motif.svg');
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	pointer-events: none;
	z-index: 0;
}
.eqc-card--course > * { position: relative; z-index: 1; }
.eqc-card--course h3 { margin-block: 0.6em 0.1em; }
.eqc-card--course .eqc-card-level {
	color: var(--eqc-text);
	font-size: var(--eqc-fs-small);
	font-weight: 500;
}
.eqc-card--course p { margin-block: 0.8em; }
/* Small centered rosette rule under the level label, between the level
   and the description. */
.eqc-card-divider { color: var(--eqc-gold-500); margin-block: 0.2em; }
.eqc-card-divider svg { width: 100%; height: auto; display: block; }

/* Whole-card link: a "stretched link" pattern — one real, invisible anchor
   sized to the entire card via inset:0, sitting above the decorative
   content (z-index:2 vs. content's z-index:1) so the full panel is
   clickable/tappable, while the circular chevron below stays a purely
   decorative (non-nested) affordance. The whole panel is the button, not
   a full-width bar under it. */
.eqc-card-link {
	position: absolute;
	inset: 0;
	z-index: 2;
	text-decoration: none;
}

/* The anchor above ships inside an Elementor HTML widget, so between it and
   the card sit two divs: .elementor-widget > .elementor-widget-container.
   Card variants that boost their own children with `> * { position: relative }`
   (.eqc-card--course, .eqc-card--pricing--featured) were therefore making the
   WIDGET the anchor's containing block — and since that widget's only child
   is the absolutely-positioned anchor itself, the widget collapses to zero
   height and the "whole card is a link" resolved to a 413x0 strip. Measured
   before this fix: every course card's link 413x0, elementFromPoint() at the
   card centre returning a <p>. The page looked and built fine; the CTA was
   simply dead.

   The fix is to stretch the wrapper chain rather than fight the `> *` rules:
   .eqc-card-link-widget is the class eqc_course_card()/eqc_pricing_card() pass
   to eqc_html(), which Elementor prints on the widget element. Specificity
   (0,2,0) also beats the `> *` rules (0,1,0) regardless of source order. */
.eqc-card > .eqc-card-link-widget {
	position: absolute;
	inset: 0;
	z-index: 2;
	margin: 0;
	padding: 0;
}
.eqc-card > .eqc-card-link-widget > .elementor-widget-container {
	position: absolute;
	inset: 0;
}

/* Same root cause, different symptom. The pricing badge and medallion are
   anchored to the CARD's top edge, so their Elementor wrappers must stay
   `static` and let the anchoring reach the card. While the featured card's
   `> * { position: relative }` was catching them, its medallion resolved
   against the widget box and rendered 38px below its three siblings', and the
   RECOMMENDED tab sat inside the card instead of astride its edge. Both
   children carry their own z-index, so a static wrapper costs nothing. */
/* Stretched to the card's padding box, exactly like .eqc-card-link-widget: the
   badge and medallion then anchor to the box they are meant to (the card), and
   the wrapper leaves the flex column entirely. `position: static` was tried
   first and re-broke the alignment a different way — a zero-height flex item
   still consumes one `gap`, which put the featured card's banner and list 9px
   below its siblings'. pointer-events:none keeps the whole-card link clickable
   underneath; nothing in here is interactive. */
.eqc-card--pricing > .eqc-pricing-anchor-widget {
	position: absolute;
	inset: 0;
	margin: 0;
	padding: 0;
	pointer-events: none;
	z-index: 3;
}

.eqc-arrow-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.6em;
	height: 2.6em;
	border-radius: 50%;
	border: 1px solid var(--eqc-border-strong);
	color: var(--eqc-green-800);
	transition: background-color var(--eqc-motion-base) var(--eqc-ease-standard),
		transform var(--eqc-motion-base) var(--eqc-ease-standard),
		color var(--eqc-motion-base) var(--eqc-ease-standard);
	text-decoration: none;
}
.eqc-card:hover .eqc-arrow-btn,
.eqc-arrow-btn:hover,
.eqc-arrow-btn:focus-visible {
	background: var(--eqc-green-800);
	color: var(--eqc-white);
	transform: translateX(3px);
}
/* On the pricing card, the colour change is kept but the sideways drift is
   dropped — the whole card lifts on hover instead (below). */
.eqc-card--pricing:hover .eqc-arrow-btn,
.eqc-card--pricing .eqc-arrow-btn:hover,
.eqc-card--pricing .eqc-arrow-btn:focus-visible { transform: none; }

/* Teacher card */
.eqc-card--teacher { text-align: center; position: relative; align-items: center; isolation: isolate; }
/* Keep the stat strip and heading full-width inside the centred column
   rather than shrink-wrapping to their text. */
.eqc-card--teacher > * { width: 100%; }

/* Girih lattice ground + lace corners (client, Round 20).
   One aria-hidden layer emitted by eqc_teacher_card(), rather than the card's
   own pseudo-elements: /teachers/ already spends ::before on the green
   portrait band, and three ornaments do not fit in the one that is left.
   z-index -1 inside the card's own stacking context (`isolation` above) puts
   it over the card's background but under every piece of content, so it can
   never sit on the name or the facts. The lattice is faded OUT across the
   middle of the card, where the text is, and kept at the edges -- texture
   around the reading area, not behind it.
   Doubled class: `.eqc-grid--teachers .eqc-card--teacher > *` sets
   `position: relative; z-index: 1` on every child at the same weight. */
.eqc-card--teacher.eqc-card--teacher > .eqc-teacher-ornament-widget {
	position: absolute;
	inset: 0;
	z-index: -1;
	width: auto;
	margin: 0;
	border-radius: inherit;
	overflow: hidden;
	pointer-events: none;
}
.eqc-teacher-ornament-widget .elementor-widget-container,
.eqc-teacher-ornament {
	display: block;
	position: absolute;
	inset: 0;
}
.eqc-teacher-ornament::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: var(--eqc-gold-500);
	opacity: 0.2;
	-webkit-mask-image: radial-gradient(ellipse 70% 62% at 50% 55%, transparent 38%, #000 100%), url('../svg/girih-lattice-fine.svg');
	mask-image: radial-gradient(ellipse 70% 62% at 50% 55%, transparent 38%, #000 100%), url('../svg/girih-lattice-fine.svg');
	-webkit-mask-size: 100% 100%, 34px 34px;
	mask-size: 100% 100%, 34px 34px;
	-webkit-mask-repeat: no-repeat, repeat;
	mask-repeat: no-repeat, repeat;
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}
/* corner-motif.svg is dense at its top-right and fades toward bottom-left,
   so the top-start corner is its mirror and the bottom-end corner its
   vertical flip -- a diagonal pair, as on the testimonial cards. */
.eqc-teacher-ornament__corner {
	position: absolute;
	inline-size: clamp(64px, 38%, 118px);
	aspect-ratio: 1;
	background-color: var(--eqc-gold-600);
	opacity: 0.34;
	-webkit-mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
	mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
}
.eqc-teacher-ornament__corner--start { inset-block-start: 0; inset-inline-start: 0; scale: -1 1; }
.eqc-teacher-ornament__corner--end { inset-block-end: 0; inset-inline-end: 0; scale: 1 -1; }
/* The teacher avatar is a smooth ellipse with a cream gap and a thin gold ring. */
/* 132u, down from 181u. Measured at 1440 the portrait came out 196x210 while
   the name beside it was 17px and the facts 14px -- a portrait roughly eleven
   times the type size, which is what the client saw as "images too big, name
   and body too small". The photo is the card's decoration; the name is its
   content, and the fix is both halves, not just the picture. The 98% cap
   became 74% so the circle cannot re-inflate to the card's full width on a
   narrow column where 132u is no longer the binding term. */
.eqc-card--teacher .eqc-teacher-photo-widget {
	position: relative;
	width: min(74%, calc(132 * var(--eqc-u)));
	aspect-ratio: 244 / 262;
	margin-inline: auto;
}
.eqc-card--teacher .eqc-teacher-photo-widget img {
	border-radius: 50%;
	border: calc(3 * var(--eqc-u)) solid var(--eqc-surface);
	outline: calc(1.4 * var(--eqc-u)) solid var(--eqc-gold-500);
	object-fit: cover;
}
/* Small "seal" badge overlapping the bottom of the photo, matching the
   reference teacher cards. Pulled up with a negative margin
   (rather than pixel-absolute positioning against the photo) so it stays
   correctly placed across the photo's own clamp(120px,30%,160px) range. */
.eqc-teacher-seal {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Client, 2026-09-17: bigger and gold. At 2.4em with a green fill it read
	   as a dark dot sitting on the portrait rather than as a mark of anything,
	   and the rehal glyph inside it was too small to be recognisable. Gold
	   ground with the deep green glyph also inverts the old pairing, which puts
	   the higher-contrast colour on the small shape -- the glyph is the part
	   that has to stay readable at this size. */
	width: 3.2em;
	height: 3.2em;
	margin: -1.7em auto 0.7em;
	border-radius: 50%;
	/* Gold rehal on a deep green ground (client, 2026-09-17 -- the previous
	   pass had these the other way round). The green disc also keeps the seal
	   reading as the site's mark rather than as a second gold dot beside the
	   portrait's own gold ring, and a gold ring around the green picks that
	   ring up deliberately instead of competing with it. */
	background: var(--eqc-green-900);
	color: var(--eqc-gold-300);
	border: 3px solid var(--eqc-surface);
	box-shadow: 0 0 0 1px var(--eqc-gold-500), 0 3px 9px rgba(20, 35, 27, 0.28);
}
.eqc-teacher-seal .eqc-icon { width: 1.65em; height: 1.65em; }
.eqc-card--teacher .eqc-teacher-photo-widget img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--eqc-motion-slow) var(--eqc-ease-soft);
}
.eqc-card--teacher:hover .eqc-teacher-photo-widget img { transform: none; }
/* h3 here for correct heading hierarchy (H2 section title -> H3 card
   title, no skipped level) while keeping the compact card-title size. */
.eqc-card--teacher h3 { margin-block: 0.9em 0.1em; font-size: var(--eqc-fs-h4); font-weight: 600; font-family: var(--eqc-font-body); }
.eqc-card--teacher .eqc-teacher-role {
	color: var(--eqc-bronze-600);
	font-size: var(--eqc-fs-small);
	font-weight: 600;
	margin-bottom: 0.8em;
}
/* Boxed "stat strip" treatment (inspired by common instructor-directory
   patterns: a distinct tinted panel separating quick facts from the rest
   of the card) — content stays our own verified fields (experience,
   certification, specialty), just given clearer visual hierarchy. */
.eqc-teacher-facts {
	list-style: none;
	margin: 0 0 1em;
	padding: 0.85em 1em;
	display: flex;
	flex-direction: column;
	gap: 0.55em;
	font-size: var(--eqc-fs-small);
	text-align: left;
	background: var(--eqc-cream-50);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
}
.eqc-teacher-facts li { display: flex; gap: 0.6em; align-items: flex-start; }
.eqc-teacher-facts .eqc-icon { color: var(--eqc-bronze-600); }

/* Pricing card, following the reference design:
   a dark medallion overlapping the top edge, a notched frequency ribbon,
   gold star bullets and a price row closing in a decorative circular
   arrow, all card panel. */
.eqc-card--pricing { text-align: center; position: relative; padding-top: 3.4rem; overflow: visible; }
/* The featured card's gold border and shadow extend to all four so they read
   as one matched set — content/badge/sparkle stay
   featured-only, only the border colour/width and shadow are shared. */
.eqc-card--pricing {
	border-color: var(--eqc-gold-500);
	border-width: 2px;
	box-shadow: 0 18px 40px rgba(169, 130, 53, 0.26);
}
/* With the card no longer enlarged, the border and the sparkle field ARE the
   emphasis, so both carry more weight. A 2px gold
   edge plus a soft outer gold ring reads as a deliberate double frame at any
   width, without moving the card's box (`outline` and `box-shadow` both paint
   outside the border box, so the four cards stay dimensionally identical). */
/* A thicker gold edge than its three siblings (client, 2026-09-17), so the
   recommended plan is identifiable before the badge is even noticed. 4px
   against the 2px the other three carry -- measured, not assumed; at 3px the
   difference was a single pixel and read as an accident: enough to read as deliberate at a
   glance, not so much that the card looks outlined. The card's own box is
   unchanged in size -- border-width grows inward against a fixed min-height,
   so the four cards keep their shared top and bottom edges. */
.eqc-card--pricing--featured {
	border-color: var(--eqc-gold-500);
	border-width: 4px;
	outline: 1px solid rgb(var(--eqc-gold-600-rgb) / 0.34);
	outline-offset: 4px;
	box-shadow: 0 18px 40px rgba(169, 130, 53, 0.26);
}
/* The featured plan is NOT enlarged. All four cards share the same top and
   bottom edges; the recommended one is marked by the gold double-border, the
   sparkle field and the RECOMMENDED tab alone. Scaling this card pushes its
   every row out of line with its siblings and lifts the badge clear of the
   card. z-index keeps its border and badge painting over the neighbours'
   edges. */
.eqc-card--pricing--featured { z-index: 2; }
/* Soft all-over sparkle field, featured plan only — the extra bit of
   contrast/shine the user asked for on the "Recommended" card. Real
   content is boosted to z-index:1 (below) so it always paints above this. */
.eqc-card--pricing--featured::before {
	content: '';
	position: absolute;
	inset: 0;
	/* Tint in the paint's own alpha, not element `opacity`, so the glow
	   filter below renders at full strength. */
	background-color: rgb(var(--eqc-gold-500-rgb) / 0.62);
	-webkit-mask-image: url('../svg/sparkle-dust.svg');
	mask-image: url('../svg/sparkle-dust.svg');
	-webkit-mask-size: cover;
	mask-size: cover;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	/* A faint bloom on each mote so the field reads as light rather than as
	   flat gold specks. */
	filter: drop-shadow(0 0 2px rgb(var(--eqc-gold-300-rgb) / 0.55));
	pointer-events: none;
	z-index: 0;
}
.eqc-card--pricing--featured > * { position: relative; z-index: 1; }
/* Re-assert the stretched card-link's higher z-index (its own rule lives
   far earlier in this file, in the course-card section, so on the tied
   specificity above it would otherwise lose the cascade to the featured
   card's own later `> *` rule and stop covering the icon/badge areas). */
.eqc-card--pricing .eqc-card-link { z-index: 2; }
/* Dark scalloped calendar medallion inside the cusped cream-and-gold shell
   reused from the approved alphabet cartouche geometry. */
.eqc-pricing-icon {
	position: absolute;
	top: -1.9rem;
	left: 50%;
	transform: translateX(-50%);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.8em;
	height: 3.8em;
	background: none;
	filter: drop-shadow(0 4px 5px rgb(20 35 27 / 18%));
	z-index: 2;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-pricing-icon::before,
.eqc-pricing-icon::after {
	content: '';
	position: absolute;
	pointer-events: none;
}
.eqc-pricing-icon::before {
	inset: -0.42em;
	background: var(--eqc-surface);
	mask: url('../svg/pricing-medallion-shell-mask.svg') center / 100% 100% no-repeat;
}
.eqc-pricing-icon::after {
	inset: -0.42em;
	background: var(--eqc-green-800);
	mask: url('../svg/pricing-medallion-mask.svg') center / 100% 100% no-repeat;
}
.eqc-pricing-icon-ring {
	position: absolute;
	inset: -0.42em;
	color: var(--eqc-gold-500);
	pointer-events: none;
	z-index: 1;
}
.eqc-pricing-icon-ring svg { width: 100%; height: 100%; }
.eqc-pricing-icon .eqc-icon { position: relative; z-index: 2; width: 1.6em; height: 1.6em; color: var(--eqc-white); }
/* No rotation on hover: rotating about the translated origin throws the
   medallion visibly to the right. A gentle scale only, kept centred. */
.eqc-card--pricing:hover .eqc-pricing-icon { transform: translateX(-50%) scale(1.05); }
/* "Recommended" pill — a normal flow child between the medallion and the
   frequency banner (see .eqc-pricing-badge below for the full rationale;
   this used to be an absolutely-positioned diagonal ribbon here, fully
   superseded, not just overridden, by that later block). */
.eqc-pricing-freq {
	display: block;
	background: var(--eqc-green-800);
	color: var(--eqc-white);
	border-radius: var(--eqc-radius-pill);
	padding: 0.65em 1.4em;
	font-weight: 700;
	letter-spacing: 0.02em;
	box-shadow: 0 6px 16px rgba(20, 35, 27, 0.2);
	margin-block: 0.8em 0.55em;
}
/* A later, more specific block for .eqc-pricing-list and
   .eqc-pricing-price-divider (client-review refinements, each layered in by
   source-order cascade rather than editing these) lives further down this
   file, search for "the BLOCK they form is centred in the card". */
.eqc-pricing-list {
	list-style: none;
	margin: 0 0 1.2em;
	padding: 0;
	text-align: left;
	display: flex;
	flex-direction: column;
	gap: 0.55em;
}
.eqc-pricing-list li { display: flex; gap: 0.6em; align-items: flex-start; font-size: var(--eqc-fs-small); }
.eqc-pricing-bullet { flex: none; width: 0.75em; height: 0.75em; margin-top: 0.35em; color: var(--eqc-gold-500); }
/* No `margin-block-start: auto` here. Pinning the divider to the bottom of a
   343u min-height card opens an empty band: the list ends, then ~90px of
   nothing, then the price row. The card centres its content instead (see .eqc-card--pricing's
   justify-content below), so the block fills the card evenly. */
.eqc-pricing-price-divider { width: 100%; color: var(--eqc-gold-500); line-height: 0; }
.eqc-pricing-price-divider .eqc-divider-svg { display: block; width: 100%; height: auto; }
.eqc-pricing-price {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.75em;
}
.eqc-pricing-price-figure {
	font-family: var(--eqc-font-display);
	font-size: 2.25rem;
	color: var(--eqc-heading);
	display: flex;
	align-items: baseline;
	gap: 0.35em;
}
.eqc-pricing-price small { font-family: var(--eqc-font-body); font-size: var(--eqc-fs-small); color: var(--eqc-muted); font-weight: 600; }
/* The circular arrow closing the price row is purely decorative — the
   card's whole surface is the real CTA (.eqc-card-link, see the
   course-card comment above), so it never nests inside another link.
   Its hover/active reaction already comes from the generic
   `.eqc-card:hover .eqc-arrow-btn` rule further up this file. */


/* Testimonial card — centered avatar overlapping the top edge with the
   quote badge on its lower-right. Both are positioned against the card so they
   track each other at every width. */
.eqc-card--testimonial { position: relative; text-align: center; padding-top: 3.5rem; }
.eqc-testimonial-avatar-wrap {
	position: absolute;
	top: -2.4rem;
	left: 50%;
	transform: translateX(-50%);
	width: 84px;
	height: 84px;
}
.eqc-testimonial-photo {
	width: 100%;
	height: 100%;
	border-radius: 50%;
	overflow: hidden;
	border: 3px solid var(--eqc-surface);
	box-shadow: var(--eqc-shadow-card);
}
.eqc-testimonial-photo img { width: 100%; height: 100%; object-fit: cover; }
.eqc-testimonial-quote-mark {
	position: absolute;
	bottom: -0.2em;
	right: -0.2em;
	width: 2em;
	height: 2em;
	border-radius: 50%;
	background: var(--eqc-green-800);
	color: var(--eqc-white);
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--eqc-font-display);
	border: 2px solid var(--eqc-surface);
}
/* h3 here for correct heading hierarchy (see .eqc-card--teacher h3 above). */
.eqc-card--testimonial h3 { margin-block: 0 0.1em; font-size: var(--eqc-fs-h4); font-weight: 600; font-family: var(--eqc-font-body); }
.eqc-testimonial-location {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 0.4em;
	color: var(--eqc-muted);
	font-size: var(--eqc-fs-small);
	margin-bottom: 0.4em;
}
.eqc-testimonial-divider { color: var(--eqc-gold-500); width: fit-content; margin: 0.5em auto 0.9em; }
/* Sized to stay visible on a ~340px card; at 90px this rule reads as a
   barely-there smudge. */
.eqc-testimonial-divider svg { display: block; width: calc(100 * var(--eqc-u)); min-width: 120px; height: auto; }
/* Bordered stat strip closing the card, matching the reference's boxed
   "Expert Tutors · Monthly Tracking · Personalised Focus" footer instead of
   a bare border-top divider — pinned to the card bottom via .eqc-card__foot
   (passed as this widget's _css_classes) so it aligns across a row
   regardless of how long each quote runs. */
.eqc-testimonial-tags {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.4em 1.3em;
	margin-top: 1.1em;
	padding: 0.85em 1em;
	background: var(--eqc-cream-50);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
	font-size: var(--eqc-fs-small);
	font-weight: 600;
	color: var(--eqc-heading);
}
.eqc-testimonial-tags span { display: inline-flex; align-items: center; gap: 0.4em; }
.eqc-testimonial-tags .eqc-icon { color: var(--eqc-bronze-600); }

/* Generic one-card-at-a-time carousel — shared by the testimonials section
   and the homepage teacher row (see initCarousel() in eqc.js), matching the
   arrow+dot reference pattern. N cards visible
   at once via the track's --_visible custom property (responsive above).
   Auto-advances every ~6s, pauses on hover/focus, and never starts under
   prefers-reduced-motion (motion.css). Markup: .eqc-carousel >
   .eqc-carousel-viewport > .eqc-carousel-track > (cards), plus sibling
   .eqc-carousel-arrow buttons and an .eqc-slider-dots row. */
.eqc-carousel { position: relative; padding-inline: clamp(0px, 2vw, 2.75em); }
/* pan-y: the track is transform-positioned, not natively scrollable, so a
   finger swipe has nothing to grab without JS (see the pointer handlers in
   initCarousel(), eqc.js). pan-y leaves vertical page scroll to the browser
   untouched and hands horizontal drags to that JS, with no preventDefault()
   fight needed. */
.eqc-carousel-viewport { overflow: hidden; touch-action: pan-y; }
.eqc-carousel-track {
	/* !important on display/flex-wrap: Elementor's own container default is
	   flex-wrap:wrap, which this single-row sliding track can never allow —
	   at desktop (3 visible) 3 items' percentage widths happened to just
	   barely fit one row by floating-point luck, masking the bug, but at
	   1-visible mobile widths every card is 100% wide and wraps onto its
	   own row, stacking all 9 cards vertically instead of sliding. */
	display: flex !important;
	flex-wrap: nowrap !important;
	gap: var(--eqc-grid-gap);
	transition: transform var(--eqc-motion-slow) var(--eqc-ease-standard);
	will-change: transform;
	--_visible: 3;
}
/* While a drag is live the transform is set per pointermove frame, not by
   the transition above — with the transition still active, each frame
   would visibly lag behind the finger instead of tracking it 1:1. */
/* --dragging follows the finger; --instant is the seamless loop's silent
   reposition after it has slid onto the clone set (see setupCarousel in
   eqc.js). Both need the transition off for exactly one frame. */
.eqc-carousel-track.eqc-carousel--dragging,
.eqc-carousel-track.eqc-carousel--instant { transition: none; }
@media (max-width: 61.25rem) { .eqc-carousel-track { --_visible: 2; } }
@media (max-width: 36rem) { .eqc-carousel-track { --_visible: 1; } }
/* !important: each card here is an Elementor Container in its own right
   (eqc_container() in eqc_carousel()/eqc_teacher_card()/etc.), and
   Elementor's own generated per-element CSS gives every "e-con" child a
   flex-basis of its own (observed: flex-basis: auto with implicit grow),
   at a specificity this plain child-combinator selector cannot beat by
   source order alone — without !important all 9 testimonial cards were
   observed shrinking to fit one single row (~114px each) instead of
   showing 3 at a time. Same class of override as .eqc-form-wrap's Fluent
   Forms rules above (DESIGN.md §19: child-theme CSS is the approved place
   to override chrome a plugin/widget doesn't expose a control for). */
.eqc-carousel-track > * {
	flex: 0 0 calc((100% - (var(--_visible) - 1) * var(--eqc-grid-gap)) / var(--_visible)) !important;
	min-width: 0;
}
.eqc-carousel-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 2.75em;
	height: 2.75em;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	border: 1px solid var(--eqc-border-strong);
	background: var(--eqc-surface);
	color: var(--eqc-green-800);
	cursor: pointer;
	z-index: 2;
	transition: background-color var(--eqc-motion-base) var(--eqc-ease-standard),
		color var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-carousel-arrow:hover,
.eqc-carousel-arrow:focus-visible { background: var(--eqc-green-800); color: var(--eqc-white); }
.eqc-carousel-arrow:disabled { opacity: 0.35; cursor: default; background: var(--eqc-surface); color: var(--eqc-green-800); }
.eqc-carousel-arrow--prev { left: 0; }
.eqc-carousel-arrow--next { right: 0; }
.eqc-carousel-arrow--prev .eqc-icon { transform: rotate(180deg); }
@media (max-width: 30rem) {
	.eqc-carousel-arrow { display: none; }
}
/* width:100% matters where this is inserted as a sibling inside a flex row
   (the home teachers row, .eqc-teachers-split — initTeacherRows() in eqc.js
   appends it after .eqc-teachers-cards): without it, a flex item's default
   basis is its own shrink-to-fit content width, so `justify-content:center`
   has nothing to center within and the dots read as pinned to one side.
   No-op everywhere else this is used (a normal
   block already fills its container). */
.eqc-slider-dots { display: flex; justify-content: center; gap: 0.6rem; width: 100%; margin-top: clamp(1.5rem, 1.2rem + 1vw, 2.25rem); }
/* Button itself is a 24px tap target (Lighthouse/axe target-size minimum;
   DESIGN.md's 44px guidance would make the visible dot look oversized) —
   the small 10px dot users actually see is a ::before centered inside it,
   so appearance is unchanged while the clickable area grows. */
.eqc-slider-dot {
	width: 24px;
	height: 24px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: none;
	padding: 0;
	background: transparent;
	cursor: pointer;
}
.eqc-slider-dot::before {
	content: '';
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--eqc-border-strong);
	transition: background-color var(--eqc-motion-base) var(--eqc-ease-standard), transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-slider-dot.is-active::before { background: var(--eqc-bronze-600); transform: scale(1.35); }
.eqc-slider-dot:focus-visible { outline: 3px solid var(--eqc-gold-500); outline-offset: 3px; }

/* Blog card */
/* .eqc-card--blog is a grid item (`.eqc-grid--blog { display: grid }`),
   which stretches it to match the tallest card in its row by default. The
   card itself is fine stretched, but `.eqc-blog-media` is an `<a>` — an
   inline element by default — and `aspect-ratio` does not reliably apply
   to inline boxes, so without `display: block` here the image's
   `height: 100%` instead resolves against the stretched card height,
   swallowing the whole card and pushing .eqc-blog-body out of view
   under `overflow: hidden`. */
.eqc-card--blog { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.eqc-blog-media { position: relative; display: block; flex: none; aspect-ratio: 16/10; overflow: hidden; }
.eqc-blog-media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--eqc-motion-slow) var(--eqc-ease-soft); }
.eqc-card--blog:hover .eqc-blog-media img { transform: scale(1.05); }
/* A flex column that GROWS. `.eqc-card--blog .eqc-read-more` has always asked
   for `margin-block-start: auto; align-self: flex-end`, but this element was a
   plain block box, where both properties are inert -- so the pin never once
   worked and "Read More" drifted with the title and excerpt above it (measured
   121px apart across one row on /blog/). Growing to fill the card is what gives
   the auto margin space to consume. */
.eqc-blog-body {
	padding: clamp(1.1rem, 1rem + 0.5vw, 1.6rem);
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}
.eqc-blog-meta {
	display: flex;
	gap: 0.9em;
	align-items: center;
	font-size: var(--eqc-fs-small);
	color: var(--eqc-bronze-600);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	margin-bottom: 0.6em;
}
.eqc-blog-body h3 { font-size: var(--eqc-fs-h4); font-family: var(--eqc-font-body); font-weight: 700; margin: 0 0 0.5em; }
.eqc-blog-excerpt { color: var(--eqc-muted); margin-bottom: 1em; }
.eqc-read-more {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	color: var(--eqc-bronze-700);
	font-weight: 700;
	font-size: var(--eqc-fs-small);
	text-decoration: none;
}
.eqc-read-more:hover { text-decoration: underline; }

/* Trust / benefit tiles */
.eqc-trust-tile {
	display: flex;
	align-items: flex-start;
	gap: 0.9em;
	background: var(--eqc-surface);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
	padding: 1.1em 1.2em;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-base) var(--eqc-ease-standard),
		border-color var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-trust-tile:hover {
	transform: translateY(-3px);
	border-color: var(--eqc-gold-300);
}
.eqc-trust-tile .eqc-icon {
	flex: none;
	width: 2.1em;
	height: 2.1em;
	color: var(--eqc-green-800);
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-trust-tile:hover .eqc-icon { transform: scale(1.12) rotate(-6deg); }
.eqc-trust-tile-title { margin: 0 0 calc(3 * var(--eqc-u)); font-size: var(--eqc-fs-body); font-weight: 700; color: var(--eqc-heading); }
.eqc-trust-tile p { margin: 0; font-size: var(--eqc-fs-small); color: var(--eqc-muted); line-height: 1.42; }

/* The reference's trust strip is a white rounded PANEL sitting on the hero's
   cream ground (x109-1212, y750-927 native = 1104x178), not tiles rendered
   straight onto a section background. Its own class so the about section's
   stat row, which reuses .eqc-grid--trust, is not restyled with it. */
.eqc-trust-panel {
	background: var(--eqc-white);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-panel);
	box-shadow: var(--eqc-shadow-card);
	/* The panel hugs its content: the tiles set the height, not a reserved
	   min-height, which left dead space above and below them. */
	width: calc(1104 * var(--eqc-u));
	max-width: 100%;
	margin-inline: auto;
	padding: calc(15 * var(--eqc-u)) calc(30 * var(--eqc-u));
	align-items: center;
}
.eqc-trust-panel .eqc-trust-tile { padding-inline: calc(14 * var(--eqc-u)); }
.eqc-trust-panel .eqc-trust-tile .eqc-icon { width: var(--eqc-icon-lg); height: var(--eqc-icon-lg); }
/* Sits directly under the hero on the same ground: 20 native px above the
   panel, 3 below it. */
.eqc-section--truststrip { padding-block: calc(2 * var(--eqc-u)) calc(3 * var(--eqc-u)); background: var(--eqc-cream-100); }
.eqc-section--truststrip > .e-con,
.eqc-section--truststrip .eqc-container { padding-block: 0; padding-inline: 0; }
/* Full-height hairlines between the four columns, as the reference shows
   (finding 13). Applied to the tile rather than the grid so it survives the
   auto-fit reflow: the rule is suppressed on any tile that starts a row,
   which is what `:first-child` alone could not do once the row wraps. */
/* Tiles only. Step CARDS reuse .eqc-grid--trust for its column logic, and
   there the hairline landed on each card's Elementor wrapper: a stray 1px
   line beside every card after the first, exposed below the card whenever
   it lifted on hover (client, Round 20). A card draws its own edge. */
.eqc-grid--trust > * + :not(:has(.eqc-card)) { border-inline-start: 1px solid var(--eqc-border); }
@media (max-width: 61.25rem) {
	.eqc-grid--trust > * + :not(:has(.eqc-card)) { border-inline-start: 0; }
}

/* Shared green back-plate: a second copy of the card's own outline, moved up
   and left, sitting behind it.

   It is a box-shadow with ZERO blur and ZERO spread, and both matter. A
   box-shadow takes the element's border-radius, so with no spread it is the
   card's exact shape -- same size, same corner curve on all four corners --
   whatever radius the card has (card, tag card, tile or panel). Any spread
   breaks that: shrinking a shadow shrinks its corner radii with it, so the
   plate's curve stops matching the card's and its ends fall short of the
   card (client, Round 20, on a negative-spread version). Blur would soften
   the edge the design wants hard.

   Controls (tokens.css): --eqc-plate-offset (4px, 2px on phones) and
   --eqc-plate-color. --eqc-plate is assembled HERE, on the element, rather
   than in :root: a custom property built from other custom properties
   resolves where it is declared, so building it at :root would freeze the
   offset for the whole site and a per-component override would do nothing.
   Hover rules reuse var(--eqc-plate) and only swap the soft shadow.

   The home trust panel carries the plate itself, so its inner tiles cancel
   theirs (.eqc-trust-panel .eqc-trust-tile).

   An ancestor with overflow:hidden clips the plate on any child touching its
   edge -- confirmed once on .eqc-benefits at <=75rem, whose own overflow:hidden
   (kept for its girih end ornaments) was still active after those ornaments
   were display:none'd, silently truncating the plate on edge tiles. */
.eqc-benefit,
.eqc-plate--green,
.eqc-card--course,
.eqc-trust-tile {
	--eqc-plate: calc(-1 * var(--eqc-plate-offset)) calc(-1 * var(--eqc-plate-offset)) 0 0 var(--eqc-plate-color);
	box-shadow: var(--eqc-plate), var(--eqc-shadow-card);
}
/* Hover: the plated components that lift on hover swap only the soft shadow
   and keep the plate. Every one of them has a plain :hover rule elsewhere
   that sets box-shadow outright and would drop the plate (the course card
   did: `.eqc-card:hover` outranked it, so its plate vanished on hover). This
   is the ONE place that restores it -- add a component here, not a copy of
   the shadow beside its own hover rule. Each selector is two classes plus
   :hover, one step above those plain rules wherever they sit in the file;
   the desktop cancels (.eqc-trust-panel .eqc-trust-tile:hover and
   .eqc-benefits .eqc-benefit:hover) are equal weight and later, so they
   still win. */
.eqc-benefit.eqc-benefit:hover,
.eqc-card.eqc-plate--green:hover,
.eqc-card.eqc-card--course:hover,
.eqc-course-meta-tile.eqc-plate--green:hover,
.eqc-trust-tile.eqc-trust-tile:hover {
	box-shadow: var(--eqc-plate), var(--eqc-shadow-card-hover);
}

/* ---------------------------------------------------------------------------
   Tag strips become SEPARATE cards on phones and small tablets.
   Client, 2026-09-17: at desktop these are one horizontal panel with hairline
   dividers, which is right for a single row. Folded to 2x2 that reading breaks
   down -- the dividers become a cross through the middle of one box and each
   tag stops looking like a thing of its own. Below 75rem the panel drops its
   own chrome and every tag takes it instead, so four tags read as four cards
   in a symmetrical 2x2. The switch sits at 75rem, the same width at which
   both strips fold from four across to 2x2 (client, 2026-09-19: at tablet width
   the folded panel still drew a divider at the start of its second row).

   Equal card heights come from the tag-card group contract (search "Tag-card
   group contract"), not from this block.

   EVERY selector here is deliberately over-qualified, and it is not style.
   Both families -- `.eqc-benefits`/`.eqc-benefit` AND
   `.eqc-trust-panel`/`.eqc-trust-tile` -- have rules declared LATER in this
   file at the same weight this block would otherwise carry, and those rules
   set exactly what this block is trying to change: `align-items`, `gap`,
   `padding-inline`, and in the trust panel's case an explicit
   `background: none; border: 0` on the tile plus the hairline on
   `> * + *`. Written plainly, this block loses all of it to the line number.
   Doubling the container class takes each selector one step above its
   competitor so the cascade decides it instead of the order. Both were
   measured losing before this was written -- the trust tiles rendered with no
   card chrome and kept their divider, the benefits came out unequal. */
@media (max-width: 75rem) {
	/* The home panel folds here, later than the generic tag grid (61.25rem):
	   four tiles across a ~1000px panel squeezed each caption onto 3-4 lines. */
	.eqc-trust-panel.eqc-trust-panel.eqc-grid--trust { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.eqc-trust-panel.eqc-trust-panel,
	.eqc-benefits.eqc-benefits {
		background: none;
		border: 0;
		box-shadow: none;
		padding: 0;
		overflow: visible;
		gap: calc(12 * var(--eqc-u));
		align-items: stretch;
		min-height: 0;
	}
	/* The girih ornaments are anchored to the panel's ends and only make sense
	   against the panel ground that has just been removed. */
	.eqc-benefits::before,
	.eqc-benefits::after { display: none; }

	/* Dividers off -- several rules draw them between these tiles. */
	.eqc-grid--trust.eqc-grid--trust > * + *,
	.eqc-trust-panel.eqc-trust-panel > * + *,
	.eqc-benefits.eqc-benefits .eqc-benefit + .eqc-benefit,
	.eqc-benefits.eqc-benefits .eqc-benefit:nth-child(odd),
	.eqc-benefits.eqc-benefits .eqc-benefit:nth-child(even) { border-inline-start: 0; }

	/* Wrappers stretch so each card fills its cell instead of hugging its text. */
	.eqc-trust-panel.eqc-trust-panel > *,
	.eqc-benefits.eqc-benefits > * { display: flex; }
	.eqc-trust-panel.eqc-trust-panel > * > .eqc-trust-tile { flex: 1 1 auto; width: 100%; }

	/* Each tag is now a card in its own right. */
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile,
	.eqc-benefits.eqc-benefits .eqc-benefit {
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		text-align: center;
		gap: calc(8 * var(--eqc-u));
		padding: calc(14 * var(--eqc-u)) calc(10 * var(--eqc-u));
		background: var(--eqc-surface);
		border: 1px solid var(--eqc-border);
		border-radius: var(--eqc-radius-card);
		box-shadow: var(--eqc-shadow-card);
		min-inline-size: 0;
	}
	/* A flex item will not shrink below its longest word without this, which is
	   what pushed a 320px page to 330px the first time these went two-up. */
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile > *,
	.eqc-benefits.eqc-benefits .eqc-benefit > * { min-inline-size: 0; overflow-wrap: break-word; }
	/* The copy carries hard breaks tuned for the wide single-row layout ("|" in
	   eqc_trust_tile()/eqc_benefit_tile()); in a ~150px card they fall in the
	   wrong places, so wrapping goes back to the browser. */
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile br,
	.eqc-benefits.eqc-benefits .eqc-benefit__label br { display: none; }
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile-title,
	.eqc-benefits.eqc-benefits .eqc-benefit__label { line-height: 1.3; }
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile p { line-height: 1.4; }

	/* Card dress (client, 2026-09-19: the plain 2x2 cards read dull). The same
	   ornament family the course and teacher cards use: the site's green
	   back-plate, and a faint gold corner-motif in two opposite corners. The
	   motifs are the cards' only pseudo-elements; content is lifted above them. */
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile,
	.eqc-benefits.eqc-benefits .eqc-benefit {
		position: relative;
		overflow: hidden;
		box-shadow: var(--eqc-plate), var(--eqc-shadow-card);
		transition: transform var(--eqc-motion-base) var(--eqc-ease-standard), box-shadow var(--eqc-motion-base) var(--eqc-ease-standard);
	}
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile:hover,
	.eqc-benefits.eqc-benefits .eqc-benefit:hover {
		transform: translateY(-3px);
		box-shadow: var(--eqc-plate), var(--eqc-shadow-card-hover);
	}
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile::before,
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile::after,
	.eqc-benefits.eqc-benefits .eqc-benefit::before,
	.eqc-benefits.eqc-benefits .eqc-benefit::after {
		content: '';
		position: absolute;
		inline-size: clamp(44px, 22%, 72px);
		aspect-ratio: 1;
		background-color: rgb(var(--eqc-gold-600-rgb) / 0.3);
		-webkit-mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
		mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
		pointer-events: none;
		z-index: 0;
	}
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile::before,
	.eqc-benefits.eqc-benefits .eqc-benefit::before { inset-block-start: 0; inset-inline-end: 0; }
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile::after,
	.eqc-benefits.eqc-benefits .eqc-benefit::after { inset-block-end: 0; inset-inline-start: 0; transform: rotate(180deg); }
	.eqc-trust-panel.eqc-trust-panel .eqc-trust-tile > *,
	.eqc-benefits.eqc-benefits .eqc-benefit > * { position: relative; z-index: 1; }
}

/* ---------- Tag-card group contract -- the ONE place ----------
   Client, 2026-09-23: tag cards that sit together (a pair, a 2x2, a row of
   three or four) must be the same size on every screen. Every container that
   lays out a group of tag cards is listed here, and no other rule in this
   theme sets its row sizing.

   `grid-auto-rows: 1fr` makes every ROW as tall as the group's tallest card.
   Stretching within a row is not enough on its own: a label that wraps in
   row 1 and not in row 2 gave two card heights (measured 104/85/85/104 on
   the benefits strip, 204/161 on the course meta tiles). Grid items stretch
   by default, so each card then fills its equal cell.

   This used to be copied into each family separately -- the tag-strip fold,
   the teachers features band and the course meta grid each carried their own
   `grid-auto-rows: 1fr`, and the home hero's chip grid, which had none, is
   the group that drifted. A container that is not a grid at some width (a
   one-row panel, a stacked list) ignores the property, so the rule can apply
   everywhere unconditionally.
   To add a group: add its container here and to GROUPS in
   tests/visual/card-symmetry.mjs, which asserts equal height across the
   group, equal width across each row and one type style per group. */
.eqc-chip-row--cards,
.eqc-benefits,
.eqc-trust-panel,
.eqc-teachers-features,
.eqc-course-meta-grid { grid-auto-rows: 1fr; }

/* Chips (hero benefit chips) */
.eqc-chip-row { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.eqc-chip {
	display: flex;
	align-items: center;
	gap: 0.6em;
	background: var(--eqc-surface);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
	padding: 0.65em 1em;
	font-size: var(--eqc-fs-small);
	font-weight: 600;
	color: var(--eqc-heading);
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard),
		border-color var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-chip:hover { transform: translateY(-2px); border-color: var(--eqc-gold-300); }
.eqc-chip .eqc-icon { width: 1.35em; height: 1.35em; color: var(--eqc-bronze-600); }

/* --cards: four WHITE cards on one row, icon left of a two-line label,
   rather than one-line pills that wrap to a second row. Auto-fit rather
   than a fixed repeat(4) so the row reflows to 2x2 and then stacks below
   desktop, where the reference design is silent. */
/* Explicit column counts rather than repeat(auto-fit, minmax(min(150px,1fr)))
   — auto-fit resolved inconsistently here: the grid settled at 2 columns
   while its Elementor widget wrapper kept the height of the 4-row single
   column layout (290px for 158px of cards), leaving a large dead gap above
   the buttons on mobile. Fixed counts are deterministic and also let the
   desktop row match the reference's four-across exactly. */
.eqc-chip-row--cards {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--eqc-grid-gap);
	align-items: stretch;
	width: 100%;
}
@media (max-width: 1180px) {
	.eqc-chip-row--cards { grid-template-columns: repeat(2, 1fr); }
}
/* Three-up variant for a narrower column (the About page approach section).
   Explicit counts per DESIGN.md's card-symmetry rule: 3 -> 1, never a 2+1
   orphan row. The doubled class outranks the 2-column rule above. */
.eqc-chip-row--cards.eqc-chip-row--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 61.25rem) {
	.eqc-chip-row--cards.eqc-chip-row--3 { grid-template-columns: 1fr; }
}
/* Card measured 126x58 native, four across on a 22 gap. */
.eqc-chip--card {
	background: var(--eqc-white);
	border-color: var(--eqc-border);
	border-radius: var(--eqc-radius-card);
	min-height: var(--eqc-card-h);
	padding: 0 calc(11 * var(--eqc-u));
	gap: calc(9 * var(--eqc-u));
	align-items: center;
	font-size: var(--eqc-fs-xsmall);
}
/* Icons here read as dark, near-filled marks in the reference. Only the
   COLOUR is matched — DESIGN.md §11 forbids mixing icon families, so the
   shared Lucide outline sprite stays. */
.eqc-chip--card .eqc-icon {
	width: var(--eqc-icon-md);
	height: var(--eqc-icon-md);
	color: var(--eqc-heading);
	flex: none;
}
.eqc-chip-label { display: flex; flex-direction: column; line-height: 1.35; }
/* Title over caption, one format on every card (client, 2026-09-23): a bold
   title the eye lands on first and a regular-weight caption under it. The
   title was 600 against a 500 caption, too close to read as two roles. */
.eqc-chip--card .eqc-chip-label { font-weight: 700; color: var(--eqc-heading); }
.eqc-chip--card .eqc-chip-label > span { font-weight: 400; color: var(--eqc-text); }
/* Two chips per row down to the narrowest widths; one per row leaves a lot
   of dead height each. The card hugs its two text lines. Placed after the
   base rule so it wins the cascade.
   Spacing is px-bounded, not calc(N * --eqc-u): that unit is frozen at
   0.70px below a 915px viewport (tokens.css:112), which had every phone at
   the same cramped 6px padding and 5px icon gap regardless of width. */
@media (max-width: 640px) {
	.eqc-chip-row--cards {
		grid-template-columns: repeat(2, 1fr);
		gap: clamp(10px, 3vw, 14px);
	}
	.eqc-chip--card {
		min-height: 0;
		padding: clamp(9px, 2.6vw, 12px) clamp(10px, 3vw, 14px);
		gap: clamp(7px, 2vw, 10px);
	}
}

/* ---------- Hero eyebrow, rule and trust row ---------- */

/* The reference's hero eyebrow is sentence case in a white pill with the
   icon in its own circular cream chip — not the shared uppercase,
   letterspaced eyebrow used for section labels (finding 8). */
/* Pill measured 251x44 native at x105 y195; the circular chip is 34 across. */
.eqc-eyebrow--hero {
	text-transform: none;
	letter-spacing: 0;
	font-size: var(--eqc-fs-body);
	font-weight: 600;
	background: var(--eqc-white);
	border-color: var(--eqc-border);
	gap: calc(9 * var(--eqc-u));
	height: var(--eqc-eyebrow-h);
	padding: 0 calc(12 * var(--eqc-u)) 0 calc(5 * var(--eqc-u));
}
/* Keeps the plain pill. The cartouche is for SECTION TAGS; this is the hero
   trust badge -- sentence case, with its own circular icon chip and a tight
   asymmetric padding that puts that chip hard against the left edge. The
   frame tapers to a point exactly there, so it cut across the chip and pushed
   the label into the right-hand taper.
   Opting out means clearing the border-image AND restoring the border the base
   rule turned into cap-width: with a border-image gone but a 36/54 border
   still declared, the pill would keep a large invisible inset. */
.eqc-eyebrow--hero {
	border-image-source: none;
	border-width: 1px;
	border-radius: var(--eqc-radius-pill);
}
.eqc-eyebrow-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: calc(34 * var(--eqc-u));
	height: calc(34 * var(--eqc-u));
	border-radius: 50%;
	background: var(--eqc-cream-100);
	flex: none;
}
.eqc-eyebrow-chip .eqc-icon { width: var(--eqc-icon-sm); height: var(--eqc-icon-sm); color: var(--eqc-heading); }

/* Gold rule with a diamond terminal at each end, under the H1. Width from
   the reference: 141px on a 1307px canvas -> 207px at 1920 (finding 5). */
.eqc-hero-rule { color: var(--eqc-gold-500); line-height: 0; }
.eqc-hero-rule .eqc-divider-svg { width: calc(141 * var(--eqc-u)); }

/* Five overlapping avatars, then five gold stars above a single trust line. */
/* Avatars measured 40 across on a 36.75 pitch - an 8% overlap, not the 28%
   this previously used. Block runs x104-290, trust text starts x308. */
.eqc-hero-trust {
	display: flex;
	align-items: center;
	gap: calc(18 * var(--eqc-u));
	flex-wrap: wrap;
}
.eqc-hero-trust .eqc-avatar-stack img {
	--_avatar: var(--eqc-avatar);
	border-width: calc(2 * var(--eqc-u));
	margin-inline-start: var(--eqc-avatar-overlap);
}
.eqc-hero-trust-text { display: flex; flex-direction: column; gap: calc(2 * var(--eqc-u)); }
.eqc-hero-trust-text > span:last-child {
	font-size: var(--eqc-fs-body);
	font-weight: 600;
	color: var(--eqc-text);
}
.eqc-star-row { display: inline-flex; gap: max(2px, calc(2 * var(--eqc-u))); color: var(--eqc-gold-500); }
/* The sprite's star is an outline glyph whose own path carries fill="none";
   a presentation attribute on the inner path beats a fill inherited from the
   <svg>, so the fill has to be set on the path itself to get the reference's
   solid gold stars. Stroke is dropped so the filled shape keeps its weight.

   Bounded in px rather than sized as a bare calc() on --eqc-u (client,
   2026-09-23: the stars read as specks on a phone). --eqc-u is
   clamp(0.70px, 0.07651vw, 1.616px), so its vw term meets the floor at a
   915px viewport and the unit is FROZEN at 0.70px below that -- every phone
   and small tablet rendered these at 15 * 0.70 = 10.5px, with no way to grow
   back. The 15px floor is the size the reference actually measures (15 units
   on the 1307px design canvas, where --eqc-u resolves to 1px), so this
   restores the intended size on phones. A floor only, no ceiling: from 1307px
   up, 15 * --eqc-u is already >= 15px, so desktop and wide screens keep the
   exact size they had before (a ceiling would have shrunk them). */
.eqc-star-row .eqc-icon {
	width: max(15px, calc(15 * var(--eqc-u)));
	height: max(15px, calc(15 * var(--eqc-u)));
}
.eqc-star-row .eqc-icon path,
.eqc-star-row .eqc-icon polygon { fill: currentColor; stroke: none; }

/* ---------- Hero grid ---------- */

/* Measured off the reference: text column x105-670 (830px at 1920), gap 14
   (21px), media x684-1224 (793px) — 50.5% / 48.2% of the 1644px content
   column, not the 50/50 Elementor defaults to. The 25px this hands back to
   the text column is what lets the H1 keep the reference's two-line break
   instead of spilling "Guidance" onto a third line. */
/* Elementor gives every container 10px of inline padding. Nested two deep
   that is 40px off the hero's usable width, which is exactly what kept the
   H1's second line 24px short of fitting and spilled "Guidance" onto a third
   line. Zeroed here so the measured column widths are the real ones; the
   page's own gutter still comes from .eqc-container. */
.eqc-hero-grid,
.eqc-hero-grid > .eqc-hero-text,
.eqc-hero-grid > .eqc-hero-media { padding-inline: 0; }
/* Reference: arch y127-747, text ink y195-730. The text is not centred on
   the arch - it sits 68 native px below the arch's tip. */
.eqc-hero-grid { gap: calc(14 * var(--eqc-u)); align-items: flex-start; }
.eqc-hero-grid > .eqc-hero-text { padding-block-start: calc(68 * var(--eqc-u)); }
@media (max-width: 64rem) {
	.eqc-hero-grid > .eqc-hero-text { padding-block-start: calc(20 * var(--eqc-u)); }
}
.eqc-hero-grid > .eqc-hero-text { flex: 1 1 50.5%; }
.eqc-hero-grid > .eqc-hero-media { flex: 1 1 48.2%; }
@media (max-width: 900px) {
	.eqc-hero-grid > .eqc-hero-text,
	.eqc-hero-grid > .eqc-hero-media { flex-basis: 100%; }
}

/* ---------- Arch media ---------- */

/*
 * Islamic-arch media frame. A true pointed-arch clip-path is supplied by the
 * inline SVG mask referenced via mask-image (see eqc_arch_media() in
 * inc/template-tags.php) for browsers that support it; this rounded-panel
 * fallback keeps the image readable everywhere else.
 */
.eqc-arch-media {
	position: relative;
	width: 100%;
	aspect-ratio: 4/5;
	border-radius: var(--eqc-radius-media);
	overflow: hidden;
	border: 1px solid var(--eqc-border);
}
/* --masked's curve carries the S-curve silhouette at its own true bbox,
   307:459. A mismatch here gets stretched by mask-size:100% 100%, which
   reintroduces clipping and distortion of the arch. */
.eqc-arch-media--masked {
	border-radius: 0;
	border: none;
	overflow: visible; /* the outline (below) deliberately extends past this box */
	aspect-ratio: 307 / 459;
}
/* The mask lives on the <img> itself, not the container: a mask on a
   parent clips its ENTIRE rendered subtree (including any differently
   sized/positioned pseudo-element) to that one shape, so an outline meant
   to extend outside the photo's own silhouette would have been clipped
   right back down to it — exactly what produced a confusing double-cusp
   overlap instead of a clean frame when this lived on the container. */
.eqc-arch-media--masked img {
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	-webkit-mask-image: url('../svg/arch-mask.svg');
	mask-image: url('../svg/arch-mask.svg');
}
/* The reference design shows a thin single gold hairline sitting right
   AT the photo's edge, not a thick offset band. inset:0 (same box as the
   photo, no enlargement) + arch-outline.svg (a thin stroke traced on
   arch-mask's own exact, unpadded bbox — see gen-ornaments.mjs — so it
   shares the identical coordinate frame and can't suffer a padding/inset
   mismatch distortion). */
.eqc-arch-media--masked::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: var(--eqc-gold-500);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	pointer-events: none;
	-webkit-mask-image: url('../svg/arch-outline.svg');
	mask-image: url('../svg/arch-outline.svg');
}
/* --keel: the hero's silhouette. A SINGLE gold contour, and the photo fills
   it exactly — see the two notes on the img and ::before rules below for
   why the frame's canvas is padded and the photo's mask is 100%. */
.eqc-arch-media--keel {
	border-radius: 0;
	border: none;
	overflow: visible;
	aspect-ratio: 559 / 629;
}
/* The photo fills the frame 1:1. An inset (95.7% / 96.18%) only makes sense
   against TWO gold contours, where it opens a cream gap between them; this
   frame is a single line, so an inset leaves the photo floating, and because
   the mask is centred that slack lands unevenly — the crown almost touches
   while the foot stops 20px short of the jambs' ends. At 100% the photo's
   edge and the frame's centreline coincide the whole way round, bottom
   vertices included. */
.eqc-arch-media--keel img {
	-webkit-mask-image: url('../svg/keel-arch-mask.svg');
	mask-image: url('../svg/keel-arch-mask.svg');
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	-webkit-mask-position: center;
	mask-position: center;
}
/* The negative inset is not a nudge — it is what makes the frame an even
   weight all the way round.

   An SVG stroke paints centred on its path. keel-arch-frame.svg's jambs run
   along x=0 and x=559 for their whole height, so on a pad-0 canvas half of
   each vertical stroke falls outside the viewBox and is clipped, rendering
   the sides at half the crown's weight. Padding the generated viewBox by 2
   units a side ("-2 -2 563 633") gives the stroke room — but only inside
   the SVG. Scaling the mask up to compensate still leaves the jambs at 3px
   against the crown's 4px, because the outer half then falls outside the
   PSEUDO-ELEMENT's own box, where there is no background colour to mask.

   So the box itself grows by the pad's exact ratio (2/559 of the width,
   2/629 of the height) and the mask fills it 1:1. The contour still lands on
   the element's edges, and the full stroke has somewhere to paint. Keep the
   two fractions in step with the generator's KEEL_PAD. */
.eqc-arch-media--keel::before {
	content: '';
	position: absolute;
	inset: calc(-2 / 629 * 100%) calc(-2 / 559 * 100%);
	background-color: var(--eqc-gold-500);
	-webkit-mask-image: url('../svg/keel-arch-frame.svg');
	mask-image: url('../svg/keel-arch-frame.svg');
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	pointer-events: none;
	z-index: 2;
}

/* Rounded-foot keel: the About collage and About page close the arch's foot
   with a curve. The hero keeps its square jambs, so this is a separate asset
   pair rather than a change to the shared shape. Only the two mask URLs
   differ from --keel above. */
.eqc-arch-media--keel-round img {
	-webkit-mask-image: url('../svg/keel-arch-mask-round.svg');
	mask-image: url('../svg/keel-arch-mask-round.svg');
}
.eqc-arch-media--keel-round::before {
	-webkit-mask-image: url('../svg/keel-arch-frame-round.svg');
	mask-image: url('../svg/keel-arch-frame-round.svg');
}

/* The illuminated-Quran photo is a landscape two-page spread (918x612) shown
   in this portrait ~0.889 frame; cover always crops away ~41% of the width
   (612px of source height is the binding dimension, so at most
   612*0.889≈544px of the 918px-wide source can ever show at this ratio —
   no object-position choice changes that ceiling, only which 544px band).
   A fully-left crop (0%) keeps the left page's border but stops short of
   x≈650 where the second page's border begins, so it reads as one ornate
   corner rather than an open book. Centred (50%, window x 187-731) clears
   x≈650 and brings the second page's border and rosettes into frame
   alongside the first page's, which is what reads as an open Quran.
   Attribute-selected so it applies wherever this one photo is used (home,
   About, course pages) without needing a per-section override; kept as an
   explicit rule so the reasoning stays attached to the value if the default
   ever changes. */
.eqc-arch-media--keel-round img[src*="about-quran-illuminated"] { object-position: 50% 50%; }

/* Career page portrait. The transparent teacher cutout stands directly on
   the section's own cream ground with a soft grounding shadow, and no arch
   or mesh backdrop: bottom-anchored at 92% width the figure runs taller
   than such a backdrop (596px against 541px), so the head breaks the frame
   at the top and the arch reads as a rendering glitch. */
.eqc-about-media > .eqc-career-portrait-widget { flex: none; width: 100%; }
/* The portrait fills the width it is given and is centred in the column's
   full height, so it reads as a deliberate full-height figure beside the
   copy rather than a stranded thumbnail. Left to its intrinsic size the
   cutout sits as a small tile at the top of a mostly-empty column (at 1440
   the text column runs 876px against the media column's 536px). */
.eqc-career-portrait {
	position: relative;
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
}
.eqc-career-portrait-figure {
	width: min(100%, 34rem);
	height: auto;
	filter: drop-shadow(0 16px 24px rgb(20 35 27 / 0.25));
}
/* The widget wrapper has to pass the column's height through, or the
   flex/height chain above stops at a zero-height box — the same wrapper
   trap .eqc-card-link-widget and .eqc-pricing-anchor-widget document. */
.eqc-about-media:has(> .eqc-career-portrait-widget) { justify-content: center; }
.eqc-about-media > .eqc-career-portrait-widget { align-self: stretch; }

.eqc-arch-media:not(.eqc-arch-media--masked):not(.eqc-arch-media--keel):not(.eqc-arch-media--cartouche)::before {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 2px var(--eqc-gold-500);
	pointer-events: none;
	z-index: 2;
}
.eqc-arch-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}
/* The student photo is a portrait with the head close to the top edge, so a
   centred cover-crop in these frames cuts the top of the head off, most
   visibly in the About page's keel arch. Biasing the crop window towards the
   TOP of the source moves the subject DOWN inside the frame and keeps the
   head whole. Values are per-frame because each frame's aspect crops a
   different amount: keel 559/629 (0.889) vs source 0.801 — ~10% of the
   height is cropped; cartouche 246/423 (0.58) crops horizontally instead. */
.eqc-arch-media--keel img,
.eqc-arch-media--masked img { object-position: 50% 12%; }
.eqc-about-collage__child .eqc-arch-media--cartouche img,
.eqc-arch-media--cartouche img { object-position: 50% 18%; }

/* Keeping the subject's head clear of the frame is not something a crop
   position can do here — cover already shows ~90% of the source's
   height, and the cap starts only 5% below the source's top edge, where the
   keel arch is just 71 of its 559 units wide (keel-arch-mask-round.svg at
   y=30). So the photo itself is made smaller and lower INSIDE the frame:
   padding shrinks the img's content box (13% top, 6% each side, as a share
   of the frame width) while its border box — which the arch mask and the
   gold ::before outline are sized against — stays the full frame. Net
   effect: ~12% zoom-out, cap top moves from ~26 to ~103 of 629 arch units
   (where the arch is ~45% wide), and the bottom still crops at ~90.5% of
   the source, the same as before, so the hands and Quran are unchanged.
   The uncovered band must not be filled with gradients sampled from the
   photo's edge pixels: those render as hard vertical strips with a visible
   seam. The photo's own edges are FADED instead, into one soft warm ground drawn
   behind it: the ground is the frame's free ::after (the img is a direct
   child of the frame — Elementor emits no wrapper — and ::before is the
   gold outline at z-index 2), the photo sits between them at z-index 1.
   The photo's mask is the arch INTERSECTED with two feathers:
   - sides fade over the 6% padding edge to 9.5%, stopping short of the
     Quran's left corner (10.4% of the frame width);
   - top fades from where the photo starts (11.55% of the frame height) to
     15%, ending above the cap (16.4%).
   All stops are percentages of the frame, so they hold at every width. */
.eqc-arch-media--keel-round:has(> img[src*="about-child-reading-quran"])::after {
	content: '';
	position: absolute;
	inset: 0;
	/* Warm ground taken from the photo's own averages: the lit mosque wall at
	   the top (#d3bb97 region), the softer column tones lower down. */
	background: linear-gradient(to bottom, #d6bf9c 0%, #d0bea8 45%, #d3c7b8 100%);
	-webkit-mask: url('../svg/keel-arch-mask-round.svg') center / 100% 100% no-repeat;
	mask: url('../svg/keel-arch-mask-round.svg') center / 100% 100% no-repeat;
	pointer-events: none;
	z-index: 0;
}
.eqc-arch-media--keel-round img[src*="about-child-reading-quran"] {
	position: relative;
	z-index: 1;
	box-sizing: border-box;
	padding: 13% 6% 0;
	object-fit: cover;
	object-position: 50% 0;
	-webkit-mask-image:
		url('../svg/keel-arch-mask-round.svg'),
		linear-gradient(to right, transparent 6%, #000 9.5%, #000 90.5%, transparent 94%),
		linear-gradient(to bottom, transparent 11.55%, #000 15%);
	mask-image:
		url('../svg/keel-arch-mask-round.svg'),
		linear-gradient(to right, transparent 6%, #000 9.5%, #000 90.5%, transparent 94%),
		linear-gradient(to bottom, transparent 11.55%, #000 15%);
	-webkit-mask-size: 100% 100%, 100% 100%, 100% 100%;
	mask-size: 100% 100%, 100% 100%, 100% 100%;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	/* Every layer must be kept where ALL of them are opaque. */
	-webkit-mask-composite: source-in, source-in;
	mask-composite: intersect;
}

/* ---------- Forms (Fluent Forms wrapper) ---------- */

.eqc-form-wrap { background: var(--eqc-surface); border: 1px solid var(--eqc-border); border-radius: var(--eqc-radius-panel); padding: clamp(1.5rem, 1.2rem + 1.5vw, 2.75rem); }
.eqc-form-wrap .ff-el-form-control,
.eqc-form-wrap select.ff-el-form-control,
.eqc-form-wrap textarea.ff-el-form-control { min-height: 50px; }
/* This panel form and the CTA banner form share one control skin. */
.eqc-form-wrap .ff-el-form-control,
.eqc-form-wrap select.ff-el-form-control,
.eqc-form-wrap textarea.ff-el-form-control,
.eqc-cta-banner .ff-el-form-control {
	border-radius: var(--eqc-radius-control) !important;
	border: 1px solid var(--eqc-border-strong) !important;
	background: var(--eqc-cream-50) !important;
	font-family: var(--eqc-font-body) !important;
}
.eqc-form-wrap .ff-el-form-control:focus,
.eqc-cta-banner .ff-el-form-control:focus {
	border-color: var(--eqc-green-700) !important;
	box-shadow: 0 0 0 3px rgba(36, 80, 59, 0.15) !important;
}
.eqc-form-wrap .ff-el-input--label label,
.eqc-form-wrap .ff_wrapper label {
	font-weight: 600 !important;
	color: var(--eqc-heading) !important;
}
.eqc-form-wrap .ff-btn,
.eqc-form-wrap button[type="submit"],
.eqc-cta-banner .ff-btn,
.eqc-cta-banner button[type="submit"] {
	background: var(--eqc-bronze-700) !important;
	border-radius: var(--eqc-radius-pill) !important;
	font-weight: 600 !important;
	padding: 0.9em 1.8em !important;
	border: none !important;
}
.eqc-form-wrap .ff-btn:hover,
.eqc-cta-banner .ff-btn:hover { background: var(--eqc-bronze-600) !important; }

/* ---------- Form result states ----------
 *
 * Fluent Forms' own success and error markup was left completely unstyled, so
 * the confirmation after a submission rendered as the plugin's default: grey
 * text in a thin grey box, indistinguishable from an empty input. It is the one
 * moment in the journey where the visitor needs an unambiguous answer, and it
 * looked like nothing had happened.
 *
 * Green for success, red for the problem, each with a coloured edge and a mark
 * in the corner -- so the state is legible from the colour alone at a glance,
 * and from the icon and wording if the colour is not available.
 */
.ff-message-success,
.eqc-cta-banner .ff-message-success {
	position: relative;
	display: flex;
	gap: 0.75em;
	align-items: flex-start;
	margin: 0;
	padding: 1.1em 1.3em 1.1em 1.15em;
	border: 1px solid var(--eqc-green-700);
	border-inline-start: calc(5 * var(--eqc-u)) solid var(--eqc-gold-500);
	border-radius: var(--eqc-radius-control);
	background: rgba(36, 80, 59, 0.07);
	color: var(--eqc-green-900);
	font-weight: 600;
	line-height: 1.6;
}
/* An inline SVG tick on a green disc. Built from two crossed linear-gradients
   first, which is the trick that avoids an asset entirely -- but the two bars
   would not meet cleanly at the joint at this size and read as a stray mark
   rather than a tick, so the path is drawn properly instead. Still no network
   request: the SVG is a data URI, which keeps it in the one stylesheet. */
.ff-message-success::before {
	content: '';
	flex: 0 0 auto;
	inline-size: 1.45em;
	block-size: 1.45em;
	margin-block-start: 0.02em;
	border-radius: 50%;
	background-color: var(--eqc-green-800);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 68% 68%;
}
.ff-message-success p:last-child { margin-block-end: 0; }

/* The error text under a field, and the field itself. */
.frm-fluent-form .ff-el-is-error .ff-el-form-control,
.eqc-cta-banner .ff-el-is-error .ff-el-form-control {
	border-color: var(--eqc-danger) !important;
	background: rgba(155, 34, 38, 0.04) !important;
}
.frm-fluent-form .error,
.frm-fluent-form .text-danger,
.eqc-cta-banner .error {
	display: block;
	margin-block-start: 0.4em;
	/* !important, like every other rule in this form block: Fluent Forms ships
	   its own #f56c6c for this text, which measures 3.1:1 on white and fails AA
	   for body copy. The plugin's stylesheet loads after the theme's. */
	color: var(--eqc-danger) !important;
	font-size: var(--eqc-fs-small);
	font-weight: 600;
	line-height: 1.5;
}
/* The whole-form error summary Fluent Forms prints above the fields. */
.ff-errors-in-stack,
.frm-fluent-form .ff_submit_failed {
	padding: 0.9em 1.1em;
	border: 1px solid var(--eqc-danger);
	border-inline-start: calc(5 * var(--eqc-u)) solid var(--eqc-danger);
	border-radius: var(--eqc-radius-control);
	background: rgba(155, 34, 38, 0.06);
	color: var(--eqc-danger);
	font-weight: 600;
}

/* ---------- FAQ accordion ---------- */

.eqc-faq-group + .eqc-faq-group { margin-top: var(--eqc-stack-gap); }
/* Only /faq/ passes group titles, and at the serif H3 default they rendered
   at body weight in the body colour — six lines that read as stray text
   between the bars rather than as the category headings they are. Small
   caps plus a trailing hairline gives each group a visible start. */
.eqc-faq-group h3 {
	display: flex;
	align-items: center;
	gap: 0.9em;
	margin-bottom: 0.85em;
	font-family: var(--eqc-font-body);
	font-weight: 700;
	font-size: var(--eqc-fs-small);
	letter-spacing: 0.09em;
	text-transform: uppercase;
	/* bronze-700, not -600: at 14px over the /faq/ photo the lighter copper
	   measured 3.77-3.81:1, under the 4.5:1 AA floor for body-size text
	   (contrast.mjs, 390 and 1440). The darker token is the same copper
	   family and measures 4.9:1 on the worst pixel. */
	color: var(--eqc-bronze-700);
}
.eqc-faq-group h3::after {
	content: '';
	flex: 1 1 auto;
	height: 1px;
	background: linear-gradient(90deg, var(--eqc-gold-500), transparent);
}
/* Solid green question bars with a white chevron. The item itself carries
   no border or background — the question bar IS the visible surface
   when closed, and the answer's own white background (below) is what
   shows once opened, so the border moves there instead. */
.eqc-faq-item {
	border-radius: var(--eqc-radius-control);
	overflow: hidden;
}
.eqc-faq-item + .eqc-faq-item { margin-top: 0.75rem; }
.eqc-faq-question {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	text-align: left;
	background: var(--eqc-green-800);
	border: none;
	cursor: pointer;
	padding: 1.1em 1.3em;
	font-family: var(--eqc-font-body);
	font-weight: 700;
	font-size: var(--eqc-fs-body);
	color: #fff;
	transition: background var(--eqc-motion-base) var(--eqc-ease-standard),
		color var(--eqc-motion-base) var(--eqc-ease-standard);
	/* <button> carries `white-space: nowrap` in the browser's own UA
	   stylesheet (confirmed via getComputedStyle — nothing in this file
	   was setting it), inherited straight into the question span below.
	   Without resetting it, narrow-width text overflows the icon instead of
	   wrapping: the flex sizing (span below) lets the box shrink while its
	   text still physically cannot wrap, so it spills over the icon at
	   360/390px. Both fixes are required. */
	white-space: normal;
}
/* On hover and when open the bar darkens while the type and the glyph go
   gold, so the active question reads as prominent. The contrast of the gold
   on the darkened bar is measured, not assumed. */
.eqc-faq-question:hover,
.eqc-faq-item[data-open="true"] .eqc-faq-question {
	background: var(--eqc-green-900);
	color: var(--eqc-gold-300);
}
.eqc-faq-question:focus-visible { outline: 3px solid var(--eqc-gold-500); outline-offset: -3px; }
/* The question text is a flex item with no explicit min-width, so its
   default min-width:auto stopped it shrinking below its own text's
   intrinsic width — the classic flexbox overflow trap. flex:1 1 auto plus
   min-width:0 lets the question column actually shrink and wrap within the
   space left for it, on every FAQ list site-wide (home, /faq/, per-course,
   pricing, kids) since they all render through eqc_faq_item_html(). */
.eqc-faq-question > span:first-child { flex: 1 1 auto; min-width: 0; }
/* A chevron with no circle backdrop, rotating 180deg open. */
.eqc-faq-icon {
	flex: none;
	width: 1.3em;
	height: 1.3em;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #fff;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard),
		color var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-faq-item[data-open="true"] .eqc-faq-icon { transform: rotate(180deg); }
/* The glyph goes gold with its label. */
.eqc-faq-question:hover .eqc-faq-icon,
.eqc-faq-item[data-open="true"] .eqc-faq-icon { color: var(--eqc-gold-300); }
.eqc-faq-answer {
	display: grid;
	grid-template-rows: 0fr;
	background: var(--eqc-surface);
	border: 1px solid var(--eqc-border);
	border-top: none;
	transition: grid-template-rows var(--eqc-motion-reveal) var(--eqc-ease-standard);
}
.eqc-faq-item[data-open="true"] .eqc-faq-answer { grid-template-rows: 1fr; }
.eqc-faq-answer-inner { overflow: hidden; }
/* The answer needs a gap above it, or its first line sits flush against the
   question bar — the paragraph carries side and bottom margins but no top
   margin of its own. The padding sits on the
   inner wrapper so the gap exists on all four sides and can't be lost to
   margin-collapsing — and is scoped to the open state, because the answer
   animates via grid-template-rows: 0fr -> 1fr and a permanently-padded
   inner box would stop the closed row collapsing to zero. */
.eqc-faq-item[data-open="true"] .eqc-faq-answer-inner { padding: 1.15em 1.3em 1.25em; }
.eqc-faq-answer p { margin: 0; color: var(--eqc-text); }
/* A closed item's answer collapses to grid-template-rows:0fr, but the
   1px border above still renders a hairline seam under every closed bar
   (confirmed live) — border-block-start on the item itself would double
   with the answer's own top border once opened. Zero the answer's border
   only while closed, where it has no visible content to frame anyway. */
.eqc-faq-item:not([data-open="true"]) .eqc-faq-answer { border-color: transparent; }

/* ---------- FAQ split layout ----------
 * A full-bleed branded photo beside the accordion. A single centred column
 * leaves the section's left and right thirds empty (a 559px accordion inside
 * a 1295px section). One shared builder renders every FAQ on the site (home,
 * courses, pricing, kids, career, /faq/ and the six course-detail pages), so
 * this one definition covers all of them. */
/* The photo touches the section's own top, bottom and outer edge with no gap
   or padding, so both the section's and the split's Elementor-generated
   padding are zeroed here (!important —
   Elementor bakes `padding` as per-element generated CSS, which beats a
   bare class rule; the same fight .eqc-btn-group documents). */
.eqc-section--faq { padding: 0 !important; overflow: hidden; }
.eqc-faq-split { padding: 0 !important; gap: 0 !important; }
/* Plain-class grid, same technique .eqc-grid already uses to override
   Elementor's own generated flex CSS on this container (components.css,
   "Layout" section) — a container element's `flex_direction` setting
   still wins over a bare `display:flex` re-declaration, but a `display:
   grid` on a different property entirely takes over cleanly. Single
   column until there is room for the photo beside the accordion without
   squeezing either below a readable width.

   That threshold is 80rem, the same width the header switches to its
   desktop layout at. It is not a device guess: the photo is shown whole,
   so the narrower its column the shorter the row it can fill, while the
   accordion beside it does not shrink to match. Measured on the home
   page's six-item list, the column stops being tall enough somewhere
   below 1280px — at 992px the list ran 636px against a 503px photo and
   cropped a third of the image away, which is the exact defect the whole
   aspect-spacer block below exists to prevent. Below 80rem the photo
   becomes the faint full-width background instead (further down), the
   same treatment /faq/ and the phone layout already use. */
.eqc-faq-split { display: grid; grid-template-columns: 1fr; }
@media (min-width: 80rem) {
	/* The media column is slightly the wider of the two. That is not a
	   styling preference: the photo is 1335x1178 (1.133:1) and is shown
	   WHOLE (see the aspect spacer below), so the column's width is what
	   sets the row's height — and the accordion beside it has to fit in
	   that height. A wider photo column buys the list more vertical room. */
	.eqc-faq-split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); align-items: stretch; }
}
.eqc-faq-split-media { position: relative; overflow: hidden; }
.eqc-faq-split-media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
@media (min-width: 80rem) {
	/* The photo shows whole, flush to all four edges, with no clipping on any
	   side. `position: sticky` with a clamped height scrolls it independently
	   of the list and leaves a 283px band of empty cream below it; letting it
	   stretch with the row makes `object-fit: cover` crop 34% of it away.

	   The ::before spacer gives this box the source's exact 1335:1178 ratio,
	   so when the row's height is set by the photo (the normal case, since
	   the accordion beside it is tuned to fit) `cover` has nothing to crop
	   and the whole image shows, flush to all four edges of its cell. If a
	   page's list ever runs taller than that, the cell stretches and cover
	   degrades gracefully rather than tearing the layout.

	   The long /faq/ page can't be served this way at all (its list is
	   ~1600px tall), so it uses the --bg variant below instead. */
	.eqc-faq-split-media { position: relative; top: auto; height: auto; align-self: stretch; margin-inline-start: 0; }
	.eqc-faq-split-media::before { content: ''; display: block; padding-block-start: calc(1178 / 1335 * 100%); }
	.eqc-faq-split-media img { position: absolute; inset: 0; }
	/* Centred in whatever height the photo sets, rather than padded away
	   from the section's edges — the section itself now has no padding. */
	/* Near-zero: the column is vertically centred in the height the photo
	   sets, so it needs no padding of its own unless a page's list is the
	   taller of the two. That 100px of block padding was the whole remaining
	   overshoot keeping the row taller than the photo's natural height.
	   Scoped through .eqc-faq-split deliberately: the base rule below is
	   LATER in the file at the same specificity, so a bare
	   `.eqc-faq-split-body` here would silently lose to it (measured: padTop
	   stayed at 50.18px, exactly the base clamp's value). */
	.eqc-faq-split .eqc-faq-split-body { align-self: center; padding-block: clamp(0.25rem, 0.2rem + 0.3vw, 0.5rem); }
	/* The list has to FIT the photo's natural height, or the row grows and
	   the photo gets cropped again. Type and spacing are tuned so every
	   question sits inside the section. Scoped to the split so /faq/ and any
	   other context keeps the full-size treatment. */
	.eqc-faq-split-body .eqc-section-heading { gap: calc(9 * var(--eqc-u)); }
	/* No font-size override: this reads as the section header it is, at the
	   same size as every other H2 on the page. It used to be shrunk to buy
	   vertical room for the photo fit, which left the FAQ the only section
	   on the site with a visibly smaller title. The measured slack between
	   this column and the photo column pays for the full size instead — see
	   the fit note above; the tighter line-height keeps a two-line title
	   inside that budget. */
	.eqc-faq-split-body .eqc-section-heading h2 { line-height: 1.12; }
	.eqc-faq-split-body .eqc-heading-rule--ornate { margin-block: 0; }
	.eqc-faq-split-body .eqc-heading-rule--ornate .eqc-divider-svg { width: calc(205 * var(--eqc-u)); }
	.eqc-faq-split-body .eqc-faq-question { padding: 0.78em 1.15em; }
	.eqc-faq-split-body .eqc-faq-item + .eqc-faq-item { margin-top: 0.45rem; }
	/* The header needs to read as a header, which means clear air under its
	   rule before the first bar — not the hairline gap it had. Qualified
	   through .eqc-faq-split because the base `.eqc-faq-split-body
	   .eqc-faq-group:first-of-type` rule below is LATER in the file at equal
	   specificity and would otherwise win here, media query or not. */
	.eqc-faq-split .eqc-faq-split-body .eqc-faq-group:first-of-type { margin-top: 1.35rem; }
}
/* Narrow-viewport / fallback padding. The >= 62rem block above overrides
   the block axis through a higher-specificity selector, since this rule is
   later in the file. */
.eqc-faq-split-body {
	padding-block: clamp(2rem, 1.5rem + 2vw, 3.5rem);
	padding-inline: clamp(1.5rem, 1rem + 3vw, 4rem);
}
.eqc-faq-split-body .eqc-faq-group:first-of-type { margin-top: var(--eqc-stack-gap); }
/* Below the split breakpoint the photo must not stack above the
   accordion (client instruction) — it becomes a faint background behind
   the whole column instead. Opacity chosen and checked against the
   accordion's own green bars/body text for contrast, not by eye alone. */
@media (max-width: 79.999rem) {
	.eqc-faq-split { position: relative; }
	.eqc-faq-split-media {
		position: absolute;
		inset: 0;
		z-index: 0;
		/* 0.17, down from Round 19's 0.3: at 0.3 the photo's own lettering
		   showed through the questions and read as a mess (client, Round 20).
		   Enough to see the room behind the accordion, not enough to compete
		   with it. */
		opacity: 0.17;
		pointer-events: none;
		margin-inline-start: 0;
	}
	/* Bars running the section's full width read as a wall of green — the
	   client's own objection to /faq/ before it was bounded. The column
	   keeps a readable, centred measure here for the same reason. */
	.eqc-faq-split-body { position: relative; z-index: 1; max-inline-size: min(58rem, 100%); margin-inline: auto; }
}

/* ---------- FAQ split: full-background variant ----------
 * Used by /faq/ only. That page carries 6 category groups and 14 questions,
 * a ~1600px column. Cover-cropping a photo beside it exposes only ~31% of the
 * 1335px source's width, narrower than the ~695px logo lockup, so the
 * branding would be cropped away entirely. Here the photo becomes a faint
 * full-section background behind a full-width accordion instead — the same
 * treatment the narrow breakpoint uses, applied at every width. */
.eqc-faq-split--bg { position: relative; }
/* !important: the >= 62rem rule above sets the two-column template at the
   same specificity, and this modifier must beat it at every width. The
   same Elementor/media-query specificity fight .eqc-btn-group and
   .eqc-nav-drawer-cta already document. */
.eqc-faq-split--bg { grid-template-columns: 1fr !important; }
/* `inset: 0` is what stretches this to the full section; do NOT add a
   `top`/`height` reset after it to "undo" the >= 62rem rule above — that
   longhand wins over the shorthand and drops the element back to its
   static position (measured: top 430.9px, height 1126px instead of 1557px
   when `top: auto` was present). The shorthand already covers both. */
.eqc-faq-split--bg .eqc-faq-split-media {
	position: absolute;
	inset: 0;
	z-index: 0;
	/* Matches the in-page variant above -- one strength for both. */
	opacity: 0.17;
	pointer-events: none;
	margin-inline-start: 0;
}
/* Bias the crop towards the logo lockup, which sits at ~52% of the
   source's height (1335x1178). */
.eqc-faq-split--bg .eqc-faq-split-media img { object-position: center 45%; }
.eqc-faq-split--bg .eqc-faq-split-body { position: relative; z-index: 1; }
/* This variant has no photo COLUMN to bleed against, so the two rules that
   exist for the split — the section's zeroed padding and the body's
   near-zero `padding-block` (both above) — leave the list flush against the
   hero above it and the footer below. It owns its own rhythm instead: a
   centred, bounded measure with real air around it. Later in the file at
   equal-or-higher specificity than both, deliberately, so it wins at every
   width including inside the >= 62rem block. */
.eqc-faq-split--bg .eqc-faq-split-body {
	max-inline-size: min(58rem, 100%);
	margin-inline: auto;
	padding-block: clamp(2.5rem, 1.8rem + 3vw, 5rem);
	padding-inline: clamp(1.25rem, 0.5rem + 3vw, 2.5rem);
}
/* Six categories need a visible break between them; the shared stack gap
   (~15px) left them running together as one list of fourteen. Each group is
   its own Elementor HTML widget, so the groups are not actually siblings —
   `+` never matches and every one of them is its wrapper's :first-of-type.
   The margin therefore goes on the group itself, at a specificity that
   beats the base :first-of-type rule earlier in this file. */
.eqc-faq-split--bg .eqc-faq-split-body .eqc-faq-group:first-of-type { margin-top: clamp(0.9rem, 0.5rem + 1vw, 1.6rem); }
/* The page header needs more air under it than the gap between two
   categories, or the six groups and the title read as one flat list. */
.eqc-faq-split--bg .eqc-section-heading { margin-block-end: clamp(0.5rem, 0.3rem + 0.8vw, 1.1rem); }

/* ---------- Section texture & ornaments ----------
 * Every section pairs its cream/surface background with a faint gold corner
 * motif and/or a near-invisible geometric texture, rather than a solid flat
 * fill. Defined once here rather than per-page: the section builder injects
 * the two corner-motif spans as a section's first child; any
 * section carrying `eqc-section--ornamented` gets them positioned and
 * layered correctly regardless of what else it contains. */

/* Honeycomb hex tile (assets/svg/hex-tessellation.svg, a genuine seamless
 * tiling) as a mask over a solid gold fill, rather than a hardcoded-color
 * data-URI background-image. The tiling must interlock edge-to-edge or
 * adjacent tiles' points fall short of touching and read as scattered
 * asterisks rather than a lattice. A mask inherits background-color like
 * every other ornament in this file, so the colour follows --eqc-gold-500
 * and can adapt for dark sections; a colour baked into a data URI cannot.
 */
.eqc-section--textured {
	position: relative;
}
.eqc-section--textured::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: var(--eqc-gold-500);
	opacity: 0.1;
	-webkit-mask-image: url('../svg/hex-tessellation.svg');
	mask-image: url('../svg/hex-tessellation.svg');
	/* Cell measured at 52x90 native; as fixed px it stayed the same size
	   while everything around it scaled, so at 1920 the weave read ~31% too
	   dense against the reference. */
	-webkit-mask-size: calc(52 * var(--eqc-u)) calc(90 * var(--eqc-u));
	mask-size: calc(52 * var(--eqc-u)) calc(90 * var(--eqc-u));
	-webkit-mask-repeat: repeat;
	mask-repeat: repeat;
	pointer-events: none;
	z-index: 0;
}
.eqc-section--textured > .e-con { position: relative; z-index: 1; }

.eqc-section--ornamented { position: relative; overflow: hidden; }
/* Elementor renders every nested Container (eqc_inner, grids, etc.) as a
   direct-child `.e-con` div; boosting those above the ornament layer here
   covers every ornamented section regardless of its own content shape. */
.eqc-section--ornamented > .e-con { position: relative; z-index: 1; }

.eqc-corner-motif {
	position: absolute;
	width: clamp(130px, 15vw, 240px);
	height: clamp(130px, 15vw, 240px);
	/* Tint carried in the colour's own alpha (not element `opacity`) so the
	   drop-shadow below renders at full strength instead of being multiplied
	   down with it. That is also why this number can be lowered freely: the
	   carved depth lives in the filter, not in how opaque the gold is. */
	background-color: rgb(var(--eqc-gold-600-rgb) / 0.26);
	-webkit-mask-image: url('../svg/lattice-corner.svg');
	mask-image: url('../svg/lattice-corner.svg');
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	/* A dark cast below-right plus a fine light lift top-left carves the corner
	   arabesque off the surface; without them it reads flat. drop-shadow
	   follows the mask silhouette, not a box. */
	filter: drop-shadow(1px 3px 3px rgb(20 35 27 / 0.5)) drop-shadow(-1px -1px 0 rgb(255 253 249 / 0.4));
	pointer-events: none;
	z-index: 0;
	--_motif-inset: 0;
}
/* lattice-corner.svg is drawn dense at its own top-right corner (see the
   asset's own comment), so .eqc-corner-motif--tr needs no transform and
   --bl's 180deg rotation naturally maps that dense corner to bottom-left.
   The asset is a genuine arabesque bracket (concentric arcs + rosette +
   finial, girih fill clipped to a curved wedge) rather than a lattice
   field cropped to a square — its own radial-gradient mask fades alpha to
   true zero well inside the canvas, so this element-level opacity is a
   second, smaller multiplier on top — deliberately higher than
   DESIGN.md §9's 3-10% baseline per explicit user feedback that the
   previous motif read as "boring and dull" at that strength. */
/* Flush to the true corner, with no inset; an inset opens a visible gap
   between the ornament and the section edge. This is safe only because the
   per-corner drift keyframes (motion.css eqc-drift-tl/tr/bl/br) move each
   motif INWARD, toward the section middle, never outward past its start
   position. A single shared drift direction carries motifs outward and clips
   them against `overflow: hidden`. If the drift direction ever changes,
   re-check this. */
.eqc-corner-motif--tr { top: var(--_motif-inset); right: var(--_motif-inset); }
.eqc-corner-motif--bl { bottom: var(--_motif-inset); left: var(--_motif-inset); transform: rotate(180deg); }
/* The remaining two corners, by the same mapping: mirroring the asset puts
   its dense corner top-left, and mirroring the other axis puts it
   bottom-right. The About section's arabesque sits top-LEFT, above the
   collage, which is the pair it uses. */
.eqc-corner-motif--tl { top: var(--_motif-inset); left: var(--_motif-inset); transform: scaleX(-1); }
.eqc-corner-motif--br { bottom: var(--_motif-inset); right: var(--_motif-inset); transform: scaleY(-1); }
/* Smaller pair for a nested panel (e.g. .eqc-pricing-panel below) rather
   than a full section — the reference's arches sit tight against the
   pricing panel's own corners, not spread across the whole section. */
.eqc-corner-motif--sm { width: clamp(70px, 8vw, 130px); height: clamp(70px, 8vw, 130px); background-color: rgb(var(--eqc-gold-600-rgb) / 0.28); }
/* Slow ambient drift so the ornament reads as gently alive rather than a static
   watermark. This shorthand supplies the timing; motion.css then overrides
   `animation-name` per corner so each drifts along its own diagonal (a single
   shared direction pulls opposite corners inconsistently).
   `eqc-drift` stays the default name so a motif shipped without a corner
   modifier still animates sanely. */
html.eqc-js .eqc-corner-motif { animation: eqc-drift 24s var(--eqc-ease-soft) infinite alternate; }

/* Framed white panel wrapping the pricing cards and inclusion strip, giving
   the section the bordered ground a flat fill lacks. */
.eqc-pricing-panel {
	/* No overflow:hidden here (deliberately, unlike .eqc-section--ornamented):
	   the medallions and the RECOMMENDED tab both overhang the cards' top
	   edge and would be clipped this close to the panel edge. The corner
	   motifs' own opacity already fades to zero well inside their canvas, so
	   leaving this visible costs nothing. */
	position: relative;
	background: var(--eqc-surface);
	border: 1px solid var(--eqc-gold-300);
	border-radius: var(--eqc-radius-panel);
	box-shadow: var(--eqc-shadow-card);
	/* Was clamp(2.25rem, 1.5rem + 3vw, 4rem) on all four sides — 64px of
	   vertical inset inside a section that already pads 77px. The panel is a
	   frame around the cards, not a second section. */
	padding: calc(26 * var(--eqc-u)) clamp(1rem, 0.5rem + 1.6vw, 2.25rem);
}
.eqc-pricing-panel > .e-con { position: relative; z-index: 1; }
/* With the corner motif flush (--_motif-inset: 0), its dense corner pixel
   lands exactly on the panel's own rounded corner, and this panel
   deliberately has no overflow:hidden (see above), so nothing else clips it
   there. border-radius clips an element's own background/mask paint even
   without overflow:hidden, so rounding this element's corner to match the
   panel's curve stops the ink spilling past it. Both --tr and --bl are,
   before their own transform, dense at their own top-right corner (--bl gets
   there via rotate(180deg), not a different asset), so one declaration
   serves both. */
.eqc-pricing-panel .eqc-corner-motif--sm.eqc-corner-motif--tr,
.eqc-pricing-panel .eqc-corner-motif--sm.eqc-corner-motif--bl {
	border-top-right-radius: var(--eqc-radius-panel);
}

/* ---------- Section heading block ---------- */

/* max-width now set from the measured reference further down. */
.eqc-section-heading--center {
	max-width: var(--eqc-content-narrow);
	margin-inline: auto;
	align-items: center;
	text-align: center;
}
.eqc-section-heading--center .eqc-heading-rule { margin-inline: auto; }

/* ---------- Blog single post ----------
 * The post's vertical rhythm lives here as one scale, not as inline styles
 * on the template. Section-sized spacing under the featured image plus the
 * header's own full section padding opens a large empty band between the
 * image and the first paragraph, pushing the title high and starting the
 * body low. */
.eqc-single-header {
	padding-block: clamp(1.75rem, 1.2rem + 2vw, 3.25rem) clamp(1rem, 0.7rem + 1.2vw, 1.75rem);
	background: var(--eqc-cream-100);
	text-align: center;
}
.eqc-single-meta {
	justify-content: center;
	gap: 0.75rem;
	margin-block-end: clamp(0.6rem, 0.45rem + 0.5vw, 1rem);
}
.eqc-single-cat {
	color: var(--eqc-bronze-700);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.eqc-single-cat + .eqc-single-date::before { content: '·'; margin-inline-end: 0.75rem; color: var(--eqc-muted); }
.eqc-single-title { margin: 0; }
/* The gap under the image is deliberately small — this is the same visual
   block as the title above it, not a separate section. */
.eqc-single-figure {
	margin: 0;
	padding-block-end: clamp(0.75rem, 0.55rem + 0.8vw, 1.25rem);
	background: var(--eqc-cream-100);
}
.eqc-single-figure-frame {
	max-width: var(--eqc-content-max);
	margin-inline: auto;
	border-radius: var(--eqc-radius-panel);
	overflow: hidden;
	/* The banner is deliberately shallow rather than tall: the space it gives
	   back is taken out of the gap below it rather than left empty. A ratio
	   like 16/7.2 makes this a tall block instead. The max-height stops it
	   growing into a slab on very wide screens. */
	aspect-ratio: 16 / 5.6;
	max-block-size: 26rem;
	box-shadow: var(--eqc-shadow-card);
}
.eqc-single-figure-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The body moves UP to close the gap the shallow banner leaves, instead of
   the banner growing down into it. */
.eqc-single-content {
	padding-block: clamp(1rem, 0.75rem + 1vw, 1.75rem) clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);
	font-size: var(--eqc-fs-body-l);
}
.eqc-single-content > *:first-child { margin-block-start: 0; }

/* Closing ornament and a way back into the blog, so a post ends deliberately
   instead of running straight into the global CTA banner. */
.eqc-single-end {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(0.9rem, 0.7rem + 0.7vw, 1.5rem);
	padding-block-end: clamp(2rem, 1.5rem + 2vw, 3.5rem);
}
/* The divider art fills from `currentColor`; without this it inherited the
   body's near-black and read as a grey rule. Gold matches every other
   divider and ornament on the site. */
.eqc-single-end-rule { display: flex; justify-content: center; width: 100%; color: var(--eqc-gold-600); }
.eqc-single-end-rule .eqc-divider-svg { width: calc(240 * var(--eqc-u)); max-width: 100%; color: inherit; }
.eqc-single-end-rule .eqc-divider-svg * { fill: currentColor; stroke: currentColor; }
.eqc-single-back {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	font-weight: 600;
	font-size: var(--eqc-fs-small);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--eqc-bronze-700);
	text-decoration: none;
}
.eqc-single-back:hover { color: var(--eqc-green-800); text-decoration: underline; }
.eqc-single-back .eqc-icon { width: 1em; height: 1em; }

/* ---------- Blog single-post prose ---------- */

.eqc-single-content h2 { font-size: var(--eqc-fs-h3); margin-top: 1.6em; }
.eqc-single-content h3 { font-size: var(--eqc-fs-h4); font-family: var(--eqc-font-body); font-weight: 700; margin-top: 1.4em; }
.eqc-single-content p { margin-block: 1.1em; }
.eqc-single-content ul, .eqc-single-content ol { padding-inline-start: 1.4em; margin-block: 1.1em; }
.eqc-single-content li + li { margin-top: 0.4em; }
.eqc-single-content a { color: var(--eqc-bronze-700); text-decoration-color: var(--eqc-border-strong); }
.eqc-single-content blockquote {
	border-left: 3px solid var(--eqc-gold-500);
	margin: 1.6em 0;
	padding: 0.2em 0 0.2em 1.2em;
	color: var(--eqc-heading);
	font-family: var(--eqc-font-display);
	font-size: 1.15em;
}
/* In-content images always fill the measure, keep their own aspect, cap
   their height so a portrait upload can't run off the screen, and carry the
   same card radius and shadow as the featured banner. Unconstrained, an
   upload wider or taller than the measure breaks the column's rhythm. */
.eqc-single-content img {
	display: block;
	width: 100%;
	height: auto;
	max-block-size: 34rem;
	object-fit: cover;
	border-radius: var(--eqc-radius-card);
	box-shadow: var(--eqc-shadow-card);
	margin-block: 1.6em;
}
.eqc-single-content figure { margin: 1.6em 0; }
.eqc-single-content figure img { margin-block: 0; }
.eqc-single-content figcaption {
	margin-block-start: 0.6em;
	text-align: center;
	font-size: var(--eqc-fs-small);
	color: var(--eqc-muted);
}
/* An alignwide/alignfull image may exceed the text measure by design; keep
   it from exceeding the viewport. */
.eqc-single-content .alignwide,
.eqc-single-content .alignfull { max-width: 100%; }

/* ---------- Utility ---------- */

.eqc-align-center { text-align: center; }
.eqc-body-l { font-size: var(--eqc-fs-body-l); }

/* Body copy is scannable, with the load-bearing phrase per paragraph picked
   out. A dedicated weight/colour rather than raw <strong> bold, so it reads
   as a deliberate highlight, not shouting. */
.eqc-emphasis { font-weight: 600; color: var(--eqc-green-900); }
/* Hero benefit triplet (client, 2026-09-23: make the description easy to
   focus on). Line 1 stays a sentence; line 2 is three short phrases the eye
   can land on one at a time. A step up in weight and colour from the body
   copy makes it read as its own line rather than the sentence's tail, while
   staying below the bold "1-o-1 live classes" lead. The gold dots are
   aria-hidden in the markup, so they are decoration only. */
.eqc-hero-benefits { font-weight: 500; color: var(--eqc-green-800); }
.eqc-hero-benefits__sep { color: var(--eqc-gold-600); font-weight: 700; margin-inline: 0.1em; }
/* A phrase breaks as a unit ("Personalized / learning" split across lines
   read as two ideas); the line can still wrap at the dots. */
.eqc-hero-benefits__item { white-space: nowrap; }
/* On a phone the column only holds one phrase per line, so the inline dots
   ended up dangling at line ends. There the triplet becomes a short list with
   a gold dot LEADING each phrase instead -- three clean landing points. */
@media (max-width: 40rem) {
	.eqc-hero-benefits {
		display: flex;
		flex-direction: column;
		gap: 0.15em;
		margin-block-start: 0.4em;
	}
	.eqc-hero-benefits__sep { display: none; }
	.eqc-hero-benefits__item {
		display: inline-flex;
		align-items: center;
		gap: 0.55em;
	}
	.eqc-hero-benefits__item::before {
		content: '';
		inline-size: 0.4em;
		block-size: 0.4em;
		border-radius: 50%;
		background: var(--eqc-gold-600);
		flex: none;
	}
}

/* The load-bearing phrase inside a section title, picked out in the warm
   accent so a long heading has one obvious place for the eye to land
   instead of reading as an even wall of type. Colour only — no weight or
   size change: the heading is already display-weight, and shifting either
   would break the line's rhythm rather than guide it.
 *
 * Bronze, not the ornament gold. --eqc-gold-600 (what two of these headings
 * used inline) measures 3.2:1 on cream-100 and 2.98:1 on the reviews band's
 * cream-150 — the latter fails WCAG AA even at large-text sizes. This runs
 * 6.6-7.8:1 on every light ground a heading actually sits on. Gold stays the
 * ornament/divider colour; bronze is the typographic accent. */
.eqc-heading-accent { color: var(--eqc-bronze-700); }
/* Bronze inverts badly on the dark panels (1.6:1); the light gold is the
   readable accent there (7.2:1). */
.eqc-footer-cta .eqc-heading-accent { color: var(--eqc-gold-300); }

.eqc-visually-hidden {
	position: absolute !important;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.eqc-skip-link {
	position: absolute;
	left: 1rem;
	top: -100px;
	background: var(--eqc-green-900);
	color: #fff;
	padding: 0.8em 1.2em;
	border-radius: var(--eqc-radius-control);
	z-index: 1000;
	transition: top var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-skip-link:focus { top: 1rem; }

/* Focus-visible baseline across the site */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
	outline: 3px solid var(--eqc-gold-500);
	outline-offset: 2px;
}

/* Hero section: the reference opens the hero immediately under the header —
   the arch's tip (y127 native) sits level with the header bar's lower edge,
   so there is no top padding at all. The previous --tight padding pushed the
   whole column 119px down at 1920. Bottom padding is 0 too: the trust panel
   that follows carries its own 20-unit offset. */
.eqc-section--hero {
	padding-block: 0;
}
/* The negative pull that tucks the hero under the header only makes sense
   where the hero sits BESIDE the nav pill. Applied at every width it leaves
   the mobile eyebrow 2px under the bar at 390px, because the stacked hero's
   first element is the eyebrow, not the arch. */
@media (min-width: 56.25rem) {
	.eqc-section--hero { margin-block-start: calc(-27 * var(--eqc-u)); }
}
@media (max-width: 56.24rem) {
	.eqc-section--hero { padding-block-start: calc(26 * var(--eqc-u)); }
}
.eqc-section--hero > .e-con,
.eqc-section--hero .eqc-container,
.eqc-section--hero .eqc-hero-grid { padding-block: 0; padding-inline: 0; }
.eqc-section--hero .eqc-hero-media { padding-inline: 0; }

/* Mobile/tablet hero photo panel (client request, 2026-09-22, revised
   2026-09-23; reference QA/qa-15092026/New_hero_ref.png). Below the hero's
   own stacking breakpoint (56.25rem / 900px, matches .eqc-hero-grid at
   :1793) the keel-arch photo card is dropped and the mosque/rehal photo
   sits in the section's top-RIGHT corner instead.

   Measured off the reference (a 900x1600 phone screenshot): the photo is a
   right-hand panel, not a full-bleed layer. Its left edge dissolves between
   about 50% and 78% of the page width, the left half stays plain cream
   under the heading, and the photo fades out along its bottom at roughly
   80% of the viewport height, around the feature-chip row. A first pass
   that stretched the photo edge-to-edge under a diagonal cream wash was
   rejected by the client for exactly this reason.

   It is a MASKED `::after`, not a `background-image` with cream gradients
   painted over it. A cream wash hides whatever is underneath, including
   this section's gold hex texture (.eqc-section--textured::before), so the
   photo ends the wash in a flat cream field. Masking fades the photo's own
   alpha instead, so the cream AND the hex texture read through the fade and
   the panel genuinely dissolves into the section's ground. Two gradients
   composited with `mask-composite: intersect` is the same idiom this file
   already uses for the girih lattice fields (:851, :2060, :2996, :3521 and
   shell.css:630).

   `::after` specifically: .eqc-section--textured::before (:2505) already
   owns this element's only `::before`, and a second one would silently lose
   to it (the one-pseudo-per-element trap noted there and at :3403).
   `::after` is free on this element in every stylesheet.

   The photo is pre-cropped to 797x1374 (tools/06-media.php
   $crops['hero-bg'], from the portrait Hero_new1.png, feathered first
   by tools/graphics/feather-hero-bg.mjs). A landscape source in a box this
   tall forced `cover` to discard most of its width, which kept throwing the
   mosque dome out of frame.

   The panel's geometry is derived (see PINNED GEOMETRY below); the mask and
   wash stops were tuned live against the reference at 320/390/768. */
@media (max-width: 56.25rem) {
	.eqc-section--hero::after {
		content: '';
		position: absolute;
		/* PINNED GEOMETRY (client, 2026-09-23: "the rehal must always be at this
		   designated place at all the screens of the mobiles or tablet").

		   The pin is `background-position: 63.8% 69%` -- the rehal's own centre
		   inside the artwork, found by density-mapping the stand's wood against
		   QA/qa-15092026/Hero_new1.png (the stand occupies x 38.5%-89.1%,
		   y 58%-80% of the 797x1374 crop). A percentage background-position
		   aligns THAT point of the image with the SAME point of the box,
		   whatever `cover` scaled and cropped to get there. So the rehal lands
		   63.8% across and 69% down this panel on every screen, and cropping can
		   no longer move it -- only what surrounds it changes.
		   The panel is then placed so that point falls where the client drew it
		   (box 2 of QA/qa-15092026/qa1.png, centred at 79% of the width).
		   Flush right it sits at (100% - w) + 0.638 w, so w = 58% puts it at
		   79%, and the photo's fade begins at 42% of the width -- a little left
		   of centre, so the blend has room to be gradual (client, 2026-09-23). A 65%-tall panel anchored to the section's top puts the
		   rehal at 0.69 x 65% = 45% of the height.
		   The crop was widened to the LEFT (tools/06-media.php) rather than the
		   panel stretched or the art scaled: with the crop's right edge fixed
		   at the source's own, crop and panel widen in proportion and `cover`
		   lands on the same scale, so the rehal keeps its size and place.
		   Crop, panel width, background-position-x and the REHAL/ART constants
		   in tests/visual/hero-rehal.mjs move together.

		   Sizing the panel in vw with a locked aspect-ratio was tried first and
		   is wrong: the hero's own height/width ratio runs from 2.53 at 320px to
		   0.63 at 860px (the copy stops wrapping as it widens), so a
		   width-driven panel grew taller than the section itself and pushed the
		   rehal clean out of the bottom at tablet sizes.
		   tests/visual/hero-rehal.mjs asserts all of this; don't retune by hand
		   without re-running it. */
		inset-block-start: 0;
		inset-inline: auto 0;
		inline-size: 58%;
		block-size: 65%;
		/* TONE-MATCHED BLEND (client, 2026-09-23: "no messy or subtle lines").
		   The mask below fades the photo's opacity, but opacity alone cannot
		   hide an edge where the photo itself is DARK -- the crop's left edge
		   is a shadowed pillar, its top is carved wood, its bottom dark
		   carpet -- because a light-to-dark change still reads as a line
		   however soft its alpha. So the first three layers wash the photo's
		   own edges toward the page cream as well: the eye then travels cream
		   -> pale photo -> full photo, never cream -> dark wood. The washes
		   sit INSIDE the masked panel, so where the mask fades out they fade
		   with it and the section's hex texture still reads through. Each wash
		   reaches a little past its mask ramp (left: 54% of the panel against
		   the ramp's 43%) so there is no point where one stops and the other
		   is still going. Eased stops, for the same Mach-band reason as the
		   mask. The photo is the LAST layer; hero-rehal.mjs reads its size and
		   position from that layer. */
		background-image:
			linear-gradient(to right, var(--eqc-cream-100) 0%, color-mix(in srgb, var(--eqc-cream-100) 86%, transparent) 9%, color-mix(in srgb, var(--eqc-cream-100) 64%, transparent) 18%, color-mix(in srgb, var(--eqc-cream-100) 38%, transparent) 28%, color-mix(in srgb, var(--eqc-cream-100) 17%, transparent) 38%, color-mix(in srgb, var(--eqc-cream-100) 5%, transparent) 46%, transparent 54%),
			linear-gradient(to bottom, var(--eqc-cream-100) 0%, color-mix(in srgb, var(--eqc-cream-100) 55%, transparent) 8%, color-mix(in srgb, var(--eqc-cream-100) 18%, transparent) 18%, transparent 28%),
			linear-gradient(to top, var(--eqc-cream-100) 0%, color-mix(in srgb, var(--eqc-cream-100) 60%, transparent) 10%, color-mix(in srgb, var(--eqc-cream-100) 22%, transparent) 22%, transparent 34%),
			url('../img/hero-bg.webp');
		background-repeat: no-repeat;
		background-position: 0 0, 0 0, 0 0, 63.8% 69%;
		background-size: 100% 100%, 100% 100%, 100% 100%, cover;
		/* First gradient dissolves the panel's left edge into the cream the
		   heading sits on; second lifts its bottom edge off the ground below
		   the carpet; third does the same for the top edge, which the pinned
		   geometry puts partway down the section, where an unfaded panel drew
		   a hard horizontal seam straight across the arch. Intersect so a pixel
		   survives only where ALL of them keep it, which is what rounds the
		   fade's corners.
		   Every ramp is EASED (many stops approximating a smoothstep), not
		   linear. A linear ramp starts and ends with a kink in its slope,
		   which the eye reads as an edge (Mach banding), and it left ~17%
		   alpha on the dark pillar shadow at the crop's own left edge -- a
		   visible vertical line down the hero (client, 2026-09-23). Eased,
		   that pillar gets ~2% and the edge has nothing to draw.
		   The left ramp is the same eased curve over the panel's first 43%:
		   with the panel spanning 42%-100% of the page, the photo emerges from
		   42% and is fully opaque from ~67% (client, 2026-09-23: the fade
		   starts further left for a smoother blend). A mask fades opacity
		   only, so a hard edge inside the ramp still reads as a line -- the
		   wall/pillar corner of the arch did, at ~59%. That is fixed in the
		   image, not here: tools/graphics/feather-hero-bg.mjs blurs the
		   artwork progressively across the fade (soft at its left edge, sharp
		   by the arch), so detail dissolves where the photo does.
		   The bottom fade still starts late (26%) on purpose: an earlier one
		   ghosted straight through the open Quran instead of only
		   dissolving the carpet under it. */
		-webkit-mask-image:
			linear-gradient(to right, transparent 0%, rgb(0 0 0 / 0.02) 6%, rgb(0 0 0 / 0.1) 13.2%, rgb(0 0 0 / 0.32) 21.5%, rgb(0 0 0 / 0.62) 29.8%, rgb(0 0 0 / 0.86) 37%, #000 43%),
			linear-gradient(to top, transparent 0%, rgb(0 0 0 / 0.06) 6%, rgb(0 0 0 / 0.3) 12%, rgb(0 0 0 / 0.68) 18%, #000 26%),
			linear-gradient(to bottom, transparent 0%, rgb(0 0 0 / 0.1) 5%, rgb(0 0 0 / 0.45) 10%, rgb(0 0 0 / 0.85) 15%, #000 20%);
		mask-image:
			linear-gradient(to right, transparent 0%, rgb(0 0 0 / 0.02) 6%, rgb(0 0 0 / 0.1) 13.2%, rgb(0 0 0 / 0.32) 21.5%, rgb(0 0 0 / 0.62) 29.8%, rgb(0 0 0 / 0.86) 37%, #000 43%),
			linear-gradient(to top, transparent 0%, rgb(0 0 0 / 0.06) 6%, rgb(0 0 0 / 0.3) 12%, rgb(0 0 0 / 0.68) 18%, #000 26%),
			linear-gradient(to bottom, transparent 0%, rgb(0 0 0 / 0.1) 5%, rgb(0 0 0 / 0.45) 10%, rgb(0 0 0 / 0.85) 15%, #000 20%);
		-webkit-mask-composite: source-in;
		mask-composite: intersect;
		pointer-events: none;
		/* Above the texture ::before (also 0, declared earlier) and below the
		   content, which .eqc-section--textured > .e-con lifts to 1 (:2523). */
		z-index: 0;
	}
	/* The narrowest phones: at 320px the hero is 2.6x taller than it is wide,
	   so a 65%-tall panel made `cover` scale the art up until the rehal lost
	   its right leg past the screen edge. A shorter panel set
	   lower keeps the SAME pin -- top + 0.69 x height = 6.9% + 0.69 x 55% =
	   44.85%, exactly the 0.69 x 65% used above -- while the smaller box lets
	   the whole stand fit. tests/visual/hero-rehal.mjs checks both. */
	@media (max-width: 22rem) {
		.eqc-section--hero::after { inset-block-start: 6.9%; block-size: 55%; }
	}
	/* The photo lives in the section-level panel above at every width; on
	   desktop the empty .eqc-hero-media column only holds the grid's right
	   half open so the copy keeps its 50.5% measure. Stacked on a phone it
	   has nothing to hold, so it goes. */
	.eqc-section--hero .eqc-hero-media { display: none; }

	/* Keep the description clear of the photo panel (client, 2026-09-23, box 1
	   in QA/qa-15092026/qa1.png: the copy ran the full width and collided with
	   the rehal). 66% is that box's measured right edge, and it stops short of
	   the panel's solid edge at 83%. A spatial constraint, not a typographic
	   one, so it is a percentage of the column rather than a `ch` measure like
	   the step cards (:4331) or the footer blurb (shell.css:954).

	   The size has to come down with it, and --eqc-fs-body-l cannot do it:
	   clamp(17px, calc(16.5 * var(--eqc-u)), 27px) meets its 17px floor at
	   every phone width, because --eqc-u is itself frozen at 0.70px below a
	   915px viewport (tokens.css:112). Frozen at 17px inside a 66% column the
	   two sentences broke across five ragged lines. A vw term restores the
	   scaling the frozen unit cannot give: it holds the reference's two-lines-
	   per-sentence break down to 360px, and the 13.5px floor keeps it legible
	   at 320px. The cap returns it to the token's own value before the layout
	   switches to the desktop hero. */
	.eqc-section--hero .eqc-hero-text .eqc-body-l {
		max-inline-size: 66%;
		font-size: clamp(13.5px, 3.6vw, 17px);
	}

	/* The hexagon field reads as a hard grid behind this hero on a phone
	   (client, 2026-09-23). Toned down here only -- the shared rule at :2516 is
	   left alone, so the kids/career tight sections, the course-detail sections
	   and this hero's own desktop rendering all keep the full 0.1. */
	.eqc-section--hero.eqc-section--textured::before { opacity: 0.04; }
}

/* Desktop/laptop hero photo panel (client, 2026-09-26, marked screenshot
   QA/qa-15092026/image22.png): the landscape Hero_new.png, not the mobile
   portrait; touching the nav bar; down to the trust panel; visible up to a
   line through the H1's "Online" (~41% of the screen) and covering the whole
   right side, with no hex texture showing there.
   The same pseudo-element as the mobile panel above, with its own box and
   its own file, hero-bg-desktop.webp (Hero_new.png uncropped, 1672x941).
   The landscape art suits this box: its left ~60% is plain wall and floor,
   so the fade dissolves wall into the cream ground with no hard edge in it,
   and between 901px and ~2500px the box is narrower than the art's 1.78
   ratio, so `cover` scales it by the section's height and only ever crops
   plain wall off the left. The arch, the window and the rehal stay whole.
   - Box: the full section height plus a lift behind the header, down to the
     trust panel. Top and bottom ramps (smootherstep, as below): beside the
     nav pill the photo fades up into the page ground; under the pill it is
     already well visible at the pill's edge (no cream gap -- the round-3
     ramp started inside the section and left one) and full 80u lower; at
     the bottom it fades out over 80u instead of stopping in a line.
   - Width: flush right from 30% of the screen. The mask ramps from 30% to
     50% (the panel's first 28.6%) with smootherstep (6t^5 - 15t^4 + 10t^3,
     sampled every tenth) -- flat at both ends, so no Mach band where it
     starts or stops -- which puts the photo at ~60% opacity on the client's
     41% line and fully opaque from 50%. The wall there is itself near-cream.
   - Position `100% 72%`: pinned to the right edge; the 72% (the rehal's row)
     only matters past ~2500px, where the box outgrows the art's ratio and
     `cover` crops top and bottom instead.
   - The hex texture (.eqc-section--textured::before) fades out over the same
     30% -> 50% with the inverted ramp, so photo and texture cross-fade and
     neither shows through the other on the right.
   tests/visual/hero-rehal.mjs asserts all of it from an alpha map. */
@media (min-width: 56.26rem) {
	.eqc-section--hero::after {
		content: '';
		position: absolute;
		/* Lifted above the section, behind the header: the section starts at
		   the nav pill's mid-height, so its own top edge showed as a hard line
		   beside the pill. The photo fades in from the page top (never more
		   than ~95px above the section) through the header's bottom (27u into
		   the section), where it is already ~60-80% strong -- touching the nav,
		   but not starting at full strength, which read as cut off by the pill
		   -- to fully opaque 80u below it. The bottom fades out over its last
		   80u into the trust panel. Anything lifted above the page top is
		   simply off-screen. */
		--_lift: 110px;
		--_top-ramp: calc(var(--_lift) + 107 * var(--eqc-u));
		--_bottom-ramp: calc(80 * var(--eqc-u));
		inset-block: calc(-1 * var(--_lift)) 0;
		inset-inline: auto 0;
		inline-size: 70%;
		background-image: url('../img/hero-bg-desktop.webp');
		background-repeat: no-repeat;
		background-position: 100% 72%;
		background-size: cover;
		-webkit-mask-image: linear-gradient(to right, transparent 0%, rgb(0 0 0 / 0.009) 2.9%, rgb(0 0 0 / 0.058) 5.7%, rgb(0 0 0 / 0.163) 8.6%, rgb(0 0 0 / 0.317) 11.4%, rgb(0 0 0 / 0.5) 14.3%, rgb(0 0 0 / 0.683) 17.1%, rgb(0 0 0 / 0.837) 20%, rgb(0 0 0 / 0.942) 22.9%, rgb(0 0 0 / 0.991) 25.7%, #000 28.6%), linear-gradient(to bottom, transparent 0, rgb(0 0 0 / 0.009) calc(var(--_top-ramp) * 0.1), rgb(0 0 0 / 0.058) calc(var(--_top-ramp) * 0.2), rgb(0 0 0 / 0.163) calc(var(--_top-ramp) * 0.3), rgb(0 0 0 / 0.317) calc(var(--_top-ramp) * 0.4), rgb(0 0 0 / 0.5) calc(var(--_top-ramp) * 0.5), rgb(0 0 0 / 0.683) calc(var(--_top-ramp) * 0.6), rgb(0 0 0 / 0.837) calc(var(--_top-ramp) * 0.7), rgb(0 0 0 / 0.942) calc(var(--_top-ramp) * 0.8), rgb(0 0 0 / 0.991) calc(var(--_top-ramp) * 0.9), #000 var(--_top-ramp)), linear-gradient(to top, transparent 0, rgb(0 0 0 / 0.009) calc(var(--_bottom-ramp) * 0.1), rgb(0 0 0 / 0.058) calc(var(--_bottom-ramp) * 0.2), rgb(0 0 0 / 0.163) calc(var(--_bottom-ramp) * 0.3), rgb(0 0 0 / 0.317) calc(var(--_bottom-ramp) * 0.4), rgb(0 0 0 / 0.5) calc(var(--_bottom-ramp) * 0.5), rgb(0 0 0 / 0.683) calc(var(--_bottom-ramp) * 0.6), rgb(0 0 0 / 0.837) calc(var(--_bottom-ramp) * 0.7), rgb(0 0 0 / 0.942) calc(var(--_bottom-ramp) * 0.8), rgb(0 0 0 / 0.991) calc(var(--_bottom-ramp) * 0.9), #000 var(--_bottom-ramp));
		mask-image: linear-gradient(to right, transparent 0%, rgb(0 0 0 / 0.009) 2.9%, rgb(0 0 0 / 0.058) 5.7%, rgb(0 0 0 / 0.163) 8.6%, rgb(0 0 0 / 0.317) 11.4%, rgb(0 0 0 / 0.5) 14.3%, rgb(0 0 0 / 0.683) 17.1%, rgb(0 0 0 / 0.837) 20%, rgb(0 0 0 / 0.942) 22.9%, rgb(0 0 0 / 0.991) 25.7%, #000 28.6%), linear-gradient(to bottom, transparent 0, rgb(0 0 0 / 0.009) calc(var(--_top-ramp) * 0.1), rgb(0 0 0 / 0.058) calc(var(--_top-ramp) * 0.2), rgb(0 0 0 / 0.163) calc(var(--_top-ramp) * 0.3), rgb(0 0 0 / 0.317) calc(var(--_top-ramp) * 0.4), rgb(0 0 0 / 0.5) calc(var(--_top-ramp) * 0.5), rgb(0 0 0 / 0.683) calc(var(--_top-ramp) * 0.6), rgb(0 0 0 / 0.837) calc(var(--_top-ramp) * 0.7), rgb(0 0 0 / 0.942) calc(var(--_top-ramp) * 0.8), rgb(0 0 0 / 0.991) calc(var(--_top-ramp) * 0.9), #000 var(--_top-ramp)), linear-gradient(to top, transparent 0, rgb(0 0 0 / 0.009) calc(var(--_bottom-ramp) * 0.1), rgb(0 0 0 / 0.058) calc(var(--_bottom-ramp) * 0.2), rgb(0 0 0 / 0.163) calc(var(--_bottom-ramp) * 0.3), rgb(0 0 0 / 0.317) calc(var(--_bottom-ramp) * 0.4), rgb(0 0 0 / 0.5) calc(var(--_bottom-ramp) * 0.5), rgb(0 0 0 / 0.683) calc(var(--_bottom-ramp) * 0.6), rgb(0 0 0 / 0.837) calc(var(--_bottom-ramp) * 0.7), rgb(0 0 0 / 0.942) calc(var(--_bottom-ramp) * 0.8), rgb(0 0 0 / 0.991) calc(var(--_bottom-ramp) * 0.9), #000 var(--_bottom-ramp));
		-webkit-mask-composite: source-in;
		mask-composite: intersect;
		pointer-events: none;
		z-index: 0;
	}
	.eqc-section--hero.eqc-section--textured::before {
		-webkit-mask-image: linear-gradient(to right, #000 30%, rgb(0 0 0 / 0.991) 32%, rgb(0 0 0 / 0.942) 34%, rgb(0 0 0 / 0.837) 36%, rgb(0 0 0 / 0.683) 38%, rgb(0 0 0 / 0.5) 40%, rgb(0 0 0 / 0.317) 42%, rgb(0 0 0 / 0.163) 44%, rgb(0 0 0 / 0.058) 46%, rgb(0 0 0 / 0.009) 48%, transparent 50%), url('../svg/hex-tessellation.svg');
		mask-image: linear-gradient(to right, #000 30%, rgb(0 0 0 / 0.991) 32%, rgb(0 0 0 / 0.942) 34%, rgb(0 0 0 / 0.837) 36%, rgb(0 0 0 / 0.683) 38%, rgb(0 0 0 / 0.5) 40%, rgb(0 0 0 / 0.317) 42%, rgb(0 0 0 / 0.163) 44%, rgb(0 0 0 / 0.058) 46%, rgb(0 0 0 / 0.009) 48%, transparent 50%), url('../svg/hex-tessellation.svg');
		-webkit-mask-size: 100% 100%, calc(52 * var(--eqc-u)) calc(90 * var(--eqc-u));
		mask-size: 100% 100%, calc(52 * var(--eqc-u)) calc(90 * var(--eqc-u));
		-webkit-mask-repeat: no-repeat, repeat;
		mask-repeat: no-repeat, repeat;
		-webkit-mask-composite: source-in;
		mask-composite: intersect;
	}
	/* The photo's carpet runs under the bottom of the copy column. Every other
	   element there sits on its own solid chip or button; the social-proof
	   line was bare text and fell to 1.5:1 on the carpet at 1024. It gets the
	   hero eyebrow's white pill (.eqc-eyebrow--hero) instead of the photo
	   being cut back. `align-self` because the copy column is a flex column,
	   which would stretch the pill to its full width. Desktop only: on phones the
	   photo sits above the copy, never behind this line. */
	.eqc-section--hero .eqc-hero-trust {
		align-self: flex-start;
		inline-size: fit-content;
		/* One row: the padding would otherwise push the text under the
		   avatars in the narrow 901-1180px column. */
		flex-wrap: nowrap;
		gap: calc(12 * var(--eqc-u));
		padding: calc(6 * var(--eqc-u)) calc(18 * var(--eqc-u)) calc(6 * var(--eqc-u)) calc(6 * var(--eqc-u));
		background: var(--eqc-white);
		border: 1px solid var(--eqc-border);
		border-radius: var(--eqc-radius-pill);
	}
}

/* Hero column rhythm. Reference ink gaps down the column measure 33 / 26 / 27
   / 30 / 24 / 32 native px; as flex box-gaps (leading already inside each
   box) that lands at 22 units. */
.eqc-hero-text { gap: calc(22 * var(--eqc-u)); }
a.eqc-btn .eqc-icon, button.eqc-btn .eqc-icon,
.elementor-widget-button.eqc-btn .elementor-button .eqc-icon {
	width: var(--eqc-icon-md);
	height: var(--eqc-icon-md);
}

/* Inside the trust panel the four tiles are NOT cards: they are plain
   columns separated by full-height hairlines. Measured off the reference:
   icon 34 across at x155, text block x218-330 (112 wide), which is what wraps
   both the title and the caption onto two lines. Constraining that text width
   reproduces the reference's line breaks; without it the title fits on one
   line and the tile reads completely differently. */
.eqc-trust-panel .eqc-trust-tile {
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0 calc(20 * var(--eqc-u));
	gap: calc(14 * var(--eqc-u));
	align-items: flex-start;
	/* Cancel the tile-level green plate here specifically: the PANEL these
	   tiles sit inside already carries its own (.eqc-trust-panel is
	   .eqc-plate--green), and these tiles have no background/border for a
	   second offset shadow to read against — it would just be a stray green
	   shape with nothing behind it. */
	box-shadow: none;
}
/* No max-width here. The reference's four tiles break at points no single
   width can reproduce ("Your child's safety is | our top priority" wraps at
   ~105 native while "Recognize your progress | with achievement" runs to
   ~150), so the breaks are carried in the copy via eqc_trust_tile()'s "|"
   separator - content, not styling, per TASK-DESIGN-PARITY.md 2. */
.eqc-trust-panel .eqc-trust-tile .eqc-icon {
	width: calc(34 * var(--eqc-u));
	height: calc(34 * var(--eqc-u));
}
.eqc-trust-panel .eqc-trust-tile:hover { transform: none; box-shadow: none; }
/* Hairlines run the full height of the panel's content box, as in the
   reference; the shared .eqc-grid--trust rule only draws a plain edge. */
.eqc-trust-panel > * + * { border-inline-start: 1px solid var(--eqc-border); }
/* Four across (above 75rem): each column is at least as wide as its own copy
   at the "|" line breaks, and only the space left over is shared equally.
   Equal 1fr columns gave "Recognize your progress" 142px of the ~160px it
   needs at 1201-1300px, so the fourth tile wrapped to five lines beside
   four-line neighbours. */
.eqc-trust-panel.eqc-grid--trust { grid-template-columns: repeat(4, minmax(max-content, 1fr)); }
.eqc-trust-panel .eqc-trust-tile-title { line-height: 1.3; }
.eqc-trust-panel .eqc-trust-tile p { line-height: 1.45; }

/* ---------- About section ---------- */

/* A fine girih lattice, strongest at the far left edge and faded out well
   before the text column; the right half is clean. A coarser tile with a
   softer fade (44u at 48%) reads as a large honeycomb under all the copy. */
.eqc-section--about::before {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--eqc-gold-500);
	/* The lattice carries across roughly the left half before it dissolves,
	   rather than dying out a third of the way in. 0.10 keeps the mesh
	   present without competing with the collage; 0.13 overpowers it. */
	/* A multi-stop fade, so the mesh dissolves gradually into the cream
	   ground rather than reading as a mesh block with an edge; a two-stop
	   ramp from 14% to 52% leaves a visible cliff. */
	opacity: 0.10;
	mask-image: linear-gradient(90deg, #000 0%, #000 8%, rgba(0, 0, 0, 0.55) 28%, transparent 55%), url('../svg/girih-lattice-fine.svg');
	mask-size: 100% 100%, calc(30 * var(--eqc-u)) calc(30 * var(--eqc-u));
	mask-repeat: no-repeat, repeat;
	/* No -webkit-mask-composite pair here (unlike the -webkit-/unprefixed
	   mask-image pairs elsewhere in this file): evergreen WebKit/Blink read
	   the unprefixed `mask-composite` below directly and never consult the
	   legacy keyword-based prefixed property once it's present, so a
	   `-webkit-mask-composite: source-in;` line here was dead on every
	   browser this project targets — removed rather than kept as inert
	   cargo-culted compat. */
	mask-composite: intersect;
	pointer-events: none;
}
/* No keel-arch watermark behind the collage; it competes with the images.
   The girih mesh above (::before) stays; only this ::after is gone. */
.eqc-ornament-rail {
	display: flex;
	align-items: center;
	gap: calc(12 * var(--eqc-u));
	color: var(--eqc-gold-500);
}
.eqc-ornament-rail::before,
.eqc-ornament-rail::after {
	content: '';
	flex: 1;
	height: 1px;
	background: currentColor;
}
.eqc-ornament-rail > svg { flex: none; width: calc(35 * var(--eqc-u)); height: auto; }
.eqc-courses-closing { width: min(100%, calc(470 * var(--eqc-u))); margin: calc(22 * var(--eqc-u)) auto 0; }
.eqc-courses-closing > svg { width: calc(42 * var(--eqc-u)); }

/* Right column measured 608 of the 1119u content column (54.3%); the collage
   fills the rest and deliberately BLEEDS left of the column, running to x95
   against the column's own left edge at x317. That overflow is the
   composition, not an accident, so the media column is allowed to exceed its
   track rather than being clipped to it. */
.eqc-about-grid { gap: calc(21 * var(--eqc-u)); align-items: center; }
.eqc-about-grid > .eqc-about-media { flex: 0 1 45.7%; min-width: 0; }
.eqc-about-grid > .eqc-about-text { flex: 0 0 54.3%; min-width: 0; }
.eqc-about-grid,
.eqc-about-grid > .eqc-about-media,
.eqc-about-grid > .eqc-about-text { padding-inline: 0; }
.eqc-about-text { gap: calc(26 * var(--eqc-u)); }

/* Ornament rail across the top of the column - the reference uses this
   instead of the pill eyebrow the other sections carry. */
.eqc-about-rail { width: 100%; color: var(--eqc-gold-500); line-height: 0; }
.eqc-about-rail .eqc-divider-svg { width: 100%; height: auto; }
/* Small centred ornament under the heading. */
/* `align-self: center` has no effect here: .eqc-about-rule is nested inside
   its Elementor html-widget wrapper, not itself a direct flex child of
   .eqc-about-text, so it never centres and hangs to the left.
   margin-inline:auto centres any narrower block regardless of the parent's
   own layout mode. */
.eqc-about-rule { color: var(--eqc-gold-500); line-height: 0; display: block; margin-inline: auto; }
.eqc-about-rule .eqc-divider-svg { width: calc(200 * var(--eqc-u)); display: block; margin-inline: auto; }

/* The heading is a display size, larger than the other sections' h2, and is
   a single colour - the reference gives it no bronze tail. */
.eqc-display-heading,
h2.eqc-display-heading { font-size: var(--eqc-fs-display-xl); line-height: 1.12; color: var(--eqc-heading); }

/* Stats: label above value, each icon in a rosette-framed disc, full-height
   hairlines between the three. */
.eqc-about-stats {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	width: 100%;
	align-items: start;
}
.eqc-about-stat {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: calc(7 * var(--eqc-u));
	text-align: center;
	padding-inline: calc(12 * var(--eqc-u));
}
/* Structural, not a class-sibling selector: two of the three tiles are now
   Elementor Counter widgets wrapped in their own container, one level
   deeper than the plain-markup third tile, so `.eqc-about-stat +
   .eqc-about-stat` would miss that pairing. Targeting the grid's own direct
   children draws the same three dividers regardless of what is inside each
   cell (client request 2026-09-17: counter animations). */
.eqc-about-stats > *:not(:first-child) { border-inline-start: 1px solid var(--eqc-border); }
.eqc-about-stat__disc {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: calc(56 * var(--eqc-u));
	height: calc(56 * var(--eqc-u));
	border-radius: 50%;
	background: var(--eqc-cream-100);
	border: 1px solid var(--eqc-border-strong);
	margin-block-end: calc(4 * var(--eqc-u));
}
.eqc-about-stat__disc .eqc-icon { width: calc(26 * var(--eqc-u)); height: calc(26 * var(--eqc-u)); color: var(--eqc-gold-700); }
.eqc-about-stat__label { font-size: var(--eqc-fs-small); line-height: 1.4; color: var(--eqc-muted); }
.eqc-about-stat__value { font-family: var(--eqc-font-body); font-size: var(--eqc-fs-h3); line-height: 1; font-weight: 700; color: var(--eqc-heading); }
/* The three tiles are built two ways -- Counter widgets inside Elementor
   containers, and one plain-markup tile -- so every metric that decides
   where the icon, label and value land is pinned here for both: no
   container padding above the icon (Elementor's default 10px pushed the two
   counter tiles below the third), the same label/value line-heights, and
   the same gap between label and value (client, 2026-09-19: "same
   formatting and alignment across the 3"). */
.e-con.e-con.eqc-about-stat { padding-block: 0; }
/* The two numeric tiles (Students Taught, Countries Served) are native
   Elementor Counter widgets now, so the client can edit/animate them in the
   editor (client, 2026-09-17). "1-o-1 Private Quran Lessons" is not a
   number and keeps the plain __label/__value markup above. Counter's own
   DOM is title-then-number with `title_position: before`, so this mirrors
   the label-above-value order without touching eqc_about_stat(). */
.eqc-about-stat .elementor-counter { align-items: center; gap: calc(7 * var(--eqc-u)); }
/* Three classes, not two: Elementor's Number/Title style controls both carry
   a `global` default (Kit Primary/Secondary color + typography), so it
   ALWAYS writes a `.elementor-element-<id> .elementor-counter-title`-shaped
   rule per instance regardless of whether an editor customized it -- not
   just when a value is set. That rule is two classes deep, the same as a
   bare `.eqc-about-stat .elementor-counter-title`, and Elementor's own
   per-post CSS loads after the theme stylesheet, so equal specificity means
   it always won. Chaining the real ancestor grid class in front
   (`.eqc-about-stats .eqc-about-stat ...`) is still an accurate selector
   and outranks it. Colour is NOT set here: it is the widget's own setting
   (eqc_counter()), so an editor's colour change applies. */
.eqc-about-stats .eqc-about-stat .elementor-counter-title { font-family: var(--eqc-font-body); font-size: var(--eqc-fs-small); justify-content: center; line-height: 1.4; font-weight: 400; }
.eqc-about-stats .eqc-about-stat .elementor-counter-number-wrapper {
	font-family: var(--eqc-font-body);
	font-size: var(--eqc-fs-h3);
	font-weight: 700;
	text-align: center;
	font-variant-numeric: tabular-nums;
	justify-content: center;
}
/* Phones (QA/qa-15092026/1.png): the three labels must wrap to the same
   number of lines. "Private Quran Lessons" is the longest, and at 14px in a
   ~75px tile it broke onto three lines beside two-line neighbours. The row
   is its own container, so the labels scale with the tile width -- sized so
   "Private Quran" still fits one line down to ~350px -- and the tiles give
   up most of their side padding at this width. Below that the 12px floor
   wins over symmetry: legibility first. */
.eqc-about-stats { container-type: inline-size; }
@container (max-width: 22rem) {
	.eqc-about-stats .eqc-about-stat { padding-inline: 2px; }
	.eqc-about-stats .eqc-about-stat__label,
	.eqc-about-stats .eqc-about-stat .elementor-counter-title { font-size: clamp(12px, 4.3cqi, 14px); }
}

/* Collage: the large Quran page offset right, with the child overlapping its
   lower left. The figure margin reset must come BEFORE the main's auto
   margin — the other way round it cancelled it, the main sat flush left and
   covered the child exactly, which read as a missing image. */
.eqc-about-collage { position: relative; width: 100%; padding-block: 4% 9%; }
.eqc-about-collage figure { margin: 0; }
/* The keel-framed Quran page is the ANCHOR of this collage: it dominates the
   column while the alphabet cartouche and the child photo are small pieces
   laid over its corners. At 72% the three images read as similar weights; 88%
   restores the hierarchy. `margin-inline: auto 2%` keeps a slight left shift
   now that the panel is wider. */
.eqc-about-collage .eqc-about-collage__main {
	width: 88%;
	/* Offset with `left`, NOT a margin. Elementor's own frontend reset
	   `.elementor .elementor-widget:not(...):not(...) figure { margin: 0 }`
	   scores (0,4,1) and silently zeroes any margin-inline:auto set here — the
	   figure stayed pinned to the column's left edge no matter what this rule
	   asked for. The element is already `position: relative`, so `left` moves
	   it without competing with that reset at all.
	   Pushed right so the child cartouche at left:0 lands over the keel arch's
	   LEFT side rather than beside it. */
	left: 12%;
	/* Taller than the arch's native 559/629. The mask stretches with the box,
	   so this is a deliberate, modest vertical extension — "slightly
	   vertically bigger" — not a re-cut of the contour. */
	aspect-ratio: 559 / 706;
}
/* The two small panels sit at the extremes of the taller main arch, so the
   vertical run between them stays open instead of the three images crowding
   into the middle third. */
.eqc-about-collage__alphabet {
	position: absolute;
	width: 42%;
	aspect-ratio: 276 / 300;
	top: 0;
	left: 2%;
	z-index: 3;
	filter: drop-shadow(0 8px 10px rgb(20 35 27 / 12%));
}
/* This panel holds the alphabet chart image. The cartouche mask and its gold
   frame are what tie this tile to the pricing medallions and the About
   collage's other shapes, so the photo is cover-fitted inside that same
   contour. */
.eqc-alphabet-panel {
	position: relative;
	display: grid;
	place-items: center;
	width: 100%;
	height: 100%;
	background: var(--eqc-surface);
	mask: url('../svg/cartouche-alphabet-mask.svg') center / 100% 100% no-repeat;
}
/* `contain`, not `cover`: the chart is a 6-column grid of letters and a
   cover-crop cut it off mid-row, which reads as a mistake rather than a
   crop. The cartouche is portrait and the chart landscape, so contain
   leaves a little cream above and below inside the frame — which is what
   the panel's own background is there for. The inset keeps the outer
   letters clear of the cartouche's curved shoulders. */
.eqc-alphabet-panel img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	object-position: center;
	display: block;
	padding: 12% 9%;
	box-sizing: border-box;
}
.eqc-about-collage__alphabet::after {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--eqc-gold-500);
	mask: url('../svg/cartouche-alphabet-frame.svg') center / 100% 100% no-repeat;
	pointer-events: none;
}

.eqc-about-collage__child {
	position: absolute;
	left: 0;
	bottom: 0;
	width: 38%;
	z-index: 3;
}
.eqc-arch-media--cartouche {
	aspect-ratio: 246 / 423;
	border: 0;
	border-radius: 0;
	overflow: visible;
	filter: drop-shadow(0 8px 10px rgb(20 35 27 / 12%));
}
.eqc-arch-media--cartouche img { mask: url('../svg/cartouche-child-mask.svg') center / 100% 100% no-repeat; }
.eqc-arch-media--cartouche::before {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--eqc-gold-500);
	mask: url('../svg/cartouche-child-frame.svg') center / 100% 100% no-repeat;
	z-index: 2;
	pointer-events: none;
}

/* Dark-green CTA with its icon in a filled disc, as the reference draws
   "More About Us" / "Book a Free Trial". Reuses the shared .eqc-btn box;
   only the skin differs.
   Element-qualified like every other .eqc-btn variant above. A bare
   `.eqc-btn--green` selector also matches an Elementor button widget's
   wrapper div, which carries the same class, painting a green
   background/border onto the wrapper while the real `.elementor-button`
   anchor inside keeps Elementor's default skin — a green corner border
   around an otherwise unstyled button. */
a.eqc-btn--green, button.eqc-btn--green,
.elementor-widget-button.eqc-btn--green .elementor-button {
	background: var(--eqc-bronze-700);
	color: var(--eqc-white);
	border-color: var(--eqc-green-800);
}
a.eqc-btn--green:hover, button.eqc-btn--green:hover,
.elementor-widget-button.eqc-btn--green .elementor-button:hover { background: var(--eqc-bronze-700); border-color: var(--eqc-green-900); }
.eqc-btn--icon-disc .eqc-icon {
	box-sizing: content-box;
	padding: calc(7 * var(--eqc-u));
	border-radius: 50%;
	background: var(--eqc-gold-500);
	color: var(--eqc-green-900);
}

@media (max-width: 900px) {
	/* flex-basis alone never stacks these: the container's flex-wrap stays the
	   Elementor default (nowrap), so with text's flex-shrink:0 demanding its
	   full 100% basis and media's flex-shrink:1 giving way, the two columns
	   stay on one row — media crushed to a sliver, text's heading drawn over
	   it. Wrap is what breaks them onto their own rows. */
	.eqc-about-grid { flex-wrap: wrap; }
	.eqc-about-grid > .eqc-about-media,
	.eqc-about-grid > .eqc-about-text { flex-basis: 100%; }
	.eqc-about-collage .eqc-about-collage__main { width: 76%; }
	/* The two overlays are sized as a FRACTION of the collage, but they stack
	   against its HEIGHT — and the collage's height falls with its width, so
	   the same percentages that clear each other on desktop collide on a
	   phone. Measured at 390px with the desktop values: the child covered the
	   alphabet chart's bottom row by 28px. Shrunk here so the pair still reads
	   as two distinct panels laid over the arch. */
	.eqc-about-collage__alphabet { width: 34%; }
	.eqc-about-collage__child { width: 33%; }
}

/* ---------- Courses section ---------- */

/* Cards measured 313u wide on an 88u gap, three across (3x313 + 2x88 = 1115
   against the 1119u content column). The shared --eqc-grid-gap is 22u, which
   is the hero's feature-card gap, so this section carries its own. */
/* Equal gap on both axes between the course cards, overriding the
   reference's measured asymmetric row/column gap. */
.eqc-grid--courses { gap: calc(30 * var(--eqc-u)); }

/* "A quick way to choose the right course" rows link down to the matching
   course card. scroll-margin keeps the jumped-to card clear of the sticky
   header. */
/* Not a flex row with the arrow trailing inline inside
   .eqc-course-guide-a, so it floated at a different x-position on every row
   depending on that row's answer length. A grid with the arrow in its own
   fixed final column keeps question/answer/arrow aligned down the whole
   list regardless of text length. */
.eqc-course-guide-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
	align-items: center;
	gap: 0.75rem;
	padding: 1.1rem 1.5rem;
	text-decoration: none;
	transition: background-color var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-course-guide-row:hover,
.eqc-course-guide-row:focus-visible { background: var(--eqc-cream-100); }
.eqc-course-guide-row + .eqc-course-guide-row { border-top: 1px solid var(--eqc-border); }
.eqc-course-guide-q { font-weight: 600; color: var(--eqc-heading); }
.eqc-course-guide-a { color: var(--eqc-bronze-700); font-weight: 600; justify-self: end; text-align: right; }
.eqc-course-guide-arrow { display: flex; align-items: center; color: var(--eqc-bronze-700); }
/* Below ~560px three grid columns get cramped — stack question above
   answer+arrow on their own row instead. */
@media (max-width: 35rem) {
	.eqc-course-guide-row { grid-template-columns: 1fr auto; }
	.eqc-course-guide-q { grid-column: 1 / -1; }
	.eqc-course-guide-a { justify-self: start; text-align: left; }
}
.eqc-card--course { scroll-margin-top: calc(var(--eqc-header-h, 96px) + 24px); }
.eqc-card--course {
	min-height: calc(274 * var(--eqc-u));
	padding: calc(26 * var(--eqc-u)) calc(33 * var(--eqc-u));
	gap: calc(5 * var(--eqc-u));
}
.eqc-card--course p { font-size: var(--eqc-fs-body); line-height: 1.55; text-wrap: balance; }
.eqc-card--course h3 { font-size: var(--eqc-fs-course-title); }
.eqc-card--course .eqc-card-level { font-size: var(--eqc-fs-h4); }
.eqc-card--course .eqc-card-divider .eqc-divider-svg { width: calc(113 * var(--eqc-u)); }
.eqc-card--course .eqc-arrow-btn {
	width: calc(50 * var(--eqc-u));
	height: calc(50 * var(--eqc-u));
}
.eqc-card--course .eqc-card-index { width: calc(49 * var(--eqc-u)); height: calc(49 * var(--eqc-u)); font-size: var(--eqc-fs-card-index); }

/* The section heading block was capped at --eqc-content-narrow (558u), which
   forced the reference's two-line heading onto three lines. Its longest line
   measures 707u, so the block needs room for that plus its own leading. */
.eqc-section-heading { max-width: calc(760 * var(--eqc-u)); }
.eqc-section-heading--center { max-width: calc(820 * var(--eqc-u)); margin-inline: auto; }
/* Left-aligned ornate divider under the heading, 359u in the reference. */
.eqc-heading-rule--ornate .eqc-divider-svg { width: calc(240 * var(--eqc-u)); }

/* --plain (a bare gold icon and caps with no pill) and --courses (an
   oversized white tag) are retired into the shared pill, so the tag shape is
   consistent site-wide. The class names stay as near-no-ops so every page
   that already bakes them keeps rendering correctly without re-authoring.
   Delete the classes from the builders if they are ever confirmed
   permanently unwanted. */
.eqc-eyebrow--plain,
.eqc-eyebrow--courses {
	/* Ground, border and padding all come from the base rule's border-image
	   now. Re-declaring any of them here would either paint a rectangle over
	   the cartouche or reset the border widths the caps are drawn into --
	   these variants only carry colour and type. */
	color: var(--eqc-bronze-600);
	font-size: var(--eqc-fs-eyebrow);
	gap: 0.5em;
	width: auto;
	box-shadow: none;
}
.eqc-eyebrow--plain .eqc-icon,
.eqc-eyebrow--courses .eqc-icon {
	width: var(--eqc-icon-sm);
	height: var(--eqc-icon-sm);
	color: var(--eqc-gold-600);
}

/* Our render of the heading's second line runs ~10% wider than the
   reference's for the same string and size, so the block needs the extra
   room to keep the reference's two-line break rather than spilling to three. */
.eqc-section-heading { max-width: calc(820 * var(--eqc-u)); }

/* Card content is denser in the reference: 284u total against our 418u, most
   of the excess being inter-element gaps rather than type size. */
.eqc-card--course .eqc-card-level { margin: 0; line-height: 1.3; }
/* Two lines are RESERVED whether or not this title uses them. Measured at
   1440 on the home grid: "Quran Reading with Tajweed" wraps while its two row
   siblings do not, which pushed that card's divider, body copy and arrow 32px
   below theirs -- the misalignment the client photographed. Reserving the
   taller case costs a one-line card some white space and buys every card in
   the row one shared baseline. Same technique as .eqc-course-meta-tile-label. */
.eqc-card--course h3 { line-height: 1.2; margin: 0; min-block-size: 2.4em; }

/* The reference pins the course card's arrow to the bottom RIGHT, and pairs
   the index badge with a short rule to its right. */
/* The arrow sits BESIDE the body, bottom-right, which is what makes the
   reference card landscape (364 x 281 native = 1.30) rather than portrait.
   Given a row of its own it added ~65px and turned every card upright. It
   is decorative -- the whole card is one link (.eqc-card-link) -- so taking
   it out of flow costs nothing; the body reserves its column via max-width
   so long copy can never run underneath it. */
/* Course card content is centre-aligned, and the arrow is a centred
   affordance below the copy rather than a floating bottom-right accent. */
.eqc-card--course { text-align: center; align-items: center; }
.eqc-card--course > * { width: 100%; }
/* `margin-block-start: auto`, not a fixed top margin. The shared
   .eqc-card__foot { margin-top: auto } pin was being overridden here by a 6u
   top margin at higher specificity, so nothing held the arrow to the card's
   bottom edge: a card whose description ran to three lines carried its arrow
   21px below its neighbours. Minimum breathing room comes from the card's own
   `gap`, so the pin does not need a fixed margin to help it. */
.eqc-card--course .eqc-card__foot {
	position: static;
	margin-block: auto 0;
	margin-inline: auto;
	display: flex;
	justify-content: center;
}
.eqc-card--course p { max-width: 100%; }
.eqc-card--course .eqc-card-index { display: inline-flex; align-items: center; margin-inline: auto; }
/* No short gold rule beside the index number: with the card content centred
   it reads as a stray dash hanging off the badge. */

/* Centre the rosette rule under the level label. It inherits the card's
   text-align but the SVG is a block at 113u, so it needs its own centring. */
.eqc-card--course .eqc-card-divider {
	display: flex;
	justify-content: center;
	width: 100%;
}

/* "(Beginner)", "(All Levels)" read as a gold label rather than muted body
   text. gold-700 is the only gold on the ramp that clears WCAG AA on cream at
   this size (6.3:1); gold-600 would be 3.2:1 and fail. */
.eqc-card--course .eqc-card-level {
	color: var(--eqc-gold-700);
	font-weight: 600;
	letter-spacing: 0.02em;
}

/* ---------- Pricing section ---------- */

.eqc-section--pricing { position: relative; isolation: isolate; }
.eqc-section--pricing > .eqc-container { position: relative; z-index: 1; }
/* The doubled class outranks Elementor's own `.e-con::before`, which sets
   `height: max(100% + ..., 100%)` on every container's ::before. That was
   stretching this square to the full section height, so `contain` sized the
   ornament to the width but centred it vertically -- the left corner painted
   halfway down the section instead of in the corner. `height: auto` restores
   `aspect-ratio` control. ::after is untouched by Elementor and was already
   correct, which is why only one of the two looked wrong. */
.eqc-section.eqc-section--pricing::before,
.eqc-section.eqc-section--pricing::after { content: ''; }
.eqc-section.eqc-section--pricing::before,
.eqc-section.eqc-section--pricing::after,
.eqc-corner-plate {
	position: absolute;
	inset: 0 auto auto 0;
	height: auto;
	width: min(20%, calc(186 * var(--eqc-u)));
	aspect-ratio: 1;
	/* corner-ornament.svg is finished two-tone artwork (cream ground, gold
	   rules) rather than a silhouette, so it is painted directly instead of
	   tinting a mask -- a mask can only ever be one flat colour, and the
	   reference corner is two. */
	background: url('../svg/corner-ornament.svg') top left / contain no-repeat;
	/* .eqc-section--textured declares ::before on the SAME element on
	   course-detail pages, and a pseudo-element only exists once — so while
	   this rule wins the background-image, --textured's
	   `mask-image: hex-tessellation.svg` and its gold background-color
	   survive into it and perforate the left corner ornament into a faint
	   hexagon field. ::after is never touched by --textured, which is why
	   only one of the two is affected. Reset explicitly so this can never
	   inherit another section modifier's ::before again. */
	-webkit-mask-image: none;
	mask-image: none;
	background-color: transparent;
	/* Depth here is a LIGHTING problem, not a cast-shadow problem; treating it
	   as a cast shadow turns this ornament grey.
	   corner-ornament.svg is a pierced girih panel: cream tiles separated by
	   fine gold rules, with real holes between them. `drop-shadow` follows that
	   whole silhouette, so a heavy stack deposits dark ink around and THROUGH
	   every one of those holes — the cream tiles end up floating on a grey
	   ground, which reads as the tiles being raised. The intent is the
	   opposite: the gold rules stand proud, the cream tiles sit quietly
	   behind them, and the whole corner stays light against the cream
	   section.
	   So: one tight, low-alpha contact shadow for lift, and a fine light
	   highlight up-left. The relief on the rules themselves comes from the
	   asset's own gold gradients — `contrast` sharpens those against the tiles
	   instead of a shadow trying to fake them. */
	opacity: 0.62;
	filter:
		contrast(1.12) saturate(1.08)
		drop-shadow(1px 2px 2px rgb(20 35 27 / 0.16))
		drop-shadow(-1px -1px 0 rgb(255 255 255 / 0.7));
	pointer-events: none;
	z-index: 0;
}
.eqc-section.eqc-section--pricing::before { left: 0; right: auto; }
.eqc-section.eqc-section--pricing::after { right: 0; left: auto; scale: -1 1; }
/* A section only has one ::before, and a page hero already spends its own on
   .eqc-section--textured's hex field, so a hero that opens on these corners
   renders them as child elements instead (eqc_corner_plates()). --no-corners
   then keeps the pricing section further down from drawing a second pair. */
.eqc-corner-plate--tl { left: 0; right: auto; }
.eqc-corner-plate--tr { right: 0; left: auto; scale: -1 1; }
/* Girih mesh behind a tall section, tinted through a mask like every other
   ornament here (the asset's strokes are currentColor, so as a plain
   background-image it would paint black). The vertical gradient is composited
   with the tile so the weave is present where the section opens and gone
   before its lower content, which keeps it a ground rather than a pattern
   competing with the cards. */
.eqc-lattice-field {
	position: absolute;
	inset: 0;
	background-color: var(--eqc-gold-500);
	/* Higher than the hero's 0.1 hex field because this tile is half the size:
	   thinner strokes over the same cream need more alpha to read at all. The
	   gradient still drops it to about 0.09 where the cards begin. */
	opacity: 0.14;
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, rgb(0 0 0 / 0.5) 42%, transparent 76%), url('../svg/girih-lattice-fine.svg');
	mask-image: linear-gradient(to bottom, #000 0%, rgb(0 0 0 / 0.5) 42%, transparent 76%), url('../svg/girih-lattice-fine.svg');
	-webkit-mask-size: 100% 100%, calc(30 * var(--eqc-u)) calc(30 * var(--eqc-u));
	mask-size: 100% 100%, calc(30 * var(--eqc-u)) calc(30 * var(--eqc-u));
	-webkit-mask-repeat: no-repeat, repeat;
	mask-repeat: no-repeat, repeat;
	/* Keep only what both layers cover. */
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
	pointer-events: none;
	z-index: 0;
}
.eqc-section--pricing.eqc-section--no-corners::before,
.eqc-section--pricing.eqc-section--no-corners::after { content: none; }
.eqc-section--pricing .eqc-heading-rule--ornate .eqc-divider-svg { width: calc(160 * var(--eqc-u)); }
/* On /pricing/ the cards are the FIRST thing in the section — there is no
   section heading above them, the page hero carries it — so without an
   offset they start 48px down while the corner ornaments run 186px down,
   and the cards (and their overhanging medallions, which sit ~29px proud of
   the card's top edge) cut straight through the ornament. Offset
   by the ornament's own size rather than a fixed number: a percentage
   margin resolves against the containing block's WIDTH, which is exactly
   how the ornament's width — and therefore its height, it is square — is
   computed, so the two stay in step at every viewport. Sections that DO
   have a heading above the panel already clear the ornament and are
   deliberately untouched by the :first-child scope. */
.eqc-section--pricing .eqc-container > .eqc-pricing-panel:first-child {
	margin-block-start: min(20%, calc(186 * var(--eqc-u)));
}
/* /pricing/ opens the section with its intro paragraph instead. The copy
   sits IN the ornament band rather than leaving it empty,
   which is why the panel-offset rule above is scoped to a panel that is the
   first child — with the intro present it no longer applies and the cards
   move back up. The block padding is what keeps the text itself clear of
   the ornaments' inner edge. */
.eqc-pricing-intro {
	max-width: calc(760 * var(--eqc-u));
	margin-inline: auto;
	/* The bottom margin is doing real work: it is what keeps the cards'
	   overhanging medallions clear of the corner ornaments now that the
	   panel-offset rule no longer applies. Measured at 1440 — 44px left the
	   medallion 17px inside the ornament; this clears it. */
	margin-block: 0 clamp(2.75rem, 2.2rem + 2.6vw, 5rem);
	padding-inline: clamp(0rem, -6rem + 22vw, 12rem);
	text-align: center;
	font-size: var(--eqc-fs-body-l);
	line-height: 1.75;
	color: var(--eqc-text);
	box-sizing: content-box;
}
/* /pricing/ renders the shared `.eqc-benefits` panel, whose own
   margin-block-start (further down this file) carries the gap above it. */

/* Calibrated at s=1.345: the card row and benefits strip both span
   1505px = the 1119u content column. Cards 262u on a 31u gap. */
/* The section already pads; the panel padded again around the grid (32px top
   and bottom) and Elementor added its default 10px on the grid container on
   top of that -- 84px of nesting the reference does not have. */
.eqc-pricing-panel { padding-block: 0; }
.eqc-grid--pricing { grid-template-columns: repeat(4, 1fr); gap: calc(31 * var(--eqc-u)); padding-block: 0; }
@media (max-width: 61.25rem) { .eqc-grid--pricing { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 36rem) { .eqc-grid--pricing { grid-template-columns: 1fr; } }
/* Stacked cards below 61.25rem need a floor-proof row gap. Each card's
   medallion badge (.eqc-pricing-icon, `top: -1.9rem`, plus its `::before`
   shell's further `-0.42em` inset) overhangs ~36px above its own card's top
   edge — but the row gap is `calc(31 * var(--eqc-u))`, and --eqc-u floors at
   0.70px for any viewport narrower than ~915px (tokens.css), so the gap is
   stuck at ~22px there regardless of how narrow the viewport gets. A ~36px
   badge overhang inside a ~22px gap measures out to the next card's badge
   overlapping the previous card's bottom edge by 13-14px, confirmed by
   getBoundingClientRect at both the 2-column (tablet) and 1-column (phone)
   widths this breakpoint covers. Fixed with a `rem`-based row-gap — not tied
   to --eqc-u, so it never floors — sized to clear the measured overhang with
   room to spare. Only row-gap needs it; the 2-column width's column-gap is
   unaffected (badges don't overhang sideways) and keeps the `gap` shorthand
   above. */
@media (max-width: 61.25rem) { .eqc-grid--pricing { row-gap: 2.75rem; } }
/* justify-content: center moves the banner, list, divider and price row down
   together to fill the card, instead of leaving a dead band. The gap rises
   with it so the block breathes rather than clumping in the middle. */
.eqc-card--pricing {
	min-height: calc(343 * var(--eqc-u));
	/* Deeper top padding than the other three sides: the medallion overhangs
	   this edge and needs clear air between it and the "N Days/Week"
	   banner. */
	padding: calc(44 * var(--eqc-u)) calc(20 * var(--eqc-u)) calc(20 * var(--eqc-u));
	gap: calc(14 * var(--eqc-u));
	justify-content: center;
}
/* In the 4-up row the frequency banner spans nearly the card's width, and the
   award badge pinned on the featured card's corner hangs its ribbons down into
   the card's top band. At 44u the tails came within 1px of the banner at
   1024px (tests/visual/badge-geom.mjs). All four cards take the extra
   headroom, not just the featured one, so the rows stay aligned. */
@media (min-width: 61.3125rem) {
	.eqc-card--pricing { padding-block-start: calc(66 * var(--eqc-u)); }
}
/* The shared `.eqc-card__foot { margin-top: auto }` convention pins a card's
   last row to its bottom edge, which on a pricing card opens 84px of nothing
   between the divider and the price row. Every plan carries the same five
   features, so the rows line up across the four cards without being
   force-pinned. */
.eqc-card--pricing .eqc-card__foot { margin-top: 0; }

/* This heading measures 545u for its first line against the courses section's
   604u for a same-length string — the reference genuinely sets it smaller, so
   it carries its own size rather than moving the shared token. */
/* The courses section carries the largest section heading on the site;
   pricing keeps the generic one. */
.eqc-section--courses .eqc-section-heading h2 { font-size: var(--eqc-fs-h2-courses); }
/* Client, 2026-09-17, phones only: the eyebrow leads and the long heading steps
   back behind it. Purely visual -- the h2 is still an h2 and still the section's
   heading in the accessibility tree, because changing the element would put the
   heading-order skip back that the sweep's heading check was added to catch.
   The heading string carries a hardcoded <br> sized for the desktop measure; at
   this size it breaks in the wrong place, so the line break goes back to being
   the browser's decision. */
@media (max-width: 40rem) {
	.eqc-section--courses .eqc-section-heading h2 {
		font-size: var(--eqc-fs-h3);
		line-height: 1.35;
		font-weight: 600;
		color: var(--eqc-text);
	}
	.eqc-section--courses .eqc-section-heading h2 br { display: none; }
	.eqc-section--courses .eqc-section-heading .eqc-eyebrow {
		font-size: var(--eqc-fs-h2-compact);
		/* The eyebrow is a framed tag at every other size; as this section's
		   visual headline on a phone it sheds the frame and reads as type.
		   The frame's fixed height and cap-width border have to go with it, or
		   a 24-63px headline would be boxed into a 44u tag. */
		background: none;
		border: 0;
		border-image-source: none;
		padding: 0;
		block-size: auto;
		min-block-size: 0;
		letter-spacing: 0.02em;
		color: var(--eqc-heading);
		font-family: var(--eqc-font-display);
		text-transform: none;
	}
}
/* The home page's courses section carries an oversized tag, ~75% of that
   section's heading size, icon included. Derived from the heading's own
   token rather than a fixed size, so the ratio holds as the heading scales,
   and capped so the pill cannot outgrow the band it sits in. A deliberate,
   tightly-scoped exception to the shared one-tag-size rule.

   .eqc-eyebrow--lg carries the identical treatment for the one other place
   that earns it: the "Our Courses" tag above the /courses/ archive's own H1
   (Reviews.md R09 -- it was rendering at the default 13.44px against the 32px
   the same label gets on the home page). A class rather than a second
   structural selector, because that eyebrow sits in a bare div inside an
   Elementor HTML widget with no stable ancestor to hang a selector on, and
   the only id available regenerates on every save. Everything else keeps the
   one shared tag size Round 15 settled on. */
.eqc-section--courses .eqc-section-heading .eqc-eyebrow,
.eqc-eyebrow--lg {
	font-size: clamp(16px, calc(var(--eqc-fs-h2-courses) * 0.5), 32px);
	letter-spacing: 0.05em;
	padding: 0.42em 0.85em;
	gap: 0.4em;
	min-block-size: 0;
	/* The one tag allowed its own height (client, Round 20). The 3em floor the
	   section tags use would make a 32px label a 96px frame; 2em keeps the
	   cartouche's proportion without the frame dwarfing the heading. */
	--_eyebrow-h: max(var(--eqc-eyebrow-h), 2em);
}
.eqc-section--courses .eqc-section-heading .eqc-eyebrow .eqc-icon,
.eqc-eyebrow--lg .eqc-icon {
	width: 1.35em;
	height: 1.35em;
}
.eqc-section--pricing .eqc-section-heading h2 { font-size: var(--eqc-fs-h2); }

/* Dark-green "N Days/Week" banner, drawn on the site's cusped cartouche
   contour filled green — the same shape family as the pricing eyebrow and
   medallions, rather than a hexagon chamfer.
   pricing-banner-mask.svg is the solid-fill horizontal cartouche; extra
   inline padding keeps the text clear of the lobed ends. */
.eqc-pricing-banner {
	display: block;
	width: calc(214 * var(--eqc-u));
	max-width: 100%;
	margin-inline: auto;
	padding: calc(12 * var(--eqc-u)) calc(26 * var(--eqc-u));
	/* Vertical sheen rather than a flat fill: a lit top edge and a darker
	   foot are what make the lobed plaque read as raised rather than printed. */
	background: linear-gradient(180deg, #2C5843 0%, var(--eqc-green-800) 46%, #11261C 100%);
	color: var(--eqc-white);
	font-family: var(--eqc-font-display);
	font-size: var(--eqc-fs-h4);
	text-align: center;
	line-height: 1.15;
	-webkit-mask: url('../svg/pricing-banner-mask.svg') center / 100% 100% no-repeat;
	mask: url('../svg/pricing-banner-mask.svg') center / 100% 100% no-repeat;
	/* drop-shadow (not box-shadow) because the element is masked — box-shadow
	   would trace the rectangle, drop-shadow traces the lobed silhouette. The
	   pale second shadow above the shape is the bevel highlight. Element
	   opacity stays 1 or both are multiplied down. */
	filter:
		drop-shadow(0 3px 5px rgb(20 35 27 / 0.42))
		drop-shadow(0 1px 0 rgb(20 35 27 / 0.35))
		drop-shadow(0 -1px 0 rgb(255 253 249 / 0.28));
}
/* The text sits on the plaque, so it takes its own soft shadow to keep the
   engraved feel rather than floating flat on the gradient. */
.eqc-pricing-banner { text-shadow: 0 1px 2px rgb(9 20 14 / 0.55); }

/* Price row: figure, cream unit pill, dark-green arrow disc. */
.eqc-pricing-price { display: flex; align-items: center; gap: calc(12 * var(--eqc-u)); margin: 0; }
.eqc-pricing-price-figure { font-family: var(--eqc-font-display); font-size: var(--eqc-fs-price); color: var(--eqc-heading); line-height: 1; }
/* The "Month" tag is a solid beige lozenge, not a hairline outline: it takes
   the gold-100 fill and the full heading colour so it reads as prominent. */
.eqc-pricing-unit {
	background: var(--eqc-cream-200);
	border: 1px solid var(--eqc-gold-300);
	border-radius: var(--eqc-radius-pill);
	padding: calc(7 * var(--eqc-u)) calc(16 * var(--eqc-u));
	font-size: var(--eqc-fs-body);
	font-weight: 600;
	color: var(--eqc-heading);
	line-height: 1.1;
}
.eqc-card--pricing .eqc-arrow-btn {
	margin-inline-start: auto;
	width: calc(46 * var(--eqc-u));
	height: calc(46 * var(--eqc-u));
	background: var(--eqc-green-800);
	color: var(--eqc-white);
	border-color: var(--eqc-green-800);
}

/* Benefits strip: 1120 x 96u, four hairline-separated tiles. */
.eqc-benefits {
	display: grid;
	/* One row. Four is what fits: the strip's inline padding has to leave the
	   girih ornaments their own band at each end, so the tiles share roughly
	   1086px at 1440 and each label needs about 170px to stay on two lines. */
	grid-template-columns: repeat(4, 1fr);
	align-items: center;
	width: 100%;
	min-height: calc(82 * var(--eqc-u));
	/* 6u puts the strip only 23px under a 504px card. The reference leaves
	   roughly a tenth of the card's height between the two blocks; the grid's
	   own row-gap contributes the rest, so this is 14u rather than the full
	   ~35u the ratio implies, opened up further now that the cards sit lower
	   in the section. */
	margin-block-start: clamp(1.75rem, 1.3rem + 1.8vw, 3rem);
	/* The inline padding opens up to give each girih ornament its own band at
	   the panel's ends, so the ornament sits beside the tiles rather than
	   underneath the first and last label. */
	padding: calc(16 * var(--eqc-u)) clamp(2.25rem, 1rem + 4vw, 5.5rem);
	background: var(--eqc-white);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-panel);
	box-shadow: var(--eqc-shadow-card);
	position: relative;
	/* Safe here (unlike .eqc-pricing-panel, whose medallions overhang): the
	   strip's own content never leaves its box, and the radius has to clip
	   the ornaments or their square corners spill past the rounded ends. */
	overflow: hidden;
	isolation: isolate;
}
/* The girih ornament on both ends of the benefits panel uses
   lattice-corner.svg — the same arabesque bracket the site's section corner
   motifs use (.eqc-corner-motif above) — so it reads as one ornament family
   with them wherever a pricing panel appears: home, /pricing/ and all six
   course pages.
   The asset is a MASK, not a picture: its strokes are currentColor and it
   carries its own radial alpha fade, dense at its top-right corner and
   zero well inside the canvas. So it is tinted through background-color
   exactly like .eqc-corner-motif, and needs no second gradient mask — it
   already fades toward the middle of the strip on its own. */
.eqc-benefits::before,
.eqc-benefits::after {
	content: '';
	position: absolute;
	inset-block-start: 0;
	/* Sized by WIDTH and allowed to run past the strip's short height (the
	   panel's overflow:hidden + radius crop it). Sized to the ~82px strip
	   height instead, the lattice's 1.2-unit strokes on a 300-unit canvas
	   rendered at ~0.3px and all but vanished; at this size they hold, the
	   dense corner still fills the strip's end, and the fade reaches zero
	   before the first label's text (measured). */
	inline-size: clamp(96px, 9vw, 150px);
	aspect-ratio: 1;
	/* Alpha in the tint rather than element opacity, as .eqc-corner-motif
	   does. Stronger than that motif's 0.26: this sits on a white panel at a
	   smaller size, where 0.26 hairlines read as grey dust. No drop-shadow —
	   on hairlines it greys the lattice instead of lifting it. */
	background-color: rgb(var(--eqc-gold-600-rgb) / 0.55);
	-webkit-mask-image: url('../svg/lattice-corner.svg');
	mask-image: url('../svg/lattice-corner.svg');
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	pointer-events: none;
	z-index: 0;
}
/* The asset is dense at its own top-right corner, so the right end uses it
   as drawn and the left end mirrors it (the same mapping as
   .eqc-corner-motif--tr / --tl). */
.eqc-benefits::before { inset-inline-start: 0; scale: -1 1; }
.eqc-benefits::after { inset-inline-end: 0; }
.eqc-benefit { position: relative; z-index: 1; }
/* Tighter inline padding than the original four-tile strip: the width it
   gives back goes into the disc and the label below, which is what makes the
   tile read as one bigger unit rather than a small icon beside small text. */
.eqc-benefit { display: flex; align-items: center; gap: calc(15 * var(--eqc-u)); padding-inline: calc(12 * var(--eqc-u)); }
/* Cancel the shared plate at desktop: here the tile is a bare column in the
   .eqc-benefits panel, with no background/border for a second offset shadow
   to read against -- same reasoning as .eqc-trust-panel .eqc-trust-tile.
   :hover too: the shared hover rule (.eqc-benefit.eqc-benefit:hover) would
   otherwise bring the plate back on hover. Equal weight and later, so this
   wins; the <=75rem card strip re-plates at higher weight. */
.eqc-benefits .eqc-benefit,
.eqc-benefits .eqc-benefit:hover { box-shadow: none; }
.eqc-benefit + .eqc-benefit { border-inline-start: 1px solid var(--eqc-border); }
.eqc-benefit__disc {
	display: inline-flex; align-items: center; justify-content: center; flex: none; position: relative;
	width: calc(52 * var(--eqc-u)); height: calc(52 * var(--eqc-u));
	background: none;
}
.eqc-benefit__disc::before,
.eqc-benefit__disc::after {
	content: ''; position: absolute; inset: 0;
	mask: url('../svg/seal-filled.svg') center / 100% 100% no-repeat;
}
.eqc-benefit__disc::before { background: var(--eqc-gold-500); }
.eqc-benefit__disc::after { inset: calc(1.2 * var(--eqc-u)); background: var(--eqc-cream-50); }
.eqc-benefit__disc .eqc-icon { position: relative; z-index: 1; width: calc(31 * var(--eqc-u)); height: calc(31 * var(--eqc-u)); color: var(--eqc-green-800); }
/* Fluid rather than fixed: the tiles share a fixed content width, so the
   label can only grow as the panel does. Bottom of the range is the old
   14px, which is what still fits at the narrowest four-across width. */
.eqc-benefit__label { font-size: clamp(0.875rem, 0.72rem + 0.32vw, 1rem); line-height: 1.4; color: var(--eqc-heading); }
@media (max-width: 75rem) {
	.eqc-benefits { grid-template-columns: repeat(2, 1fr); row-gap: calc(18 * var(--eqc-u)); }
	/* Stated for both parities so the three-column rule above cannot leave a
	   row-opening tile with a border here, or strip one that belongs. */
	.eqc-benefit:nth-child(odd) { border-inline-start: 0; }
	.eqc-benefit:nth-child(even) { border-inline-start: 1px solid var(--eqc-border); }
}
@media (max-width: 36rem) {
	/* Stays 2x2 (client, 2026-09-17) -- see the .eqc-grid--trust note, including
	   why only an even-sized group goes two-up. Every .eqc-benefits strip on the
	   site currently holds four, but the rule is written on the count rather
	   than on that assumption. The column count does not change for an even
	   group, so the odd/even border parity set at 75rem above still holds
	   and must not be reset: dropping the divider on every tile would leave the
	   second column edge-to-edge with the first. Only the horizontal padding
	   tightens, because two columns at 320px leave each tile about 150px. */
	.eqc-benefits:not(:has(> :last-child:nth-child(even))) { grid-template-columns: 1fr; }
	.eqc-benefits:not(:has(> :last-child:nth-child(even))) .eqc-benefit + .eqc-benefit { border-inline-start: 0; }
	.eqc-benefit { padding-inline: calc(6 * var(--eqc-u)); gap: calc(10 * var(--eqc-u)); }
}

/* The pricing eyebrow inherits the shared pill exactly and keeps only its
   little rosette glyph as the leading mark, so the pricing tag still reads
   as the pricing tag without being a different shape from every other
   section tag. */
.eqc-eyebrow--rosette {
	align-self: center;
	position: relative;
	gap: calc(10 * var(--eqc-u));
}
.eqc-eyebrow--rosette::before {
	content: '';
	width: calc(18 * var(--eqc-u));
	height: calc(18 * var(--eqc-u));
	background: var(--eqc-gold-600);
	mask: url('../svg/rosette-simple.svg') center / contain no-repeat;
	flex: none;
}

/* The pricing panel was insetting the card grid by ~44u a side; in the
   reference the cards span the full 1119u content column, same as the
   benefits strip beneath them. */
.eqc-pricing-panel { padding-inline: 0; }
.eqc-pricing-panel > .e-con { padding-inline: 0; }
/* Feature rows are the bulk of the card's height; the reference runs them
   tighter (card 343u against our 406u). */
/* The plan feature list sits at body size in the full heading colour; a step
   smaller it reads as low-contrast fine print. */
/* Refines .eqc-pricing-list / .eqc-pricing-price-divider, first declared
   near .eqc-pricing-bullet above (search "No `margin-block-start: auto`") —
   these apply by later source order, not by higher specificity; keep that in
   mind before editing either block in isolation.
   The bullets left-align to each other, but the BLOCK they form is centred
   in the card. With the list spanning the full content width instead, ragged
   line ends read as broken alignment against the centred banner, price row
   and divider. */
.eqc-pricing-list { gap: calc(7 * var(--eqc-u)); margin: 0; width: fit-content; margin-inline: auto; text-align: left; }
/* The card body sits a notch above body size, scaled off --eqc-fs-body
   rather than jumping to the next role token, so it still tracks the global
   type ramp at every viewport. */
.eqc-pricing-list li {
	font-size: calc(var(--eqc-fs-body) * 1.09);
	line-height: 1.45;
	gap: calc(9 * var(--eqc-u));
	color: var(--eqc-heading);
}
/* Centred, near-full-width rule between the list and the price row. Measured
   38px left of the card's centre before this (240u wide, pinned to the content
   box's left edge) — the "divider should be centre aligned" note. */
.eqc-pricing-price-divider {
	width: 100%;
	margin-inline: auto;
	display: flex;
	justify-content: center;
	color: var(--eqc-gold-500);
}

/* An icon-only seal in the card's top-right corner, OUT OF FLOW.
   See the long note in eqc_pricing_card(): as a flow child this badge was the
   sole cause of the featured card's 23px misalignment, because
   .eqc-card--pricing centres its column inside a shared min-height and that
   only holds the four cards level while they carry the same children.

   Positioning goes on the WIDGET, not the badge -- the same wrapper trap
   .eqc-card-link-widget and .eqc-pricing-anchor-widget document above: between
   the card and this span sit two Elementor divs, and a `> * { position: relative }`
   rule on the featured card would otherwise make the wrapper the containing
   block. Specificity (0,2,0) beats those `> *` rules whatever the source order. */
.eqc-card--pricing > .eqc-pricing-badge-widget {
	position: absolute;
	/* Pinned ON the card's top-right corner (client, Round 20): the centre of
	   the round disc sits exactly on the corner point, the rosette overlapping
	   the gold edge and its ribbons hanging down the card's side like an
	   applied seal. The wrapper's own top-right is placed on the corner and
	   then shifted by the disc's position within the artwork: the disc centre
	   is at 50% of its width and 36.5% of its height (viewBox 224 116 575 790,
	   disc centre y 404). */
	/* Offsets are from the PADDING edge; -4px reaches the outer corner of the
	   featured card's 4px border. */
	inset-block-start: -4px;
	inset-inline-end: -4px;
	transform: translate(50%, -36.5%);
	z-index: 3;
	width: auto;
	line-height: 0;
}
/* Below the 4-up row the featured card is the right-hand (or only) card and
   sits inside the page gutter, which is narrower than half the badge: pinned
   exactly on the corner it ran off the screen and the page scrolled sideways
   (measured at 600 and 768px). There the disc centre moves inward just enough
   that the badge's edge stays inside the viewport. */
@media (max-width: 61.25rem) {
	.eqc-card--pricing > .eqc-pricing-badge-widget { transform: translate(18%, -36.5%); }
}
/* The client's rosette-and-ribbons artwork, re-traced into three layers
   (tools/graphics/trace-award-badge.mjs -> assets/svg/award-badge.svg): gold
   body and tails, copper disc, pale gold eight-point star at its centre. No
   round background -- the rosette is the badge. Its gold and copper gradients
   live in the SVG file itself, so it looks the same opened on its own. */
.eqc-pricing-badge {
	display: block;
	/* 575:790 is the artwork's own viewBox; width drives, height follows. */
	/* Larger now that it sits on the corner rather than inside the card's
	   top band (client, Round 20: "bigger, more prominent", then "slightly
	   smaller" -- 50-68px, down from 58-80px). */
	inline-size: clamp(50px, 4.1vw, 68px);
	aspect-ratio: 575 / 790;
	filter: drop-shadow(0 2px 3px rgba(20, 35, 27, 0.28));
	transform-origin: 50% 8%;
}
.eqc-pricing-badge .eqc-award {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	overflow: visible;
}
/* All four medallions now ride at the same height, because the featured card
   is no longer scaled and no longer has to clear a floating badge. */
/* The reference sets the four cards straight on the section ground; the
   enclosing panel frame is ours, not the design's. */
.eqc-pricing-panel { background: none; border: 0; box-shadow: none; }

/* All four medallions read as the SAME size. Scaling the featured card's
   medallion to dodge the "Recommended" badge breaks that; the badge moves
   instead (above), so this card's icon inherits the same fixed 3.8em every
   other card uses, with no per-width override. */

/* The pricing cards lift more distinctly than other cards on hover — a clean
   vertical rise, no sideways movement. */
.eqc-card--pricing:hover {
	transform: translateY(-10px);
	box-shadow: 0 26px 52px rgba(20, 35, 27, 0.16);
}

/* ---------- Teachers section ---------- */

/* Two-column split, not the full-width carousel this replaced. The reference's
   content column decomposes exactly: left 268u + gap 51u + cards 800u = 1119u. */
.eqc-teachers-split { gap: calc(45 * var(--eqc-u)); align-items: stretch; padding-inline: 0; }
.eqc-teachers-split > .eqc-teachers-aside { flex: 0 0 calc(275 * var(--eqc-u)); padding-inline: 0; }
.eqc-teachers-split > .eqc-teachers-cards {
	flex: 1 1 auto;
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: calc(22 * var(--eqc-u));
	align-items: stretch;
	padding-inline: 0;
}
.eqc-teachers-aside { gap: calc(10 * var(--eqc-u)); }
/* This column, not the cards, sets the teachers row height: it stacks a
   heading, a rule, a paragraph, three feature tiles and two controls in a
   268u column, so its text wraps hard. Reducing the CARD height does not
   move the section at all. Getting it under one screen at 1366 would mean
   shortening the copy or dropping a feature tile — content decisions, so
   it is left at ~1.15 viewports. */
.eqc-section--teachers { padding-block: calc(34 * var(--eqc-u)); }
/* A section tag like any other, sharing the one pill shape. Only the nowrap
   is special here, because this aside's column is narrow enough that the
   label would otherwise break mid-phrase. */
.eqc-teachers-aside .eqc-eyebrow { letter-spacing: 0; white-space: nowrap; }
.eqc-teachers-aside .elementor-widget-text-editor { font-size: max(16px, calc(12 * var(--eqc-u))); }
.eqc-teachers-split > .eqc-teachers-cards { padding-block-start: calc(40 * var(--eqc-u)); }
/* This heading sits in a 268u column and is correspondingly smaller than the
   other sections' — measured 209u of ink for "Learn From". */
.eqc-section--teachers .eqc-teachers-aside h2 { font-size: var(--eqc-fs-h2-compact); line-height: 1.16; }
.eqc-teachers-rule { color: var(--eqc-gold-500); line-height: 0; }
.eqc-teachers-rule .eqc-divider-svg { width: calc(120 * var(--eqc-u)); }
/* A one-column GRID, not a flex column, so the tag-card group contract's
   equal rows reach the stacked layout too: as a flex column the middle card
   (one-line caption) sat ~18px shorter than its two neighbours on phones and
   desktop (client, 2026-09-23). Visually still a stack of rows. */
.eqc-teachers-features { display: grid; gap: calc(8 * var(--eqc-u)); }
.eqc-teachers-features .eqc-trust-tile { padding: calc(10 * var(--eqc-u)) calc(13 * var(--eqc-u)); gap: calc(11 * var(--eqc-u)); align-items: center; }
.eqc-teachers-features .eqc-trust-tile-title { font-size: var(--eqc-fs-body); font-weight: 700; }
/* This caption sits on ONE line inside a 257u text column. At --eqc-fs-small
   it measures 273px in a 260px column, wraps, and adds a third row to every
   tile -- 84px on the aside, which is the tallest element in this section and
   therefore what sets the card height. The reference implies ~11px here; 13px
   is a deliberate departure for legibility. */
.eqc-teachers-features .eqc-trust-tile p { font-size: var(--eqc-fs-xsmall); }
.eqc-teachers-features .eqc-icon { width: calc(24 * var(--eqc-u)); height: calc(24 * var(--eqc-u)); }
/* Once the aside runs full width (below 75rem) three one-line rows became
   three long, mostly empty strips (client, 2026-09-19). From tablet width up
   they sit side by side as three equal cards instead: icon on top, title,
   caption, a gold corner-motif, the same dress as the 2x2 tag cards. Phones
   keep the stacked rows, which fill their width. */
@media (min-width: 36.01rem) and (max-width: 75rem) {
	.eqc-teachers-features.eqc-teachers-features {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: calc(14 * var(--eqc-u));
	}
	.eqc-teachers-features.eqc-teachers-features > * { display: flex; min-inline-size: 0; }
	.eqc-teachers-features.eqc-teachers-features .eqc-trust-tile {
		position: relative;
		overflow: hidden;
		flex: 1 1 auto;
		inline-size: 100%;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		text-align: center;
		gap: calc(8 * var(--eqc-u));
		padding: calc(16 * var(--eqc-u)) calc(12 * var(--eqc-u));
	}
	.eqc-teachers-features.eqc-teachers-features .eqc-trust-tile::before {
		content: '';
		position: absolute;
		inset-block-start: 0;
		inset-inline-end: 0;
		inline-size: clamp(44px, 26%, 72px);
		aspect-ratio: 1;
		background-color: rgb(var(--eqc-gold-600-rgb) / 0.3);
		-webkit-mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
		mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
		pointer-events: none;
		z-index: 0;
	}
	.eqc-teachers-features.eqc-teachers-features .eqc-trust-tile > * { position: relative; z-index: 1; min-inline-size: 0; }
	.eqc-teachers-features.eqc-teachers-features .eqc-icon { width: calc(30 * var(--eqc-u)); height: calc(30 * var(--eqc-u)); }
	.eqc-teachers-features.eqc-teachers-features .eqc-trust-tile p { font-size: var(--eqc-fs-small); text-wrap: balance; }
}
/* gap: 0, with the arrows carrying their own trailing margin instead.
   The prev/next pair is display:none above 61.25rem, but its Elementor widget
   wrapper stays in the flow as a zero-width flex item -- and a flex `gap` is
   drawn between items regardless of how wide they are, so the row still spent
   14u on a control that is not there. That pushed "View All Teachers" a
   measured 15px right of the trust tiles stacked directly above it, which
   reads as a misalignment rather than as an indent. */
/* `gap: 0` and the nav's own trailing margin existed to keep the arrow pair
   tight against the button beside it. With the arrows removed the bar holds a
   single control, so it simply centres it. */
.eqc-teachers-controls { gap: 0; align-items: center; justify-content: center; padding-inline: 0; }
/* This pill's circular arrow sits AFTER the label, unlike the about-section
   CTAs which lead with theirs. Scoped so those are untouched. */
.eqc-teachers-controls .eqc-btn--icon-disc { flex-direction: row-reverse; }

/* A carousel with nothing to page to hides its controls (see eqc.js
   buildDots) and reclaims the inline padding they reserved -- that padding
   is what held the testimonial cards 22px narrower than the reference. */
.eqc-carousel--static .eqc-carousel-arrow,
.eqc-carousel--static .eqc-slider-dots { display: none; }
/* Hiding the controls leaves their Elementor widget wrappers in the flow at
   zero height, but each one still draws a 20px container gap either side --
   30px above the track and 70px below it. Collapsing the gap removes both;
   the track is the only visible child left. */
.eqc-carousel--static { padding-inline: 0; padding-block: 0; gap: 0; }
/* The teacher row's prev/next arrows exist only for the widths where the row
   actually scrolls. Measured at 1024px and wider the row's scrollWidth equals
   its clientWidth, so syncButtons() disables both arrows and they sit there as
   permanently dead weight -- the exact defect Reviews.md R13 raises. eqc.js
   already drops the dot strip above 61.25rem for this same reason
   (matchMedia '(max-width: 61.25rem)' in setupTeacherRow); this mirrors that
   one breakpoint rather than inventing a second. Below it the arrows return
   and keep their 44x44 ::after hit area. */
/* Gone at EVERY width (client, 2026-09-17). They were already hidden above
   61.25rem as dead weight (Reviews.md R13); below it they duplicated a control
   the visitor already has -- the row is a scroll-snap strip that swipes, and
   the dot strip underneath it shows position and jumps. Three affordances for
   one action, two of which only exist on the width where swiping is easiest.
   With the arrows gone the row's control bar holds just the "View All
   Teachers" button, which no longer has to share the line. */
.eqc-teachers-nav { display: none; }
/* Numbered process cards ("How Matching Works" on /teachers/). The card hugs
   its content and the content carries its weight — index badge, a properly
   sized icon, body-size copy in --eqc-text. Left at fs-small with a
   default-size icon inside a card carrying .eqc-card's full height, the copy
   leaves a dead band across the middle. */
.eqc-card--step {
	text-align: center;
	align-items: center;
	gap: calc(6 * var(--eqc-u));
	min-height: 0;
	padding: calc(24 * var(--eqc-u)) calc(20 * var(--eqc-u)) calc(26 * var(--eqc-u));
	/* The card is the unit its decorations are sized against (Round 20).
	   They used to be sized against the VIEWPORT -- the numeral a fixed
	   2.9em x 1.1rem (51px everywhere), the seal 58 x --eqc-u, which stops
	   shrinking below a 915px viewport. In the 2-column phone grid the card
	   kept narrowing to 117px while both stayed full size, so they collided
	   and pushed the title into a sliver. `cqi` below is a percentage of THIS
	   card's content width, so the seal and numeral shrink with the column
	   and never outgrow it. */
	container-type: inline-size;
}
/* Sizes, as token streams: an unregistered custom property keeps `cqi`
   unresolved until a descendant uses it, so it resolves against this card.
   Bounds are plain px on purpose: an --eqc-u bound would bring back the
   915px floor this replaces. */
.eqc-card--step {
	--_seal: clamp(42px, 36cqi, 70px);
	--_chip: clamp(24px, calc(var(--_seal) * 0.46), 32px);
	--_chip-inset: clamp(8px, 5cqi, 18px);
}
.eqc-card--step .eqc-card-index { margin-inline: auto; }
@media (max-width: 22.5rem) {
	/* At 320-360px a 2-up card is ~117px wide. The desktop padding would
	   leave ~77px for the title -- "Quran Reading with Tajweed" wrapped to
	   four lines. */
	.eqc-card--step { padding-inline: 10px; }
}
/* In the narrowest cards the title steps down a little so a two-word line
   ("with Tajweed", "Multiple Learners") fits instead of breaking per word.
   150px, not 130px: at a 430px viewport the /about/ card has 144px of content
   and "Multiple Learners" (~150px at full size) still broke the title onto
   three lines; at 15.5px it is ~137px. Wider cards are unaffected. */
@container (max-width: 150px) {
	/* Doubled class: the base h3/p rules sit later in this file at equal weight. */
	.eqc-card--step.eqc-card--step h3 { font-size: 15.5px; }
	.eqc-card--step.eqc-card--step p { font-size: 14.5px; }
}
/* The step icon sits in the same scalloped gold seal the pricing benefits
   strip uses (.eqc-benefit__disc) rather than floating as a bare dark glyph.
   A plain green icon on a white card reads as small and flat; the seal gives
   each step a gold ring and a cream well, so the row reads as designed rather
   than as four icons dropped on four boxes. */
.eqc-card--step .eqc-step-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	position: relative;
	flex: none;
	width: var(--_seal);
	height: var(--_seal);
	margin: calc(2 * var(--eqc-u)) auto calc(4 * var(--eqc-u));
}
.eqc-card--step .eqc-step-icon::before,
.eqc-card--step .eqc-step-icon::after {
	content: '';
	position: absolute;
	inset: 0;
	mask: url('../svg/seal-filled.svg') center / 100% 100% no-repeat;
}
.eqc-card--step .eqc-step-icon::before { background: var(--eqc-gold-500); }
.eqc-card--step .eqc-step-icon::after { inset: calc(1.6 * var(--eqc-u)); background: var(--eqc-cream-50); }
.eqc-card--step .eqc-step-icon .eqc-icon {
	position: relative;
	z-index: 1;
	width: 48%;
	height: 48%;
	color: var(--eqc-green-800);
}
/* The numeral. On a card WITH an icon seal it is a small chip in the card's
   top-left corner, and the seal is the card's single centred lead object.
   It used to sit on the seal's upper-left rim, which pulled the seal-and-chip
   group off the card's centre line and read as a cluster squeezed onto the
   icon (client, Round 20). The corner is the card's own coordinate, inset
   in `cqi`, so it holds at every width: in the narrowest 2-up phone card
   (117px) the chip spans 8-32px and the 42px seal starts at 37px.
   Only seal cards do this. The version before Round 20 pinned EVERY step
   card's numeral to the corner, including course-detail steps that have no
   seal, where it sat on the paragraph; seal-less cards keep the numeral in
   flow as their lead object (below). */
.eqc-card--step { position: relative; }
.eqc-card--step .eqc-card-index {
	inline-size: var(--_chip);
	block-size: var(--_chip);
	font-size: calc(var(--_chip) * 0.5);
	line-height: 1;
	margin-inline: auto;
}
.eqc-card--step:has(> .eqc-step-icon) .eqc-card-index {
	position: absolute;
	z-index: 2;
	inset-inline-start: var(--_chip-inset);
	inset-block-start: var(--_chip-inset);
	margin: 0;
	background: var(--eqc-surface);
	border: 1.5px solid var(--eqc-gold-500);
	color: var(--eqc-bronze-700);
	box-shadow: 0 2px 6px rgba(20, 35, 27, 0.14);
}
/* Without a seal the numeral is the card's lead object: a larger ring, in
   flow, above the text. */
.eqc-card--step:not(:has(> .eqc-step-icon)) {
	--_chip: clamp(36px, 30cqi, 56px);
}
/* --prose: a numbered step whose content is a paragraph, not a title
   (course-detail "How Classes Run"). Centred multi-line paragraphs under a
   lone numeral gave the eye nowhere to start (client, Round 20). Here the
   card reads like a step in a sequence: the numeral leads at the top left, a
   gold rule runs from it to the card's edge, "Step N" labels it, and the
   paragraph is left-aligned at reading size with generous leading. */
.eqc-card--step.eqc-card--step-prose {
	text-align: start;
	align-items: stretch;
	gap: calc(14 * var(--eqc-u));
	padding: clamp(22px, calc(30 * var(--eqc-u)), 40px);
}
.eqc-card--step-prose .eqc-step-head {
	display: flex;
	align-items: center;
	gap: 12px;
}
.eqc-card--step.eqc-card--step-prose .eqc-card-index {
	margin: 0;
	flex: none;
	inline-size: clamp(44px, 18cqi, 56px);
	block-size: clamp(44px, 18cqi, 56px);
	font-size: clamp(20px, 8cqi, 26px);
	background: var(--eqc-green-900);
	border: 0;
	box-shadow: 0 0 0 2px var(--eqc-surface), 0 0 0 3px var(--eqc-gold-500);
	color: var(--eqc-gold-300);
}
.eqc-card--step-prose .eqc-step-label {
	font-size: var(--eqc-fs-eyebrow);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--eqc-bronze-600);
	white-space: nowrap;
}
.eqc-card--step-prose .eqc-step-head::after {
	content: '';
	flex: 1 1 auto;
	block-size: 1px;
	background: linear-gradient(90deg, rgb(var(--eqc-gold-500-rgb) / 0.8), transparent);
}
.eqc-card--step.eqc-card--step.eqc-card--step-prose p {
	font-size: clamp(16px, calc(15 * var(--eqc-u)), 19px);
	line-height: 1.7;
	color: var(--eqc-text);
	max-inline-size: 42ch;
	/* Left-aligned reading copy: balance would pull lines short of the
	   measure, so this one keeps `pretty` (no orphan, full lines). */
	text-wrap: pretty;
}
.eqc-card--step-prose:hover .eqc-card-index {
	background: var(--eqc-gold-500);
	color: var(--eqc-green-900);
}

/* ---------- Invitation panel (free-trial / contact asides) ----------
   A dark green panel against the cream form column. Without it these two
   pages are the flattest on the site — a white card on a cream ground, all
   body-colour text. Green here is the same move the footer CTA makes, so it
   reads as part of the system rather than a one-off. */
.eqc-panel--invite {
	background: linear-gradient(160deg, var(--eqc-green-700) 0%, var(--eqc-green-900) 100%);
	border: 1px solid var(--eqc-green-700);
	border-radius: var(--eqc-radius-panel);
	padding: clamp(1.5rem, 1.2rem + 1.4vw, 2.5rem);
	color: var(--eqc-cream-100);
	position: relative;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	gap: calc(14 * var(--eqc-u));
}
/* Girih watermark in the panel's own corner, same treatment as the dark
   footer CTA. Tint in the paint's alpha so it stays a texture. */
.eqc-panel--invite::after {
	content: '';
	position: absolute;
	inset-block-start: 0;
	inset-inline-end: 0;
	width: calc(150 * var(--eqc-u));
	height: calc(150 * var(--eqc-u));
	background-color: rgb(var(--eqc-gold-300-rgb) / 0.16);
	mask: url('../svg/corner-motif.svg') top right / 100% 100% no-repeat;
	pointer-events: none;
}
.eqc-panel--invite > * { position: relative; z-index: 1; }
.eqc-panel--invite h3 {
	margin: 0;
	font-family: var(--eqc-font-display);
	font-size: var(--eqc-fs-h2-compact);
	line-height: 1.15;
	color: var(--eqc-white);
}
.eqc-panel--invite h3 em { font-style: normal; color: var(--eqc-gold-300); }
.eqc-panel--invite p { margin: 0; color: rgb(247 243 236 / 0.82); line-height: 1.6; }
.eqc-panel--invite .eqc-panel-actions { display: flex; flex-direction: column; gap: calc(10 * var(--eqc-u)); align-items: stretch; }
.eqc-panel--invite .eqc-btn { justify-content: center; width: 100%; }
.eqc-panel--invite .eqc-panel-foot {
	margin-block-start: auto;
	padding-block-start: calc(14 * var(--eqc-u));
	border-block-start: 1px solid rgb(var(--eqc-gold-300-rgb) / 0.28);
	font-size: var(--eqc-fs-small);
	color: rgb(247 243 236 / 0.72);
}
.eqc-panel--invite .eqc-panel-foot a { color: var(--eqc-gold-300); }
.eqc-panel--invite .eqc-panel-contact {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: calc(11 * var(--eqc-u));
}
.eqc-panel--invite .eqc-panel-contact li {
	display: flex;
	align-items: center;
	gap: calc(11 * var(--eqc-u));
	color: var(--eqc-cream-100);
	font-size: var(--eqc-fs-body);
	overflow-wrap: anywhere;
}
.eqc-panel--invite .eqc-panel-contact .eqc-icon {
	flex: none;
	width: var(--eqc-icon-sm);
	height: var(--eqc-icon-sm);
	color: var(--eqc-gold-300);
}
.eqc-panel--invite .eqc-panel-contact a { color: inherit; text-decoration: none; }
.eqc-panel--invite .eqc-panel-contact a:hover { text-decoration: underline; }
/* The bronze CTA keeps its own fill inside the green panel; only the outlined
   secondary needs the light-on-dark treatment the dark sections already set. */
.eqc-panel--invite a.eqc-btn--secondary {
	color: var(--eqc-cream-100);
	border-color: rgb(var(--eqc-gold-300-rgb) / 0.45);
}
.eqc-panel--invite a.eqc-btn--secondary:hover { background: rgb(255 255 255 / 0.08); }
.eqc-panel--invite a.eqc-btn--whatsapp:hover,
.eqc-panel--invite a.eqc-btn--whatsapp:focus-visible {
	background: var(--eqc-whatsapp-green);
	border-color: var(--eqc-whatsapp-green-dark);
	color: var(--eqc-heading);
}

/* Reassurance list under the invitation panel. Every line restates a promise
   already made elsewhere on the page — nothing new is claimed here. */
.eqc-reassure { display: flex; flex-direction: column; gap: calc(10 * var(--eqc-u)); margin: 0; padding: 0; list-style: none; }
.eqc-reassure li { display: flex; align-items: flex-start; gap: calc(10 * var(--eqc-u)); color: var(--eqc-text); line-height: 1.45; }
.eqc-reassure .eqc-icon { flex: none; width: var(--eqc-icon-sm); height: var(--eqc-icon-sm); margin-block-start: 0.15em; color: var(--eqc-gold-700); }
.eqc-reassure strong { color: var(--eqc-heading); font-weight: 600; }

/* The two-column form layout: the aside column is much shorter than the form,
   which left ~600px of dead cream beside it. Aligning the columns to the top
   and letting the aside stick keeps it beside the fields the whole way down
   instead of stranding it. */
.eqc-form-grid { align-items: flex-start; gap: calc(40 * var(--eqc-u)); }
.eqc-form-grid > .eqc-form-wrap { flex: 1 1 58%; }
.eqc-form-grid > .eqc-form-aside {
	flex: 1 1 34%;
	display: flex;
	flex-direction: column;
	gap: calc(24 * var(--eqc-u));
	/* Elementor's own container default (see the near-identical note on
	   .eqc-pricing-panel above) — left in, the column's content starts 10px
	   below the form's, most visible on Contact. */
	padding-block-start: 0;
}
@media (min-width: 62rem) {
	.eqc-form-grid > .eqc-form-aside { position: sticky; top: calc(var(--eqc-header-h, 96px) + 28px); }
}
@media (max-width: 61.99rem) {
	.eqc-form-grid > .eqc-form-wrap,
	.eqc-form-grid > .eqc-form-aside { flex-basis: 100%; }
}
/* On Contact the aside card is aligned to the form on both axes. Measured:
   the aside column (invite panel + reassurance list)
   is naturally ~640px tall against a ~564px form — TALLER than the form, the
   opposite of Free Trial's much longer form (~1166px vs a ~632px aside),
   which is what the shared .eqc-form-grid rule above was built for.
   Sticky is right for Free Trial (it keeps a short aside beside a long,
   scrolling form) but wrong for Contact: with the aside already at least as
   tall as the form, sticky just detaches it from the form as the page
   scrolls, which reads as exactly the misalignment reported. `stretch`
   fixes both axes at once here — the row's cross-size already comes out to
   the taller column's height, so the shorter one (the form) grows to match
   it, giving equal tops (already true) and equal bottoms, with no extra
   markup needed inside either column. Scoped to Contact only via this
   modifier class (15-contact.php) rather than changing the shared rule,
   since Free Trial still needs the sticky/flex-start behaviour. */
.eqc-form-grid--balanced { align-items: stretch; }
@media (min-width: 62rem) {
	.eqc-form-grid--balanced > .eqc-form-aside { position: static; }
}

.eqc-card--step h3 {
	margin: 0;
	text-wrap: balance;
	overflow-wrap: break-word;
	font-family: var(--eqc-font-body);
	font-size: var(--eqc-fs-h4);
	font-weight: 700;
	line-height: 1.25;
	color: var(--eqc-heading);
}
.eqc-card--step p {
	margin: 0;
	font-size: var(--eqc-fs-body);
	line-height: 1.5;
	color: var(--eqc-text);
	max-width: 100%;
	/* Centred two- and three-line copy reads best with even lines. */
	text-wrap: balance;
}

.eqc-nav-btn {
	width: calc(42 * var(--eqc-u)); height: calc(42 * var(--eqc-u));
	border-radius: 50%; border: 1px solid var(--eqc-border-strong);
	background: none; color: var(--eqc-heading); cursor: pointer;
	display: inline-flex; align-items: center; justify-content: center;
}
.eqc-nav-btn:first-child .eqc-icon { transform: rotate(180deg); }
.eqc-nav-btn .eqc-icon { width: calc(18 * var(--eqc-u)); height: calc(18 * var(--eqc-u)); }
/* The base button rule is written as `a.eqc-btn, button.eqc-btn, ...` (0,1,1),
   so a plain `.eqc-btn--sm` (0,1,0) modifier lost every cascade and the small
   button kept the full 53u inline padding -- 65px a side, which pushed the
   "View All Teachers" pill to 305px inside a 337px column. The modifier has to
   carry the same element+class weight as the rule it modifies. */
a.eqc-btn--sm, button.eqc-btn--sm, .eqc-btn--sm { --_h: max(44px, calc(38 * var(--eqc-u))); padding-inline: calc(18 * var(--eqc-u)); font-size: var(--eqc-fs-small); min-inline-size: 0; }
.eqc-btn--sm.eqc-btn--icon-disc .eqc-icon { padding: calc(5 * var(--eqc-u)); }

/* Card: 187 x 394u, oval portrait overlapping the top edge. */
.eqc-card--teacher { min-height: calc(394 * var(--eqc-u)); padding: calc(16 * var(--eqc-u)); gap: calc(5 * var(--eqc-u)); text-align: center; align-items: center; }
/* Up one step (h4 -> h3, 17px -> 20px at 1440). The name is the card's
   subject and was rendering smaller than the course-card titles beside it. */
.eqc-card--teacher h3 { font-size: var(--eqc-fs-h3); line-height: 1.2; font-family: var(--eqc-font-body); font-weight: 700; }
.eqc-card--teacher .eqc-teacher-role { font-size: var(--eqc-fs-small); color: var(--eqc-gold-700); }
.eqc-card--teacher .eqc-teacher-facts { gap: calc(8 * var(--eqc-u)); }
/* Body, not caption: these three lines are the card's actual substance
   (years taught, specialism, who the teacher works with), so they read at the
   card-body size like every other card's copy rather than as meta text. */
.eqc-card--teacher .eqc-teacher-facts li { font-size: var(--eqc-fs-body); gap: calc(8 * var(--eqc-u)); }
/* "View Profile" on the home teacher row -- a link through to that teacher on
   /teachers/. (The /teachers/ page itself no longer has this control: every
   profile is open there, client 2026-09-20.)
   Round 20: SOLID deep green, cream label, a gold ring inset inside the edge.
   It was meant to be cream with a gold edge, but the generic
   `a.eqc-btn--outline, button.eqc-btn--outline { background: none }` rule sits
   later in this file at higher weight (0,1,1) and won -- the button was
   transparent over the card's lattice and blended into it (client: "too
   blending with the BG"). Every declaration here is element-qualified, so it
   outranks that rule instead of depending on source order.
   Hover turns gold, so the card's one action is also its one warm accent. */
a.eqc-btn.eqc-teacher-profile {
	width: 100%;
	justify-content: center;
	gap: calc(8 * var(--eqc-u));
	background: linear-gradient(160deg, var(--eqc-green-800), var(--eqc-green-900));
	border: 1px solid var(--eqc-green-900);
	box-shadow: inset 0 0 0 2px rgb(var(--eqc-gold-500-rgb) / 0.55), 0 3px 10px rgba(20, 35, 27, 0.16);
	color: var(--eqc-cream-50);
	font-weight: 700;
	letter-spacing: 0.02em;
	transition: background var(--eqc-motion-base) var(--eqc-ease-standard),
		color var(--eqc-motion-base) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-base) var(--eqc-ease-standard),
		transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
a.eqc-btn.eqc-teacher-profile:hover,
a.eqc-btn.eqc-teacher-profile:focus-visible {
	background: linear-gradient(160deg, var(--eqc-gold-300), var(--eqc-gold-500));
	border-color: var(--eqc-gold-500);
	box-shadow: inset 0 0 0 2px rgb(255 255 255 / 0.35), 0 6px 16px rgba(20, 35, 27, 0.2);
	color: var(--eqc-green-900);
}
/* A card still carrying the retired disclosure button (baked into a page's
   saved Elementor data before 2026-09-20) must not show it: the profile it
   used to open is already on the page. */
button.eqc-teacher-profile { display: none; }
/* With the cards stretched to equal height, the pill has to be pushed to the
   bottom or a shorter card floats it mid-air. */
.eqc-card--teacher .eqc-card__foot { margin-block-start: auto; width: 100%; }
/* button. as well as a. -- several outline controls render as a <button>, and
   without the element-qualified half they fell through to Hello Elementor
   reset.css's hardcoded #cc3366 pink (see the note at the top of this file).
   Every other .eqc-btn modifier already pairs the two. */
a.eqc-btn--outline, button.eqc-btn--outline { background: none; border-color: var(--eqc-border-strong); color: var(--eqc-heading); }

/* Tertiary "view all" CTA — the FAQ sections' link through to /faq/. A
   full-size solid-green pill sitting directly under a column of solid-green
   question bars read as one more bar rather than as the section's exit link,
   so this variant is deliberately shorter, narrower and outlined: the
   hierarchy is visible before the label is read. */
a.eqc-btn--quiet, button.eqc-btn--quiet,
.elementor-widget-button.eqc-btn--quiet .elementor-button {
	--_h: max(44px, calc(44 * var(--eqc-u)));
	min-inline-size: 0;
	padding-inline: calc(26 * var(--eqc-u));
	font-size: var(--eqc-fs-small);
	font-weight: 700;
	letter-spacing: 0.02em;
	/* Not transparent at rest (client, 2026-09-17: "quite dull, not capturing
	   focus"). A soft gold wash with a full-strength gold edge reads as a
	   control immediately while still sitting a clear step below the solid
	   primary buttons -- which is the whole point of this variant, since it
	   sits directly under a column of solid green FAQ bars and must not
	   compete with them. */
	background: var(--eqc-cream-200);
	color: var(--eqc-bronze-700);
	border-color: var(--eqc-gold-500);
}
a.eqc-btn--quiet:hover, button.eqc-btn--quiet:hover,
.elementor-widget-button.eqc-btn--quiet .elementor-button:hover {
	background: var(--eqc-bronze-700);
	border-color: var(--eqc-bronze-700);
	color: var(--eqc-white);
}

@media (max-width: 75rem) {
	.eqc-teachers-split { flex-wrap: wrap; }
	.eqc-teachers-split > .eqc-teachers-aside,
	.eqc-teachers-split > .eqc-teachers-cards { flex-basis: 100%; }
}
/* The HOME section's cards live in .eqc-teachers-cards, not
   .eqc-grid--teachers, so they need this snap-scroll treatment of their own;
   without it they are a plain vertical stack on phones (at 390px, four cards
   at x=25, 464px apart). Both places then behave like the reviews row. The
   aside's prev/next buttons page this container, and so does a
   .eqc-slider-dots row built right after it — see initTeacherRows() in
   eqc.js. */
@media (max-width: 75rem) {
	.eqc-teachers-split > .eqc-teachers-cards {
		grid-template-columns: none;
		grid-auto-flow: column;
		grid-auto-columns: calc((100% - var(--eqc-grid-gap)) / 2);
		gap: var(--eqc-grid-gap);
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		padding-bottom: 0.5rem;
		/* Replaced by the dot strip below — see the comment on
		   .eqc-grid--teachers above, same reasoning. */
		scrollbar-width: none;
	}
	.eqc-teachers-split > .eqc-teachers-cards::-webkit-scrollbar { display: none; }
	.eqc-teachers-split > .eqc-teachers-cards > * { scroll-snap-align: center; }
}
@media (max-width: 36rem) {
	.eqc-teachers-split > .eqc-teachers-cards { grid-auto-columns: 100%; }
}
/* Laptop/tablet-landscape: three whole cards, as the reviews carousel
   shows at the same width. Two cards across a ~1000px row stretched each
   to ~500px, blowing the portrait up to nearly the full card. */
@media (min-width: 60.01rem) and (max-width: 75rem) {
	.eqc-grid--teachers,
	.eqc-teachers-split > .eqc-teachers-cards { grid-auto-columns: calc((100% - 2 * var(--eqc-grid-gap)) / 3); }
}

/* Elementor marks entrance-animated cards outside the initial viewport as
   elementor-invisible. In a horizontal mobile row those cards are offscreen
   by design, so they never get a vertical entrance intersection and remain
   hidden when the user swipes to them. Keep the offscreen cards discoverable;
   the row's own snap interaction supplies the reveal context. */
@media (max-width: 75rem) {
	.eqc-grid--teachers > .elementor-invisible,
	.eqc-teachers-split > .eqc-teachers-cards > .elementor-invisible {
		visibility: visible;
	}
}

/* Home-section teacher card: the oval portrait rides ABOVE the card's top
   edge with the book badge centred on that overlap; the meta rows sit plain
   on the card, not in a tinted box; the name is bold sans, not the display
   serif; and the "View Profile" pill stays inside the card.

   DESKTOP ONLY (≥61.3125rem, just past the snap-scroll breakpoint below).
   Every offset here is on the same percentage-of-card-width basis. Mixing
   bases breaks it: a percentage WIDTH against an --eqc-u vertical placement
   diverges below ~915px, where --eqc-u floors at 0.70px, and the portrait
   then swallows the card's own content. Note that
   margin-block-start/padding-block-start resolve percentages against the
   containing block's WIDTH while `inset-block-start` resolves against
   HEIGHT, so the photo and seal use `inset-block-start: 0` plus a
   `margin-block-start` percentage instead.

   Below the breakpoint this override stops applying entirely, so phones
   render the same plainer BASE
   .eqc-card--teacher/.eqc-teacher-photo-widget/.eqc-teacher-seal rules
   further up this file that the /teachers/ page grid uses — an exact match
   rather than a scaled-down approximation of this treatment.

   The desktop constants are measured, not guessed: getBoundingClientRect()
   of the card against its portrait and seal at 1920/1440/1280/1024 gives
   near-identical ratios of the card's own width at every size (for example
   marginBlockStart/cardWidth = 0.7749 at all four). */
@media (min-width: 61.3125rem) {
	.eqc-section--teachers .eqc-card--teacher {
		/* Client, 2026-09-17: the section's portraits read as too large beside
		   the name and facts. The four constants below are a measured SET --
		   the overhang, the padding that reserves the rest of the photo inside
		   the card, the seal's drop and the width all resolve against the
		   card's width and only look right relative to each other. Scaling
		   them by one ratio keeps that relationship exact and leaves the
		   original measurements readable; changing any one alone opens a gap
		   between the photo and the name. */
		--_portrait-scale: 0.755;
		overflow: visible;
		margin-block-start: calc(77.49% * var(--_portrait-scale));
		padding-block-start: calc(53.48% * var(--_portrait-scale));
	}
	.eqc-section--teachers .eqc-card--teacher .eqc-teacher-photo-widget {
		position: absolute;
		inset-block-start: 0;
		margin-block-start: calc(-77.49% * var(--_portrait-scale));
		inset-inline: 0;
		width: calc(98% * var(--_portrait-scale));
		margin-inline: auto;
		z-index: 2;
	}
	.eqc-section--teachers .eqc-card--teacher .eqc-teacher-seal {
		position: absolute;
		inset-block-start: 0;
		margin-block-start: calc(16.9% * var(--_portrait-scale));
		inset-inline: 0;
		margin-inline: auto;
		width: 24%;
		/* was a fixed calc(44*u) height — `height: %` resolves against the
		   containing block's HEIGHT (the same trap as inset-block-start
		   above), so aspect-ratio derives it from the width instead; the
		   seal is a circle, 1:1. `height: auto` is required here, not just
		   aspect-ratio — the base .eqc-teacher-seal rule sets an explicit
		   `height: 2.4em`, and aspect-ratio only fills in a dimension
		   that's actually auto; left unset, that 2.4em kept winning and the
		   seal rendered as an oval. */
		height: auto;
		aspect-ratio: 1;
		z-index: 3;
	}
}
.eqc-section--teachers .eqc-card--teacher h3 {
	font-family: var(--eqc-font-body);
	font-weight: 700;
	/* h3, matching the base rule: with the portrait reduced, the name is what
	   carries the card and it was rendering at 17px. */
	font-size: var(--eqc-fs-h3);
	color: var(--eqc-heading);
	/* Trimmed from the shared 0.9em: the seal above already carries its own
	   0.7em bottom margin, and the two don't collapse (flex items), which
	   otherwise leaves the name a measured 60px below the seal at 1920px. */
	margin-block-start: 0.35em;
}
.eqc-section--teachers .eqc-teacher-facts {
	background: none;
	border: 0;
	padding: 0;
	width: 100%;
	text-align: start;
}
/* The card's own min-height (shared with the /teachers/ page grid, further
   up this file) leaves a measured 96px of dead air between the facts list
   and the bottom-pinned "View Profile" pill on this section's 4-across row.
   Scoped to the home section only; the full /teachers/ page grid keeps its
   own min-height. */
.eqc-section--teachers .eqc-card--teacher { min-height: calc(345 * var(--eqc-u)); }
.eqc-section--teachers .eqc-teacher-profile { width: 100%; box-sizing: border-box; }

/* ---------- Round 18: teacher card height ----------
 *
 * Both teacher layouts were inflating their cards by stretching them against
 * something that is not another card, and in both cases the symptom was a
 * band of empty space rather than anything that looked like a sizing bug.
 *
 * HOME. The four-card row is a grid ITEM sitting beside the heading/trust-tile
 * column, and that column is the taller of the two -- 724px against roughly
 * 536px of card. Stretched to match it, every card became 513px tall holding
 * about 380px of content, and because .eqc-card__foot pins the CTA to the
 * bottom, the whole surplus collected in one visible gap: a measured 133px
 * between the facts list and the "View Profile" pill.
 *
 * align-self: start lets the row take its own height. The cards still stretch
 * to EACH OTHER -- that is what keeps their CTAs on one baseline, and it is
 * worth keeping -- they just no longer stretch to the column next door. The
 * residual gap is then the real difference between a 3-fact and a 4-fact card,
 * about 22px, instead of 133px of nothing.
 *
 * TEACHERS PAGE. This grid used to carry align-items: start, because while the
 * profiles were a disclosure, opening ONE of them stretched its two row
 * siblings from 597px to 1159px and left 562px of white space in each. With
 * every profile open (2026-09-20) there is no such asymmetry left: the cards
 * differ only by how long each profile runs, so they stretch to the row's
 * tallest and the panel's CTA pair sits on that shared floor (see
 * .eqc-teacher-panel further down) instead of at six different heights.
 */
.eqc-teachers-cards { align-self: start; }

/* ---------- Round 18: teacher card surface and profile panel ----------
 *
 * Everything here is scoped to .eqc-grid--teachers (the /teachers/ page) on
 * purpose. The home section's teacher cards use a different, reference-
 * calibrated treatment further up this file -- the portrait is absolutely
 * positioned so it overlaps ABOVE the card -- and these rules sit later in the
 * file at equal specificity, so an unscoped selector here would silently win
 * over that calibration. That is the later-wins trap CLAUDE.md records, and
 * scoping is the fix rather than !important.
 *
 * The card was a flat white box with a circle floating near the top and three
 * grey text rows under it: correct, and unfinished-looking. A tinted field
 * behind the upper half gives the portrait something to sit against, which is
 * what makes the ring and the seal read as deliberate.
 */
.eqc-grid--teachers .eqc-card--teacher {
	position: relative;
	overflow: hidden;
	padding-block-start: calc(20 * var(--eqc-u));
}
/* Ends well above the seal: the portrait is ~194px tall from a 16px inset, so
   the circle straddles the band and the seal lands back on the card surface,
   where its green-on-white ring still has contrast. */
.eqc-grid--teachers .eqc-card--teacher::before {
	content: '';
	position: absolute;
	inset: 0 0 auto;
	height: calc(116 * var(--eqc-u));
	background: linear-gradient(165deg, var(--eqc-green-800), var(--eqc-green-900));
	/* Below the ornament layer (z-index -1), so the lattice and corner lace
	   carry across the band too. */
	z-index: -2;
}
.eqc-grid--teachers .eqc-card--teacher > * { position: relative; z-index: 1; }

/* Name, role and facts were all reading at a similar weight and colour, so the
   eye had nothing to land on first (client: needs contrast and focus). The name
   now carries the display serif at the card-title size in the deepest green on
   the palette, which makes it unambiguously the card's subject; the role pill
   below stays small and gold; the facts stay body copy. Three clearly different
   levels rather than three shades of the same one. */
.eqc-grid--teachers .eqc-card--teacher h3 {
	margin-block: 0.5em 0.2em;
	color: var(--eqc-green-900);
	font-family: var(--eqc-font-display);
	font-weight: 700;
	font-size: var(--eqc-fs-h3);
	line-height: 1.15;
	letter-spacing: 0.01em;
}
/* A pill rather than a third line of grey text, so the role reads as a label
   and not as more biography. width:fit-content survives the card's
   `> * { width: 100% }` because the <p> sits inside its own widget wrapper. */
.eqc-grid--teachers .eqc-teacher-role {
	display: inline-flex;
	width: fit-content;
	margin-inline: auto;
	margin-block-end: 0.55em;
	padding: 0.25em 0.9em;
	border-radius: 999px;
	background: var(--eqc-cream-100);
	color: var(--eqc-bronze-700);
	font-size: var(--eqc-fs-xsmall);
	font-weight: 700;
	letter-spacing: 0.04em;
}
.eqc-grid--teachers .eqc-teacher-facts {
	margin-block-end: 0.85em;
	padding: 0.7em 0.9em;
	gap: 0.45em;
	background: var(--eqc-cream-50);
}
.eqc-grid--teachers .eqc-teacher-facts li { align-items: center; }

/* ---------- Testimonials section ---------- */

/* Calibrated at s=1.313 (cards x50-1519 = 1469px = 1119u). Unlike every
   other section, this heading is set in BOLD SANS, not the display serif —
   measured 420u of ink for "Trusted by Families" at 48.4u. */
.eqc-section--testimonials .eqc-section-heading h2 {
	font-family: var(--eqc-font-body);
	font-weight: 800;
	font-size: var(--eqc-fs-h2-sans);
	line-height: 1.05;
}
/* The reviews band sits between two --surface sections and has to read as
   its own section: a deeper warm cream than the standard --cream token,
   distinct from both neighbours. */
.eqc-section--testimonials { background: var(--eqc-cream-150); }
.eqc-section--testimonials .eqc-card--testimonial {
	width: calc(354 * var(--eqc-u));
	max-width: 100%;
	min-height: calc(330 * var(--eqc-u));
	margin-block-start: calc(54 * var(--eqc-u));
	padding: calc(58 * var(--eqc-u)) calc(22 * var(--eqc-u)) calc(18 * var(--eqc-u));
	overflow: visible;
	text-align: center;
}
/* The corner motif sits on BOTH top corners of every card, dark enough to
   read, rather than one faint mark alternating sides card to card. */
.eqc-section--testimonials .eqc-card--testimonial::before,
.eqc-section--testimonials .eqc-card--testimonial::after {
	content: '';
	position: absolute;
	top: 0;
	width: calc(100 * var(--eqc-u));
	height: calc(108 * var(--eqc-u));
	background: var(--eqc-gold-600);
	/* Quieter than the section-level motifs: on a small card the lace sits
	   right beside the avatar and the name, so it has to stay a texture
	   rather than compete with them. */
	opacity: 0.2;
	mask: url('../svg/corner-motif.svg') center / 100% 100% no-repeat;
	pointer-events: none;
	/* The card is `overflow: visible` — it has to be, the avatar overhangs its
	   top edge — so nothing else clips this square ornament to the card's
	   ROUNDED corner, and the lace spills out into the gap between cards.
	   `border-radius` clips a pseudo-element's own painted area, so the
	   ornament follows the card's corner instead.
	   Only the outer corner needs it; the other three sit inside the card.
	   ::before is mirrored with `scale: -1 1`, which flips this radius onto
	   its visual top-LEFT — so one declaration serves both corners. */
	border-top-right-radius: var(--eqc-radius-card);
}
.eqc-section--testimonials .eqc-card--testimonial::before { left: 0; scale: -1 1; }
.eqc-section--testimonials .eqc-card--testimonial::after { right: 0; }
/* Circular avatar riding the card's top edge with the quote badge at its
   lower right, as the reference draws it. left:50% + translateX is used
   rather than inset-inline:0 + margin:auto so it stays dead-centre even when
   the carousel sizes the card wider than its own width token. */
.eqc-section--testimonials .eqc-testimonial-avatar-wrap {
	position: absolute;
	inset-block-start: calc(-54 * var(--eqc-u));
	left: 50%;
	transform: translateX(-50%);
	width: calc(108 * var(--eqc-u));
	height: calc(108 * var(--eqc-u));
	z-index: 2;
}
.eqc-section--testimonials .eqc-testimonial-photo,
.eqc-section--testimonials .eqc-testimonial-photo img {
	width: 100%; height: 100%; border-radius: 50%; object-fit: cover;
}
.eqc-section--testimonials .eqc-testimonial-photo { border: calc(3 * var(--eqc-u)) solid var(--eqc-gold-300); box-sizing: border-box; }
.eqc-section--testimonials .eqc-testimonial-quote-mark {
	position: absolute; inset-block-end: calc(-2 * var(--eqc-u)); inset-inline-end: calc(-4 * var(--eqc-u));
	width: calc(38 * var(--eqc-u)); height: calc(38 * var(--eqc-u));
	border-radius: 50%; background: var(--eqc-green-800); color: var(--eqc-white);
	display: flex; align-items: center; justify-content: center;
}
.eqc-section--testimonials .eqc-testimonial-quote-mark .eqc-icon { width: calc(16 * var(--eqc-u)); height: calc(16 * var(--eqc-u)); }
.eqc-section--testimonials .eqc-card--testimonial h3 { font-family: var(--eqc-font-body); font-weight: 700; font-size: var(--eqc-fs-h4); }
.eqc-section--testimonials .eqc-testimonial-location { font-size: var(--eqc-fs-small); color: var(--eqc-gold-700); justify-content: center; }
.eqc-section--testimonials .eqc-card--testimonial p { font-size: var(--eqc-fs-body); line-height: 1.7; }

/* Cream inset strip of three mini-features, 324 x 64u, hairline-separated. */
.eqc-section--testimonials .eqc-testimonial-tags {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	/* The cells are divided by hairline borders, not by a gap. The base
	   .eqc-testimonial-tags rule is a flex row with `gap: 0.4em 1.3em`, and
	   that 1.3em survived the switch to grid as an 18.8px column gap -- 38px
	   off the three cells, which wrapped "Personalised Focus" to two lines. */
	gap: 0;
	width: 100%;
	min-height: calc(64 * var(--eqc-u));
	margin-block-start: auto;
	background: var(--eqc-cream-50);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
	padding: calc(9 * var(--eqc-u)) 0;
	/* This strip is inset 19u from the card edge while the quote above it is
	   inset 48u, so the strip is deliberately wider than the text column. At
	   the card's own padding each cell measures 108px against a 120px label
	   and all three labels wrap to two lines. */
	margin-inline: calc(-8 * var(--eqc-u));
	width: auto;
}
.eqc-section--testimonials .eqc-testimonial-tags > span {
	display: flex; flex-direction: column; align-items: center; gap: calc(5 * var(--eqc-u));
	font-size: var(--eqc-fs-xsmall); color: var(--eqc-text); text-align: center;
	padding-inline: calc(2 * var(--eqc-u));
}
.eqc-section--testimonials .eqc-testimonial-tags > span + span { border-inline-start: 1px solid var(--eqc-border); }
.eqc-section--testimonials .eqc-testimonial-tags .eqc-icon { width: calc(21 * var(--eqc-u)); height: calc(21 * var(--eqc-u)); color: var(--eqc-gold-700); }
/* Measured against the reference: the quote sets on a 1.42 line-height (the
   inherited 1.7 body leading runs 13px taller over three lines), the name is
   a 17.9u role rather than the 14.7u h4 the teacher card uses, and the
   mini-feature label needs its own tight leading. */
.eqc-section--testimonials .eqc-card--testimonial .elementor-widget-text-editor p { line-height: 1.45; }
.eqc-section--testimonials .eqc-card--testimonial h3 { font-size: var(--eqc-fs-h3); }
.eqc-section--testimonials .eqc-testimonial-tags > span { line-height: 1.25; }
/* The avatar sits 10px below the intro; the container row gap plus the track
   padding alone would put it 62px below. */
/* Pulls the cards up under the heading rule. The limit is the avatars, which
   overhang each card and would touch the rule before the cards themselves
   look tight. */
/* The avatar hangs above its card (the -46u below), so the carousel's own
   box starts well above the first thing you actually see. Without the
   offset the avatars rose into the heading's ornate divider; this keeps a
   real gap between the divider and the topmost avatar instead. */
.eqc-section--testimonials .eqc-carousel { margin-block-start: 0; }
.eqc-section--testimonials .eqc-carousel--static .eqc-carousel-track { padding-block: 0; }
/* Client, Round 20: "move the cards up slightly". The topmost avatar sat
   67-78px below the divider (tests/visual/gap.mjs).
   The space is taken from the container's row gap between the heading and the
   carousel -- empty gap -- and only a little from the card's top margin. The
   margin cannot go much lower: an Elementor wrapper around the carousel clips
   its overflow, and at 22u the avatars rose past that edge and were cut flat
   across the top (measured -14px at 1440). 40u + 6px keeps at least 6px
   between every avatar and that edge (plain 40u left 0px at 1920). */
.eqc-section--testimonials .eqc-card--testimonial { margin-block-start: calc(40 * var(--eqc-u) + 6px); }
.e-con.eqc-section--testimonials > .e-con.eqc-container { --row-gap: 0px; row-gap: 0; }

/* Client, 2026-09-17: too much air above and below the review cards, on both
   mobile and desktop. Three separate spacings stacked here and none of them
   was reduced at any width -- the section's own 48u padding, the carousel's
   top margin (20u, now 8u above) and the dots' margin below. Measured at 1440
   before: 73px from the heading to the topmost avatar, 180px from the last
   card to the section's bottom edge.
   The card's 46u offset above is deliberately left alone: that is what holds
   the overhanging avatar clear of the heading's divider, and it is the one
   number here that is doing real work. */
.eqc-section--testimonials { padding-block: calc(12 * var(--eqc-u)); }
/* Third reduction (client, Round 20: less gap above AND below the cards).
   Above: the container row gap between the heading and the carousel is now 0
   and the card's own top margin is 40u + 6px -- the floor there is the
   carousel wrapper's clipping edge, which cuts the overhanging avatars flat
   if the cards rise any further (measured; see the card rule).
   Below: the dots sit closer to the cards, and the section's own padding is
   12u. */
.eqc-section--testimonials .eqc-slider-dots { margin-block-start: clamp(0.35rem, 0.25rem + 0.25vw, 0.6rem); }

/* ---------- Blog section ---------- */

/* s=1.282 (cards x86-1520 = 1435px = 1119u). Like the testimonials heading,
   this one is bold sans rather than the display serif. */
.eqc-section--blog .eqc-section-heading h2 {
	font-family: var(--eqc-font-body);
	font-weight: 800;
	font-size: var(--eqc-fs-h2-sans);
	line-height: 1.18;
}
.eqc-card--blog { position: relative; min-height: calc(410 * var(--eqc-u)); overflow: visible; }
.eqc-card--blog .eqc-blog-media { border-radius: var(--eqc-radius-card); overflow: hidden; display: block; }
/* White date chip over the image's top-left corner, 65 x 79u. */
.eqc-blog-date {
	position: absolute;
	inset-block-start: calc(18 * var(--eqc-u));
	inset-inline-start: calc(18 * var(--eqc-u));
	z-index: 2;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	width: calc(65 * var(--eqc-u)); min-height: calc(79 * var(--eqc-u));
	background: var(--eqc-white); border-radius: var(--eqc-radius-control);
	box-shadow: var(--eqc-shadow-card); gap: calc(2 * var(--eqc-u));
	padding: calc(6 * var(--eqc-u)) 0;
}
.eqc-blog-date .eqc-icon { width: calc(18 * var(--eqc-u)); height: calc(18 * var(--eqc-u)); color: var(--eqc-gold-700); }
.eqc-blog-date__day { font-size: var(--eqc-fs-h4); font-weight: 700; color: var(--eqc-heading); line-height: 1; }
.eqc-blog-date__mon { font-size: var(--eqc-fs-xsmall); font-weight: 600; color: var(--eqc-heading); line-height: 1; }
/* Category as gold caps above the title. */
.eqc-blog-category {
	display: block;
	font-size: var(--eqc-fs-xsmall);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--eqc-gold-700);
	margin-block-end: calc(6 * var(--eqc-u));
}
/* BOTH levels, because this card renders as either. eqc_render_blog_card()
   takes a $level: the /blog/ archive passes 2 (its h1 sits directly above the
   cards), the homepage and the shortcode leave it at 3. When the archive moved
   to h2 this rule stopped matching there and the titles silently fell through
   to the global h2 -- the SECTION-heading scale, 56px at 1440 against the 26px
   intended here. Nothing failed; the page just had huge titles.
   Same trap as `a.eqc-btn--outline` never matching a <button>: an
   element-qualified selector has to name every element the component can be.
   Two lines are reserved because post titles mix one- and two-line cases in the
   same row, which moved each excerpt's first line. */
.eqc-card--blog h2,
.eqc-card--blog h3 { font-size: var(--eqc-fs-h3); line-height: 1.25; min-block-size: 2.5em; }
.eqc-card--blog .eqc-blog-excerpt { font-size: var(--eqc-fs-body); line-height: 1.65; }
/* "Read More" with a gold double-chevron disc, bottom right. */
.eqc-card--blog .eqc-read-more {
	margin-block-start: auto;
	align-self: flex-end;
	display: inline-flex; align-items: center; gap: calc(9 * var(--eqc-u));
	font-size: var(--eqc-fs-small); font-weight: 700; color: var(--eqc-gold-700);
}
.eqc-read-more__disc {
	display: inline-flex; align-items: center; justify-content: center;
	width: calc(31 * var(--eqc-u)); height: calc(31 * var(--eqc-u));
	border-radius: 50%; background: var(--eqc-gold-600); color: var(--eqc-white);
}
.eqc-read-more__disc .eqc-icon { width: calc(15 * var(--eqc-u)); height: calc(15 * var(--eqc-u)); }

/* ---------- Search / blog pagination ----------
 * paginate_links() emits bare <a class="page-numbers"> and the theme styled
 * none of it, so /?s= rendered its page links as unpadded digits -- measured
 * 9x24 and 8x24, the smallest targets anywhere on the site.
 *
 * Sized to the 44px floor DIRECTLY rather than with the ::after hit-area trick
 * used further down, because these controls sit side by side: growing each
 * one's pseudo-element to 44px would make adjacent targets OVERLAP, which WCAG
 * 2.5.8 counts against just as it does undersized ones. A real box plus the
 * row gap keeps clear space between them.
 *
 * The layout properties were inline on the <nav> in archive.php; they belong
 * here, with the rest of the presentation.
 */
.eqc-pagination {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: calc(9 * var(--eqc-u));
	margin-block-start: var(--eqc-section-space);
}
.eqc-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding-inline: 0.75em;
	border: 1px solid var(--eqc-cream-200);
	border-radius: var(--eqc-radius-control);
	background: var(--eqc-cream-50);
	color: var(--eqc-bronze-700);
	font-size: var(--eqc-fs-small);
	font-weight: 700;
	text-decoration: none;
}
.eqc-pagination a.page-numbers:hover,
.eqc-pagination a.page-numbers:focus-visible {
	border-color: var(--eqc-gold-500);
	color: var(--eqc-green-800);
}
.eqc-pagination .page-numbers.current {
	background: var(--eqc-green-800);
	border-color: var(--eqc-green-800);
	color: var(--eqc-white);
}
/* An ellipsis is text, not a control -- it must not look or size like one. */
.eqc-pagination .page-numbers.dots {
	min-width: 0;
	border-color: transparent;
	background: none;
}

/* ---------- Tap-target floors (DESIGN.md §22, TASK §9) ---------- */

/* Carousel dots and footer links are visually small by design, but a 24x24
   dot and a 33px-tall link are below the 44px minimum. Expanding the HIT AREA
   with a pseudo-element keeps the visual size exactly as designed while
   giving pointer and touch input a full-size target — no layout shift. */
.eqc-slider-dot { position: relative; }
.eqc-slider-dot::after {
	content: '';
	position: absolute;
	inset: 50% auto auto 50%;
	translate: -50% -50%;
	width: 44px;
	height: 44px;
}
.eqc-footer-links a,
.eqc-footer-contact a { position: relative; }
.eqc-footer-links a::after,
.eqc-footer-contact a::after {
	content: '';
	position: absolute;
	inset-block: -6px;
	inset-inline: 0;
	min-height: 44px;
}

/* Shrinking the header and the type scale pulled these under 44px too. Same
   technique — expand the hit area, leave the visual size alone. The nav link
   uses ::before because its ::after is the hover underline. */
.eqc-nav-list a { position: relative; }
.eqc-nav-list a::before {
	content: '';
	position: absolute;
	inset: 50% auto auto 50%;
	translate: -50% -50%;
	width: 100%;
	height: 44px;
}
.eqc-read-more,
.eqc-nav-btn,
.eqc-logo-link,
.eqc-single-back { position: relative; }
.eqc-read-more::after,
.eqc-nav-btn::after,
.eqc-logo-link::after,
.eqc-single-back::after {
	content: '';
	position: absolute;
	inset: 50% auto auto 50%;
	translate: -50% -50%;
	width: max(100%, 44px);
	height: max(100%, 44px);
}

/* ---------- Vertical density pass ----------
 * Measured against the reference: the courses section spans 940u there
 * against 1256u unadjusted (+34%). Section-height ratios against the hero
 * show the same excess across about/pricing/teachers/testimonials, and those
 * ratios are immune to the composite's uncertain vertical scale, so the
 * excess is real rather than a scaling artefact.
 *
 * The excess is NOT type size (those are measured) — it is the gaps between
 * elements and the eyebrow's oversized icon. */
.eqc-section-heading { gap: calc(8 * var(--eqc-u)); }
/* No --plain icon override here (it was 30u square): --plain is no longer a
   distinct treatment (see the shared .eqc-eyebrow block), and such a rule
   would re-inflate its icon AFTER that block and reintroduce the
   inconsistency the shared block removes. */
.eqc-card--course { gap: calc(2 * var(--eqc-u)); }
.eqc-card--course p { line-height: 1.45; }
.eqc-card--course .eqc-card-divider { margin-block: calc(3 * var(--eqc-u)); }

/* Elementor adds --widgets-spacing (20px by default) as a bottom margin on
   every widget, which stacks ON TOP of the flex `gap` these cards already
   set. Inside a card that is a second, invisible gap on every row — the main
   reason each card ran ~50u taller than its reference. Zeroed where the card
   owns its own rhythm; the page-level containers keep Elementor's spacing. */
.eqc-card,
.eqc-section-heading,
.eqc-hero-text,
.eqc-about-text,
.eqc-teachers-aside { --widgets-spacing: 0px; }
.eqc-card > .elementor-widget,
.eqc-section-heading > .elementor-widget { margin-block-end: 0; }

/* The heading element itself still carried 8px/16px of its own margin inside
   that widget, on top of the stack's gap. The stack owns the rhythm. */
.eqc-section-heading h1,
.eqc-section-heading h2,
.eqc-section-heading h3,
.eqc-section-heading p { margin-block: 0; }

/* Inside a card the widget wrappers carry paragraph margins on top of the
   card's own flex gap — measured 20.8u on the body copy and 6u on the divider
   of every course card. The card owns its rhythm, so the inner margins go.
   Multi-paragraph bodies (the about column) keep theirs. */
.eqc-card .elementor-widget-text-editor p:only-child,
.eqc-card .eqc-card-divider,
.eqc-card .eqc-teacher-divider,
.eqc-card .eqc-testimonial-divider { margin-block: 0; }
.eqc-card .elementor-widget-text-editor p:only-child { margin: 0; }

/* ---------- Course detail pages ---------- */

/* Course meta tags: cream tiles with the icon centred above a two-line
   label, matching the reference's "Why Choose" tile treatment rather than a
   small inline pill row. */
/* The tiles must come out the same size. Two things break that, both
   measured at 390px: without `grid-auto-rows` each ROW sizes independently
   (row 1 at 204px against row 2's 161px), and a label that wraps to two
   lines pushes its own value down to 134px while its neighbour's sits at
   112px. Equal rows come from the tag-card group contract; the reserved
   two-line label box below fixes the second, without touching the copy. */
.eqc-course-meta-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--eqc-grid-gap); }
.eqc-course-meta-tile {
	background: var(--eqc-cream-50);
	border-radius: var(--eqc-radius-card);
	padding: clamp(1.75rem, 1.4rem + 1.4vw, 2.5rem) 1.25rem;
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	transition: transform var(--eqc-motion-base) var(--eqc-ease-standard), box-shadow var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-course-meta-tile:hover { transform: translateY(-4px); box-shadow: var(--eqc-shadow-card-hover); }
.eqc-course-meta-tile .eqc-icon { width: 2.8em; height: 2.8em; color: var(--eqc-green-700); margin-block-end: 0.7em; }
/* The reference's tiles carry one bold, generously-sized statement each.
   This tile pairs a label with a value the reference does not have, so
   rather than dropping that second line, both are sized up together: the
   label to heading scale, the value to full body size rather than a
   small/muted caption role, which reads as an afterthought beside the
   reference's tiles. */
/* min-block-size reserves the two lines the longest label ("Course
   Duration") needs, so every tile's value starts on the same baseline
   whether its own label wrapped or not. */
.eqc-course-meta-tile-label {
	display: flex;
	align-items: center;
	justify-content: center;
	min-block-size: 2.6em;
	font-size: var(--eqc-fs-h4);
	font-weight: 700;
	line-height: 1.3;
	color: var(--eqc-heading);
}
.eqc-course-meta-tile-value { display: block; color: var(--eqc-text); font-size: var(--eqc-fs-body); line-height: 1.4; margin-block-start: 0.3em; }
@media (max-width: 720px) {
	.eqc-course-meta-grid { grid-template-columns: repeat(2, 1fr); }
	/* Tighter type and icon at phone widths so "Course Duration" stays on
	   one line in a half-width tile rather than forcing the reserved
	   two-line box to be the normal case. */
	.eqc-course-meta-tile { padding-inline: 0.85rem; }
	.eqc-course-meta-tile-label { font-size: var(--eqc-fs-body); min-block-size: 2.8em; }
	.eqc-course-meta-tile-value { font-size: var(--eqc-fs-small); }
	.eqc-course-meta-tile .eqc-icon { width: 2.3em; height: 2.3em; }
}

/* Course Summary table: a full panel with its own heading and a small icon
   per row, vertically centred so it does not read as sparse next to the
   taller Course Features checklist beside it (.eqc-grid--2col). Cream/gold
   palette rather than the reference's yellow — the reference screenshots are
   inspiration, not a literal palette to clone (DESIGN.md). */
.eqc-summary-table {
	background: var(--eqc-cream-50);
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-panel);
	padding: clamp(1.4rem, 1.1rem + 1.5vw, 2.25rem);
	display: flex;
	flex-direction: column;
	justify-content: center;
	height: 100%;
}
.eqc-summary-table h3 { margin: 0 0 0.9em; font-size: var(--eqc-fs-h4); }
.eqc-summary-table table { width: 100%; border-collapse: collapse; }
.eqc-summary-table tr + tr th,
.eqc-summary-table tr + tr td { border-top: 1px solid var(--eqc-border); }
.eqc-summary-table th,
.eqc-summary-table td { text-align: left; padding-block: 0.85em; vertical-align: middle; font-weight: 400; }
/* Never `display: flex` a `th`: it takes the cell out of the table
   formatting context, the row then generates anonymous cells, and with a
   nowrap label column wider than the viewport can give it the borders and
   alignment fall apart at narrow widths. The flex box lives inside the cell
   as .eqc-summary-label instead, and there is no nowrap. */
.eqc-summary-table th {
	color: var(--eqc-muted);
	font-weight: 600;
	padding-inline-end: 1em;
}
.eqc-summary-label { display: flex; align-items: center; gap: 0.6em; }
.eqc-summary-table th .eqc-icon { flex: none; width: 1.3em; height: 1.3em; color: var(--eqc-gold-600); }
.eqc-summary-table td { color: var(--eqc-heading); font-weight: 600; }
/* Elementor's reset.css gives EVERY table cell a grey 1px border and a zebra
   background on odd rows. Collapsed borders hide most of that on desktop, but
   below 40rem the cells become blocks, nothing collapses, and each one paints
   its own box, leaving a grid of grey rectangles. The child combinators here
   outrank reset.css's `tbody > tr:nth-child(2n+1) > td`, so the panel draws
   only its own hairline row separators. */
.eqc-summary-table tbody > tr > th,
.eqc-summary-table tbody > tr > td {
	border: 0;
	background: transparent;
}
/* The zebra stripe needs its own reset: reset.css scores it with a
   pseudo-class and four elements, which outranks the rule above, so this one
   mirrors that selector and adds our class to win on specificity rather than
   with !important. */
.eqc-summary-table table tbody > tr:nth-child(2n+1) > th,
.eqc-summary-table table tbody > tr:nth-child(2n+1) > td { background: transparent; }
.eqc-summary-table tbody > tr + tr > th,
.eqc-summary-table tbody > tr + tr > td { border-top: 1px solid var(--eqc-border); }
@media (max-width: 40rem) {
	/* Two columns cannot both stay readable at 360px — "Languages Offered"
	   alone needs most of the width. Each row becomes a stacked
	   label-over-value block, the standard responsive-table pattern, while
	   the native <table> semantics stay intact for assistive tech. The row,
	   not the cell, carries the separator so label and value read as one
	   unit. */
	.eqc-summary-table table,
	.eqc-summary-table tbody,
	.eqc-summary-table tr,
	.eqc-summary-table th,
	.eqc-summary-table td { display: block; width: 100%; }
	.eqc-summary-table tbody > tr + tr { border-top: 1px solid var(--eqc-border); margin-top: 0.9em; padding-top: 0.9em; }
	.eqc-summary-table tbody > tr + tr > th,
	.eqc-summary-table tbody > tr + tr > td { border-top: 0; }
	.eqc-summary-table th { padding: 0 0 0.3em; font-size: var(--eqc-fs-small); }
	.eqc-summary-table td { padding: 0; line-height: 1.45; }
	.eqc-summary-table th .eqc-icon { width: 1.15em; height: 1.15em; }
}

/* Course Levels: numbered rosette badge (reusing the plain .eqc-card-index
   treatment already shared with the Beginner Pathway steps) plus a small
   icon on each Objective/Topics/Outcome sub-heading, so the four cards read
   as a distinct, attention-grabbing progression rather than four blocks of
   plain paragraph text.
   Named .eqc-level-heading, not .eqc-card-level: that name is already taken
   by the plain "(BEGINNER)" course-card label
   (".eqc-card--course .eqc-card-level"). Reusing it here leaks `display:flex`
   onto that unrelated label, and a flex item ignores the card's own
   `text-align:center`, breaking its centring. */
/* Course-level cards: the three sections line up ACROSS the row.
   Each card hands its five slots (index, title, objective, topics, outcome) to
   the row's own grid with `grid-template-rows: subgrid`, so every slot's height
   is the taller of the two cards and the next slot starts at the same place in
   both. Nothing else achieves this here: the sections are genuinely different
   lengths, so no fixed min-height is right at every width, and the older trick
   of reserving space for the longest case would leave a visible hole on the
   short card at most viewports.

   Two pieces of plumbing:
   - The Elementor HTML widget sits between the grid and the card, so the WIDGET
     is the grid item, not the card. `display: contents` removes that box so the
     card itself becomes the item -- subgrid can only inherit rows from its own
     parent grid. The selector carries .eqc-grid too (0,3,0) so it outranks the
     `.eqc-grid > .elementor-widget-html { display: flex }` rule near the top of
     this file, which is (0,2,0) and would otherwise win or lose on source order
     alone.
   - `.eqc-card.eqc-card--level` (0,2,0) beats `.eqc-card`'s own
     `display: flex` (0,1,0) without depending on order.

   Guarded by @supports because `grid-row: span 5` WITHOUT subgrid would put the
   card across five implicit auto rows and pull its own content apart -- a worse
   result than the misalignment being fixed. Browsers without subgrid keep the
   plain flex card. This is the only @supports in the stylesheet, and it is here
   because the fallback is actively harmful rather than merely different. */
.eqc-grid--levels { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 36rem) {
	.eqc-grid--levels { grid-template-columns: 1fr; }
}
@supports (grid-template-rows: subgrid) {
	.eqc-grid.eqc-grid--levels > .elementor-widget-html { display: contents; }
	.eqc-grid--levels .eqc-card.eqc-card--level {
		display: grid;
		grid-row: span 5;
		grid-template-rows: subgrid;
		row-gap: 0;
	}
}
.eqc-card--level { position: relative; }
.eqc-card--level h3 { margin-block: 0.5em 0.2em; }
/* Each section's heading opens its own block now, so the "first heading has no
   top margin" rule moves from the card to the block. */
.eqc-level-block > .eqc-level-heading:first-child { margin-block-start: 0; }
.eqc-level-block + .eqc-level-block { margin-block-start: 1em; }
.eqc-level-block > :last-child { margin-block-end: 0; }
.eqc-level-heading {
	display: flex;
	align-items: center;
	gap: 0.5em;
	margin: 1em 0 0.3em;
	font-weight: 700;
	color: var(--eqc-bronze-700);
	font-size: var(--eqc-fs-small);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}
.eqc-level-heading .eqc-icon { width: 1.1em; height: 1.1em; }
.eqc-level-heading:first-of-type { margin-top: 0; }

/* CTA banner: a white form card sitting inside a full-bleed green band.
   Rendered once, globally, by footer.php immediately above the footer's own
   CTA panel — not per-page — so it appears on every route from one
   definition.

   The band is simply the whole section (inset: 0, edge to edge), and the
   section's own SYMMETRIC block padding is what shows as green above and
   below the card. That centres the card vertically by construction at every
   viewport and at every card height, with no percentage to drift.

   Two shapes to avoid, both of which have been measured here. A band sized
   to only part of the section (for example an 83px stripe flush to the
   section's bottom) leaves the card straddling nothing, with the footer's
   own cream top padding showing between the stripe and the dark footer
   panel: cream / thin green stripe / cream / dark panel. And a band that
   bleeds INTO the footer merges with the footer's own dark CTA panel and
   reads as one indeterminate dark mass rather than a panel behind this card.
   The separation from the footer's dark panel comes from the footer's own
   top padding below this section. */
/* Block padding deliberately tight: this is the green showing above and
   below the card, and it is also what centres the card, so both edges move
   together. */
.eqc-cta-banner-section { position: relative; padding-block: clamp(0.9rem, 0.65rem + 0.9vw, 1.6rem); overflow: visible; }
.eqc-cta-banner-section::before {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--eqc-green-900);
	z-index: 0;
}
.eqc-cta-banner {
	position: relative;
	z-index: 1;
	display: flex;
	background: var(--eqc-white);
	border-radius: var(--eqc-radius-panel);
	box-shadow: var(--eqc-shadow-card);
	/* A compact single-row prompt bar, not a tall card; deeper block padding
	   makes this read as a form SECTION instead. Inline padding is
	   deliberately left alone. */
	padding: clamp(0.6rem, 0.45rem + 0.55vw, 1rem) clamp(1.25rem, 1rem + 1.5vw, 2rem);
	align-items: center;
	gap: clamp(1rem, 0.6rem + 2vw, 2rem);
	flex-wrap: wrap;
	overflow: hidden;
	isolation: isolate;
	border: 1px solid rgba(169, 130, 53, 0.38);
	background: linear-gradient(135deg, var(--eqc-white) 0%, #fffaf0 72%, #f7edd4 100%);
}
/* `display: flex` has to be set on .eqc-cta-banner itself, not just
   align-items/gap/flex-wrap: without it the card computes to its default
   `display: block` and the heading renders as a full-width block ABOVE the
   form instead of beside it. A bounded flex-basis (rather than 1 1 220px,
   free to grow) keeps the title acting as a left-hand label rather than
   eating room from the form row. */
.eqc-cta-banner-title { flex: 0 1 15rem; margin: 0; color: var(--eqc-green-900); font-size: clamp(1.5rem, 1.25rem + 0.9vw, 2rem); line-height: 1.1; letter-spacing: 0.01em; text-wrap: balance; }
.eqc-cta-banner-title::after {
	content: '';
	display: block;
	width: clamp(3.25rem, 4vw, 5rem);
	height: 3px;
	margin-block-start: 0.55em;
	background: var(--eqc-gold-500);
	transform: scaleX(0);
	transform-origin: left center;
	animation: eqc-cta-line 900ms var(--eqc-ease-standard) 180ms forwards;
}
.eqc-cta-banner .fluentform,
.eqc-cta-banner form.frm-fluent-form { margin: 0; flex: 2 1 360px; }
/* FluentForms wraps EACH field in its own `.ff-el-group` (label div +
   content div, stacked) with no wrapper around the set of groups besides
   `fieldset` — the previous rule here flexed the inside of a single group
   (label beside its own input) but never the fieldset itself, so the two
   fields and the submit button just stacked as three block-level groups.
   This targets the actual row: the fieldset holds Name / Phone / Submit
   side by side on wide screens and wraps to one-per-line on phones. */
.eqc-cta-banner form fieldset { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem; }
.eqc-cta-banner .ff-el-group { flex: 1 1 11rem; margin: 0; }
/* Client, 2026-09-19: no visible labels on this compact banner; the
   placeholders carry the cue. The labels stay native (FluentForms editor
   owns them) and remain in the accessibility tree -- visually hidden, not
   removed. !important because FluentForms' own label rules load later. */
.eqc-cta-banner .ff-el-group .ff-el-input--label {
	display: block !important;
	position: absolute !important;
	inline-size: 1px !important;
	block-size: 1px !important;
	margin: -1px !important;
	padding: 0 !important;
	overflow: hidden !important;
	clip: rect(0, 0, 0, 0) !important;
	clip-path: inset(50%) !important;
	white-space: nowrap !important;
}
.eqc-cta-banner .ff-el-group { margin-block-end: 0 !important; }
.eqc-cta-banner .ff_submit_btn_wrapper { flex: 0 0 auto; margin: 0; }
.eqc-cta-banner .ff-el-form-control {
	min-height: 52px;
	width: 100%;
	/* Green-edged boxes: they read as inputs against the cream card and
	   echo the green ring graphics behind them. */
	border: 2px solid rgba(20, 49, 38, 0.32) !important;
	background: var(--eqc-cream-50) !important;
	box-shadow: 0 3px 0 rgba(20, 49, 38, 0.08);
	transition: border-color var(--eqc-motion-base) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-base) var(--eqc-ease-standard),
		transform var(--eqc-motion-base) var(--eqc-ease-standard);
}
.eqc-cta-banner .ff-el-form-control::placeholder { color: var(--eqc-muted); opacity: 1; }
.eqc-cta-banner .ff-el-form-control:focus {
	border-color: var(--eqc-green-800) !important;
	box-shadow: 0 0 0 4px rgba(20, 49, 38, 0.16), 0 4px 0 rgba(20, 49, 38, 0.1) !important;
	transform: translateY(-1px);
}
.eqc-cta-banner .ff-btn, .eqc-cta-banner button[type="submit"] { white-space: nowrap; flex: none; }
.eqc-cta-banner .ff-btn,
.eqc-cta-banner button[type="submit"] {
	background: var(--eqc-bronze-700) !important;
	color: var(--eqc-white) !important;
	border: 1px solid var(--eqc-bronze-700) !important;
	box-shadow: 0 8px 18px rgba(122, 67, 42, 0.2), 0 0 0 2px rgba(169, 130, 53, 0.22);
	transition: background-color var(--eqc-motion-fast) var(--eqc-ease-standard),
		border-color var(--eqc-motion-fast) var(--eqc-ease-standard),
		box-shadow var(--eqc-motion-fast) var(--eqc-ease-standard),
		transform var(--eqc-motion-fast) var(--eqc-ease-standard);
}
.eqc-cta-banner .ff-btn:hover,
.eqc-cta-banner button[type="submit"]:hover {
	border-color: var(--eqc-gold-500) !important;
	box-shadow: 0 11px 22px rgba(122, 67, 42, 0.26);
	transform: translateY(-2px);
}
@media (max-width: 40rem) {
	/* Client, 2026-09-17: on phones the green band goes and the banner itself
	   runs edge to edge.
	   Three things have to move together or it only half works. The band is
	   the section's ::before, so it is switched off rather than resized (the
	   pseudo-element stays in place -- nothing else on this element uses it,
	   and removing `content` would be a second rule for no gain). The card is
	   inside .eqc-container, whose width is `100% - 2 * gutter`, so the gutter
	   is what actually holds it off the edges and it has to go. And a card
	   sitting flush against both edges with rounded corners and a drop shadow
	   reads as a mistake, so both are dropped at this width only. */
	.eqc-cta-banner-section::before { background: none; }
	.eqc-cta-banner-section > .eqc-container { width: 100%; }
	.eqc-cta-banner { border-radius: 0; box-shadow: none; }
	.eqc-cta-banner { flex-direction: column; align-items: stretch; text-align: center; }
	/* flex-basis tracks the main axis, which this rule just flipped to
	   vertical — the desktop 15rem/360px bases above (meant as max/min
	   WIDTHS) were computing as forced HEIGHTS once column direction took
	   effect: a 240px-tall title, then a 360px-tall form wrapper holding
	   only 233px of actual fields, opening a huge blank gap between them
	   (found live: title height 240px, .fluentform height 360px, both at
	   390px). Reset both to auto so height goes back to content height. */
	.eqc-cta-banner-title,
	.eqc-cta-banner .fluentform,
	.eqc-cta-banner form.frm-fluent-form { flex-basis: auto; }
	/* Labels are hidden, so this gap is the only thing separating one
	   field from the next: tight enough to read as one form, open enough
	   that each box is its own tap target. The button gets a little more
	   so it reads as the conclusion rather than a third field. */
	.eqc-cta-banner form fieldset { flex-direction: column; align-items: stretch; gap: 0.9rem !important; }
	.eqc-cta-banner .ff-el-group { flex: none; width: 100%; }
	.eqc-cta-banner .ff_submit_btn_wrapper { margin-block-start: 0.35rem; }
	.eqc-cta-banner .ff_submit_btn_wrapper,
	.eqc-cta-banner .ff_submit_btn_wrapper .ff-btn { width: 100%; }
	.eqc-cta-banner-title::after { margin-inline: auto; }
}

@media (max-width: 40rem) {
	.eqc-form-grid {
		width: calc(100% + 20px);
		margin-inline: -10px;
	}
	.eqc-form-grid > .eqc-form-aside {
		padding-inline: 0;
		width: calc(100% + 20px);
		margin-inline: -10px;
	}
}

@media (max-width: 40rem) {
	.eqc-section--about .eqc-about-text .elementor-heading-title {
		font-size: clamp(28px, 9vw, 35.7px);
		letter-spacing: -0.015em;
		text-wrap: balance;
	}
}

/* ---------- Teacher profile (Reviews.md R14; always open, client 2026-09-20) --
   Every profile on /teachers/ is part of its card, with no "View Profile"
   control and nothing to expand. It used to be a disclosure whose single grid
   row animated 0fr -> 1fr; six profiles on one page did not earn the extra
   click, and an always-open profile is readable with no JavaScript at all.
   The [hidden] override keeps a card that still carries the old markup (baked
   into a page's saved Elementor data before that date) readable too. */
.eqc-teacher-panel {
	display: grid;
	grid-template-rows: 1fr;
	inline-size: 100%;
	text-align: start;
}
.eqc-teacher-panel[hidden] { display: grid; }
/* Cards in a row are equal height but their profiles are not equal length, so
   the panel takes the leftover height and the CTA pair sits on the card's
   floor. Without this the two buttons land wherever each profile happens to
   end and the row's one action reads as ragged. */
/* Both wrappers: with Elementor's optimized DOM output the widget holds the
   panel directly, and with it off there is an .elementor-widget-container in
   between. Whichever exists has to grow, or the panel below cannot. */
.eqc-card--teacher > .eqc-teacher-panel-widget,
.eqc-teacher-panel-widget > .elementor-widget-container {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
}
.eqc-card--teacher .eqc-teacher-panel { flex: 1 1 auto; }
.eqc-teacher-panel-inner { display: flex; flex-direction: column; }
.eqc-teacher-panel-cta { margin-block-start: auto; }
/* An inset panel rather than more of the card. The profile used to run
   straight on from the facts list in the same size and colour as everything
   above it, so a long one read as an undifferentiated column of small grey
   text with no entry point. */
.eqc-teacher-panel-inner {
	min-block-size: 0;
	padding: calc(16 * var(--eqc-u));
	margin-block-start: calc(14 * var(--eqc-u));
	border: 1px solid var(--eqc-border);
	border-radius: var(--eqc-radius-control);
	background: var(--eqc-cream-50);
	text-align: start;
}

.eqc-teacher-bio {
	margin: 0 0 calc(14 * var(--eqc-u));
	font-size: var(--eqc-fs-body);
	line-height: 1.7;
	color: var(--eqc-text);
}
/* Label ABOVE its value, not beside it. The two-column grid gave the label
   column whatever "Teaching focus" needed -- about 130px -- and left the value
   in a ~180px measure on a 388px card, which wrapped every answer after four
   or five words into a tall ragged stack. Stacking them gives the value the
   full width and reads as a short labelled section instead. */
.eqc-teacher-detail {
	display: block;
	margin: 0 0 calc(14 * var(--eqc-u));
	font-size: var(--eqc-fs-small);
	line-height: 1.6;
}
.eqc-teacher-detail dt {
	margin-block-start: 0.85em;
	color: var(--eqc-green-800);
	font-size: var(--eqc-fs-xsmall);
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	white-space: normal;
}
.eqc-teacher-detail dt:first-child { margin-block-start: 0; }
.eqc-teacher-detail dd {
	margin: 0.2em 0 0;
	color: var(--eqc-text);
}
.eqc-teacher-tags {
	display: flex;
	flex-wrap: wrap;
	gap: calc(6 * var(--eqc-u));
	margin: 0 0 calc(14 * var(--eqc-u));
	padding: 0;
	list-style: none;
}
.eqc-teacher-tags li {
	padding: 0.3em 0.75em;
	background: var(--eqc-surface);
	font-weight: 600;
	border: 1px solid var(--eqc-gold-500);
	border-radius: 999px;
	font-size: var(--eqc-fs-xsmall);
	color: var(--eqc-bronze-700);
	/* align-self stops the pill stretching to the row width: these sit in a
	   flex context, the same trap the section tags hit in Round 15. */
	align-self: flex-start;
}
/* The two CTAs wrap rather than shrink, so neither label is ever clipped on a
   narrow card. */
.eqc-teacher-panel-cta {
	display: flex;
	flex-wrap: wrap;
	gap: calc(8 * var(--eqc-u));
	/* The row is its own size container: the label swap below follows the
	   PANEL's width, not the screen's. */
	container-type: inline-size;
}
/* Short labels whenever the row cannot hold both full ones (client, Round 20:
   "Chat on WhatsApp" spilled past its pill on desktop). The shared swap in
   the button section is a viewport query at 28rem, which is right for the
   hero pair and wrong here: this panel sits in a three-up grid, so it is at
   its NARROWEST on a desktop -- a 220-465px row between 1024 and 2560px,
   against 341-485px needed for both full labels -- and widest on a tablet
   (453px at 768, needing 341). No pixel breakpoint separates those two
   cases, because the need grows with the type and the padding. Measured in
   the row's own em it does: the largest need is 28.5em (2560px), so below
   29em the short labels show. The accessible name is the full wording at
   every width (aria-label, see eqc_btn_label()). */
@container (max-width: 29em) {
	.eqc-teacher-panel-cta .eqc-btn-label-full { display: none; }
	.eqc-teacher-panel-cta .eqc-btn-label-short { display: inline; }
}
/* Equal halves at EVERY width (client, 2026-09-17). `flex: 0 1 auto` sized
   each button to its own label, so the pair came out lopsided -- one wide, one
   narrow -- and wrapped unpredictably. `1 1 0` ignores content width and splits
   the row evenly; min-inline-size:0 is what actually lets a button shrink below
   its label's width, since `auto` is a flex item's default minimum. */
.eqc-teacher-panel-cta .eqc-btn {
	flex: 1 1 0;
	min-inline-size: 0;
	justify-content: center;
	padding-inline: calc(12 * var(--eqc-u));
	white-space: nowrap;
}
/* One button per line only when even the SHORT pair cannot share the row.
   The client asked for this pair side by side on every screen (2026-09-17),
   and it stays that way wherever it physically fits. The narrowest panels
   are the exception: at 320px the row is 160px, each half 77px, and
   "WhatsApp" with its icon needs ~111px, so the label ran 7.5px past its
   pill; at 360px it touched the edge. The short pair needs ~16em of row
   (two ~111px buttons plus the gap, at the row's 15px type). Doubled class:
   the base rule above has the same specificity. */
@container (max-width: 16em) {
	.eqc-teacher-panel-cta.eqc-teacher-panel-cta .eqc-btn { flex-basis: 100%; }
}

/* ---------- Four-stat band (Reviews.md R17; rebuilt Round 20) ----------
   Website_banner.png: a cream lead statistic beside three supporting figures
   on deep green, as ONE panel.

   Every part is an Elementor container now (native Counter widgets, so the
   figures are editable), and a container brings its own padding and gap. Left
   at their defaults they broke the panel into pieces the client flagged as
   "shapes looking very bad": the band's rounded outline showed around inset
   blocks, a 20px gap and a 2px gold bar split the halves, and every cell drew
   its own cream outline, which read as heavy pipes. Container padding and
   gaps are therefore zeroed here explicitly (`.e-con` doubled into the
   selector: Elementor's own container rules are as specific as a bare class).

   Separators are short gold hairlines that fade out at both ends, with a
   small diamond at the centre -- the divider language the section headings
   already use -- instead of full-height lines.

   Colours of the figures and labels are NOT set here: they are the Counter
   widgets' own settings (eqc_counter() in tools/elementor-helpers.php), so an
   editor's colour change in Elementor applies. */
.e-con.eqc-stats-band,
.e-con.eqc-stats-lead,
.e-con.eqc-stats-cells,
.e-con.eqc-stats-cell {
	--padding-top: 0;
	--padding-right: 0;
	--padding-bottom: 0;
	--padding-left: 0;
	--gap: 0px;
	--row-gap: 0px;
	--column-gap: 0px;
	gap: 0;
	padding: 0;
}
.e-con.eqc-stats-band {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	align-items: stretch;
	inline-size: 100%;
	border-radius: var(--eqc-radius-panel);
	overflow: hidden;
	border: 1px solid rgb(var(--eqc-gold-500-rgb) / 0.45);
	box-shadow: var(--eqc-shadow-card);
	background: var(--eqc-green-900);
}
.e-con.eqc-stats-lead {
	background: linear-gradient(145deg, var(--eqc-cream-50), var(--eqc-cream-100));
	padding: clamp(22px, calc(30 * var(--eqc-u)), 46px);
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: calc(6 * var(--eqc-u));
}
/* One gradient behind all three cells, so there are no seams between them. */
.e-con.eqc-stats-cells {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	background: linear-gradient(120deg, var(--eqc-green-800), var(--eqc-green-900) 70%);
}
.e-con.eqc-stats-cell {
	position: relative;
	background: none;
	box-shadow: none;
	padding: clamp(22px, calc(30 * var(--eqc-u)), 46px) clamp(18px, calc(28 * var(--eqc-u)), 42px);
	display: flex;
	flex-direction: column;
	justify-content: center;
}
/* Separators: a hairline that fades in and out, and a diamond on it. Drawn on
   every cell after the first, and on the first cell against the lead panel. */
.e-con.eqc-stats-cell::before,
.e-con.eqc-stats-cell::after {
	content: '';
	position: absolute;
	pointer-events: none;
}
.e-con.eqc-stats-cell::before {
	inset-block: 20%;
	inset-inline-start: 0;
	inline-size: 1px;
	background: linear-gradient(180deg, transparent, rgb(var(--eqc-gold-500-rgb) / 0.75) 50%, transparent);
}
.e-con.eqc-stats-cell::after {
	inset-block-start: 50%;
	inset-inline-start: 0;
	inline-size: 7px;
	block-size: 7px;
	background: var(--eqc-gold-500);
	transform: translate(-50%, -50%) rotate(45deg);
}
/* The first cell's left edge is the seam with the cream lead panel: a solid
   gold line, full height, and NO diamond. A diamond there straddled two
   different grounds -- half on cream, half on green -- and read as a
   misplaced chip (client, Round 20). The diamonds belong only to the
   separators between the green cells, where both sides match. */
.e-con.eqc-stats-cell:first-child::before { inset-block: 0; background: var(--eqc-gold-500); inline-size: 2px; }
.e-con.eqc-stats-cell:first-child::after { display: none; }

/* Type only -- see the colour note above. Two ancestor classes: Elementor's
   per-widget rule for the Kit's global typography is as specific as one, and
   loads later. */
.eqc-stats-band .eqc-stats-lead .elementor-counter,
.eqc-stats-band .eqc-stats-cells .elementor-counter { align-items: flex-start; gap: calc(4 * var(--eqc-u)); }
.eqc-stats-band .eqc-stats-lead .elementor-counter-number-wrapper,
.eqc-stats-band .eqc-stats-cells .elementor-counter-number-wrapper {
	margin: 0;
	font-family: var(--eqc-font-display);
	font-size: clamp(34px, calc(46 * var(--eqc-u)), 66px);
	font-weight: 400;
	line-height: 1.05;
	text-align: start;
	justify-content: flex-start;
	font-variant-numeric: tabular-nums;
}
.eqc-stats-band .eqc-stats-lead .elementor-counter-title,
.eqc-stats-band .eqc-stats-cells .elementor-counter-title {
	margin: 0;
	font-family: var(--eqc-font-body);
	font-size: var(--eqc-fs-body);
	font-weight: 600;
	letter-spacing: 0.01em;
	line-height: 1.3;
	justify-content: flex-start;
	text-align: start;
}
.eqc-stats-band .eqc-stats-lead .elementor-counter-title { font-weight: 700; }
/* Elementor gives the prefix and suffix spans flex-grow: 1, so a centred
   counter stays centred. In a left-aligned figure the empty prefix grew and
   pushed the digits away from their label ("1,500+" sat visibly to the right). */
.eqc-stats-band .elementor-counter-number-wrapper > span { flex-grow: 0; }
.eqc-stats-note p {
	margin: 0;
	font-size: var(--eqc-fs-small);
	line-height: 1.55;
	color: var(--eqc-text);
}
/* Reserve inline space for each counter's longest string (prefix+number+
   suffix) so the surrounding layout never shifts while it counts up. */
.eqc-figure-reserve-3 .elementor-counter-number-wrapper { min-inline-size: 3.2ch; }
.eqc-figure-reserve-4 .elementor-counter-number-wrapper { min-inline-size: 4ch; }
.eqc-figure-reserve-6 .elementor-counter-number-wrapper { min-inline-size: 6.4ch; }

/* Stacked: the lead panel on top, the three figures in a row under it while
   they still fit, then one per row on a phone. The separators turn with the
   layout -- horizontal between stacked rows. */
@media (max-width: 52rem) {
	.e-con.eqc-stats-band { grid-template-columns: minmax(0, 1fr); }
	.e-con.eqc-stats-cell:first-child::before { inset-block: 20%; background: linear-gradient(180deg, transparent, rgb(var(--eqc-gold-500-rgb) / 0.75) 50%, transparent); inline-size: 1px; }
	.e-con.eqc-stats-lead { border-block-end: 2px solid var(--eqc-gold-500); }
}
@media (max-width: 36rem) {
	.e-con.eqc-stats-cells { grid-template-columns: minmax(0, 1fr); }
	.e-con.eqc-stats-cell { padding-block: 20px; }
	.e-con.eqc-stats-cell::before,
	.e-con.eqc-stats-cell:first-child::before {
		inset-block: 0 auto;
		inset-inline: 14%;
		inline-size: auto;
		block-size: 1px;
		background: linear-gradient(90deg, transparent, rgb(var(--eqc-gold-500-rgb) / 0.75) 50%, transparent);
	}
	.e-con.eqc-stats-cell::after { inset-block-start: 0; inset-inline-start: 50%; }
	.e-con.eqc-stats-cell:first-child::before,
	.e-con.eqc-stats-cell:first-child::after { display: none; }
}
