/*
 * QuickLink theme — v0.3 design system CSS.
 * Implements docs/design-v03/02 (tokens), 03 (type/grid), 04 (homepage),
 * 05 (page family), 06 (responsive/RTL), 07 (motion), 08 (components),
 * 09 (a11y/perf). Logical properties throughout; assets/css/rtl.css only
 * carries what logical properties cannot express (see 06 §RTL rules).
 */

/* ---------------------------------------------------------------------
 * 1. Per-language font stacks (html[lang]) — design-v03/03 §1
 * ------------------------------------------------------------------- */
:root {
	--font-display: "Playfair Display", Georgia, serif;
	--font-text: Onest, "Segoe UI", system-ui, sans-serif;
	--ql-arabic-scale: 1;
}

html[lang^="ar"] {
	--font-display: Almarai, "IBM Plex Sans Arabic", sans-serif;
	--font-text: "IBM Plex Sans Arabic", Onest, Tahoma, sans-serif;
	--ql-arabic-scale: 0.92;
}

html[lang^="hi"] {
	--font-display: "Noto Sans Devanagari", sans-serif;
	--font-text: "Noto Sans Devanagari", Onest, sans-serif;
}

html[lang^="ru"] {
	--font-display: "Playfair Display", Georgia, serif;
	--font-text: Onest, "Segoe UI", system-ui, sans-serif;
}

/* ---------------------------------------------------------------------
 * 2. Base
 * ------------------------------------------------------------------- */
* {
	box-sizing: border-box;
}

html {
	overflow-x: hidden;
	scroll-behavior: auto;
}

@media (prefers-reduced-motion: no-preference) {
	html:focus-within {
		scroll-behavior: smooth;
	}
}

body {
	overflow-x: hidden;
	font-family: var(--font-text);
}

html[lang^="ar"] body,
html[dir="rtl"] body {
	line-height: 1.9;
}

html[lang^="hi"] body {
	line-height: 1.8;
}

/* Per design-v03/03 §2: only display-1/display-2/h2 use the display
 * (serif/Almarai/Noto-display) family; h3 and smaller use the text family
 * at 600 weight, matching the type scale table exactly. */
h1, h2, .wp-block-heading {
	font-family: var(--font-display);
	text-wrap: balance;
}

h3, h4, h5, h6 {
	font-family: var(--font-text);
	font-weight: 600;
	text-wrap: balance;
	color: var(--wp--preset--color--ink);
	line-height: 1.3;
}

/* The shared heading scale (report 18 S2-5).
 *
 * theme.json used to carry `styles.blocks.core/heading.typography.fontSize:
 * var(--wp--preset--font-size--h2)`. That preset is `--h-2`; `--h2` has never
 * existed, so the declaration was invalid at computed-value time, font-size
 * fell back to `inherit`, and EVERY `.wp-block-heading` -- the section titles
 * the importer writes on the homepage, the About page and the service pages --
 * rendered at the inherited body size (18px at 1440). The broken override is
 * gone; the scale now lives here, on element selectors, so any component rule
 * that already sets its own size (all of them carry at least one class) keeps
 * winning on specificity. */
h1 { font-size: var(--wp--preset--font-size--display-2); }
h2 { font-size: var(--wp--preset--font-size--h-2); }
h3 { font-size: var(--wp--preset--font-size--h-3); }
h4 { font-size: var(--wp--preset--font-size--h-4); }
h5, h6 { font-size: var(--wp--preset--font-size--body); }

/* Display headings never break mid-word (report 18 S2-3). Russian and Hindi
 * carry single words far longer than any English one; with
 * `overflow-wrap: break-word` Chromium chopped them at an arbitrary letter.
 * Word breaking is switched off on every heading.
 *
 * Release 0.3.2 (Fable, r15): hyphenation was `auto`, which handed the break
 * to Chromium's dictionary -- and Chromium duly hyphenated the Russian
 * display headline mid-word at every width ("нотари-/альные" at 1440,
 * "докумен-/тальное" at 820, three breaks at 390). A display headline is set,
 * not justified body copy: it wraps on word boundaries and takes the extra
 * line. `manual` keeps the browser from inventing breaks while still
 * honouring a `&shy;` placed deliberately in the source, which is the escape
 * hatch if one specific word ever overflows at 390. */
h1, h2, h3, h4, h5, h6,
.wp-block-heading,
.wp-block-post-title {
	overflow-wrap: normal;
	word-break: normal;
	hyphens: manual;
}

/* Almarai only ships 700/800 (no 600); IBM Plex Sans Arabic text ships
 * 400/500/700. Arabic h1/h2 (Almarai) and h3-h6 (Plex) both need a
 * available-weight override so the browser never synthesises bold. */
html[lang^="ar"] h1, html[lang^="ar"] h2, html[lang^="ar"] .wp-block-heading {
	font-weight: 700;
}

html[lang^="ar"] h3, html[lang^="ar"] h4, html[lang^="ar"] h5, html[lang^="ar"] h6 {
	font-weight: 700;
}

html[lang^="ar"] h1, html[lang^="ar"] h2, html[lang^="ar"] .wp-block-heading,
html[lang^="hi"] h1, html[lang^="hi"] h2, html[lang^="hi"] .wp-block-heading {
	line-height: 1.25;
	letter-spacing: 0;
}

/* Latin/foreign fragments inside RTL or Devanagari copy stay isolated and
   left-to-right (brand name, emails, phone numbers, URLs) — design-v03/06. */
bdi,
.ql-bdi {
	unicode-bidi: isolate;
}

:focus-visible {
	outline: 3px solid var(--wp--preset--color--brand-blue-deep);
	outline-offset: 2px;
	border-radius: 2px;
}

.skip-link {
	position: absolute;
	inset-inline-start: 8px;
	top: -60px;
	background: var(--wp--preset--color--navy-950);
	color: var(--wp--preset--color--white);
	padding: 0.75rem 1.25rem;
	border-radius: var(--wp--custom--radius--s);
	z-index: 9999;
	transition: top var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.skip-link:focus {
	top: 8px;
}

/* ---------------------------------------------------------------------
 * 3. Layout foundation — report 16 §1.1 / §2 D1
 *
 * Division of labour (Fable decision 2026-09-22, Q2):
 *   - core `alignfull`   owns the BAND: background, edge-to-edge bleed.
 *   - `.ql-container-*`  owns the MEASURE inside the band (1280/1080/720).
 *   - theme.json `contentSize: 720px` stays the default measure for
 *     un-composed post content (articles, legal pages, imported pages).
 *
 * Every composed section in every template and in QL_Layout_Apply now
 * carries align:"full"; before this, core's zero-specificity constrained
 * rule clamped each one to 720px at every viewport.
 * ------------------------------------------------------------------- */

/* The header/footer template parts wrap their own <header>/<footer> in a
   <div class="wp-block-template-part">. Without this the page has TWO
   banner and TWO contentinfo landmarks (axe: landmark-no-duplicate-banner
   / -contentinfo / landmark-banner-is-top-level — report 16 §1.10 O2), and
   the sticky header can only travel inside that wrapper's 72px box. A div
   carries no semantics, so removing its box is lossless. */
.wp-block-template-part {
	display: contents;
}

:root {
	--ql-gutter: 20px;
}

@media (min-width: 600px) { :root { --ql-gutter: 32px; } }
@media (min-width: 1280px) { :root { --ql-gutter: 48px; } }

.ql-container-wide,
.ql-container-content,
.ql-container-prose {
	margin-inline: auto;
	padding-inline: var(--ql-gutter);
	width: 100%;
}

.ql-container-wide { max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2); }
.ql-container-content { max-width: calc(var(--wp--custom--container--content) + var(--ql-gutter) * 2); }
.ql-container-prose { max-width: calc(var(--wp--custom--container--prose) + var(--ql-gutter) * 2); }

/* Safety net. A `.ql-section`/`.ql-hero`/`.ql-page-hero`/`.ql-cta` that has
   lost its `alignfull` (older generated content, or an editor toggling the
   alignment off) must still read as a band rather than collapsing back to a
   720px slab. This reproduces what core's own alignfull rule does under
   `useRootPaddingAwareAlignments`; it is a fallback, not the mechanism. */
.is-layout-constrained > .ql-section:not(.alignfull),
.is-layout-constrained > .ql-hero:not(.alignfull),
.is-layout-constrained > .ql-page-hero:not(.alignfull),
.is-layout-constrained > .ql-cta:not(.alignfull) {
	max-width: none;
	width: auto;
	margin-inline: calc(-1 * var(--wp--style--root--padding-right, 0px)) calc(-1 * var(--wp--style--root--padding-left, 0px));
}

/* A full-bleed band supplies its own inner measure, so core must not add
   its root padding on top of the container's gutter. */
.ql-section.has-global-padding,
.ql-hero.has-global-padding,
.ql-page-hero.has-global-padding,
.ql-cta.has-global-padding {
	padding-inline: 0;
}

.ql-section > .is-layout-constrained,
.ql-page-hero > .is-layout-constrained,
.ql-hero > .is-layout-constrained {
	max-width: none;
}

.ql-section {
	padding-block: 56px;
	position: relative;
}

@media (min-width: 600px) {
	.ql-section {
		padding-block: 80px;
	}
}

@media (min-width: 1200px) {
	.ql-section {
		padding-block: 112px;
	}
}

/* Two consecutive bands of the same surface read as one section: collapse
   the doubled vertical rhythm rather than leaving a 224px dead gap. */
.ql-section.is-base + .ql-section.is-base,
.ql-section.is-surface + .ql-section.is-surface,
.ql-section.is-night + .ql-section.is-night {
	padding-block-start: 0;
}

/* Same for a page hero whose surface matches the band below it: a light
   hero sits on paper, so its 80px tail plus the next band's 112px head was
   reading as ~200px of empty paper between the H1 block and the first real
   content (measured on the service-detail and services templates). */
.ql-page-hero.is-light + .ql-section.is-base,
.ql-page-hero:not(.is-light) + .ql-section.is-night {
	padding-block-start: 0;
}

.ql-section.is-base {
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
}

.ql-section.is-surface {
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--ink);
}

.ql-section.is-night {
	background: var(--wp--preset--color--navy-950);
	color: var(--wp--preset--color--white);
}

.ql-section.is-night h1, .ql-section.is-night h2, .ql-section.is-night h3, .ql-section.is-night h4 {
	color: var(--wp--preset--color--white);
}

/* Links on a night surface are brand blue -- except the ones that are drawn
 * as buttons, which carry their own foreground against their own fill. The
 * core button class was already excluded; `.ql-empty-state__group-link a` is
 * the 410 page's "Browse <group>" pill, and this rule (0,3,1) was outranking
 * its own `color: white` (0,1,1), painting brand blue on brand-green-deep at
 * 2.1:1 -- the one serious axe violation in the Stage 4 sweep, on 410 in
 * EN/RU/HI. White on #1F7A46 is 5.3:1. */
.ql-section.is-night a:not(.wp-block-button__link):not(.ql-empty-state__group-link a) {
	color: var(--wp--preset--color--brand-blue);
}

.ql-section.is-grad-paper {
	background: var(--wp--custom--gradient--paper);
}

/* Eyebrow label (design-v03/08) */
.ql-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand-blue-deep);
	margin-block-end: 12px;
}

.ql-section.is-night .ql-eyebrow {
	color: var(--wp--preset--color--green-glow);
}

.ql-eyebrow::before {
	content: "";
	display: inline-block;
	width: 24px;
	height: 3px;
	border-radius: 2px;
	background: var(--wp--custom--gradient--link);
}

/* Ledger rule divider (design-v03/02 §5) */
.ql-ledger-rule {
	display: flex;
	align-items: center;
	gap: 0;
	border-block-start: 1px solid var(--wp--preset--color--line);
	margin-block: 0;
	position: relative;
	height: 1px;
}

.ql-ledger-rule::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: -3.5px;
	width: 6px;
	height: 6px;
	background: var(--wp--preset--color--navy-900);
}

.ql-ledger-rule::after {
	content: "";
	position: absolute;
	inset-inline-start: 10px;
	top: -1px;
	width: 40px;
	height: 2px;
	background: var(--wp--custom--gradient--link);
}

.ql-section.is-night .ql-ledger-rule {
	border-color: var(--wp--preset--color--line-dark);
}

/* Lead paragraph */
.ql-lead {
	font-size: var(--wp--preset--font-size--lead);
	line-height: 1.5;
	color: var(--wp--preset--color--ink-soft);
	max-width: 60ch;
}

.ql-section.is-night .ql-lead {
	color: rgba(255,255,255,0.82);
}

.ql-prose {
	max-width: var(--wp--custom--container--prose);
	font-size: var(--wp--preset--font-size--body);
	line-height: 1.65;
}

html[lang^="ar"] .ql-prose,
html[dir="rtl"] .ql-prose {
	line-height: 1.9;
}

/* ---------------------------------------------------------------------
 * 4. Buttons, chips, cards (design-v03/08)
 * ------------------------------------------------------------------- */
.wp-block-button__link {
	min-height: 52px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		box-shadow var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		background-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.wp-block-button__link:hover {
	transform: translateY(-1px);
	box-shadow: var(--wp--custom--shadow--2);
}

.wp-block-button__link:active {
	transform: scale(0.98);
}

/* Dark-surface button treatment. This list must name EVERY dark band, not
   just `.ql-section.is-night`: the hero, the dark page heroes and the closing
   CTA plate are dark surfaces that are not `.ql-section`, and while they were
   missing here their outline buttons inherited `color: ink` — near-black text
   on navy, which is the unreadable "Explore services" / "استكشف الخدمات" /
   "Все услуги" / "सेवाएँ देखें" ghost button visible in every r4 hero
   capture. */
.ql-section.is-night .wp-block-button:not(.is-style-outline) .wp-block-button__link,
.ql-hero .wp-block-button:not(.is-style-outline) .wp-block-button__link,
.ql-page-hero:not(.is-light) .wp-block-button:not(.is-style-outline) .wp-block-button__link,
.ql-cta .wp-block-button:not(.is-style-outline) .wp-block-button__link {
	/* !important is required, not decorative: the blocks carry the core preset
	   class .has-brand-green-deep-background-color, and WordPress emits preset
	   colour classes with !important, so a plain declaration here loses however
	   specific it is. The result was navy-950 ink (set below) on #1F7A46 =
	   3.29:1 -- the one serious axe violation left on home EN/AR/HI and the
	   services page after r6. Navy on brand-green #4FC576 is 8.0:1. */
	background: var(--wp--preset--color--brand-green) !important;
	color: var(--wp--preset--color--navy-950);
}

.ql-section.is-night .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.ql-hero .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.ql-page-hero:not(.is-light) .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.ql-cta .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover {
	background: var(--wp--preset--color--green-glow) !important;
	color: var(--wp--preset--color--navy-950);
}

.wp-block-button.is-style-outline .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--ink);
	border: 1.5px solid var(--wp--preset--color--ink);
	box-shadow: none;
}

.ql-section.is-night .wp-block-button.is-style-outline .wp-block-button__link,
.ql-hero .wp-block-button.is-style-outline .wp-block-button__link,
.ql-page-hero:not(.is-light) .wp-block-button.is-style-outline .wp-block-button__link,
.ql-cta .wp-block-button.is-style-outline .wp-block-button__link {
	color: var(--wp--preset--color--white);
	border-color: rgba(255,255,255,0.6);
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background: rgba(15,34,51,0.08);
}

.ql-section.is-night .wp-block-button.is-style-outline .wp-block-button__link:hover,
.ql-hero .wp-block-button.is-style-outline .wp-block-button__link:hover,
.ql-page-hero:not(.is-light) .wp-block-button.is-style-outline .wp-block-button__link:hover,
.ql-cta .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background: rgba(255,255,255,0.1);
}

.wp-block-button.is-style-ghost .wp-block-button__link {
	background: none;
	color: var(--wp--preset--color--brand-blue-deep);
	padding-inline: 4px;
	min-height: auto;
	text-underline-offset: 6px;
	box-shadow: none;
}

.wp-block-button.is-style-ghost .wp-block-button__link:hover {
	text-decoration: underline;
	transform: none;
}

/* Chip / tag */
.ql-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 32px;
	padding-inline: 14px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--ink);
	font-size: 0.8125rem;
	font-weight: 600;
	border: none;
	cursor: pointer;
	transition: background-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

/* A chip that is actually operable (the services-directory jump nav renders
   chips as <a>, the group filters as <button>) must not wear the body link
   underline, and must meet the 44px target the brief sets. A decorative
   `.ql-chip--glass` in the hero is a <span> and stays 32px. */
a.ql-chip,
button.ql-chip {
	text-decoration: none;
	min-height: 44px;
	height: auto;
	padding-block: 10px;
}

.ql-chip:hover {
	background: var(--wp--preset--color--sky-2);
}

.ql-chip[aria-pressed="true"],
.ql-chip.is-active {
	background: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
}

.ql-chip--glass {
	background: var(--wp--custom--glass--dark-bg);
	backdrop-filter: blur(var(--wp--custom--glass--dark-blur));
	-webkit-backdrop-filter: blur(var(--wp--custom--glass--dark-blur));
	color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--custom--glass--dark-border);
}

@supports not (backdrop-filter: blur(1px)) {
	.ql-chip--glass {
		background: var(--wp--preset--color--navy-900);
	}
}

/* Card / plate */
.ql-plate {
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--l);
	padding: 32px;
	box-shadow: var(--wp--custom--shadow--1);
	transition: box-shadow var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out);
}

@media (hover: hover) {
	.ql-plate:hover {
		box-shadow: var(--wp--custom--shadow--2);
		transform: translateY(-4px);
	}
}

.ql-section.is-night .ql-plate {
	background: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--line-dark);
	box-shadow: none;
}

/* Icon */
.ql-icon {
	width: 24px;
	height: 24px;
	flex-shrink: 0;
}

.ql-icon--sm { width: 18px; height: 18px; }
.ql-icon--lg { width: 32px; height: 32px; }

/* ---------------------------------------------------------------------
 * 5. Header (S1) — design-v03/04 §S1, 08 (mega menu / mobile sheet / lang)
 *
 * Report 16 §2 D4: one 72px instrument bar at every viewport (64px below
 * 820), a real horizontal row of links at >=1024, the sheet below that
 * (Fable decision Q1, doc 04 §S1 "T/M" rule; docs/design-v03/06 §Tablet
 * revised 2026-09-22 to match).
 * ------------------------------------------------------------------- */
.ql-header {
	position: sticky;
	top: 0;
	z-index: 500;
	background: var(--wp--preset--color--paper);
	border-block-end: 1px solid transparent;
	transition: background-color var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out),
		border-color var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out),
		box-shadow var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out);
}

.ql-header.is-scrolled {
	background: var(--wp--custom--glass--bg);
	backdrop-filter: blur(var(--wp--custom--glass--blur)) saturate(1.4);
	-webkit-backdrop-filter: blur(var(--wp--custom--glass--blur)) saturate(1.4);
	border-block-end-color: var(--wp--preset--color--line);
	box-shadow: 0 1px 0 rgba(7,26,43,.04), 0 10px 30px -18px rgba(7,26,43,.35);
}

@supports not (backdrop-filter: blur(1px)) {
	.ql-header.is-scrolled {
		background: var(--wp--preset--color--paper);
	}
}

.ql-header__bar {
	display: flex;
	align-items: center;
	gap: 16px;
	height: 64px;
	max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--ql-gutter);
}

@media (min-width: 1024px) {
	.ql-header__bar {
		height: 72px;
		gap: 24px;
	}
}

.ql-brand {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
}

.ql-brand img,
.ql-site-logo img {
	width: auto;
	height: 36px;
	max-width: 132px;
	object-fit: contain;
	display: block;
}

@media (min-width: 1024px) {
	.ql-brand img,
	.ql-site-logo img {
		height: 44px;
		max-width: 168px;
	}
}

/* Centre lane: the Services disclosure + the primary menu, one row. */
.ql-header-nav {
	display: none;
	align-items: center;
	gap: 2px;
	flex: 1 1 auto;
	justify-content: center;
	min-width: 0;
}

.ql-header__actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 0 0 auto;
	margin-inline-start: auto;
}

@media (min-width: 1024px) {
	.ql-header-nav { display: flex; }
	.ql-header__actions { margin-inline-start: 0; }
	.ql-nav-toggle { display: none !important; }
}

/* The classic-menu block's className lands on the <nav> wrapper that
   get_block_wrapper_attributes() prints, not on the <ul> that
   wp_nav_menu() prints inside it — so the reset and the row have to target
   the descendant ul/li explicitly (Fable review 14, B1). */
.ql-header__primary-links,
.ql-header__primary-links > ul {
	display: flex;
	align-items: center;
	gap: 2px;
	list-style: none;
	margin: 0;
	padding: 0;
	flex-wrap: nowrap;
}

.ql-header__primary-links > ul > li {
	list-style: none;
	margin: 0;
	white-space: nowrap;
}

.ql-header__primary-links > ul > li > a,
.ql-header-nav .ql-services-menu__trigger {
	position: relative;
	display: inline-flex;
	align-items: center;
	height: 44px;
	padding-inline: 12px;
	font-family: var(--font-text);
	font-size: 0.9375rem;
	font-weight: 500;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	border-radius: var(--wp--custom--radius--s);
	transition: color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

/* The active/hover marker is a drawn rule, not a text underline: it stays
   off the descenders and animates from the centre out. */
.ql-header__primary-links > ul > li > a::after,
.ql-header-nav .ql-services-menu__trigger::before {
	content: "";
	position: absolute;
	inset-inline: 12px;
	bottom: 6px;
	height: 2px;
	border-radius: 2px;
	background: var(--wp--custom--gradient--link);
	transform: scaleX(0);
	transform-origin: center;
	transition: transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-header__primary-links > ul > li > a:hover,
.ql-header-nav .ql-services-menu__trigger:hover,
.ql-header__primary-links > ul > li.current-menu-item > a,
.ql-header__primary-links > ul > li.current_page_item > a {
	color: var(--wp--preset--color--brand-blue-deep);
}

.ql-header__primary-links > ul > li > a:hover::after,
.ql-header__primary-links > ul > li > a:focus-visible::after,
.ql-header__primary-links > ul > li.current-menu-item > a::after,
.ql-header__primary-links > ul > li.current_page_item > a::after,
.ql-header-nav .ql-services-menu__trigger:hover::before,
.ql-header-nav .ql-services-menu__trigger[aria-expanded="true"]::before {
	transform: scaleX(1);
}

/* A menu with more entries than the bar can hold (the RU/HI menus before
   the rebuild) must still be one legible row, never three. */
@media (min-width: 1024px) and (max-width: 1279px) {
	.ql-header__primary-links > ul > li > a,
	.ql-header-nav .ql-services-menu__trigger {
		padding-inline: 9px;
		font-size: 0.875rem;
	}
}

.ql-header-cta .wp-block-button__link {
	min-height: 44px;
	padding-block: 0;
	padding-inline: 20px;
	font-size: 0.9375rem;
	white-space: nowrap;
}

@media (max-width: 599px) {
	.ql-header-cta { display: none; }
}

/* Services mega menu — design-v03/04 §S1, 08.
 *
 * Report 16 §1.3: the panel used to be absolutely positioned against
 * `.ql-services-menu` (the ~90px trigger button) and centred on it with
 * `inset-inline-start: 50%; translate(-50%)`, so a 1180px panel started at
 * x = -120 and its first column fell off the left edge of the screen. The
 * panel is now anchored to the sticky header itself (a sticky element is a
 * positioned ancestor), spans the full bar, and centres its own columns on
 * the wide container measure via a computed inline padding — so the white
 * surface bleeds edge to edge while the content lines up with every other
 * section on the page.
 */
.ql-services-menu {
	display: flex;
	align-items: center;
}

.ql-services-menu__trigger {
	background: none;
	border: none;
	cursor: pointer;
	gap: 6px;
	font-family: var(--font-text);
}

.ql-services-menu__trigger::after {
	content: "";
	width: 8px;
	height: 8px;
	border-inline-end: 1.75px solid currentColor;
	border-block-end: 1.75px solid currentColor;
	transform: rotate(45deg);
	margin-block-start: -4px;
	transition: transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-services-menu__trigger[aria-expanded="true"]::after {
	transform: rotate(225deg);
	margin-block-start: 2px;
}

@media (min-width: 1024px) {
	.ql-services-menu__panel {
		position: absolute;
		top: 100%;
		inset-inline: 0;
		z-index: 600;
		background: var(--wp--preset--color--white);
		border-block-start: 1px solid var(--wp--preset--color--line);
		border-end-start-radius: var(--wp--custom--radius--l);
		border-end-end-radius: var(--wp--custom--radius--l);
		box-shadow: var(--wp--custom--shadow--2);
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, 0.9fr);
		gap: 40px;
		align-items: start;
		padding-block: 36px 40px;
		/* Centre the columns on the 1280px measure, keep the surface full-bleed. */
		padding-inline: max(var(--ql-gutter), calc((100% - var(--wp--custom--container--wide)) / 2 + var(--ql-gutter)));
		opacity: 0;
		visibility: hidden;
		transform: translateY(-8px);
		transition: opacity var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out),
			transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out),
			visibility var(--wp--custom--motion--dur-2);
	}

	.ql-services-menu__panel:not([hidden]) {
		opacity: 1;
		visibility: visible;
		transform: translateY(0);
	}
}

.ql-services-menu__column {
	min-width: 0;
}

.ql-services-menu__group-heading {
	display: block;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
	padding-block-end: 10px;
	margin-block-end: 10px;
	border-block-end: 2px solid transparent;
	border-image: var(--wp--custom--gradient--link) 1;
}

.ql-services-menu__group-heading:hover {
	color: var(--wp--preset--color--ink);
}

.ql-services-menu__group-toggle {
	display: none;
}

.ql-services-menu__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.ql-services-menu__list a {
	display: flex;
	align-items: center;
	min-height: 40px;
	font-size: 0.9375rem;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	border-radius: var(--wp--custom--radius--s);
	padding-inline: 10px;
	margin-inline: -10px;
	transition: background-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-services-menu__list a:hover {
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
}

.ql-services-menu__finder-col {
	background: var(--wp--custom--gradient--paper);
	border: 1px solid var(--wp--preset--color--sky-2);
	border-radius: var(--wp--custom--radius--m);
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	align-self: start;
}

.ql-services-menu__finder-col .ql-motif {
	width: 100%;
	max-width: 180px;
	height: auto;
	color: var(--wp--preset--color--brand-blue-deep);
	opacity: 0.85;
}

.ql-services-menu__finder-col strong {
	font-family: var(--font-display);
	font-size: 1.25rem;
	font-weight: 500;
	line-height: 1.25;
	color: var(--wp--preset--color--ink);
}

.ql-services-menu__finder-col p {
	margin: 0;
	font-size: 0.9375rem;
	color: var(--wp--preset--color--ink-soft);
}

/* Below the desktop breakpoint the mega panel is never shown: the mobile
   sheet renders its own server-side accordion instead (report 16 §1.4). */
@media (max-width: 1023px) {
	.ql-services-menu,
	.ql-services-menu__panel {
		display: none;
	}
}

/* Language selector */
.ql-lang-selector {
	position: relative;
}

.ql-lang-selector__trigger {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 44px;
	padding-inline: 10px;
	background: none;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	text-transform: uppercase;
}

.ql-lang-selector__panel {
	position: absolute;
	top: calc(100% + 8px);
	inset-inline-end: 0;
	min-width: 200px;
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--m);
	box-shadow: var(--wp--custom--shadow--2);
	padding: 8px;
	list-style: none;
	margin: 0;
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	transition: opacity var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		visibility var(--wp--custom--motion--dur-1);
	z-index: 20;
}

.ql-lang-selector__panel:not([hidden]) {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.ql-lang-selector__panel a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	min-height: 44px;
	padding-inline: 12px;
	border-radius: var(--wp--custom--radius--s);
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	font-size: 0.9375rem;
}

.ql-lang-selector__panel a:hover {
	background: var(--wp--preset--color--sky);
}

.ql-lang-selector__panel a[aria-current="true"] {
	font-weight: 700;
	color: var(--wp--preset--color--brand-blue-deep);
}

/* Flat, always-visible usages of the same panel markup: the footer's
   "list" variant (no trigger button, no [hidden] attribute by design) and
   the mobile sheet's JS clone of the header popover (mobile-menu.js strips
   [hidden] so it displays inline). Both must NOT inherit the floating
   popover treatment above (position:absolute + white card), or the panel
   renders as a white box detached from layout -- Fable visual-check
   finding 2026-09-22 (B4: "popover outside the sheet, covering the
   address"; M2: "white English popover permanently visible bottom-right"). */
.ql-lang-selector--list .ql-lang-selector__list,
.ql-mobile-sheet__langs-slot .ql-lang-selector__list {
	position: static;
	top: auto;
	inset-inline-end: auto;
	min-width: 0;
	background: none;
	box-shadow: none;
	padding: 0;
	margin: 0;
	/* list-style:none lives on .ql-lang-selector__panel; the "list" variant
	   renders a .ql-lang-selector__list ul, so it must set it itself or the
	   browser draws disc markers (seen on the mobile sheet in r6). */
	list-style: none;
	opacity: 1;
	visibility: visible;
	transform: none;
	display: flex;
	flex-wrap: wrap;
	gap: 4px 16px;
	z-index: auto;
}

.ql-lang-selector--list .ql-lang-selector__list a,
.ql-mobile-sheet__langs-slot .ql-lang-selector__list a {
	/* display:inline-flex is load-bearing: the anchors are inline boxes, and
	   min-height does nothing to an inline box, so the footer language links
	   measured 45x17 / 24x17 (r6 sweep) despite the min-height below. */
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-inline: 0;
	color: rgba(255,255,255,0.78);
}

.ql-mobile-sheet__langs-slot .ql-lang-selector__list a {
	min-height: 44px;
}

.ql-lang-selector--list .ql-lang-selector__list a:hover,
.ql-mobile-sheet__langs-slot .ql-lang-selector__list a:hover {
	background: none;
	color: var(--wp--preset--color--brand-blue);
	text-decoration: underline;
}

.ql-lang-selector--list .ql-lang-selector__list a[aria-current="true"],
.ql-mobile-sheet__langs-slot .ql-lang-selector__list a[aria-current="true"] {
	color: var(--wp--preset--color--white);
}

/* Mobile nav toggle */
.ql-nav-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	background: none;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--s);
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	position: relative;
	flex: 0 0 auto;
}

.ql-nav-toggle__bar,
.ql-nav-toggle__bar::before,
.ql-nav-toggle__bar::after {
	content: "";
	display: block;
	width: 18px;
	height: 1.75px;
	background: currentColor;
	border-radius: 1px;
	transition: transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-in-out),
		opacity var(--wp--custom--motion--dur-1);
}

.ql-nav-toggle__bar::before { position: absolute; transform: translateY(-6px); }
.ql-nav-toggle__bar::after  { position: absolute; transform: translateY(6px); }

.ql-nav-toggle[aria-expanded="true"] .ql-nav-toggle__bar { background: transparent; }
.ql-nav-toggle[aria-expanded="true"] .ql-nav-toggle__bar::before { transform: rotate(45deg); }
.ql-nav-toggle[aria-expanded="true"] .ql-nav-toggle__bar::after  { transform: rotate(-45deg); }

/* ---------------------------------------------------------------------
 * 5b. Mobile navigation sheet — design-v03/04 §S1 (T/M), 08.
 *
 * Rebuilt for Fable review 14 B4. It is now a full-viewport dialog rendered
 * server-side by quicklink/mobile-sheet (its own markup, its own labels, in
 * the current language) instead of a 380px drawer holding a JS clone of the
 * desktop mega panel.
 * ------------------------------------------------------------------- */
.ql-mobile-sheet__scrim {
	position: fixed;
	inset: 0;
	/* The scrim and the sheet are children of the header group, which core
	   styles as .is-layout-flow: every non-first child gets
	   margin-block-start: var(--wp--style--block-gap). On a fixed box with
	   top:0 and bottom:0 that margin is not ignored -- it pushed both boxes
	   down 24px and shortened them to 876px at 390x900 (r6 capture). */
	margin: 0;
	background: rgba(7,26,43,0.6);
	z-index: 900;
	opacity: 0;
	transition: opacity var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out);
}

.ql-mobile-sheet__scrim[hidden] { display: none; }
.ql-mobile-sheet__scrim.is-open { opacity: 1; }

.ql-mobile-sheet {
	position: fixed;
	inset: 0;
	margin: 0; /* see .ql-mobile-sheet__scrim: core .is-layout-flow block-gap */
	z-index: 1000;
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	display: flex;
	flex-direction: column;
	transform: translateX(100%);
	transition: transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-in-out);
}

/* Hidden means hidden: no duplicate links in the tab order or the
   accessibility tree while the sheet is closed. */
.ql-mobile-sheet[hidden] { display: none; }

html[dir="rtl"] .ql-mobile-sheet { transform: translateX(-100%); }

.ql-mobile-sheet.is-open { transform: translateX(0); }

/* The RTL closed state above is (0,2,1) -- an attribute selector, a class and
   a type -- while `.ql-mobile-sheet.is-open` is only (0,2,0), so on Arabic the
   closed transform kept winning and the sheet stayed parked at x = -390: the
   toggle "opened" a menu that was entirely off-screen, and because an
   off-screen element still passes toBeVisible() the evidence capture recorded
   an empty screen rather than a menu. The open state must out-specify the
   direction state, not merely follow it. */
html[dir="rtl"] .ql-mobile-sheet.is-open { transform: translateX(0); }

.ql-mobile-sheet__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	height: 64px;
	padding-inline: var(--ql-gutter);
	border-block-end: 1px solid var(--wp--preset--color--line-dark);
	flex: 0 0 auto;
}

.ql-mobile-sheet__logo {
	height: 32px;
	width: auto;
	max-width: 132px;
	object-fit: contain;
	filter: brightness(0) invert(1);
	opacity: 0.92;
}

.ql-mobile-sheet__close {
	width: 44px;
	height: 44px;
	background: none;
	border: 1px solid rgba(255,255,255,0.28);
	border-radius: var(--wp--custom--radius--s);
	color: var(--wp--preset--color--white);
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
}

.ql-mobile-sheet__close-x,
.ql-mobile-sheet__close-x::before,
.ql-mobile-sheet__close-x::after {
	display: block;
	width: 16px;
	height: 1.75px;
	background: currentColor;
	border-radius: 1px;
}

.ql-mobile-sheet__close-x { background: transparent; position: relative; }
.ql-mobile-sheet__close-x::before { content: ""; position: absolute; transform: rotate(45deg); }
.ql-mobile-sheet__close-x::after  { content: ""; position: absolute; transform: rotate(-45deg); }

.ql-mobile-sheet__scroll {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
	padding: 24px var(--ql-gutter) 40px;
	display: flex;
	flex-direction: column;
	gap: 28px;
}

.ql-mobile-sheet .ql-eyebrow {
	color: var(--wp--preset--color--green-glow);
	margin-block-end: 8px;
}

.ql-mobile-sheet__primary-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.ql-mobile-sheet__primary-list li { list-style: none; }

.ql-mobile-sheet__primary-list > li > a {
	display: block;
	padding-block: 14px;
	font-family: var(--font-display);
	font-size: 1.5rem;
	line-height: 1.2;
	color: var(--wp--preset--color--white);
	text-decoration: none;
	border-block-end: 1px solid var(--wp--preset--color--line-dark);
}

html[lang^="ar"] .ql-mobile-sheet__primary-list > li > a,
html[lang^="hi"] .ql-mobile-sheet__primary-list > li > a {
	font-size: 1.375rem;
	line-height: 1.35;
}

.ql-mobile-sheet__primary-list > li > a:hover,
.ql-mobile-sheet__primary-list .current-menu-item > a {
	color: var(--wp--preset--color--green-glow);
}

/* Services accordion — real group labels, 56px rows, grid-row height
   animation (design-v03/07 §5). */
.ql-sheet-accordion {
	border-block-end: 1px solid var(--wp--preset--color--line-dark);
}

.ql-sheet-accordion__heading {
	margin: 0;
	font-size: inherit;
	font-family: inherit;
	font-weight: inherit;
}

.ql-sheet-accordion__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	width: 100%;
	min-height: 56px;
	padding: 0;
	background: none;
	border: none;
	color: var(--wp--preset--color--white);
	font-family: var(--font-text);
	font-size: 1.0625rem;
	font-weight: 600;
	text-align: start;
	cursor: pointer;
}

.ql-sheet-accordion__label { flex: 1 1 auto; min-width: 0; }

.ql-sheet-accordion__icon {
	flex: 0 0 auto;
	width: 10px;
	height: 10px;
	border-inline-end: 1.75px solid currentColor;
	border-block-end: 1.75px solid currentColor;
	transform: rotate(45deg);
	margin-block-end: 4px;
	transition: transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-sheet-accordion__toggle[aria-expanded="true"] .ql-sheet-accordion__icon {
	transform: rotate(-135deg);
	margin-block: 4px 0;
}

.ql-sheet-accordion__panel[hidden] { display: none; }

.ql-sheet-accordion__panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-in-out);
}

.ql-sheet-accordion__panel.is-open { grid-template-rows: 1fr; }
.ql-sheet-accordion__list { overflow: hidden; }

.ql-sheet-accordion__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.ql-sheet-accordion__list li { list-style: none; }

.ql-sheet-accordion__list a {
	display: flex;
	align-items: center;
	min-height: 48px;
	padding-inline-start: 14px;
	border-inline-start: 2px solid var(--wp--preset--color--line-dark);
	color: rgba(255,255,255,0.82);
	text-decoration: none;
	font-size: 0.9375rem;
}

.ql-sheet-accordion__list a:hover {
	color: var(--wp--preset--color--white);
	border-inline-start-color: var(--wp--preset--color--brand-green);
}

.ql-sheet-accordion__list .ql-sheet-accordion__all {
	color: var(--wp--preset--color--green-glow);
	font-weight: 600;
	padding-block-end: 12px;
}

.ql-mobile-sheet__contact {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
}

.ql-mobile-sheet .ql-chip--action {
	height: 44px;
	padding-inline: 18px;
	background: rgba(255,255,255,0.08);
	border: 1px solid var(--wp--preset--color--line-dark);
	color: var(--wp--preset--color--white);
	text-decoration: none;
}

.ql-mobile-sheet__cta .wp-block-button__link {
	display: flex;
	width: 100%;
	min-height: 52px;
	text-decoration: none;
}

@media (min-width: 1024px) {
	.ql-mobile-sheet,
	.ql-mobile-sheet__scrim {
		display: none !important;
	}
}

@media (prefers-reduced-motion: reduce) {
	.ql-mobile-sheet,
	.ql-mobile-sheet__scrim,
	.ql-sheet-accordion__panel {
		transition: none;
	}
}

/* ---------------------------------------------------------------------
 * 6. Hero (S2) — design-v03/04 §S2, 11
 *
 * Report 16 §1.1 cause B: `.ql-hero` used to become `display:flex` at
 * >=1200px with no `flex-direction`, which put the 2-column inner grid, the
 * finder card and the motif layers on ONE flex row. The inner grid's
 * `minmax(0, 6fr)` tracks shrank to 83.5px and the 88px headline overflowed
 * one word per line. The hero is a block again; the finder card overlap is
 * a negative margin, not a flex concern.
 * ------------------------------------------------------------------- */
.ql-hero {
	position: relative;
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	overflow: clip;
	padding-block: 48px 0;
	isolation: isolate;
}

@media (min-width: 1024px) {
	.ql-hero { padding-block-start: 72px; }
}

@media (min-width: 1200px) {
	.ql-hero { padding-block-start: 88px; }
}

.ql-hero__inner {
	position: relative;
	z-index: 2;
	display: grid;
	gap: 40px;
	align-items: center;
	max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--ql-gutter);
	padding-block-end: 88px;
	min-height: 0;
}

@media (min-width: 1024px) {
	.ql-hero__inner {
		grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
		gap: 56px;
		padding-block-end: 120px;
		min-height: min(72vh, 620px);
	}
}

@media (min-width: 1280px) {
	.ql-hero__inner { gap: 72px; }
}

.ql-hero__content {
	min-width: 0;
	max-width: 100%;
}

.ql-hero__content .ql-eyebrow {
	color: var(--wp--preset--color--green-glow);
}

.ql-hero__content h1 {
	font-size: var(--wp--preset--font-size--display-1);
	line-height: 1.02;
	color: var(--wp--preset--color--white);
	margin-block: 0 20px;
	max-width: 15ch;
	text-wrap: balance;
}

html[lang^="ar"] .ql-hero__content h1 {
	font-size: calc(var(--wp--preset--font-size--display-1) * 0.92);
	line-height: 1.25;
	max-width: 16ch;
}

/* Hindi and Russian set the display sizes down a step: their longest single
 * word has to fit the column at every width without hyphenation, because
 * Chromium ships no hyphenation dictionary for either language. 0.82 puts the
 * 1440px headline at 72px, where the longest Russian word measures ~470px
 * inside a 659px column, and the 390px headline at 36px inside 326px. */
html[lang^="hi"] .ql-hero__content h1 {
	font-size: calc(var(--wp--preset--font-size--display-1) * 0.82);
	line-height: 1.3;
	max-width: 18ch;
}

html[lang^="ru"] .ql-hero__content h1 {
	font-size: calc(var(--wp--preset--font-size--display-1) * 0.82);
	line-height: 1.12;
	max-width: 19ch;
}

/* S2-12: one left edge for the whole hero column.
 *
 * `.ql-hero__content` is a constrained-layout group, so core hands every
 * block-level child `max-width: 720px; margin-left: auto !important;
 * margin-right: auto !important`. The eyebrow is `inline-flex` and escaped it,
 * the headline and standfirst have their own `max-width` in `ch` and were
 * centred inside the column, and the button row and chip row were centred
 * inside 720px -- four different left edges (32 / 50 / 111 / 118 at 820px).
 * The content size is released for this subtree and the auto margins are
 * cancelled; the headline keeps its own measure, flush to the inline start. */
.ql-hero__content {
	--wp--style--global--content-size: 100%;
}

.ql-hero__content > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.ql-hero__content .ql-lead {
	color: rgba(255,255,255,0.86);
	max-width: 46ch;
}

.ql-hero__actions {
	display: flex;
	gap: 14px;
	flex-wrap: wrap;
	margin-block: 28px 28px;
}

.ql-hero__actions .wp-block-button__link {
	white-space: nowrap;
}

@media (max-width: 519px) {
	.ql-hero__actions { display: grid; gap: 12px; }
	.ql-hero__actions .wp-block-button,
	.ql-hero__actions .wp-block-button__link { width: 100%; }
}

.ql-hero__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: center;
}

.ql-hero__chips .ql-chip {
	height: auto;
	min-height: 34px;
	padding-block: 6px;
	cursor: default;
	max-width: 100%;
	white-space: normal;
	line-height: 1.3;
	text-align: start;
}

.ql-hero__visual {
	position: relative;
	min-height: 240px;
	display: grid;
	place-items: center;
	min-width: 0;
}

@media (min-width: 1024px) {
	.ql-hero__visual { min-height: 420px; }
}

.ql-hero__skyline {
	position: absolute;
	inset-inline: -10%;
	bottom: -8%;
	width: 120%;
	height: auto;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.2;
	pointer-events: none;
}

.ql-hero__lattice {
	position: absolute;
	top: -8%;
	inset-inline-end: -6%;
	width: 280px;
	max-width: 70%;
	height: auto;
	color: var(--wp--preset--color--white);
	opacity: 0.07;
	pointer-events: none;
}

.ql-hero__document-stack {
	position: relative;
	z-index: 2;
	width: min(100%, 300px);
	margin-inline: auto;
	filter: drop-shadow(0 28px 48px rgba(0,0,0,0.45));
}

@media (min-width: 1024px) {
	.ql-hero__document-stack { width: min(100%, 420px); }
}

.ql-hero__document-stack .ql-motif-sheet-front { animation: ql-hero-settle 0.6s var(--wp--custom--motion--ease-out) both; }

@keyframes ql-hero-settle {
	from { transform: translateY(12px); opacity: 0; }
	to { transform: translateY(0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.ql-hero__document-stack .ql-motif-sheet-front { animation: none; }
}

/* Service finder — design-v03/04 §S2 (glass card overlapping the hero) */
.ql-service-finder {
	background: var(--wp--custom--glass--bg);
	backdrop-filter: blur(var(--wp--custom--glass--blur)) saturate(1.3);
	-webkit-backdrop-filter: blur(var(--wp--custom--glass--blur)) saturate(1.3);
	border: 1px solid var(--wp--custom--glass--border);
	border-radius: var(--wp--custom--radius--l);
	box-shadow: var(--wp--custom--shadow--3);
	padding: 20px;
	position: relative;
	z-index: 3;
}

@media (min-width: 600px) { .ql-service-finder { padding: 24px 28px; } }

@supports not (backdrop-filter: blur(1px)) {
	.ql-service-finder { background: var(--wp--preset--color--white); }
}

/* The card sits ON the hero's bottom edge (doc 04 §S2: "overlapping the
   hero's bottom edge by 48px"). The hero has no bottom padding of its own;
   the overlap is a negative margin on this wrapper. */
.ql-hero .ql-service-finder-wrap {
	position: relative;
	z-index: 3;
	max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--ql-gutter);
	margin-block-start: -64px;
}

@media (min-width: 1024px) {
	.ql-hero .ql-service-finder-wrap { margin-block-start: -76px; }
}

/* The finder inside a night page hero (services directory) is inline, not
   an overlapping card. */
.ql-service-finder-wrap.is-inline {
	margin-block-start: 28px;
	max-width: 720px;
}

.ql-service-finder__form {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	gap: 14px;
}

.ql-service-finder__field {
	flex: 1 1 300px;
	display: flex;
	flex-direction: column;
	gap: 8px;
	min-width: 0;
}

.ql-service-finder__label {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.ql-service-finder select,
.ql-service-finder__field select {
	height: 52px;
	width: 100%;
	border-radius: var(--wp--custom--radius--s);
	border: 1px solid var(--wp--preset--color--line);
	background: var(--wp--preset--color--white);
	padding-inline: 14px;
	font-size: 1rem;
	font-family: var(--font-text);
	color: var(--wp--preset--color--ink);
}

.ql-service-finder select:focus-visible {
	border-color: var(--wp--preset--color--brand-blue-deep);
}

.ql-service-finder__submit {
	flex: 0 0 auto;
	height: 52px;
	min-width: 140px;
	padding-inline: 28px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand-green-deep);
	color: var(--wp--preset--color--white);
	border: none;
	font-family: var(--font-text);
	font-size: 1rem;
	font-weight: 600;
	cursor: pointer;
	transition: transform var(--wp--custom--motion--dur-1), box-shadow var(--wp--custom--motion--dur-1), background-color var(--wp--custom--motion--dur-1);
}

.ql-service-finder__submit:hover {
	transform: translateY(-1px);
	background: var(--wp--preset--color--brand-blue-deep);
	box-shadow: var(--wp--custom--shadow--2);
}

.ql-service-finder__submit:active { transform: scale(0.98); }

@media (max-width: 519px) {
	.ql-service-finder__submit { width: 100%; }
}

.ql-service-finder__quicklinks {
	margin-block-start: 16px;
	padding-block-start: 16px;
	border-block-start: 1px solid var(--wp--preset--color--line);
	font-size: 0.875rem;
	color: var(--wp--preset--color--ink-soft);
	display: flex;
	flex-wrap: wrap;
	gap: 6px 10px;
}

.ql-service-finder.is-compact {
	background: var(--wp--preset--color--white);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	box-shadow: var(--wp--custom--shadow--1);
	max-width: 640px;
	margin-inline: auto;
}

/* ---------------------------------------------------------------------
 * 7. Trust & statistics strip (S3) — design-v03/04 §S3
 * ------------------------------------------------------------------- */
.ql-stats-band {
	background: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
	padding-block: 40px;
}

@media (min-width: 1024px) {
	.ql-stats-band { padding-block: 48px; }
}

.ql-stats__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 32px 20px;
}

@media (min-width: 1024px) {
	.ql-stats__grid {
		grid-template-columns: repeat(4, 1fr);
		gap: 0;
	}

	.ql-stats__item {
		border-inline-start: 1px solid var(--wp--preset--color--line-dark);
		padding-inline-start: 32px;
	}

	.ql-stats__item:first-child {
		border-inline-start: none;
		padding-inline-start: 0;
	}
}

.ql-stats__value {
	font-family: var(--font-display);
	font-size: clamp(3rem, 3rem + 0.0228571 * (100vw - 390px), 3rem);
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--white);
	line-height: 1;
	margin: 0;
}

@media (min-width: 1024px) {
	.ql-stats__value {
		font-size: var(--wp--preset--font-size--stat);
	}
}

.ql-stats__label {
	font-size: 0.9375rem;
	color: rgba(255,255,255,0.72);
	margin-block-start: 8px;
}

.ql-stats__rule {
	width: 40px;
	height: 2px;
	background: var(--wp--custom--gradient--link);
	margin-block-start: 12px;
}

/* ---------------------------------------------------------------------
 * 8. Service map (S4) — design-v03/04 §S4
 * ------------------------------------------------------------------- */
/* The head is a flex row whose first child is a constrained-layout group, so
 * its section title was capped at the 720px content size and centred inside
 * the flex track -- a ~90px indent against the eyebrow above it (report 18
 * S2-5). Releasing the content size for that subtree lines the two up. */
.ql-service-map__head > .is-layout-constrained,
.ql-intro__text {
	--wp--style--global--content-size: 100%;
}

.ql-service-map__head {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: flex-end;
	gap: 20px;
	margin-block-end: 40px;
}

.ql-service-map__filters {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}

.ql-service-map__rails {
	display: grid;
	gap: 20px;
}

@media (min-width: 1024px) {
	.ql-service-map__rails {
		grid-template-columns: repeat(3, 1fr);
		align-items: start;
	}

	.ql-service-map__rails[data-hover] .ql-rail {
		transition: flex-grow var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-in-out);
	}

	.ql-service-map__rails {
		display: flex;
	}

	.ql-rail {
		flex: 1 1 0;
		min-width: 0;
	}

	.ql-rail:hover,
	.ql-rail:focus-within {
		flex-grow: 1.4;
	}
}

.ql-rail {
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--l);
	padding: 28px;
	box-shadow: var(--wp--custom--shadow--1);
}

.ql-rail__motif {
	width: 48px;
	height: 48px;
	color: var(--wp--preset--color--brand-blue-deep);
	margin-block-end: 16px;
}

/* S2-4: one styled header for every width.
 *
 * `.ql-rail__header` is a <button> the service-map block renders in all three
 * rails. Every declaration it had lived inside `@media (max-width: 1023px)`,
 * so from 1024px up it fell back to the UA button stylesheet -- grey
 * background, 2px outset border, 13.33px Arial -- and the three group headers
 * on the homepage rendered as grey boxes with an oversized default sans
 * title. The component is defined here, unconditionally; the accordion
 * affordances below are the only part that is width-dependent. */
.ql-rail__header {
	display: flex;
	width: 100%;
	align-items: center;
	gap: 12px;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	border-radius: 0;
	color: inherit;
	font: inherit;
	text-align: start;
	appearance: none;
	-webkit-appearance: none;
}

.ql-rail__title {
	display: block;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--h-3);
	line-height: 1.15;
	color: var(--wp--preset--color--ink);
	margin: 0 0 8px;
}

.ql-rail__header-chevron {
	flex: 0 0 auto;
	margin-inline-start: auto;
	transition: transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out);
}

/* From 1024px up the three rails are always open, so the header is a label,
   not a control: the chevron goes, the cursor stays default and the motif
   sits above the title exactly as the static rail intended. service-map.js
   strips `aria-expanded` and takes the button out of the tab order at these
   widths so the accessibility tree does not advertise a control that does
   nothing. */
@media (min-width: 1024px) {
	.ql-rail__header {
		display: block;
		cursor: default;
	}

	.ql-rail__header-chevron { display: none; }

	.ql-rail__title { margin-block-end: 10px; }
}

.ql-rail__desc {
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.9375rem;
	margin: 0 0 20px;
}

.ql-rail__ledger {
	list-style: none;
	margin: 0 0 16px;
	padding: 0;
	display: grid;
	gap: 2px;
}

@media (min-width: 600px) and (max-width: 1023px) {
	.ql-rail__ledger { grid-template-columns: repeat(2, 1fr); gap: 4px 16px; }
}

.ql-rail__ledger li a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	min-height: 48px;
	padding-inline: 4px;
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	border-block-end: 1px solid var(--wp--preset--color--line);
	font-size: 0.9375rem;
	gap: 8px;
}

.ql-rail__ledger li a .ql-icon {
	color: var(--wp--preset--color--brand-blue-deep);
	transition: transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
	flex-shrink: 0;
}

.ql-rail__ledger li a:hover {
	color: var(--wp--preset--color--brand-blue-deep);
}

.ql-rail__ledger li a:hover .ql-icon,
.ql-rail__ledger li a:focus-visible .ql-icon {
	transform: translateX(4px);
}

html[dir="rtl"] .ql-rail__ledger li a:hover .ql-icon,
html[dir="rtl"] .ql-rail__ledger li a:focus-visible .ql-icon {
	transform: translateX(-4px);
}

.ql-rail__all {
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
}

/* Mobile accordion mode */
@media (max-width: 1023px) {
	.ql-service-map__rails {
		display: block;
	}

	.ql-rail {
		padding: 0;
		box-shadow: none;
		border-radius: 0;
		border-block-end: 1px solid var(--wp--preset--color--line);
		background: none;
	}

	.ql-rail__header {
		padding-block: 20px;
		cursor: pointer;
	}

	.ql-rail__title {
		font-size: 1.25rem;
		margin: 0;
	}

	.ql-rail__motif {
		width: 28px;
		height: 28px;
		margin-block-end: 0;
	}

	.ql-rail.is-open .ql-rail__header-chevron { transform: rotate(180deg); }

	.ql-rail__body {
		display: grid;
		grid-template-rows: 0fr;
		transition: grid-template-rows var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-in-out);
	}

	.ql-rail__body > div { overflow: hidden; }

	.ql-rail.is-open .ql-rail__body {
		grid-template-rows: 1fr;
	}

	.ql-rail:not(.is-open) .ql-rail__body { grid-template-rows: 0fr; }

	.ql-rail__body:not(.ql-js-accordion) { grid-template-rows: 1fr; }
}

/* Directory mode (services archive) — full-width sections instead of rails */
.ql-service-map.is-directory .ql-service-map__rails {
	display: block;
}

.ql-service-map.is-directory .ql-rail {
	display: grid;
	gap: 24px;
	box-shadow: none;
	border-radius: 0;
	border-block-end: 1px solid var(--wp--preset--color--line);
	padding-block: 40px;
	background: none;
}

@media (min-width: 900px) {
	.ql-service-map.is-directory .ql-rail {
		grid-template-columns: 280px 1fr;
	}

	.ql-service-map.is-directory .ql-rail__ledger {
		grid-template-columns: repeat(2, 1fr);
		gap: 4px 32px;
	}
}

.ql-service-map.is-directory .ql-rail__ledger li a {
	flex-direction: column;
	align-items: flex-start;
	min-height: 64px;
	justify-content: center;
	gap: 2px;
}

.ql-service-map.is-directory .ql-rail__ledger .ql-rail__item-subtitle {
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
	font-weight: 400;
}

.ql-service-map__jump {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
	position: sticky;
	top: 76px;
	z-index: 10;
	background: var(--wp--preset--color--paper);
	padding-block: 12px;
	margin-block-end: 12px;
}

/* ---------------------------------------------------------------------
 * 8b. Service-group archive — design-v03/05
 * ------------------------------------------------------------------- */
.ql-group-archive__ledger {
	list-style: none;
	margin: 0 0 40px;
	padding: 0;
	display: grid;
	gap: 2px;
}

@media (min-width: 900px) {
	.ql-group-archive__ledger {
		grid-template-columns: repeat(2, 1fr);
		gap: 4px 32px;
	}
}

.ql-group-archive__ledger li {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	min-height: 64px;
	padding-inline: 4px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-group-archive__link {
	display: flex;
	flex-direction: column;
	gap: 2px;
	text-decoration: none;
	color: var(--wp--preset--color--ink);
}

.ql-group-archive__request {
	flex-shrink: 0;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
	white-space: nowrap;
	padding: 6px 14px;
	border: 1px solid var(--wp--preset--color--brand-blue-deep);
	border-radius: var(--wp--custom--radius--pill);
}

.ql-group-archive__request:hover {
	background: var(--wp--preset--color--sky);
}

.ql-group-archive__related {
	margin-block-start: 40px;
	padding-block-start: 32px;
	border-block-start: 1px solid var(--wp--preset--color--line);
}

.ql-group-archive__related-list {
	list-style: none;
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
	margin: 12px 0 0;
	padding: 0;
}

.ql-group-archive__related-list a {
	display: inline-flex;
	align-items: center;
	height: 44px;
	padding-inline: 20px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
	font-weight: 600;
}

/* ---------------------------------------------------------------------
 * 9. Company introduction (S5) — design-v03/04 §S5
 * ------------------------------------------------------------------- */
.ql-intro {
	display: grid;
	gap: 32px;
	align-items: center;
}

@media (min-width: 1024px) {
	.ql-intro {
		grid-template-columns: 5fr 7fr;
		gap: 64px;
	}

	.ql-intro.is-media-first {
		grid-template-columns: 7fr 5fr;
	}

	.ql-intro.is-media-first .ql-intro__media { order: 2; }
	.ql-intro.is-media-first .ql-intro__text { order: 1; }
}

.ql-intro__media {
	position: relative;
}

.ql-intro__media img {
	border-radius: var(--wp--custom--radius--xl);
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	display: block;
	position: relative;
	z-index: 2;
}

.ql-intro__media::before {
	content: "";
	position: absolute;
	inset-block-start: 16px;
	inset-inline-end: -16px;
	inset-block-end: -16px;
	inset-inline-start: 16px;
	border: 8px solid var(--wp--preset--color--navy-900);
	border-radius: var(--wp--custom--radius--xl);
	z-index: 1;
}

html[dir="rtl"] .ql-intro__media::before {
	inset-inline-end: 16px;
	inset-inline-start: -16px;
}

.ql-intro__caption {
	display: inline-block;
	margin-block-start: 12px;
	font-size: 0.8125rem;
	background: var(--wp--preset--color--paper-2);
	padding: 4px 12px;
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--ink-soft);
}

.ql-intro__text .wp-block-button {
	margin-block-start: 16px;
}

/* ---------------------------------------------------------------------
 * 10. How it works / process (S6) — design-v03/04 §S6
 * ------------------------------------------------------------------- */
.ql-process__path {
	width: 100%;
	height: auto;
	color: var(--wp--preset--color--brand-blue-deep);
	margin-block-end: -20px;
}

.ql-process__steps {
	display: grid;
	gap: 32px;
}

@media (min-width: 900px) {
	.ql-process__steps {
		grid-template-columns: repeat(var(--ql-process-count, 3), 1fr);
	}
}

.ql-process__step {
	text-align: center;
}

.ql-process__step-number {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--wp--preset--color--brand-blue-deep);
	color: var(--wp--preset--color--white);
	font-weight: 700;
	margin-block-end: 12px;
}

.ql-process__step h3 {
	font-size: var(--wp--preset--font-size--h-4);
	margin: 0 0 6px;
}

.ql-process__step p {
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.9375rem;
	margin: 0;
}

@media (max-width: 899px) {
	.ql-process__path { transform: rotate(90deg); max-height: 260px; width: auto; height: 100%; }
}

/* ---------------------------------------------------------------------
 * 11. Capability triptych (S7) — design-v03/04 §S7
 * ------------------------------------------------------------------- */
.ql-triptych {
	display: grid;
	gap: 20px;
}

@media (min-width: 1024px) {
	.ql-triptych {
		grid-template-columns: 5fr 4fr 3fr;
		align-items: stretch;
	}
}

.ql-triptych__panel {
	background: var(--wp--preset--color--navy-900);
	border: 1px solid var(--wp--preset--color--line-dark);
	border-radius: var(--wp--custom--radius--l);
	padding: 32px;
	color: var(--wp--preset--color--white);
	transition: transform var(--wp--custom--motion--dur-2) var(--wp--custom--motion--ease-out);
}

@media (hover: hover) {
	.ql-triptych__panel:hover {
		transform: translateY(-4px);
	}

	.ql-triptych__panel:hover .ql-motif {
		color: var(--wp--preset--color--green-glow);
	}
}

/* One anatomy for all three panels (report 18 S2-7): motif, title, body, in
 * that order, top-aligned. The tall panel used to push its content to the
 * bottom, which left its motif floating in mid-card; the quote panel used to
 * print its body first and its title last. `order` keeps the quote panel
 * correct even on pages whose stored markup predates the generator fix in
 * QL_Layout_Apply::build_capability_triptych_v03(). */
.ql-triptych__panel {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.ql-triptych__panel--tall {
	min-height: 320px;
}

.ql-triptych__panel .ql-motif {
	width: 56px;
	height: 56px;
	color: var(--wp--preset--color--brand-blue);
	margin-block-end: 20px;
	transition: color var(--wp--custom--motion--dur-2);
}

.ql-triptych__panel h3 {
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--h-3);
	margin-block: 0 8px;
}

.ql-triptych__panel p {
	color: rgba(255,255,255,0.78);
	margin: 0;
}

.ql-triptych__proof {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 14px;
}

.ql-triptych__proof li {
	display: flex;
	gap: 10px;
	align-items: flex-start;
}

.ql-triptych__proof .ql-icon {
	color: var(--wp--preset--color--green-glow);
	flex-shrink: 0;
	margin-block-start: 2px;
}

/* Pages whose stored markup predates the generator fix have no motif in the
   values panel, which would leave its title 56px above the other two. This
   reserves the motif's box until the layout is re-applied, and takes itself
   out the moment the motif is there. */
.ql-triptych__panel--quote:not(:has(.ql-motif))::before {
	content: "";
	display: block;
	width: 56px;
	height: 56px;
	margin-block-end: 20px;
}

.ql-triptych__panel--quote .ql-motif { order: 1; }
.ql-triptych__panel--quote h3 { order: 2; }
.ql-triptych__panel--quote p { order: 3; }

/* ---------------------------------------------------------------------
 * 12. Testimonials (S8) — design-v03/04 §S8
 * ------------------------------------------------------------------- */
.ql-proof__featured {
	max-width: 68ch;
	margin: 0 auto 48px;
	text-align: center;
}

.ql-proof__featured blockquote {
	font-family: var(--font-display);
	font-style: italic;
	font-size: clamp(1.5rem, 1.5rem + 0.0114 * (100vw - 390px), 2.25rem);
	line-height: 1.3;
	margin: 0 0 20px;
	color: var(--wp--preset--color--ink);
}

html[lang^="ar"] .ql-proof__featured blockquote {
	font-style: normal;
	font-weight: 700;
}

.ql-proof__seals {
	display: flex;
	justify-content: center;
	gap: 4px;
	margin-block-end: 12px;
}

.ql-proof__seals .ql-icon {
	width: 18px;
	height: 18px;
	color: var(--wp--preset--color--brand-green-deep);
}

.ql-proof__author {
	font-weight: 600;
	color: var(--wp--preset--color--ink-soft);
}

.ql-proof__caption {
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
	margin-block-start: 4px;
}

.ql-proof__scroller {
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	padding-block: 4px 12px;
	scrollbar-width: thin;
}

.ql-proof__scroller .ql-plate {
	background: var(--wp--preset--color--paper-2);
	flex: 0 0 min(320px, 82vw);
	scroll-snap-align: start;
	box-shadow: none;
}

/* The scroller cards used to clamp at four lines with no control that could
 * reveal the rest, so five of the six quotations ended mid-sentence and could
 * not be read at all (report 18 S2-11). The cards now size to their quotation
 * and stretch to a common height inside the scroller. */
.ql-proof__quote {
	margin: 0 0 16px;
	color: var(--wp--preset--color--ink);
}

.ql-proof__controls {
	display: flex;
	justify-content: center;
	gap: 12px;
	margin-block-start: 16px;
}

.ql-proof__controls button {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--line);
	background: var(--wp--preset--color--white);
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.ql-proof__controls button:hover {
	background: var(--wp--preset--color--sky);
}

/* ---------------------------------------------------------------------
 * 13. Insights / newspaper front (S9) — design-v03/04 §S9
 * ------------------------------------------------------------------- */
.ql-knowledge {
	display: grid;
	gap: 40px;
}

@media (min-width: 1024px) {
	.ql-knowledge {
		grid-template-columns: 7fr 5fr;
	}
}

.ql-knowledge__lead .wp-block-post-featured-image img {
	border-radius: var(--wp--custom--radius--l);
	aspect-ratio: 16 / 9;
	object-fit: cover;
	filter: grayscale(0.1);
}

.ql-knowledge__lead .wp-block-post-featured-image {
	position: relative;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--l);
}

.ql-knowledge__lead .wp-block-post-featured-image::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--wp--preset--color--navy-950);
	mix-blend-mode: multiply;
	opacity: 0.35;
	transition: opacity var(--wp--custom--motion--dur-3);
}

@media (hover: hover) {
	.ql-knowledge__lead a:hover .wp-block-post-featured-image::after {
		opacity: 0;
	}

	.ql-knowledge__lead a:hover img {
		transform: scale(1.03);
	}
}

.ql-knowledge__lead img {
	transition: transform var(--wp--custom--motion--dur-3) var(--wp--custom--motion--ease-out);
}

/* S7's lead story is an h3 by document outline, so the base rule gave it the
 * text family at 600 -- it read as a bold blue sans link, not as the lead of
 * an editorial band (report 18 S2-6). The display family, the ink colour and
 * the undecorated link match .ql-newspaper__lead, which is the same object. */
.ql-knowledge__lead h3 {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--h-2);
	line-height: 1.1;
	margin-block: 16px 8px;
}

.ql-knowledge__lead h3 a { color: var(--wp--preset--color--ink); text-decoration: none; }
.ql-knowledge__lead h3 a:hover { color: var(--wp--preset--color--brand-blue-deep); }

.ql-knowledge__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
}

.ql-knowledge__list li,
.ql-knowledge__list .wp-block-post {
	border-block-end: 1px solid var(--wp--preset--color--line);
	padding-block: 16px;
}

.ql-knowledge__list h4 {
	font-size: var(--wp--preset--font-size--h-4);
	margin: 0 0 6px;
	font-family: var(--font-text);
	font-weight: 600;
}

/* Same treatment as the lead beside them and as every other ledger in the
   system: ink titles that turn brand blue on hover, not permanently blue
   links. Without this the band had an ink lead next to three blue rows. */
.ql-knowledge__list h4 a { color: var(--wp--preset--color--ink); text-decoration: none; }
.ql-knowledge__list h4 a:hover { color: var(--wp--preset--color--brand-blue-deep); }

.ql-knowledge__list time {
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
}

/* ---------------------------------------------------------------------
 * 14. FAQ (S10) — design-v03/04 §S10
 * ------------------------------------------------------------------- */
.ql-faq {
	display: grid;
	gap: 32px;
}

/*
 * The topic rail only earns its column when there is more than one
 * ql_faq_topic to filter by -- the block renders no pills otherwise, and the
 * unconditional two-column rule used to squeeze the whole accordion into the
 * 240px rail track (measured: question rows 240px wide on / and /faq/).
 */
@media (min-width: 900px) {
	.ql-faq:has(.ql-faq__topics) {
		grid-template-columns: 240px 1fr;
		align-items: start;
	}
}

.ql-faq__topics {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

@media (min-width: 900px) {
	.ql-faq__topics {
		flex-direction: column;
		position: sticky;
		top: 96px;
	}

	.ql-faq__topics .ql-chip {
		justify-content: flex-start;
	}
}

.ql-faqs {
	display: grid;
}

.ql-faqs__item {
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-faqs__question {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	min-height: 56px;
	padding-block: 14px;
	font-family: var(--font-text);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--h-4);
	cursor: pointer;
	list-style: none;
}

.ql-faqs__question::-webkit-details-marker { display: none; }

.ql-faqs__question::after {
	content: "";
	flex-shrink: 0;
	width: 10px;
	height: 10px;
	border-inline-end: 1.75px solid currentColor;
	border-block-end: 1.75px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--wp--custom--motion--dur-1);
}

.ql-faqs__item[open] .ql-faqs__question::after {
	transform: rotate(225deg);
}

.ql-faqs__answer {
	padding-block-end: 20px;
	color: var(--wp--preset--color--ink-soft);
	max-width: 68ch;
}

.ql-faq__show-more {
	margin-block-start: 16px;
}

/* --- FAQ page variant (Stage 3): the whole list, not a teaser strip. --- */
.ql-faq--page {
	gap: 24px;
}

.ql-faq__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px 24px;
	padding-block-end: 12px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-faq__count {
	margin: 0;
	font-family: var(--font-text);
	font-size: 0.875rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-mute);
}

.ql-faqs__group + .ql-faqs__group {
	margin-block-start: 40px;
}

.ql-faqs__group-title {
	margin: 0 0 8px;
	font-size: var(--wp--preset--font-size--h-4);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-mute);
}

/*
 * Each question on the FAQ page carries an id, so /faq/#faq-127 lands on a
 * specific answer. :target marks which one was linked to; the accent bar is
 * an inset shadow so it cannot add width and shift the row.
 */
.ql-faqs__item:target {
	box-shadow: inset 3px 0 0 0 var(--wp--preset--color--brand-blue);
}

html[dir="rtl"] .ql-faqs__item:target {
	box-shadow: inset -3px 0 0 0 var(--wp--preset--color--brand-blue);
}

.ql-faqs__item:target > .ql-faqs__question,
.ql-faqs__item:target > .ql-faqs__answer {
	padding-inline-start: 16px;
}

/*
 * The FAQ page's body keeps a reading measure instead of stretching the
 * question rows across the full 1280px container (measured: 1280px-wide
 * summary rows before this cap). Left-aligned, so it shares the hero
 * title's axis rather than floating in the middle of the section.
 */
.ql-faq-content {
	max-width: 820px;
}

.ql-faq-content > .ql-faq {
	margin-block-start: 40px;
}

/* The page's editor-owned intro reads as the lede above the accordion. */
.ql-faq-content > p:first-child {
	max-width: 62ch;
	font-size: var(--wp--preset--font-size--lead);
	color: var(--wp--preset--color--ink-soft);
}

/* ---------------------------------------------------------------------
 * 15. Closing CTA (S11) — design-v03/04 §S11
 * ------------------------------------------------------------------- */
.ql-cta {
	position: relative;
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	overflow: hidden;
	text-align: center;
}

.ql-cta__emblem {
	position: absolute;
	top: 50%;
	inset-inline-start: 50%;
	transform: translate(-50%, -50%);
	width: 480px;
	height: 480px;
	opacity: 0.08;
	color: var(--wp--preset--color--white);
}

.ql-cta__emblem .ql-emblem-a,
.ql-cta__emblem .ql-emblem-b {
	stroke: currentColor !important;
}

.ql-cta__inner {
	position: relative;
	z-index: 2;
	max-width: 640px;
	margin-inline: auto;
}

.ql-cta h2 {
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--display-2);
	margin-block: 0 12px;
}

.ql-cta p {
	color: rgba(255,255,255,0.82);
	margin-block-end: 28px;
}

.ql-cta__actions {
	display: flex;
	gap: 16px;
	justify-content: center;
	flex-wrap: wrap;
	margin-block-end: 20px;
}

.ql-cta__address {
	font-size: 0.875rem;
	color: rgba(255,255,255,0.6);
}

@media (max-width: 599px) {
	.ql-cta__actions .wp-block-button,
	.ql-cta__actions {
		width: 100%;
	}

	.ql-cta__actions .wp-block-button {
		width: 100%;
	}
}

/* ---------------------------------------------------------------------
 * 16. Footer (S12) — design-v03/04 §S12. Rebuilt for Fable review 14 M2:
 * balanced four-column grid, icon social links, an hours block that reads
 * as sentences instead of a 70px one-word-per-line column, and a bottom
 * bar carrying the four endonyms.
 * ------------------------------------------------------------------- */
.ql-footer {
	background: var(--wp--preset--color--navy-950);
	color: rgba(255,255,255,0.78);
	padding-block: 72px 28px;
	position: relative;
}

.ql-footer::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	height: 2px;
	background: var(--wp--custom--gradient--link);
	opacity: 0.6;
}

.ql-footer__grid {
	display: grid;
	gap: 40px 32px;
}

@media (min-width: 700px) {
	.ql-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
	.ql-footer__grid {
		grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.6fr);
		gap: 48px 40px;
	}
}

.ql-footer__heading {
	color: var(--wp--preset--color--white);
	font-family: var(--font-text);
	font-size: 0.78125rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	margin: 0 0 18px;
	padding-block-end: 10px;
	border-block-end: 1px solid var(--wp--preset--color--line-dark);
}

.ql-footer__logo img,
.ql-footer__brand img {
	width: 168px;
	max-width: 100%;
	height: auto;
	margin-block-end: 16px;
	display: block;
}

.ql-footer__about {
	font-size: 0.875rem;
	line-height: 1.6;
	letter-spacing: 0.04em;
	color: rgba(255,255,255,0.6);
	max-width: 30ch;
	margin: 0;
	/* The registered trade name is a fixed Latin string in every language. In
	   an RTL paragraph the bidi algorithm moves its trailing full stop to the
	   left edge of the line, so the Arabic footer read ".CLEARING L.L.C"
	   (Fable round 4, V7-3). Isolating the run keeps the sentence intact; the
	   column keeps its own alignment below. */
	direction: ltr;
	unicode-bidi: isolate;
}

[dir="rtl"] .ql-footer__about {
	text-align: right;
}

/* The classic-menu block's className lands on the <nav>, not the <ul>
   inside it (same root cause as the header, Fable review 14 B1/M2). */
.ql-footer__links ul,
ul.ql-footer__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 2px;
}

.ql-footer__links li { list-style: none; }

.ql-footer__links a {
	display: inline-flex;
	align-items: center;
	min-height: 36px;
	color: rgba(255,255,255,0.74);
	text-decoration: none;
	font-size: 0.9375rem;
	transition: color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-footer__links a:hover {
	color: var(--wp--preset--color--green-glow);
}

.ql-footer__links strong { font-weight: 600; color: var(--wp--preset--color--white); }

.ql-footer__col { min-width: 0; }

/* Contact card */
.ql-footer__contact .ql-contact-info { display: grid; gap: 4px; }

.ql-footer__contact p {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.55;
}

.ql-footer__contact a { color: rgba(255,255,255,0.9); text-decoration: none; }
.ql-footer__contact a:hover { color: var(--wp--preset--color--green-glow); }

.ql-footer__bottom {
	margin-block-start: 48px;
	padding-block-start: 22px;
	border-block-start: 1px solid var(--wp--preset--color--line-dark);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px 24px;
	font-size: 0.8125rem;
	color: rgba(255,255,255,0.55);
}

.ql-footer__copyright {
	display: flex;
	align-items: center;
	gap: 6px;
}

.ql-footer__copyright p,
.ql-footer__copyright .wp-block-site-title {
	margin: 0;
	font-size: 0.8125rem;
	font-family: var(--font-text);
	font-weight: 500;
	color: rgba(255,255,255,0.55);
}

.ql-footer__bottom .ql-lang-selector--list .ql-lang-selector__list {
	gap: 4px 20px;
}

/* ---------------------------------------------------------------------
 * 17. Forms — design-v03/08 (form field, select, checkbox, summary)
 * ------------------------------------------------------------------- */
.ql-request-form-block,
.ql-contact-form-block {
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--l);
	padding: 32px 24px;
	box-shadow: var(--wp--custom--shadow--1);
}

@media (min-width: 600px) {
	.ql-request-form-block, .ql-contact-form-block { padding: 40px; }
}

.ql-field {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-block-end: 20px;
}

.ql-field label {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.ql-field input:not([type="checkbox"]):not([type="radio"]),
.ql-field select,
.ql-field textarea {
	min-height: 52px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--s);
	padding: 12px 14px;
	font-size: 1rem;
	font-family: var(--font-text);
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--white);
}

.ql-field textarea { min-height: 140px; resize: vertical; }

.ql-field input:focus-visible,
.ql-field select:focus-visible,
.ql-field textarea:focus-visible {
	border-color: var(--wp--preset--color--brand-blue-deep);
}

.ql-field:has(.ql-field-error) input,
.ql-field:has(.ql-field-error) select,
.ql-field:has(.ql-field-error) textarea {
	border-color: var(--wp--preset--color--danger);
}

.ql-field-error {
	display: flex;
	align-items: center;
	gap: 6px;
	color: var(--wp--preset--color--danger);
	font-size: 0.8125rem;
}

.ql-field-error::before {
	content: "!";
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--wp--preset--color--danger);
	color: var(--wp--preset--color--white);
	font-size: 11px;
	font-weight: 700;
	flex-shrink: 0;
}

/*
 * Stage 3 form states. The error summary is the first thing in a rejected
 * form and the thing focus lands on, so it reads as a block, not as a stray
 * red line; each entry links to the field it is about.
 */
.ql-form-error-summary {
	background: rgba(179,38,30,0.08);
	border: 1px solid var(--wp--preset--color--danger);
	border-radius: var(--wp--custom--radius--s);
	padding: 16px 18px;
	margin-block-end: 24px;
}

.ql-form-error-summary:focus-visible {
	outline: 2px solid var(--wp--preset--color--danger);
	outline-offset: 3px;
}

.ql-form-error-summary .ql-form-error--general {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}

.ql-form-error-summary__title {
	margin: 0;
	font-weight: 600;
	color: var(--wp--preset--color--danger);
}

.ql-form-error-summary__list {
	margin: 8px 0 0;
	padding-inline-start: 20px;
	color: var(--wp--preset--color--danger);
	font-size: 0.9375rem;
}

.ql-form-error-summary__list li + li {
	margin-block-start: 4px;
}

.ql-form-error-summary__list a {
	color: inherit;
	display: inline-flex;
	align-items: center;
	min-height: 24px;
}

/* The required marker sits with the label text, not on its own line. */
.ql-field__required {
	color: var(--wp--preset--color--danger);
	margin-inline-start: 4px;
}

.ql-form-error--general {
	background: rgba(179,38,30,0.08);
	border: 1px solid var(--wp--preset--color--danger);
	border-radius: var(--wp--custom--radius--s);
	padding: 14px 16px;
	color: var(--wp--preset--color--danger);
	margin-block-end: 20px;
}

.ql-field--honeypot {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.ql-field--submit { margin-block-start: 8px; }

.ql-form-submit {
	min-height: 52px;
	padding-inline: 28px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand-green-deep);
	color: var(--wp--preset--color--white);
	border: none;
	font-weight: 600;
	font-size: 1rem;
	cursor: pointer;
	transition: transform var(--wp--custom--motion--dur-1), box-shadow var(--wp--custom--motion--dur-1);
}

.ql-form-submit:hover { transform: translateY(-1px); box-shadow: var(--wp--custom--shadow--2); }

.ql-form-success {
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--l);
	padding: 48px 32px;
	text-align: center;
}

.ql-form-success .ql-motif-check-seal {
	width: 72px;
	height: 72px;
	color: var(--wp--preset--color--green-glow);
	margin-block-end: 16px;
}

.ql-form-success .ql-check-seal-ring,
.ql-form-success .ql-check-seal-mark {
	stroke-dasharray: 1;
	stroke-dashoffset: 0;
	animation: ql-draw 0.8s var(--wp--custom--motion--ease-out) both;
}

.ql-form-success .ql-check-seal-mark { animation-delay: 0.5s; }

@keyframes ql-draw {
	from { stroke-dashoffset: 1; }
	to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
	.ql-form-success .ql-check-seal-ring, .ql-form-success .ql-check-seal-mark { animation: none; }
}

.ql-form-success__title {
	margin: 0 0 8px;
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--h-3);
}

.ql-form-success__body {
	max-width: 46ch;
	margin-inline: auto;
}

.ql-form-success:focus-visible {
	outline: 2px solid var(--wp--preset--color--green-glow);
	outline-offset: 3px;
}

.ql-form-success p { color: rgba(255,255,255,0.86); }

.ql-form-success a { color: var(--wp--preset--color--white); text-decoration: underline; }

/* ---------------------------------------------------------------------
 * 18. Page-family heroes — design-v03/05
 * ------------------------------------------------------------------- */
.ql-page-hero {
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	padding-block: 56px;
	position: relative;
	overflow: clip;
}

@media (min-width: 1024px) {
	.ql-page-hero { padding-block: 88px 80px; }
}

.ql-page-hero.is-short { padding-block: 48px; }

@media (min-width: 1024px) {
	.ql-page-hero.is-short { padding-block: 64px; }
}

.ql-page-hero__motif {
	position: absolute;
	inset-block-start: -40px;
	inset-inline-end: -40px;
	width: 320px;
	height: auto;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.16;
	pointer-events: none;
}

.ql-page-hero h1 {
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--display-2);
	line-height: 1.06;
	margin-block: 8px 16px;
	max-width: 20ch;
	text-wrap: balance;
}

html[lang^="ar"] .ql-page-hero h1,
html[lang^="hi"] .ql-page-hero h1 { line-height: 1.25; }

html[lang^="hi"] .ql-page-hero h1,
html[lang^="ru"] .ql-page-hero h1 {
	font-size: calc(var(--wp--preset--font-size--display-2) * 0.86);
	max-width: 24ch;
}

html[lang^="ru"] .ql-page-hero h1 { line-height: 1.14; }

.ql-page-hero .ql-lead { color: rgba(255,255,255,0.85); }
.ql-page-hero .ql-eyebrow { color: var(--wp--preset--color--green-glow); }

.ql-page-hero.is-light {
	background: var(--wp--preset--color--paper);
	background-image: none;
	color: var(--wp--preset--color--ink);
}

.ql-page-hero.is-light h1 { color: var(--wp--preset--color--ink); }
.ql-page-hero.is-light .ql-lead { color: var(--wp--preset--color--ink-soft); }
.ql-page-hero.is-light .ql-eyebrow { color: var(--wp--preset--color--brand-blue-deep); }
.ql-page-hero.is-light .ql-page-hero__motif { color: var(--wp--preset--color--brand-blue-deep); opacity: 0.1; }

/* Services directory hero: bigger type, the finder inline underneath. */
.ql-directory-hero h1 { font-size: var(--wp--preset--font-size--display-1); max-width: 14ch; }

.ql-breadcrumb {
	margin: 0 0 18px;
	font-size: 0.8125rem;
}

.ql-breadcrumb ol {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.ql-breadcrumb li { display: inline-flex; align-items: center; gap: 6px; }
/* 24px is the WCAG 2.2 target-size minimum; the breadcrumb links measured
   35x21 before the padding was added. */
.ql-breadcrumb a { color: inherit; opacity: 0.75; text-decoration: none; display: inline-flex; align-items: center; min-height: 24px; }
.ql-breadcrumb a:hover { opacity: 1; text-decoration: underline; text-underline-offset: 4px; }
.ql-breadcrumb li[aria-current] { opacity: 1; font-weight: 600; }
.ql-breadcrumb li:not(:last-child)::after { content: "/"; opacity: 0.4; }

html[dir="rtl"] .ql-breadcrumb li:not(:last-child)::after { content: "\\"; }

/* Article hero meta row */
.ql-article-hero h1 {
	font-size: var(--wp--preset--font-size--h-2);
	max-width: 22ch;
}

.ql-article-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 18px;
	margin-block-start: 20px;
	font-size: 0.875rem;
	color: var(--wp--preset--color--ink-mute);
}

/* The meta row is a core group with `is-layout-flow`, so core gives every
 * child but the first `margin-block-start: 1.5rem`. With `align-items: center`
 * the margin box -- not the text -- is what gets centred, which dropped the
 * date and the category 12px below the author (report 18 S2-9, EN and AR). */
.ql-article-meta > * { margin-block: 0; }

.ql-article-meta a { color: var(--wp--preset--color--brand-blue-deep); text-decoration: none; }
.ql-article-meta a:hover { text-decoration: underline; text-underline-offset: 4px; }

.ql-standfirst {
	font-size: var(--wp--preset--font-size--lead);
	line-height: 1.5;
	color: var(--wp--preset--color--ink-soft);
	margin-block-start: 8px;
}

.ql-legal-updated { font-size: 0.875rem; color: var(--wp--preset--color--ink-mute); }

/* ---------------------------------------------------------------------
 * 19. Service detail — design-v03/05, 11. Rebuilt as a conversion page
 * (Fable review 14 M4): hero with a contained primary action, an 8/4 body
 * with a sticky request panel, and a mobile sticky bar.
 * ------------------------------------------------------------------- */
.ql-service-hero__grid {
	display: grid;
	gap: 32px;
	align-items: center;
}

@media (min-width: 1024px) {
	.ql-service-hero__grid { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
}

.ql-service-hero__copy { min-width: 0; }

.ql-service-hero h1 {
	font-size: var(--wp--preset--font-size--display-2);
	line-height: 1.06;
	margin-block: 6px 12px;
	max-width: 18ch;
}

.ql-service-hero__motif {
	display: none;
	width: 100%;
	max-width: 220px;
	height: auto;
	margin-inline: auto;
	color: var(--wp--preset--color--brand-blue-deep);
	opacity: 0.32;
}

@media (min-width: 1024px) {
	.ql-service-hero__motif { display: block; }
}

/* The hero button is a pill, never a container-wide slab (Fable M4: a
   620px green pill). `wp:buttons` is a flex row; this keeps the link
   intrinsically sized. */
.ql-service-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-block-start: 24px;
}

.ql-service-hero__actions .wp-block-button__link {
	width: auto;
	padding-inline: 28px;
}

.ql-service-layout {
	display: grid;
	gap: 40px;
}

@media (min-width: 1024px) {
	.ql-service-layout {
		grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
		gap: 56px;
		align-items: start;
	}
}

.ql-service-main { min-width: 0; }
.ql-service-main > * { max-width: var(--wp--custom--container--prose); }
.ql-service-main .ql-service-details { max-width: none; }

/* Request panel */
.ql-service-request-panel {
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--l);
	box-shadow: var(--wp--custom--shadow--2);
	padding: 28px;
}

@media (min-width: 1024px) {
	.ql-service-request-panel { position: sticky; top: 96px; }
}

.ql-request-panel__eyebrow { margin-block-end: 14px; }

.ql-request-panel__price {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding-block-end: 16px;
	margin-block-end: 16px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-request-panel__price-label {
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-mute);
}

.ql-request-panel__price-value {
	font-family: var(--font-display);
	font-size: 1.5rem;
	font-weight: 500;
	color: var(--wp--preset--color--ink);
	text-align: end;
}

.ql-request-panel__includes {
	list-style: none;
	margin: 0 0 22px;
	padding: 0;
	display: grid;
	gap: 10px;
}

.ql-request-panel__includes li {
	display: flex;
	align-items: start;
	gap: 10px;
	font-size: 0.9375rem;
	line-height: 1.45;
	color: var(--wp--preset--color--ink-soft);
}

.ql-request-panel__includes .ql-icon {
	width: 18px;
	height: 18px;
	margin-block-start: 3px;
	color: var(--wp--preset--color--brand-green-deep);
	flex: 0 0 auto;
}

.ql-service-request-panel .wp-block-buttons,
.ql-service-request-panel .wp-block-button,
.ql-service-request-panel .wp-block-button__link {
	width: 100%;
}

.ql-request-panel__whatsapp,
.ql-request-panel__docs {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 14px 0 0;
	font-size: 0.875rem;
	color: var(--wp--preset--color--ink-soft);
}

.ql-request-panel__whatsapp a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: var(--wp--preset--color--brand-green-deep);
	font-weight: 600;
	text-decoration: none;
	min-height: 44px;
}

.ql-request-panel__whatsapp .ql-icon,
.ql-request-panel__docs .ql-icon { width: 18px; height: 18px; color: var(--wp--preset--color--brand-blue-deep); }

.ql-request-panel__note {
	margin: 16px 0 0;
	padding-block-start: 14px;
	border-block-start: 1px solid var(--wp--preset--color--line);
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--wp--preset--color--ink-mute);
}

/* Mobile sticky bar */
.ql-service-sticky-bar { display: none; }

@media (max-width: 1023px) {
	.ql-service-sticky-bar {
		display: block;
		position: sticky;
		bottom: 0;
		z-index: 400;
		background: var(--wp--preset--color--white);
		border-block-start: 1px solid var(--wp--preset--color--line);
		box-shadow: 0 -8px 28px rgba(7,26,43,0.14);
	}

	.ql-request-bar {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 14px;
		padding: 10px var(--ql-gutter);
		max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2);
		margin-inline: auto;
	}

	.ql-request-bar__title {
		font-weight: 600;
		font-size: 0.9375rem;
		line-height: 1.25;
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
	}

	.ql-request-bar .wp-block-button__link {
		min-height: 48px;
		white-space: nowrap;
		padding-inline: 20px;
	}

	.ql-service-layout > .ql-service-request-panel { display: none; }
}

.ql-service-hero-subtitle {
	font-size: var(--wp--preset--font-size--lead);
	line-height: 1.5;
	color: var(--wp--preset--color--ink-soft);
	max-width: 46ch;
	margin-block: 0;
}

.ql-service-overview-title {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-2);
	margin-block: 0 14px;
}

.ql-service-overview-text,
.ql-service-details-text {
	color: var(--wp--preset--color--ink-soft);
	margin-block-end: 20px;
	line-height: 1.7;
}

.ql-service-details { margin-block-start: 48px; }

.ql-service-features ul,
.ql-service-documents ul,
.ql-service-benefits ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.ql-service-details > div { margin-block-end: 48px; }

.ql-service-details h2 {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-2);
	margin-block: 0 20px;
	padding-block-end: 12px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-service-details .ql-service-features { counter-reset: ql-feature; }

.ql-service-details .ql-service-features li {
	counter-increment: ql-feature;
	position: relative;
	padding-inline-start: 44px;
	padding-block: 16px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-service-details .ql-service-features li::before {
	content: counter(ql-feature);
	position: absolute;
	inset-inline-start: 0;
	top: 16px;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	font-size: 0.8125rem;
	font-weight: 700;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.ql-service-details .ql-service-features strong,
.ql-service-details .ql-service-benefits strong {
	display: block;
	font-size: 1.0625rem;
	color: var(--wp--preset--color--ink);
	margin-block-end: 4px;
}

.ql-service-details .ql-service-features li > div,
.ql-service-details .ql-service-documents li > div,
.ql-service-details .ql-service-benefits li > div {
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.9375rem;
	line-height: 1.6;
}

@media (min-width: 700px) {
	.ql-service-details .ql-service-documents ul {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 0 32px;
	}
}

.ql-service-details .ql-service-documents li {
	position: relative;
	padding-inline-start: 32px;
	padding-block: 12px;
	break-inside: avoid;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

/* The tick used to be a 9x2px diagonal sliver inside the box, which at any
 * real size reads as a chevron rather than a checkmark (report 18 S2-10).
 * The box and the tick are now two pseudo-elements: a rounded square and a
 * proper two-stroke check drawn with borders, so it stays crisp at every
 * zoom level and inherits the brand green. */
.ql-service-details .ql-service-documents li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: 14px;
	width: 20px;
	height: 20px;
	border: 1.75px solid var(--wp--preset--color--brand-green-deep);
	border-radius: 5px;
	background: none;
}

.ql-service-details .ql-service-documents li::after {
	content: "";
	position: absolute;
	inset-inline-start: 5px;
	top: 19px;
	width: 9px;
	height: 5px;
	border-left: 2px solid var(--wp--preset--color--brand-green-deep);
	border-bottom: 2px solid var(--wp--preset--color--brand-green-deep);
	border-radius: 1px;
	transform: rotate(-45deg);
	transform-origin: center;
}

.ql-service-details .ql-service-benefits ul {
	display: grid;
	gap: 24px;
}

@media (min-width: 700px) {
	.ql-service-details .ql-service-benefits ul { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.ql-service-details .ql-service-benefits li {
	padding: 24px;
	background: var(--wp--preset--color--sky);
	border-radius: var(--wp--custom--radius--m);
}

.ql-service-poa-flag {
	display: inline-block;
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	border-radius: var(--wp--custom--radius--pill);
	padding: 4px 12px;
	font-size: 0.8125rem;
	font-weight: 600;
}

/* The `ql-service-price` line in the body duplicates the request panel's
   price row; the panel is the canonical one. */
.ql-service-main .ql-service-price { display: none; }

/* ---------------------------------------------------------------------
 * 20. Article — design-v03/05, 11.
 *
 * Fable review 14 M3: the reading column must BE the prose container (720)
 * with the TOC and share rails OUTSIDE it. The layout is a three-track grid
 * on the 1280 band: rail / prose(720) / rail. Below 1024 the rails collapse
 * above and below the prose and the TOC becomes a <details>.
 * ------------------------------------------------------------------- */
.ql-article-plate img {
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--xl);
	display: block;
	margin-block-end: 48px;
}

.ql-article-layout {
	display: grid;
	gap: 32px;
	align-items: start;
}

@media (min-width: 1024px) {
	.ql-article-layout {
		grid-template-columns: minmax(180px, 1fr) minmax(0, var(--wp--custom--container--prose)) minmax(180px, 1fr);
		gap: 48px;
		justify-content: center;
	}
}

.ql-article-body,
.ql-article-layout .ql-prose {
	min-width: 0;
	max-width: var(--wp--custom--container--prose);
	margin-inline: auto;
	font-size: var(--wp--preset--font-size--body);
	line-height: 1.75;
}

.ql-article-body > * { max-width: 100%; }

.ql-article-body h2 {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-2);
	margin-block: 48px 16px;
	scroll-margin-block-start: 96px;
}

.ql-article-body h3 {
	font-size: var(--wp--preset--font-size--h-3);
	margin-block: 32px 12px;
	scroll-margin-block-start: 96px;
}

.ql-article-body p { margin-block: 0 20px; }
.ql-article-body img { border-radius: var(--wp--custom--radius--m); height: auto; }
.ql-article-body figcaption { font-size: 0.8125rem; color: var(--wp--preset--color--ink-mute); }

.ql-article-body ul,
.ql-article-body ol { padding-inline-start: 1.25em; margin-block: 0 20px; }
.ql-article-body li { margin-block-end: 8px; }

.ql-article-body blockquote {
	margin: 32px 0;
	padding-inline-start: 24px;
	border-inline-start: 3px solid transparent;
	border-image: var(--wp--custom--gradient--link) 1;
	font-family: var(--font-display);
	font-size: 1.375rem;
	line-height: 1.4;
	color: var(--wp--preset--color--ink);
}

html[lang^="ar"] .ql-article-body blockquote { font-style: normal; font-weight: 700; }

/* Rails */
.ql-article-rail { min-width: 0; }

.ql-rail-label {
	font-family: var(--font-text);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-mute);
	margin: 0 0 14px;
}

@media (min-width: 1024px) {
	.ql-article-rail--toc,
	.ql-article-rail--share {
		position: sticky;
		top: 104px;
	}

	.ql-article-rail--share { text-align: end; }
	html[dir="rtl"] .ql-article-rail--share { text-align: start; }
}

@media (max-width: 1023px) {
	.ql-article-rail--toc { order: -1; }
	.ql-article-rail--share {
		border-block-start: 1px solid var(--wp--preset--color--line);
		padding-block-start: 24px;
	}
}

.ql-toc { font-size: 0.875rem; }

.ql-toc ol {
	list-style: none;
	margin: 0;
	padding: 0;
	border-inline-start: 2px solid var(--wp--preset--color--line);
	display: grid;
	gap: 2px;
	counter-reset: ql-toc;
}

.ql-toc li { counter-increment: ql-toc; }

.ql-toc a {
	display: block;
	padding-block: 8px;
	padding-inline-start: 14px;
	margin-inline-start: -2px;
	color: var(--wp--preset--color--ink-soft);
	text-decoration: none;
	border-inline-start: 2px solid transparent;
	line-height: 1.35;
	transition: color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		border-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-toc a:hover { color: var(--wp--preset--color--ink); }

.ql-toc a.is-active {
	color: var(--wp--preset--color--brand-blue-deep);
	border-inline-start-color: var(--wp--preset--color--brand-blue-deep);
	font-weight: 600;
}

/* Share controls */
.ql-share {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

@media (min-width: 1024px) {
	.ql-share { justify-content: flex-end; }
	html[dir="rtl"] .ql-share { justify-content: flex-start; }
}

.ql-share a,
.ql-share button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-width: 44px;
	min-height: 44px;
	padding-inline: 12px;
	border-radius: var(--wp--custom--radius--pill);
	border: 1px solid var(--wp--preset--color--line);
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.8125rem;
	font-family: var(--font-text);
	text-decoration: none;
	cursor: pointer;
	transition: border-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-share a:hover,
.ql-share button:hover {
	border-color: var(--wp--preset--color--brand-blue-deep);
	color: var(--wp--preset--color--brand-blue-deep);
	transform: translateY(-1px);
}

.ql-share .ql-icon { width: 18px; height: 18px; }

.ql-share__toast {
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
	transition: opacity var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		visibility var(--wp--custom--motion--dur-1);
	position: fixed;
	inset-block-end: 24px;
	inset-inline-end: 24px;
	background: var(--wp--preset--color--navy-950);
	color: var(--wp--preset--color--white);
	padding: 12px 20px;
	border-radius: var(--wp--custom--radius--pill);
	box-shadow: var(--wp--custom--shadow--3);
	z-index: 1200;
	font-size: 0.875rem;
}

.ql-share__toast.is-visible {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

/* Related reading — a ruled ledger, never a card grid. */
.ql-related-reading .wp-block-post-template {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0;
}

@media (min-width: 900px) {
	.ql-related-reading .wp-block-post-template { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 32px; }
}

.ql-related-reading li {
	list-style: none;
	padding-block: 20px;
	border-block-start: 1px solid var(--wp--preset--color--line);
}

.ql-related-reading .wp-block-post-title {
	font-family: var(--font-text);
	font-size: var(--wp--preset--font-size--h-4);
	font-weight: 600;
	margin: 6px 0 8px;
}

.ql-related-reading .wp-block-post-title a { color: var(--wp--preset--color--ink); text-decoration: none; }
.ql-related-reading .wp-block-post-title a:hover { color: var(--wp--preset--color--brand-blue-deep); }
.ql-related-reading .wp-block-post-date { font-size: 0.8125rem; color: var(--wp--preset--color--ink-mute); }

.ql-ledger__eyebrow,
.ql-ledger__eyebrow a {
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
}

@media print {
	.ql-header, .ql-footer, .ql-article-rail, .ql-cta, .ql-mobile-sheet, .skip-link, .ql-service-sticky-bar { display: none !important; }
	.ql-prose, .ql-article-body { max-width: 100%; }
}

/* ---------------------------------------------------------------------
 * 21. Empty states — 404, 410, search — design-v03/05
 * ------------------------------------------------------------------- */
/*
 * Search page summary (quicklink/search-summary). The heading and the count
 * are one unit: the count is a caption under the title, not a separate
 * paragraph competing with the search field below it.
 */
.ql-search-summary__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--display-2);
	line-height: 1.08;
	max-width: 22ch;
	/* The quoted query is arbitrary user input and can be one long token, so
	   the heading must be able to break it -- but `anywhere` also chopped the
	   heading's own words. `break-word` breaks only what cannot fit. */
	overflow-wrap: break-word;
}

.ql-search-summary__count {
	margin: 12px 0 0;
	font-family: var(--font-text);
	font-size: 0.875rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-mute);
}

.ql-search-hero .ql-search-form {
	margin-block-start: 28px;
	max-width: 560px;
}

/* The no-results state keeps the same measure as a results list, so the
 * page does not visibly jump between the two. */
.ql-empty-state--search {
	padding-block: 24px;
}

.ql-empty-state {
	text-align: center;
	position: relative;
}

.ql-empty-state h1 {
	font-size: var(--wp--preset--font-size--display-2);
	line-height: 1.06;
	margin-block: 20px 14px;
	max-width: 18ch;
	margin-inline: auto;
}

.ql-empty-state .ql-lead {
	max-width: 52ch;
	margin-inline: auto;
}

.ql-empty-state__motif {
	display: block;
	width: min(100%, 420px);
	height: auto;
	margin-inline: auto;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.5;
}

.ql-empty-state--404,
.ql-empty-state--410 {
	color: var(--wp--preset--color--white);
}

.ql-empty-state--404 h1,
.ql-empty-state--410 h1 { color: var(--wp--preset--color--white); }

.ql-empty-state--404 .ql-lead,
.ql-empty-state--410 .ql-lead { color: rgba(255,255,255,0.82); }

/* The 410 route is deliberately broken: the path stops at the second node. */
.ql-empty-state--410 .ql-empty-state__motif .ql-route-path {
	stroke-dasharray: 10 14;
	opacity: 0.55;
}

.ql-empty-state .ql-service-finder-wrap {
	max-width: 640px;
	margin: 36px auto 0;
	text-align: start;
}

/*
 * quicklink/empty-state-actions emits real core button markup
 * (.wp-block-buttons > .wp-block-button > a.wp-block-button__link), so the
 * theme's own button styles -- including the night-section contrast fix --
 * already own colour here. This ruleset therefore only does layout; the
 * plain-<a> styling below is kept for any non-button link dropped into an
 * empty state, and is explicitly held off the buttons so the two do not
 * fight (a colour override here produced ink-on-green-deep on the light
 * search no-results state).
 */
.ql-empty-state__actions {
	display: flex;
	gap: 12px;
	justify-content: center;
	flex-wrap: wrap;
	margin-block-start: 28px;
}

.ql-empty-state__actions a:not(.wp-block-button__link) {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-inline: 20px;
	border-radius: var(--wp--custom--radius--pill);
	border: 1px solid rgba(255,255,255,0.28);
	color: var(--wp--preset--color--white);
	text-decoration: none;
	font-weight: 600;
	font-size: 0.9375rem;
}

.ql-empty-state__actions a:not(.wp-block-button__link):hover { background: rgba(255,255,255,0.1); }

.ql-empty-state__group-link {
	text-align: center;
	margin-block-start: 20px;
}

.ql-empty-state__group-link a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-inline: 22px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand-green-deep);
	color: var(--wp--preset--color--white);
	text-decoration: none;
	font-weight: 600;
	font-size: 0.9375rem;
}

/* A light empty state (search no-results) inverts the palette. */
.ql-section.is-base .ql-empty-state,
.ql-section.is-surface .ql-empty-state { color: var(--wp--preset--color--ink); }

.ql-section.is-base .ql-empty-state .ql-empty-state__motif,
.ql-section.is-surface .ql-empty-state .ql-empty-state__motif {
	color: var(--wp--preset--color--brand-blue-deep);
	opacity: 0.3;
	max-width: 260px;
}

.ql-section.is-base .ql-empty-state__actions a:not(.wp-block-button__link),
.ql-section.is-surface .ql-empty-state__actions a:not(.wp-block-button__link) {
	border-color: var(--wp--preset--color--line);
	color: var(--wp--preset--color--ink);
}

/* ------------------------------------------------- Newspaper (blog index) */
/* `.ql-newspaper` is the band around the blog index and the category
   archives. Its own two-column grid, and the `.ql-newspaper__lead` /
   `.ql-newspaper__list` rules that used to sit under it, belonged to the two
   hand-copied core/query blocks that quicklink/editorial-index replaced in
   Stage 3; nothing emits those class names any more, and the grid was still
   squeezing the ledger into 714px of a 1280px band (report 18 S3-1). The
   editorial index owns its own composition now. */
.ql-newspaper {
	--ql-newspaper-gap: 40px;
}

/* Search results ledger */
.ql-search-results .wp-block-post-template { list-style: none; margin: 0; padding: 0; }

.ql-search-results li {
	list-style: none;
	padding-block: 24px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-search-results .wp-block-post-title {
	font-family: var(--font-text);
	font-size: var(--wp--preset--font-size--h-3);
	font-weight: 600;
	margin: 0 0 8px;
}

.ql-search-results .wp-block-post-title a { color: var(--wp--preset--color--ink); text-decoration: none; }
.ql-search-results .wp-block-post-excerpt { color: var(--wp--preset--color--ink-soft); font-size: 0.9375rem; }

.ql-search-form { margin-block-start: 20px; max-width: 520px; }

/* Pagination */
.wp-block-query-pagination,
.ql-pagination {
	display: flex;
	justify-content: center;
	gap: 8px;
	margin-block-start: 48px;
}

.wp-block-query-pagination-numbers a,
.wp-block-query-pagination-numbers span,
.wp-block-query-pagination-next a,
.wp-block-query-pagination-previous a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	height: 44px;
	border-radius: var(--wp--custom--radius--pill);
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	padding-inline: 12px;
	border: 1px solid var(--wp--preset--color--line);
}

.wp-block-query-pagination-numbers .current {
	background: var(--wp--preset--color--navy-900);
	border-color: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
	font-weight: 700;
}

/* quicklink/editorial-index renders its own pagination -- a status line plus
   `ul.ql-pagination__list > li > a.page-numbers` -- and NOT core's
   `wp-block-query-pagination-*` classes, so the chip rules above never reached
   it: every blog index and category archive showed a bulleted stack of
   underlined links (Fable round 4, V7-2). Same chip treatment, logical
   properties throughout so it mirrors in Arabic, 44px minimum target. */
.ql-pagination {
	flex-wrap: wrap;
	align-items: center;
}

.ql-pagination__status {
	margin: 0;
	font-size: 0.875rem;
	color: var(--wp--preset--color--ink-soft);
}

.ql-pagination__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.ql-pagination__list li {
	margin: 0;
	list-style: none;
}

.ql-pagination__list .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	height: 44px;
	padding-inline: 12px;
	border-radius: var(--wp--custom--radius--pill);
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	font-size: 0.9375rem;
	border: 1px solid transparent;
}

.ql-pagination__list a.page-numbers {
	border-color: var(--wp--preset--color--line);
}

.ql-pagination__list a.page-numbers:hover,
.ql-pagination__list a.page-numbers:focus-visible {
	background: var(--wp--preset--color--sky);
}

.ql-pagination__list .page-numbers.current {
	background: var(--wp--preset--color--navy-900);
	border-color: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
	font-weight: 700;
}

.ql-pagination__list .page-numbers.dots {
	min-width: 24px;
	padding-inline: 0;
	border-color: transparent;
	color: var(--wp--preset--color--ink-soft);
}

.ql-pagination__list .page-numbers.prev,
.ql-pagination__list .page-numbers.next {
	padding-inline: 18px;
	font-weight: 600;
}

/* ---------------------------------------------------------------------
 * 22. Motion — design-v03/07 (reveal, count-up, reduced motion)
 * ------------------------------------------------------------------- */
.ql-reveal {
	opacity: 0;
	transform: translateY(16px);
	transition: opacity var(--wp--custom--motion--dur-3) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-3) var(--wp--custom--motion--ease-out);
}

.ql-reveal.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.ql-reveal-group.is-visible > * {
	transition-delay: calc(var(--ql-stagger-index, 0) * 60ms);
}

@media (prefers-reduced-motion: reduce) {
	.ql-reveal, .ql-reveal-group > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.ql-hero__ambient,
	.ql-signature-draw,
	.ql-route-path {
		animation: none !important;
	}
}

.ql-hero__ambient {
	animation: ql-drift 12s ease-in-out infinite alternate;
}

@keyframes ql-drift {
	from { transform: translate(0, 0); }
	to { transform: translate(-4%, 2%); }
}

/* These two paths are drawn. Always. There is no undrawn resting state.
 *
 * History, because it caught us twice. Originally the paths started at
 * `stroke-dashoffset: 1` (with `pathLength="1"`, fully undrawn) and were
 * revealed only when motion-draw.js added a class. Without JavaScript, or
 * under `prefers-reduced-motion`, they stayed invisible for good. The first
 * repair moved that undrawn start behind `html.ql-motion-draw`, a class the
 * script sets only when it will animate -- which fixed the no-JS and
 * reduced-motion cases but not the real one: an IntersectionObserver never
 * fires for an element below the fold, and Chromium's full-page screenshot
 * captures past the viewport WITHOUT scrolling. So S4's signature, three
 * screens down, stayed at offset 1 in every capture, showing nothing but the
 * round line cap of its own start point as a stray dot (Fable round 3, R3-1).
 *
 * The resting state is now simply "drawn", in CSS, unconditionally. The
 * reveal is a Web Animations call in motion-draw.js that runs from offset 1
 * to 0 when the path scrolls into view; it changes nothing at rest, so a path
 * that is never scrolled to, never observed, or never reached by JavaScript
 * at all is fully drawn rather than absent. `stroke-dasharray: 1` stays
 * because the animation interpolates against it. */
.ql-signature-draw,
.ql-route-path {
	stroke-dasharray: 1;
	stroke-dashoffset: 0;
}

.ql-rail__ledger a .ql-icon-chevron-draw {
	stroke-dasharray: 1;
	stroke-dashoffset: 0;
}

/* ---------------------------------------------------------------------
 * 23. Contact info (shared: footer contact card + contact page card)
 *
 * Fable review 14 M2: the hours block was a `grid-template-columns: auto 1fr`
 * definition list inside a ~270px footer column, so the label ate 200px and
 * the value wrapped one word per line. Label and value now stack: the label
 * is an eyebrow above its sentence, at every width.
 * ------------------------------------------------------------------- */
.ql-contact-info p {
	display: flex;
	align-items: start;
	gap: 10px;
	margin: 0 0 10px;
}

.ql-contact-info p > .ql-icon {
	width: 18px;
	height: 18px;
	margin-block-start: 3px;
	color: var(--wp--preset--color--brand-blue);
	flex: 0 0 auto;
}

.ql-contact-info__whatsapp a,
.ql-contact-info__map-link a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
}

.ql-contact-info__whatsapp-link {
	font-weight: 600;
	color: var(--wp--preset--color--green-glow) !important;
}

.ql-contact-info__whatsapp-link .ql-icon { width: 20px; height: 20px; }

.ql-contact-info__hours {
	display: grid;
	gap: 2px;
	margin: 18px 0 0;
	padding-block-start: 16px;
	border-block-start: 1px solid var(--wp--preset--color--line-dark);
	font-size: 0.875rem;
}

.ql-contact-info__hours dt {
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	/* 0.6 blended ink-soft into #6F7A85 on the white contact card = 4.37:1 for
	   12px bold text, the one serious axe violation on /contact-us/ after r6.
	   0.85 keeps the label muted on both the light card and the dark footer
	   while measuring 5.2:1 on white. */
	opacity: 0.85;
	margin-block-start: 8px;
}

.ql-contact-info__hours dt:first-child { margin-block-start: 0; }

.ql-contact-info__hours dd {
	margin: 0;
	color: inherit;
	line-height: 1.5;
}

.ql-contact-info__emergency-note {
	margin-block-start: 10px;
	opacity: 0.72;
	font-size: 0.8125rem;
	line-height: 1.5;
}

.ql-contact-info__social {
	display: flex;
	gap: 10px;
	list-style: none;
	margin: 18px 0 0;
	padding: 0;
}

.ql-contact-info__social li { list-style: none; }

/* The contact-info block appears on BOTH surfaces: the night footer and the
   light contact page. It used to default to white icons on a white-ish
   border, with the light treatment scoped to `.ql-contact-card` — so on the
   contact page, where the block is not inside a card, the three social icons
   rendered white on paper and were effectively invisible
   (contact-ru-820-r5.png). The light treatment is now the DEFAULT and the
   dark bands opt in, which is the safer direction: a missed surface shows
   dark-on-light, never invisible. */
.ql-contact-info__social a {
	/* 44px: the stage-2 brief's target-size floor (40x40 in the r6 sweep). */
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--line);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--wp--preset--color--ink-soft);
	text-decoration: none;
	transition: background-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out),
		transform var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-contact-info__social a:hover {
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	transform: translateY(-2px);
}

.ql-footer .ql-contact-info__social a,
.ql-section.is-night .ql-contact-info__social a,
.ql-mobile-sheet .ql-contact-info__social a {
	border-color: var(--wp--preset--color--line-dark);
	color: rgba(255,255,255,0.85);
}

.ql-footer .ql-contact-info__social a:hover,
.ql-section.is-night .ql-contact-info__social a:hover,
.ql-mobile-sheet .ql-contact-info__social a:hover {
	background: rgba(255,255,255,0.1);
	color: var(--wp--preset--color--green-glow);
}

.ql-contact-info__social .ql-icon { width: 20px; height: 20px; }

.ql-contact-info__map-link a {
	margin-block-start: 18px;
	min-height: 44px;
}

/* On a light surface (contact page card) the same block flips its palette. */
.ql-contact-card {
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--l);
	padding: 28px;
	box-shadow: var(--wp--custom--shadow--1);
	align-self: start;
}

.ql-contact-card__heading {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-3);
	margin: 0 0 18px;
}

.ql-contact-card .ql-contact-info__hours,
.ql-contact-card .ql-contact-info__social a {
	border-color: var(--wp--preset--color--line);
}

.ql-contact-card .ql-contact-info__social a { color: var(--wp--preset--color--ink-soft); }
.ql-contact-card .ql-contact-info__social a:hover { background: var(--wp--preset--color--sky); color: var(--wp--preset--color--brand-blue-deep); }
.ql-contact-card .ql-contact-info__whatsapp-link { color: var(--wp--preset--color--brand-green-deep) !important; }
.ql-contact-card .ql-contact-info p > .ql-icon { color: var(--wp--preset--color--brand-blue-deep); }

/* ---------------------------------------------------------------------
 * 24. Order-now steps strip (design-v03/05)
 * ------------------------------------------------------------------- */
.ql-order-steps {
	display: flex;
	justify-content: center;
	gap: 8px;
	max-width: 480px;
	margin: 0 auto 40px;
	text-align: center;
}

.ql-order-steps__step {
	flex: 1;
	position: relative;
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-soft);
}

.ql-order-steps__step-dot {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0 auto 6px;
	font-weight: 700;
}

.ql-order-steps__step.is-current .ql-order-steps__step-dot {
	background: var(--wp--preset--color--brand-blue-deep);
	color: var(--wp--preset--color--white);
}

/* ---------------------------------------------------------------------
 * 25. Screen-reader utility (kept from core defaults if theme lacks it)
 * ------------------------------------------------------------------- */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

/* TOC uses a <details><summary> (toc.js) so it is collapsible on mobile and
 * open by default on desktop; style the summary like the heading it replaces. */
.ql-toc summary {
	font-size: 0.8125rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	margin: 0 0 12px;
	cursor: pointer;
	font-weight: 700;
	list-style: none;
}

.ql-toc summary::-webkit-details-marker { display: none; }


/* ---------------------------------------------------------------------
 * 26. Stage-2 repair additions (report 16) — directory, group archive,
 * contact/order layouts, closing CTA, reduced-motion and RTL details.
 * ------------------------------------------------------------------- */

/* Services directory ------------------------------------------------- */
/* The directory band opens with the sticky jump nav, which carries its own
   padding and has to sit close to the hero it follows. The inherited 112px
   section head put ~150px of empty paper between the finder card and the
   first group (measured on services-directory-en-820-r4.png). */
.ql-section.ql-directory {
	padding-block-start: 24px;
}
.ql-directory .ql-service-map__jump {
	position: sticky;
	top: 72px;
	z-index: 10;
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
	padding-block: 14px;
	margin-block-end: 8px;
	background: linear-gradient(180deg, var(--wp--preset--color--paper) 70%, transparent);
}

.ql-service-map.is-directory .ql-rail {
	display: grid;
	gap: 24px;
	box-shadow: none;
	border-radius: 0;
	border-block-end: 1px solid var(--wp--preset--color--line);
	padding: 48px 0;
	background: none;
	scroll-margin-block-start: 140px;
}

.ql-service-map.is-directory .ql-rail:last-child { border-block-end: none; }

@media (min-width: 900px) {
	.ql-service-map.is-directory .ql-rail { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 48px; }
	.ql-service-map.is-directory .ql-rail__ledger { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 40px; }
}

.ql-service-map.is-directory .ql-rail__motif {
	width: 56px;
	height: 56px;
	color: var(--wp--preset--color--brand-blue-deep);
	margin-block-end: 18px;
	display: block;
}

.ql-service-map.is-directory .ql-rail__intro { align-self: start; position: sticky; top: 148px; }

@media (max-width: 899px) {
	.ql-service-map.is-directory .ql-rail__intro { position: static; }
}

.ql-service-map.is-directory .ql-rail__desc {
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.9375rem;
	line-height: 1.6;
	margin-block: 10px 18px;
}

.ql-service-map.is-directory .ql-rail__all {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 44px;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
}

.ql-service-map.is-directory .ql-rail__all:hover { text-decoration: underline; text-underline-offset: 5px; }
html[dir="rtl"] .ql-service-map.is-directory .ql-rail__all .ql-icon { scale: -1 1; }

.ql-service-map.is-directory .ql-rail__title {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-2);
	line-height: 1.1;
}

.ql-service-map.is-directory .ql-rail__ledger li a {
	flex-direction: column;
	align-items: flex-start;
	min-height: 68px;
	justify-content: center;
	gap: 2px;
}

.ql-service-map.is-directory .ql-rail__ledger .ql-rail__item-subtitle {
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
	font-weight: 400;
	line-height: 1.4;
}

/* Service-group archive / related ledger ------------------------------ */
.ql-group-archive__heading {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-2);
	margin-block: 0 24px;
}

.ql-group-archive__ledger li {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	min-height: 72px;
	padding-inline: 8px;
	border-block-end: 1px solid var(--wp--preset--color--line);
	transition: background-color var(--wp--custom--motion--dur-1) var(--wp--custom--motion--ease-out);
}

.ql-group-archive__ledger li:hover { background: var(--wp--preset--color--sky); }

.ql-group-archive__link {
	display: grid;
	gap: 2px;
	flex: 1 1 auto;
	min-width: 0;
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	position: relative;
	padding-inline-end: 24px;
}

.ql-group-archive__name { font-weight: 600; }

.ql-group-archive__subtitle {
	font-size: 0.8125rem;
	line-height: 1.4;
	color: var(--wp--preset--color--ink-mute);
}

.ql-group-archive__chevron {
	position: absolute;
	inset-inline-end: 0;
	top: 50%;
	translate: 0 -50%;
	width: 18px;
	height: 18px;
	color: var(--wp--preset--color--brand-blue-deep);
	opacity: 0;
	transition: opacity var(--wp--custom--motion--dur-1), translate var(--wp--custom--motion--dur-1);
}

.ql-group-archive__ledger li:hover .ql-group-archive__chevron,
.ql-group-archive__link:focus-visible .ql-group-archive__chevron { opacity: 1; translate: 4px -50%; }

html[dir="rtl"] .ql-group-archive__chevron { scale: -1 1; }
html[dir="rtl"] .ql-group-archive__ledger li:hover .ql-group-archive__chevron { translate: -4px -50%; }

/* Below 600 the "Request" pill and the service description fight over a
   350px line: the description wrapped to five ~215px lines beside a ~100px
   button (service-group-en-390-r5.png). Stack them, so the action reads as
   the row's conclusion instead of a squeezed second column. */
@media (max-width: 599px) {
	.ql-group-archive__ledger li {
		display: grid;
		grid-template-columns: 1fr;
		align-items: start;
		gap: 12px;
		padding-block: 20px;
	}

	.ql-group-archive__request {
		justify-self: start;
	}

	.ql-group-archive__link { padding-inline-end: 0; }
	.ql-group-archive__chevron { display: none; }
}

/* Contact page -------------------------------------------------------- */
.ql-contact-layout { display: grid; gap: 40px; align-items: start; }

@media (min-width: 900px) {
	.ql-contact-layout { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 48px; }
}

.ql-contact-form-col { min-width: 0; }

/* Order Now ----------------------------------------------------------- */
.ql-order-steps {
	position: relative;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 12px;
	max-width: 640px;
	margin: 0 auto 48px;
	text-align: center;
}

/* quicklink/motif wraps its SVG in a <span class="ql-motif-wrap">. That span
 * was an ordinary grid item, so it took cell 1 of the three-column strip and
 * pushed step 3 onto a second row, bottom left (report 18 S2-8). `display:
 * contents` drops the span from the grid and leaves the absolutely positioned
 * SVG where it belongs. The route's three nodes sit at the vertical centre of
 * its viewBox, so translating the box up by half its own height puts them on
 * the dots' centre line (16px) whatever the strip's width. */
.ql-order-steps > .ql-motif-wrap {
	display: contents;
}

.ql-order-steps > * { margin-block: 0; }

.ql-order-steps__route {
	position: absolute;
	inset-inline: 8%;
	top: 16px;
	transform: translateY(-50%);
	width: 84%;
	height: auto;
	color: var(--wp--preset--color--brand-blue-deep);
	opacity: 0.35;
	pointer-events: none;
}

@media (max-width: 599px) {
	.ql-order-steps__route { display: none; }
}

.ql-order-steps__step {
	position: relative;
	z-index: 2;
	font-size: 0.875rem;
	line-height: 1.35;
	color: var(--wp--preset--color--ink-soft);
}

.ql-order-steps__step-dot {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: var(--wp--preset--color--white);
	border: 1.75px solid var(--wp--preset--color--brand-blue-deep);
	color: var(--wp--preset--color--brand-blue-deep);
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0 auto 10px;
	font-weight: 700;
	font-size: 0.875rem;
}

.ql-order-form { max-width: 720px; margin-inline: auto; }

/* Closing CTA (S11) --------------------------------------------------- */
.ql-cta {
	position: relative;
	overflow: clip;
	background: var(--wp--preset--color--navy-950);
	background-image: var(--wp--custom--gradient--night);
	color: var(--wp--preset--color--white);
	padding-block: 80px;
	text-align: center;
}

@media (min-width: 1024px) { .ql-cta { padding-block: 112px; } }

.ql-cta__emblem {
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	translate: -50% -50%;
	width: min(70%, 520px);
	height: auto;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.08;
	pointer-events: none;
}

.ql-cta__inner {
	position: relative;
	z-index: 2;
	max-width: calc(var(--wp--custom--container--content) + var(--ql-gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--ql-gutter);
}

.ql-cta__inner h2 {
	font-size: var(--wp--preset--font-size--display-2);
	line-height: 1.06;
	color: var(--wp--preset--color--white);
	margin-block: 0 14px;
	max-width: 18ch;
	margin-inline: auto;
}

html[lang^="ar"] .ql-cta__inner h2,
html[lang^="hi"] .ql-cta__inner h2 { line-height: 1.25; }

.ql-cta__inner > p {
	color: rgba(255,255,255,0.82);
	font-size: var(--wp--preset--font-size--lead);
	max-width: 52ch;
	margin-inline: auto;
}

.ql-cta__actions {
	display: flex;
	gap: 14px;
	justify-content: center;
	flex-wrap: wrap;
	margin-block-start: 32px;
}

.ql-cta__address {
	margin-block-start: 28px;
	font-size: 0.875rem;
	color: rgba(255,255,255,0.55);
}

@media (max-width: 519px) {
	.ql-cta__actions { display: grid; width: 100%; }
	.ql-cta__actions .wp-block-button,
	.ql-cta__actions .wp-block-button__link { width: 100%; }
}

/* Testimonials scroller: keyboard-reachable region (axe
   scrollable-region-focusable, report 16 §1.10 O3). */
.ql-proof__scroller {
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: var(--ql-gutter);
	display: flex;
	gap: 20px;
	padding-block: 8px 20px;
	overscroll-behavior-x: contain;
}

.ql-proof__scroller > * { scroll-snap-align: start; flex: 0 0 min(80%, 340px); }
.ql-proof__scroller:focus-visible { outline-offset: 4px; }

.ql-proof__seals .ql-icon { width: 20px; height: 20px; color: var(--wp--preset--color--brand-green-deep); }
.ql-proof__seals .is-empty { opacity: 0.25; }

/* Motion: honour reduced motion on everything added above. */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}
}


/* -------------------------------------------------------------------
 * Target sizes (r6 sweep, stage-2 brief "buttons with readable shapes
 * and >=44px targets"). These controls were all inline boxes, so the
 * rules that set min-height on them had no effect until they were made
 * inline-flex.
 * ------------------------------------------------------------------- */
.ql-site-logo .custom-logo-link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.ql-contact-info__phone a,
.ql-contact-info__phone-secondary a,
.ql-contact-info__email a,
.ql-contact-info__whatsapp a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 32px;
}

.ql-contact-card .ql-contact-info__phone a,
.ql-contact-card .ql-contact-info__phone-secondary a,
.ql-contact-card .ql-contact-info__email a,
.ql-contact-card .ql-contact-info__whatsapp a {
	min-height: 44px;
}

/* -------------------------------------------------------------------
 * 27. Stage 3 — long-form reading layout (legal pages + About)
 *
 * The same rail/column/rail proportions as the article, expressed once for
 * the shared quicklink/v03-reading-body pattern. Two columns rather than
 * three: a legal page has a table of contents but nothing to share, so the
 * measure sits left of centre-right rather than being framed by two rails.
 * ------------------------------------------------------------------- */
.ql-reading-layout {
	display: grid;
	gap: 32px;
	align-items: start;
}

@media (min-width: 1024px) {
	.ql-reading-layout {
		grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
		gap: 64px;
	}
}

.ql-reading-column {
	min-width: 0;
}

.ql-reading-body,
.ql-reading-layout .ql-prose {
	min-width: 0;
	max-width: var(--wp--custom--container--prose);
	font-size: var(--wp--preset--font-size--body);
	line-height: 1.78;
}

.ql-reading-body > * { max-width: 100%; }

.ql-reading-body h2 {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-3);
	margin-block: 56px 14px;
	padding-block-start: 22px;
	border-block-start: 1px solid var(--wp--preset--color--line);
	scroll-margin-block-start: 104px;
}

.ql-reading-body > h2:first-child {
	margin-block-start: 0;
	padding-block-start: 0;
	border-block-start: 0;
}

.ql-reading-body h3 {
	font-size: var(--wp--preset--font-size--h-4);
	margin-block: 30px 10px;
	scroll-margin-block-start: 104px;
}

.ql-reading-body p { margin-block: 0 18px; }
.ql-reading-body ul,
.ql-reading-body ol { margin-block: 0 20px; padding-inline-start: 22px; }
.ql-reading-body li { margin-block-end: 8px; }

/* The legal hero: title, the date it was last revised, and the one-line
   statement that the page is not advice. */
.ql-legal-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 8px;
	margin-block-start: 14px;
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
}

.ql-legal-meta__label {
	text-transform: uppercase;
	letter-spacing: 0.12em;
	font-weight: 700;
	font-size: 0.6875rem;
}

/* The date block is a flow-layout child, so core gives it
   `margin-block-start: 1.5rem`; in this baseline-aligned flex row that
   inflates the row by 24px for nothing (same shape as the article meta line,
   report 18 S2-9). */
.ql-legal-meta > * { margin-block: 0; }

.ql-legal-meta .ql-legal-updated { unicode-bidi: isolate; }

.ql-legal-notice {
	margin-block-start: 18px;
	max-width: 56ch;
	font-size: 0.9375rem;
	color: var(--wp--preset--color--ink-soft);
	padding-inline-start: 14px;
	border-inline-start: 2px solid var(--wp--preset--color--brand-blue);
}

.ql-back-to-top {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-block-start: 40px;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: none;
}

.ql-back-to-top:hover { text-decoration: underline; text-underline-offset: 5px; }

/* -------------------------------------------------------------------
 * 28. Stage 3 — About: the three pillars
 *
 * The mission, the vision and the values are the page's argument, so they
 * are set as a numbered ledger with a display-size label, not as three
 * equal cards. The numerals are decorative (aria-hidden) and drawn in the
 * display face at a size that reads as an engraved figure rather than a
 * list marker.
 * ------------------------------------------------------------------- */
.ql-pillars__list {
	list-style: none;
	margin: 24px 0 0;
	padding: 0;
	counter-reset: none;
}

.ql-pillars__item {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 18px;
	align-items: start;
	padding-block: 28px;
	border-block-start: 1px solid var(--wp--preset--color--line);
}

.ql-pillars__item:first-child {
	border-block-start: 0;
	padding-block-start: 8px;
}

@media (min-width: 768px) {
	.ql-pillars__item {
		grid-template-columns: 96px minmax(0, 1fr);
		gap: 32px;
		padding-block: 36px;
	}
}

.ql-pillars__index {
	font-family: var(--font-display);
	font-size: 2.25rem;
	line-height: 1;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.55;
	font-variant-numeric: lining-nums tabular-nums;
	unicode-bidi: isolate;
}

@media (min-width: 768px) {
	.ql-pillars__index { font-size: 3.25rem; }
}

.ql-pillars__text { min-width: 0; }

.ql-pillars__label {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-3);
	margin: 0 0 10px;
}

.ql-pillars__body {
	margin: 0;
	max-width: 62ch;
	font-size: var(--wp--preset--font-size--body);
	line-height: 1.72;
	color: var(--wp--preset--color--ink-soft);
}

/* When the table of contents hides itself (fewer than three headings, as on
   About once the pillars have been lifted out) the reading grid must close up
   instead of leaving a 260px hole where the rail was. */
.ql-reading-layout:has(> .ql-article-rail[hidden]) {
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 1024px) {
	.ql-reading-layout:has(> .ql-article-rail[hidden]) {
		grid-template-columns: minmax(0, 1fr);
	}

	/* With no rail to balance it, a 720px measure pinned to the left of a
	   1280px container leaves 560px of dead space; centre it instead. */
	.ql-reading-layout:has(> .ql-article-rail[hidden]) .ql-reading-body,
	.ql-reading-layout:has(> .ql-article-rail[hidden]) .ql-back-to-top {
		margin-inline: auto;
	}

	.ql-reading-layout:has(> .ql-article-rail[hidden]) .ql-back-to-top {
		display: flex;
		width: fit-content;
	}
}

.ql-category-index {
	margin-block-start: 20px;
}

.ql-category-index__list {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.ql-category-index__list .ql-chip.is-current {
	background: var(--wp--preset--color--navy-900);
	border-color: var(--wp--preset--color--navy-900);
	color: var(--wp--preset--color--white);
}

/*
 * The article count is small type, so its contrast is measured against the
 * 4.5:1 floor, not the 3:1 large-text one. At opacity 0.6 the blend of ink
 * over the sky chip came to 4.22:1 (axe: color-contrast, serious, on the
 * blog index and the category archives in every language). 0.75 gives
 * 6.8:1 on a resting chip and 8.7:1 on the current one, and still reads as
 * secondary to the label beside it.
 */
.ql-category-index__count {
	margin-inline-start: 6px;
	font-variant-numeric: tabular-nums;
	opacity: 0.75;
	font-size: 0.8125em;
	unicode-bidi: isolate;
}


/* ---------------------------------------------------------------------
 * 27. Report 18 round-2 corrections
 * ------------------------------------------------------------------- */

/* S3-1 -- the editorial ledger (blog index and category archives).
 *
 * quicklink/editorial-index replaced the two hand-copied core/query blocks,
 * but nothing in the theme had ever styled its class names, so the supporting
 * list rendered as the browser's default stack of underlined links with a
 * date under each one. This is the ledger the lead story sits on: eyebrow,
 * display-serif title, standfirst, date, and a rule between rows. */
.ql-editorial {
	display: grid;
	gap: 48px;
}

@media (min-width: 1024px) {
	.ql-editorial {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		gap: 56px;
		align-items: start;
	}

	.ql-editorial__rows { grid-column: 2; grid-row: 1; }
	.ql-editorial__lead { grid-column: 1; grid-row: 1; }
	.ql-editorial > .ql-pagination { grid-column: 1 / -1; }

	/* Page two and beyond render no lead (editorial-index/render.php), so
	   pinning the ledger to column 2 left the 7fr column blank for the whole
	   height of the archive -- Fable round 4, V7-1. With no lead there is no
	   two-column composition left to hold: the ledger spans the full measure,
	   and the teaser text keeps a readable line length of its own. */
	.ql-editorial--no-lead { grid-template-columns: minmax(0, 1fr); }
	.ql-editorial--no-lead .ql-editorial__rows { grid-column: 1 / -1; }
	.ql-editorial--no-lead .ql-editorial__text { max-width: 78ch; }
}

.ql-editorial__lead .ql-editorial__plate {
	display: block;
	border-radius: var(--wp--custom--radius--xl);
	overflow: hidden;
	margin-block-end: 24px;
}

.ql-editorial__lead .ql-editorial__plate img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	transition: transform var(--wp--custom--motion--dur-3) var(--wp--custom--motion--ease-out);
}

@media (hover: hover) {
	.ql-editorial__lead .ql-editorial__plate:hover img { transform: scale(1.02); }
}

.ql-ledger__eyebrow {
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand-blue-deep);
	margin: 0 0 8px;
}

.ql-editorial__title {
	font-family: var(--font-display);
	font-weight: 600;
	line-height: 1.12;
	margin: 0 0 10px;
}

.ql-editorial__lead .ql-editorial__title { font-size: var(--wp--preset--font-size--h-2); }
.ql-editorial__rows .ql-editorial__title { font-size: var(--wp--preset--font-size--h-4); }

.ql-editorial__title a {
	color: var(--wp--preset--color--ink);
	text-decoration: none;
}

.ql-editorial__title a:hover {
	color: var(--wp--preset--color--brand-blue-deep);
	text-decoration: underline;
	text-underline-offset: 4px;
}

.ql-editorial__standfirst {
	color: var(--wp--preset--color--ink-soft);
	margin: 0 0 10px;
}

.ql-editorial__rows .ql-editorial__standfirst {
	font-size: 0.9375rem;
	line-height: 1.6;
}

.ql-editorial__meta {
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
	margin: 0;
}

.ql-editorial__rows {
	display: grid;
}

.ql-editorial__row {
	padding-block: 22px;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.ql-editorial__row:first-child { padding-block-start: 0; }
.ql-editorial__row:last-child { border-block-end: none; }

.ql-editorial__empty { margin-block: 24px; }

/* S3-2 -- the FAQ page keeps a rail instead of 40% empty paper at 1440. */
.ql-faq-layout {
	display: grid;
	gap: 40px;
	align-items: start;
}

@media (min-width: 1024px) {
	.ql-faq-layout {
		grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
		gap: 64px;
	}

	.ql-faq-rail {
		position: sticky;
		top: 132px;
	}
}

.ql-faq-rail__panel {
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--l);
	padding: 28px;
	box-shadow: var(--wp--custom--shadow--1);
}

.ql-faq-rail__panel + .ql-faq-rail__panel { margin-block-start: 20px; }

.ql-faq-rail__title {
	font-family: var(--font-display);
	font-size: var(--wp--preset--font-size--h-3);
	line-height: 1.15;
	margin: 0 0 10px;
}

.ql-faq-rail__body {
	color: var(--wp--preset--color--ink-soft);
	font-size: 0.9375rem;
	margin: 0 0 20px;
}

.ql-faq-rail .ql-cta-actions,
.ql-faq-rail .wp-block-buttons {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

/* S3-3 -- search results read as rows, not as a stack of bare headings. */
.ql-search-results .wp-block-post-template { display: grid; }

.ql-search-results li {
	display: grid;
	gap: 6px;
}

.ql-result-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 14px;
	font-size: 0.8125rem;
	color: var(--wp--preset--color--ink-mute);
	margin: 0;
	order: -1;
}

.ql-result-meta__kind {
	display: inline-flex;
	align-items: center;
	min-height: 22px;
	padding: 2px 10px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--sky);
	color: var(--wp--preset--color--brand-blue-deep);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.ql-result-meta__path { color: var(--wp--preset--color--ink-mute); }

.ql-search-results .wp-block-post-title { margin: 0; }
.ql-search-results .wp-block-post-excerpt { margin: 0; }
.ql-search-results .wp-block-post-excerpt p { margin: 0; }

/* S3-4 -- the About hero is composed rather than 342px of empty paper. */
.ql-about-hero .ql-container-wide {
	position: relative;
	z-index: 2;
	max-width: calc(var(--wp--custom--container--wide) + var(--ql-gutter) * 2);
}

/* Specificity note: `.ql-page-hero.is-light .ql-page-hero__motif` sets
   opacity 0.1, which outranks a single-class selector here -- at 0.1 the
   emblem was barely on the paper. The compound selector matches it. */
.ql-page-hero.ql-about-hero .ql-page-hero__motif {
	inset-block-start: 50%;
	inset-inline-end: -60px;
	width: min(46%, 460px);
	transform: translateY(-50%);
	opacity: 0.18;
}

@media (max-width: 767px) {
	.ql-page-hero.ql-about-hero .ql-page-hero__motif {
		inset-block-start: auto;
		inset-block-end: -80px;
		inset-inline-end: -80px;
		width: 280px;
		transform: none;
		opacity: 0.1;
	}
}

.ql-about-hero h1 { max-width: 18ch; }

.ql-about-hero .ql-standfirst,
.ql-about-hero .ql-lead {
	max-width: 52ch;
	color: var(--wp--preset--color--ink-soft);
}

/* ---------------------------------------------------------------------
 * 28. S4 motif plate (owner decision: no photography in S4)
 *
 * The office photograph that used to fill this slot was removed because it
 * could not be verified as an authentic rights-cleared QuickLink image and
 * was under resolution at 2x. The replacement is built from the theme's own
 * motif kit so it scales at any width and needs no asset: a lattice field
 * behind a seal ring, with the signature path drawn beneath it.
 *
 * It keeps the slot's existing geometry -- the 4:3 box and the offset navy
 * frame from .ql-intro__media::before -- so the section's composition at
 * 390/820/1440 is unchanged. Every offset is logical (inset-inline /
 * inset-block), and the seal is centred with `inset-inline: 0` plus
 * `margin-inline: auto` rather than a translateX, so RTL mirrors correctly
 * without a direction-specific rule.
 * ------------------------------------------------------------------- */
.ql-intro__plate {
	position: relative;
	z-index: 2;
	aspect-ratio: 4 / 3;
	border-radius: var(--wp--custom--radius--xl);
	overflow: hidden;
	background:
		radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, 0.07), transparent 62%),
		linear-gradient(140deg, var(--wp--preset--color--navy-900), var(--wp--preset--color--brand-blue-deep));
}

/* The motif block wraps its SVG in a <span class="ql-motif-wrap">; dropping
 * that span from the box leaves each absolutely positioned SVG addressed to
 * the plate itself. */
.ql-intro__plate > .ql-motif-wrap {
	display: contents;
}

.ql-intro__plate .ql-motif {
	position: absolute;
	display: block;
}

.ql-intro__plate-field {
	inset: 0;
	width: 100%;
	height: 100%;
	color: var(--wp--preset--color--brand-blue);
	opacity: 0.22;
}

.ql-intro__plate-seal {
	inset-inline: 0;
	margin-inline: auto;
	inset-block-start: 16%;
	width: min(38%, 190px);
	height: auto;
	color: var(--wp--preset--color--brand-green);
	opacity: 0.95;
}

.ql-intro__plate-signature {
	inset-inline: 10%;
	width: 80%;
	inset-block-end: 16%;
	height: auto;
	color: var(--wp--preset--color--white);
	opacity: 0.85;
}

/* At phone width the plate is only ~260px tall, so the seal has to shrink
 * and rise or the signature runs straight through it. */
@media (max-width: 599px) {
	.ql-intro__plate-seal {
		inset-block-start: 11%;
		width: min(30%, 96px);
	}

	.ql-intro__plate-signature {
		inset-block-end: 12%;
	}
}

/* ---------------------------------------------------------------------
 * 26. Order Now request stage — release 0.3.1, item 1
 *
 * The old page was a tall night hero, a horizontal three-step strip and a
 * full-width form, so the hero was taller than the thing people came to do.
 * The hero is now the shortest band on the page (it holds breadcrumb,
 * eyebrow, H1 and one lead line from post content, nothing else), and the
 * work happens in a two-column stage: the form card on the left, a slim
 * sticky panel on the right. Below 1024 the stage is one column and the DOM
 * order (form first, panel second) is the reading order, so no CSS reorder
 * is needed and the tab order stays the visual order.
 * ------------------------------------------------------------------- */
.ql-page-hero.ql-order-hero { padding-block: 36px 32px; }

@media (min-width: 1024px) {
	.ql-page-hero.ql-order-hero { padding-block: 52px 44px; }
}

.ql-order-hero__lead {
	max-width: 56ch;
	margin-block: 12px 0;
}

.ql-order-hero__lead > * { margin-block: 0; }
.ql-order-hero__lead > * + * { margin-block-start: 8px; }

.ql-order-section { padding-block: 40px 56px; }

@media (min-width: 1024px) {
	.ql-order-section { padding-block: 56px 80px; }
}

.ql-order-stage {
	display: grid;
	gap: 28px;
	align-items: start;
}

@media (min-width: 1024px) {
	.ql-order-stage {
		grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
		gap: 40px;
	}

	/* 72px sticky header + 16px breathing room. */
	.ql-order-stage__aside {
		position: sticky;
		top: 88px;
	}
}

.ql-order-stage__form { min-width: 0; }
.ql-order-stage__aside { min-width: 0; }

.ql-order-next {
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--l);
	box-shadow: var(--wp--custom--shadow--1);
	padding: 24px;
}

.ql-order-next__title {
	margin: 0 0 16px;
	font-size: 1.0625rem;
	line-height: 1.3;
	color: var(--wp--preset--color--ink);
}

/* The three steps read as a vertical route inside the panel rather than the
   old horizontal strip, so they cost one column instead of the page's width. */
.ql-order-steps--stacked {
	grid-template-columns: minmax(0, 1fr);
	gap: 14px;
	max-width: none;
	margin: 0 0 20px;
	text-align: start;
}

.ql-order-steps--stacked .ql-order-steps__step {
	display: grid;
	grid-template-columns: 32px minmax(0, 1fr);
	align-items: center;
	gap: 12px;
	text-align: start;
}

.ql-order-steps--stacked .ql-order-steps__step-dot { margin: 0; }

.ql-order-next__contact {
	border-block-start: 1px solid var(--wp--preset--color--line);
	padding-block-start: 18px;
}

.ql-contact-info--compact p { margin-block: 0 10px; }

.ql-contact-info--compact .ql-contact-info__hours {
	margin-block: 14px 0;
	font-size: 0.875rem;
}

.ql-contact-info--compact .ql-contact-info__hours dt {
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.ql-contact-info--compact .ql-contact-info__hours dd {
	margin-inline-start: 0;
	color: var(--wp--preset--color--ink-soft);
}

/* R8-1b. Same defect, same panel: the WORKING HOURS label is 12px uppercase
   with 0.12em tracking at 0.85 opacity, which in Arabic and Devanagari is
   another grey smear. Scoped to the compact panel only — the footer and the
   contact card use the same component and are left alone pending a call. */
html[lang^="ar"] .ql-contact-info--compact .ql-contact-info__hours dt,
html[lang^="hi"] .ql-contact-info--compact .ql-contact-info__hours dt,
html[dir="rtl"] .ql-contact-info--compact .ql-contact-info__hours dt {
	font-size: 0.8125rem;
	letter-spacing: normal;
	text-transform: none;
	opacity: 1;
	color: var(--wp--preset--color--ink);
}

/* Field groups (About you / Your request / Message). A fieldset carries the
   grouping for assistive technology; the legend is the visible label, so the
   card reads as three short steps instead of eight loose fields. */
.ql-field-group {
	border: 0;
	margin: 0;
	padding: 0;
	min-width: 0;
}

.ql-field-group + .ql-field-group {
	border-block-start: 1px solid var(--wp--preset--color--line);
	margin-block-start: 4px;
	padding-block-start: 24px;
}

.ql-field-group__legend {
	float: none;
	width: auto;
	padding: 0;
	margin-block-end: 14px;
	font-family: var(--font-text);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-soft);
}

/* R8-1. Arabic and Devanagari have no letter case, so uppercase + tracking
   buys nothing and only leaves a small grey smear where a label should be
   (Fable, order-now-ar-1440-r13-full). Those scripts get the weight back in
   the axis they can express: a size up, ink instead of ink-soft, no tracking,
   no case transform. The separating rule above each group is kept, so the
   grouping still reads the same way it does in English. */
html[lang^="ar"] .ql-field-group__legend,
html[lang^="hi"] .ql-field-group__legend,
html[dir="rtl"] .ql-field-group__legend {
	font-size: 0.875rem;
	font-weight: 700;
	letter-spacing: normal;
	text-transform: none;
	color: var(--wp--preset--color--ink);
}

.ql-field select optgroup {
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}

.ql-field select option { font-weight: 400; }

/* Two short fields side by side at the wider form widths: name/email and
   request type/urgency pair up, the rest stay full width. */
@media (min-width: 768px) {
	.ql-field-group {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 20px;
	}

	.ql-field-group__legend { grid-column: 1 / -1; }
	.ql-field-group .ql-field { grid-column: span 1; }
	.ql-field-group .ql-field:has(textarea),
	.ql-field-group .ql-field:has(select#ql_request_service),
	.ql-field-group .ql-field--honeypot { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------------
 * 27. Header row and mobile sheet — release 0.3.1, item 2
 *
 * The bar centres its children, but core's block-gap was still adding a
 * 24px top margin to .ql-header-nav, .ql-header__actions and
 * .ql-header-cta, so the three things sat on three different lines:
 * logo centre 36px, links and language 48px, CTA 60px (measured on
 * :8780 at 1440 before this rule). Zeroing the block-gap inside the bar
 * puts all four on the bar's own centre line.
 * ------------------------------------------------------------------- */
.ql-header__bar > *,
.ql-header__bar > * > *,
.ql-header__actions > *,
.ql-header-nav > * {
	margin-block: 0;
}

@media (min-width: 1024px) {
	.ql-header__bar { gap: 20px; }
	.ql-header-nav { gap: 4px; }
	.ql-header__actions { gap: 10px; }
}

/* The mega is a list item inside the primary nav now (see the block's
   render callback), so it must not inherit the list's marker or spacing. */
.ql-header__nav-item--mega {
	list-style: none;
	margin: 0;
	display: flex;
	align-items: center;
}

.ql-header__nav-item--mega > .ql-services-menu { margin: 0; }

/* Mobile sheet: the menu scrolls, the way out does not. Languages, the two
   contact chips and the CTA are a pinned foot, so at 390 they are on screen
   the moment the sheet opens (0.3.1 item 2). */
.ql-mobile-sheet__foot {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 16px var(--ql-gutter) calc(16px + env(safe-area-inset-bottom, 0px));
	border-block-start: 1px solid var(--wp--preset--color--line-dark);
	background: rgba(4, 18, 32, 0.72);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
}

.ql-mobile-sheet__foot .ql-eyebrow { margin-block-end: 6px; }

.ql-mobile-sheet__foot .ql-mobile-sheet__languages,
.ql-mobile-sheet__foot .ql-mobile-sheet__contact,
.ql-mobile-sheet__foot .ql-mobile-sheet__cta { margin: 0; }

.ql-mobile-sheet__foot .ql-mobile-sheet__contact {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.ql-mobile-sheet__foot .ql-mobile-sheet__cta .wp-block-button__link {
	display: block;
	width: 100%;
	min-height: 48px;
	text-align: center;
}

/* Keep the scrolling part from ending flush against the foot. */
.ql-mobile-sheet__scroll { padding-block-end: 24px; }

/* ---------------------------------------------------------------------
 * 28. Homepage rhythm — release 0.3.1, item 3b
 *
 * Measured on :8780 at 1440x900 before this block: hero 1101, services
 * 1108, testimonials 1243, latest articles 882 (906 on AR). Everything
 * except testimonials has to fit one viewport, and testimonials is the one
 * section the brief exempts. The hero's height was driven by an H1 that
 * wrapped to four lines in a 6fr column, not by its padding, so the copy
 * column gets more width before the type is touched at all.
 * ------------------------------------------------------------------- */
@media (min-width: 1200px) {
	body.home .ql-section:not(.ql-stats-band),
	body.home .ql-cta { padding-block: 72px; }

	body.home .ql-hero { padding-block-start: 56px; }
}

@media (min-width: 1024px) {
	body.home .ql-hero__inner {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		padding-block-end: 88px;
		min-height: 0;
	}
}

@media (min-width: 1024px) {
	body.home .ql-hero__content h1 {
		font-size: clamp(2.5rem, 4.4vw, 3.9rem);
		line-height: 1.06;
	}
}

body.home .ql-hero__content .ql-lead { margin-block-start: 16px; }
body.home .ql-hero__actions { margin-block: 20px; }
body.home .ql-hero__chips { margin-block-start: 16px; }

/* Services: six links per rail (see the block), tighter rows, so the section
   reads as three short menus rather than one long wall. */
body.home .ql-rail__ledger a { padding-block: 9px; }
body.home .ql-rail__header { padding-block: 16px; }

@media (min-width: 1200px) {
	body.home .ql-service-map__filters { margin-block-end: 24px; }
}

/* Services section, continued: the head block and the rails carried most of
   the height, not the section padding. Homepage only. */
@media (min-width: 1200px) {
	body.home .ql-section:not(.ql-stats-band) { padding-block: 60px; }
}

body.home .ql-service-map__head { margin-block-end: 28px; }
body.home .ql-service-map__head h2 { margin-block-start: 12px; }
body.home .ql-service-map__head .ql-lead { margin-block-start: 12px; max-width: 70ch; }
body.home .ql-service-map { margin-block-start: 16px; }
body.home .ql-rail { padding-block: 18px; }
body.home .ql-rail__body .ql-rail__desc { margin-block: 0 10px; }
body.home .ql-rail__all { margin-block-start: 12px; }

/* Last of the services trims: the ledger rows and the rail chrome. Six links
   per rail stay (the brief's maximum); they just stop being 50px apart. */
body.home .ql-rail__ledger a { padding-block: 6px; }
body.home .ql-rail__ledger li + li { margin-block-start: 0; }
body.home .ql-rail__header { padding-block: 12px; }
body.home .ql-rail { padding-block: 14px; }
body.home .ql-service-map__head .ql-lead { max-width: 62ch; }

/* The services head stacked eyebrow, heading and a full-measure lead above
   the rails, which cost ~180px before a single service link. At >=1200 the
   lead sits beside the heading instead, and the section padding comes in one
   more notch; that is the last of the height the brief's "no section taller
   than one viewport" needs, in all four languages. */
@media (min-width: 1200px) {
	body.home .ql-section:not(.ql-stats-band) { padding-block: 52px; }

	body.home .ql-service-map__head > .wp-block-group {
		display: grid;
		grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
		column-gap: 48px;
		align-items: end;
	}

	body.home .ql-service-map__head .ql-eyebrow { grid-column: 1; }
	body.home .ql-service-map__head h2 { grid-column: 1; margin-block-start: 8px; }

	body.home .ql-service-map__head .ql-lead {
		grid-column: 2;
		grid-row: 1 / span 2;
		margin-block-start: 0;
		align-self: end;
	}

	body.home .ql-service-map__filters { margin-block-end: 18px; }
}

/* Russian runs ~20% longer than English in every block on this page, so the
   two sections that still crossed a viewport there (services 942, the
   triptych 952) get the last notch of padding and panel padding. Measured,
   not guessed: those two numbers came from :8780 at 1440x900 on /ru/. */
@media (min-width: 1200px) {
	body.home .ql-section:not(.ql-stats-band) { padding-block: 46px; }
	body.home .ql-triptych { margin-block-start: 16px; }
	body.home .ql-triptych__panel { padding-block: 24px; }
	body.home .ql-rail__ledger a { padding-block: 5px; }
}

/* Two RU-driven details: service titles there wrap to two lines inside a
   413px rail, and the triptych panels are equal-height, so the longest panel
   sets all three. Nothing is hidden or truncated -- the ledger just reads one
   step down the type scale at desktop, and the panels lose six pixels of
   padding. */
@media (min-width: 1200px) {
	body.home .ql-rail__ledger a { font-size: 0.875rem; line-height: 1.35; }
	body.home .ql-triptych__panel { padding-block: 18px; }
}

/* The rail header, not the link list, is what pushes the services section
   over a viewport in RU/HI: a 48px motif with 16px beneath it, above a group
   title that wraps to three lines there. The ledger rows keep their 44px
   targets untouched; the chrome above them is what gives. */
@media (min-width: 1200px) {
	body.home .ql-rail__motif { width: 36px; height: 36px; margin-block-end: 10px; }
	body.home .ql-rail__title { font-size: 1.5rem; margin-block-end: 8px; }
	body.home .ql-rail__desc { margin-block-end: 14px; }
}

/* Four pixels on /ru/ -- the triptych panels are equal height, so the quote
   panel's longest line sets all three. */
@media (min-width: 1200px) {
	body.home .ql-triptych__panel { padding-block: 14px; }
	body.home .ql-triptych { margin-block-start: 12px; }
}

/* Belt and braces: whatever the nav sets for its own row must not leak into
   the mega panel's content. */
.ql-header__nav-item--mega .ql-services-menu__panel,
.ql-header__nav-item--mega .ql-services-menu__panel * {
	white-space: normal;
}

.ql-header__nav-item--mega .ql-services-menu__panel li { white-space: normal; }

/* ---------------------------------------------------------------------
 * 29. Brand badge — release 0.3.2, item 1
 *
 * The owner's definitive asset (assets/brand/main-logo.jpeg, used exactly as
 * supplied) is a circular green-ringed badge printed on a white square. The
 * white ground IS part of the logo, so on the dark footer and the dark mobile
 * sheet it is presented as a DISC, not as a plate behind a mark: rounding the
 * box to 50% hides the square corners and nothing else.
 *
 * Nothing is cropped. The badge's outer ring sits ~2.4% inside the canvas
 * edge, so an inscribed circular clip (radius = half the box) falls outside
 * the ring in both axes — measured on the 1083x1105 master.
 *
 * The old sheet rule knocked the logo to pure white with
 * `filter: brightness(0) invert(1)`, which was right for a single-colour mark
 * and would destroy this one; it is turned off here.
 * ------------------------------------------------------------------- */
.ql-brand img,
.ql-site-logo img,
.ql-footer__logo img,
.ql-footer__brand img,
.ql-mobile-sheet__logo {
	border-radius: 50%;
	background: var(--wp--preset--color--white, #fff);
	object-fit: contain;
}

.ql-brand img,
.ql-site-logo img {
	width: 36px;
	height: 36px;
	max-width: none;
}

@media (min-width: 1024px) {
	.ql-brand img,
	.ql-site-logo img {
		width: 44px;
		height: 44px;
		max-width: none;
	}
}

.ql-footer__logo img,
.ql-footer__brand img {
	width: 88px;
	height: 88px;
}

.ql-mobile-sheet__logo {
	width: 40px;
	height: 40px;
	max-width: none;
	filter: none;
	opacity: 1;
}

/* ---------------------------------------------------------------------
 * 30. Shared premium homepage — release 0.3.2, item 3
 *
 * The requirement is ONE design across en/ar/ru/hi: same hero, same assets,
 * same components, same motion, content translated, Arabic mirrored. Every
 * rule below is language-agnostic and written in logical properties, so the
 * four pages differ in glyphs and direction only.
 *
 * What is here is presentation. WHICH blocks sit on the page is decided by
 * the layout builders (importer-owned); the builder changes needed to finish
 * the brief are listed in report 16 §16.3.
 * ------------------------------------------------------------------- */

/* --- (a) Hero: a composition, not a stock document ------------------- */

/* A seal ring behind the stack and a route drifting across it: the two
   motifs the brand already owns, used at architectural scale instead of as
   spot icons. Both are decorative and inert. */
body.home .ql-hero__visual::before,
body.home .ql-hero__visual::after {
	content: "";
	position: absolute;
	pointer-events: none;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
}

body.home .ql-hero__visual::before {
	inline-size: min(80%, 430px);
	block-size: min(80%, 430px);
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	-webkit-mask: url("../motifs/seal-ring.svg") center / contain no-repeat;
	mask: url("../motifs/seal-ring.svg") center / contain no-repeat;
	background: var(--wp--preset--color--white);
	opacity: 0.1;
	z-index: 1;
	animation: ql-hero-fade 900ms var(--wp--custom--motion--ease-out) 120ms both;
}

body.home .ql-hero__visual::after {
	inline-size: min(96%, 520px);
	block-size: 160px;
	inset-block-end: 4%;
	inset-inline-end: -4%;
	-webkit-mask: url("../motifs/route.svg") center / contain no-repeat;
	mask: url("../motifs/route.svg") center / contain no-repeat;
	background: var(--wp--preset--color--green-glow);
	opacity: 0.45;
	z-index: 3;
	animation: ql-hero-drift 900ms var(--wp--custom--motion--ease-out) 260ms both;
}

/* The owner's badge as a brand seal ON the stack -- small, deliberate, and
   never the main image. It is the same asset the header carries, so the
   hero and the bar agree. */
body.home .ql-hero__document-stack {
	isolation: isolate;
}

body.home .ql-hero__document-stack::after {
	content: "";
	position: absolute;
	inset-block-end: -10px;
	inset-inline-end: -10px;
	inline-size: 56px;
	block-size: 56px;
	border-radius: 50%;
	background: #fff url("../brand/main-logo-256.jpeg") center / contain no-repeat;
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
	z-index: 4;
	animation: ql-hero-drift 900ms var(--wp--custom--motion--ease-out) 420ms both;
}

@media (min-width: 1024px) {
	body.home .ql-hero__document-stack::after {
		inline-size: 76px;
		block-size: 76px;
		inset-block-end: -14px;
		inset-inline-end: -14px;
	}
}

@keyframes ql-hero-drift {
	from { opacity: 0; transform: translateY(14px) scale(0.98); }
	to   { opacity: var(--ql-drift-opacity, 1); transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	body.home .ql-hero__visual::before,
	body.home .ql-hero__visual::after,
	body.home .ql-hero__document-stack::after {
		animation: none;
	}
}

/* --- (a) Service finder: one elegant bar, not a grey box ------------- */

body.home .ql-service-finder {
	padding: 10px 12px;
	border-radius: 999px;
	box-shadow: var(--wp--custom--shadow--2);
	background: color-mix(in srgb, var(--wp--preset--color--white) 92%, transparent);
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-blue) 18%, transparent);
}

@supports not (background: color-mix(in srgb, red 50%, transparent)) {
	body.home .ql-service-finder { background: var(--wp--preset--color--white); }
}

@media (min-width: 768px) {
	body.home .ql-service-finder__form {
		display: flex;
		align-items: center;
		gap: 12px;
	}

	body.home .ql-service-finder__field {
		flex: 1 1 auto;
		min-width: 0;
		margin: 0;
		display: flex;
		flex-direction: row;
		align-items: center;
		gap: 14px;
	}

	body.home .ql-service-finder__label {
		flex: 0 0 auto;
		margin: 0;
		padding-inline-start: 14px;
		white-space: nowrap;
		color: var(--wp--preset--color--ink-soft);
	}

	body.home .ql-service-finder__field select {
		flex: 1 1 auto;
		min-width: 0;
		border: 0;
		background: transparent;
		box-shadow: none;
	}

	body.home .ql-service-finder__submit {
		flex: 0 0 auto;
		border-radius: 999px;
	}
}

/* --- (c) Services: three distinct cards, the section the owner sees -- */

body.home .ql-rail {
	position: relative;
	overflow: hidden;
	transition:
		transform 220ms var(--wp--custom--motion--ease-out),
		box-shadow 220ms var(--wp--custom--motion--ease-out);
}

/* A gradient top rule instead of a heavier shadow: the card is separated by
   a line of brand colour, not by weight. */
body.home .ql-rail::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 3px;
	background: var(--wp--custom--gradient--link);
}

@media (hover: hover) {
	body.home .ql-rail:hover {
		transform: translateY(-4px);
		box-shadow: var(--wp--custom--shadow--2);
	}
}

@media (prefers-reduced-motion: reduce) {
	body.home .ql-rail { transition: none; }
	body.home .ql-rail:hover { transform: none; }
}

/* --- (b) Stats: tabular figures also on the two-column layout -------- */

body.home .ql-stats__value {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1;
}

@media (max-width: 1023px) {
	body.home .ql-stats__item + .ql-stats__item {
		border-inline-start: 1px solid var(--wp--preset--color--line-dark);
		padding-inline-start: 20px;
	}

	body.home .ql-stats__grid > .ql-stats__item:nth-child(odd) {
		border-inline-start: none;
		padding-inline-start: 0;
	}
}

/* --- (f) Entrance reveals ------------------------------------------- */

/* reveal.js adds .is-visible; without JS, or under reduced motion, the
   element is simply visible (the base .ql-reveal rules above already say
   so). These are the extra targets the script now observes. */
body.home .ql-reveal--card {
	opacity: 0;
	transform: translateY(16px);
	transition:
		opacity 520ms var(--wp--custom--motion--ease-out),
		transform 520ms var(--wp--custom--motion--ease-out);
}

body.home .ql-reveal--card.is-visible {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	body.home .ql-reveal--card {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* --- (d) "Why QuickLink" proof points ------------------------------- */

/* The three numbered proof points are CONTENT: they have to come from the
   real About copy in each language, so the builder emits them (report 16
   §16.3). The component is defined here so that the moment it does, all four
   languages get the same object with no further CSS. */
body.home .ql-intro__proof {
	list-style: none;
	margin: 24px 0 0;
	padding: 0;
	display: grid;
	gap: 14px;
	counter-reset: ql-proof;
}

body.home .ql-intro__proof li {
	counter-increment: ql-proof;
	display: grid;
	grid-template-columns: 32px minmax(0, 1fr);
	align-items: start;
	gap: 12px;
	margin: 0;
}

body.home .ql-intro__proof li::before {
	content: counter(ql-proof);
	inline-size: 32px;
	block-size: 32px;
	display: grid;
	place-items: center;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--brand-blue);
	color: var(--wp--preset--color--brand-blue-deep);
	font-size: 0.8125rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

/* The seal ring is centred with a physical translate, so its entrance may not
   touch `transform` -- `ql-hero-drift` ends on `transform: none`, which would
   throw the ring off-centre the moment the animation filled forwards. */
@keyframes ql-hero-fade {
	from { opacity: 0; }
	to   { opacity: 0.1; }
}

/* The one place a heading still needs the dictionary.
 *
 * `.ql-rail__title` is not a display headline -- it is a group name inside a
 * 320px card, and the group names are taxonomy terms, so the copy cannot be
 * adjusted from the theme. At 1440 the Russian "Дополнительная экспертиза"
 * overflows that box by 30px as a single unbreakable word once `hyphens` is
 * `manual` (measured; the page itself does not scroll, the word simply runs
 * out of its card). Hyphenation is re-enabled for this ONE component rather
 * than globally, which is the trade report 18 should have made: display
 * headlines wrap on word boundaries, a narrow card title may hyphenate.
 */
.ql-rail__title,
.ql-sheet-accordion__label,
.ql-services-menu__group-heading {
	hyphens: auto;
}

/* ---------------------------------------------------------------------
 * 31. Brand badge at instrument scale — release 0.3.2, item 1b (owner ask)
 *
 * The badge read as correct but small: a 44px disc in a 72px desktop bar,
 * 36px in a 64px mobile bar — under two thirds of the bar, which on a
 * circular mark (whose corners are empty by definition) looks smaller
 * still. The owner asked for a noticeably larger disc with nothing cropped,
 * no second header row, and no crowding of the nav, the CTA or the
 * language pill.
 *
 * The badge and the bar that holds it are raised together, so the disc
 * keeps a ~77% share of the bar — the band where a circular mark reads as
 * deliberate rather than squeezed — and the clear space above and below it
 * stays at 9px:
 *
 *                 badge   bar    clear above/below
 *   < 1024         50px   68px   9px
 *   >= 1024        62px   80px   9px
 *   sheet head     48px   68px   10px
 *   footer         88px    —     unchanged (§29)
 *
 * The bar height is published as --ql-header-h so the two sticky offsets
 * that exist only to clear the header follow it, instead of each repeating
 * a now-stale 72.
 *
 * Nothing about the asset changes. It is still the owner's file, painted
 * `object-fit: contain` inside a square box rounded to 50% (§29), so the
 * inscribed circular clip still falls outside the badge's own green ring
 * and nothing is cropped — a bigger box scales that geometry, it does not
 * alter it. The largest painted box in the theme is still the 88px footer
 * badge, so `add_image_size( 'quicklink-logo', 176 )` remains exactly 2x
 * the largest box and no heavier file is pulled into the header.
 * ------------------------------------------------------------------- */
:root {
	--ql-header-h: 68px;
}

@media (min-width: 1024px) {
	:root {
		--ql-header-h: 80px;
	}
}

.ql-header__bar {
	height: var(--ql-header-h);
}

.ql-brand img,
.ql-site-logo img {
	width: 50px;
	height: 50px;
}

@media (min-width: 1024px) {
	.ql-brand img,
	.ql-site-logo img {
		width: 62px;
		height: 62px;
	}
}

/*
 * The disc is now the widest thing on the brand side, so the lane either
 * side of it grows with it. Without this the first nav link would sit 18px
 * closer to the mark than it did before, which is how a bigger logo starts
 * to look like a crowded one: 16 -> 20 below the nav breakpoint, and the
 * 20 that §27 set -> 28 above it.
 */
.ql-header__bar {
	gap: 20px;
}

@media (min-width: 1024px) {
	.ql-header__bar {
		gap: 28px;
	}
}

/*
 * The sheet head is the mobile bar's counterpart, so it answers to the same
 * variable and carries a badge of the same order (48px beside the 44px
 * close button, which stays a 44px target). §29's 40px would now read as a
 * different brand size one tap apart from the header's 50px.
 */
.ql-mobile-sheet__head {
	height: var(--ql-header-h);
}

.ql-mobile-sheet__logo {
	width: 48px;
	height: 48px;
}

/*
 * Two sticky offsets exist only to clear the sticky header. Both were
 * written against the old 72px bar (the second one says so in its own
 * comment), so an 80px bar would have tucked the directory jump bar four
 * fifths of the way underneath it.
 */
.ql-directory .ql-service-map__jump {
	top: calc(var(--ql-header-h) + 8px);
}

@media (min-width: 1024px) {
	.ql-order-stage__aside {
		top: calc(var(--ql-header-h) + 16px);
	}
}
