/*!
 * Sarv Catalyst — Base layer
 *
 * Element defaults, a minimal reset, and accessibility primitives.
 *
 * Rules:
 *   - Logical properties only. No left/right. This is what makes RTL work.
 *   - No component styles here; components own their own files.
 *   - Typography is inherited from theme.json and the token layer. This file
 *     does not restate sizes, colours or families.
 *
 * @see docs/ARCHITECTURE.md — "Design system"
 */

/* ---------------------------------------------------------------------------
 * Reset
 *
 * Deliberately small. Only the defaults that genuinely obstruct a controlled
 * layout are reset — a large opinionated reset creates more work than it saves
 * and obscures where styles come from.
 * ------------------------------------------------------------------------- */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	/* Prevent iOS Safari from inflating text in landscape. */
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;

	/* Native smooth scrolling, disabled by the reduced-motion query below. */
	scroll-behavior: smooth;
}

body {
	margin: 0;
	min-block-size: 100vh;
	overflow-wrap: break-word;
	background-color: var(--sc-color-surface);
	color: var(--sc-color-text);
	font-family: var(--sc-font-family-base);
	text-rendering: optimizelegibility;
	-webkit-font-smoothing: antialiased;
}

/* Media never overflows its container and never causes layout shift. */
img,
picture,
video,
canvas,
svg,
iframe,
embed,
object {
	display: block;
	max-inline-size: 100%;
}

img,
video {
	block-size: auto;
}

/*
 * Intrinsic aspect ratio for images with explicit dimensions, which is the
 * single largest source of Cumulative Layout Shift on an image-led site.
 * Declared in :where() so the rule carries no specificity and any component
 * rule (for example a media box that must fill its figure) can override it.
 */
:where(img[width][height]) {
	block-size: auto;
}

/* ---------------------------------------------------------------------------
 * Typography defaults
 * ------------------------------------------------------------------------- */

h1,
h2,
h3,
h4,
h5,
h6 {
	margin-block: 0 var(--sc-space-2xs);

	/* Keep a heading from being orphaned at the foot of a column. */
	text-wrap: balance;

	/* Headings are never justified. A justified heading either stretches its
	   word gaps or ends in a line that is not the shape the type was set for.
	   The weight itself is owned by theme.json (`elements.heading`), which sets
	   the brand's 700 — the top of the restrained 600–700 band — and is applied
	   from one place so the editor and the front end cannot disagree. */
	text-align: start;
}

h1:first-child,
h2:first-child,
h3:first-child,
h4:first-child,
h5:first-child,
h6:first-child {
	margin-block-start: 0;
}

p {
	margin-block: 0 var(--sc-space-sm);
	max-inline-size: var(--sc-measure);
}

p:last-child {
	margin-block-end: 0;
}

/* ---------------------------------------------------------------------------
 * Long-form justification
 *
 * Body copy on this site is justified. That is a deliberate editorial decision
 * rather than a default: the pages are read as documents by procurement and
 * process engineers, and a justified measure gives a column of technical prose
 * the even edge that makes it scannable. What follows is the rule, and the
 * three constraints that keep it from producing the two failure modes
 * justification is famous for — rivers and a patched last line.
 *
 * 1. Only editorial body copy justifies.
 *
 *    The rule is applied through container selectors, never to `p` at large.
 *    The containers below are the template regions that render multi-sentence
 *    body copy: a page's overview, a split's body, an article's body, a
 *    service's description, a timeline entry, a research focus paragraph, a
 *    lead under a section heading. Everything else — a card's summary, a
 *    caption, a metadata line, a form hint, a button, a breadcrumb — sits
 *    outside those regions and therefore stays flush without having to be named
 *    in an exclusion list that would grow with every new template.
 *
 *    `sc-text-lead` and `sc-section__lead` are the two utility classes the
 *    templates put on a standfirst; they are included because a standfirst is
 *    body copy by definition, and they are the only utility classes that are.
 *
 * 2. Latin and Cyrillic justify only where the measure can carry it.
 *
 *    Below 48rem the page is a single narrow column of about 40 characters. At
 *    that width the word space a justified line needs is a visible gap, so the
 *    rule is scoped to `width >= 48rem`. Persian justifies at every width: the
 *    script's connected letterforms absorb the extra space between words, so
 *    the condition the Latin rule guards against does not arise.
 *
 * 3. Hyphenation is on for the scripts that have it and off for the one that
 *    does not.
 *
 *    `hyphens: auto` is what stops a justified Latin or Cyrillic column from
 *    opening rivers: without it the only way to fill a line is to stretch the
 *    word space. It needs a language to look up — the `lang` attribute the
 *    document already carries — and it is switched off for Persian, where
 *    hyphenating would break a joined word and a pseudo-hyphen inside an
 *    Arabic-script word is simply wrong.
 *
 * `text-justify: inter-word` is the only value that behaves across the mixed
 * Persian/Latin and Cyrillic/Latin runs these pages contain; `inter-character`
 * would space out every letter of a Latin product code that sits inside a
 * Persian sentence.
 * ------------------------------------------------------------------------- */

.sc-entry-content > p,
.sc-entry-content > ul,
.sc-entry-content > ol,
.sc-article__body > p,
.sc-prose > p {
	max-inline-size: var(--sc-measure-justified);
}

/* The editorial body regions, in one place so the rule can be read and audited
   without opening a template. */
:is(
		.sc-entry-content,
		.sc-article__body,
		.sc-prose,
		.sc-editorial-body,
		.sc-about-overview__paragraph,
		.sc-about-bridge__body,
		.sc-split__body,
		.sc-timeline__body,
		.sc-step__body,
		.sc-callout__body,
		.sc-research-focus__paragraph,
		.sc-research-bridge__body,
		.sc-research-hero__lead,
		.sc-service-summary__description,
		.sc-contact-enquiry__aside-body,
		.sc-article__excerpt,
		.sc-text-lead,
		.sc-section__lead
	)
	> p,
.sc-about-overview__paragraph,
.sc-research-focus__paragraph,
.sc-timeline__body,
.sc-callout__body,
.sc-article__excerpt,
.sc-media-hero__lead,
.sc-hero__lead,
.sc-text-lead,
.sc-section__lead {
	text-align: justify;
	text-justify: inter-word;
}

/*
 * The measure. Justification needs a line long enough that the extra word space
 * is not a gap, so every paragraph that justifies is capped at the justified
 * measure rather than at the narrower reading measure the flush paragraphs use.
 * `sc-media-hero__lead` and `sc-hero__lead` are excluded from the cap: their
 * widths are already set by the composition they sit in.
 */
:is(
		.sc-entry-content,
		.sc-article__body,
		.sc-prose,
		.sc-editorial-body,
		.sc-about-overview__paragraph,
		.sc-about-bridge__body,
		.sc-split__body,
		.sc-timeline__body,
		.sc-step__body,
		.sc-callout__body,
		.sc-research-focus__paragraph,
		.sc-research-bridge__body,
		.sc-service-summary__description,
		.sc-contact-enquiry__aside-body,
		.sc-article__excerpt
	)
	> p {
	max-inline-size: var(--sc-measure-justified);
}

/* Latin and Cyrillic: hyphenate, and only justify once the column is wide
   enough that the hyphenation has somewhere to save space. */
:lang(en) :is(.sc-media-hero__lead, .sc-hero__lead),
:lang(en)
	:is(
		.sc-entry-content,
		.sc-article__body,
		.sc-prose,
		.sc-editorial-body,
		.sc-about-overview__paragraph,
		.sc-about-bridge__body,
		.sc-split__body,
		.sc-timeline__body,
		.sc-step__body,
		.sc-callout__body,
		.sc-research-focus__paragraph,
		.sc-research-bridge__body,
		.sc-research-hero__lead,
		.sc-service-summary__description,
		.sc-contact-enquiry__aside-body,
		.sc-article__excerpt,
		.sc-text-lead,
		.sc-section__lead
	) {
	-webkit-hyphens: auto;
	hyphens: auto;
}

:lang(ru) :is(.sc-media-hero__lead, .sc-hero__lead),
:lang(ru)
	:is(
		.sc-entry-content,
		.sc-article__body,
		.sc-prose,
		.sc-editorial-body,
		.sc-about-overview__paragraph,
		.sc-about-bridge__body,
		.sc-split__body,
		.sc-timeline__body,
		.sc-step__body,
		.sc-callout__body,
		.sc-research-focus__paragraph,
		.sc-research-bridge__body,
		.sc-research-hero__lead,
		.sc-service-summary__description,
		.sc-contact-enquiry__aside-body,
		.sc-article__excerpt,
		.sc-text-lead,
		.sc-section__lead
	) {
	-webkit-hyphens: auto;
	hyphens: auto;
}

[data-sc-font-group="persian"]
	:is(
		.sc-entry-content,
		.sc-article__body,
		.sc-prose,
		.sc-editorial-body,
		.sc-about-overview__paragraph,
		.sc-about-bridge__body,
		.sc-split__body,
		.sc-timeline__body,
		.sc-step__body,
		.sc-callout__body,
		.sc-research-focus__paragraph,
		.sc-research-bridge__body,
		.sc-research-hero__lead,
		.sc-service-summary__description,
		.sc-contact-enquiry__aside-body,
		.sc-article__excerpt,
		.sc-text-lead,
		.sc-section__lead
	) {
	text-align: justify;
	text-justify: inter-word;
	-webkit-hyphens: none;
	hyphens: none;
}

@media (width < 48rem) {
	:lang(en) :is(.sc-media-hero__lead, .sc-hero__lead),
	:lang(en)
		:is(
			.sc-entry-content,
			.sc-article__body,
			.sc-prose,
			.sc-editorial-body,
			.sc-about-overview__paragraph,
			.sc-about-bridge__body,
			.sc-split__body,
			.sc-timeline__body,
			.sc-step__body,
			.sc-callout__body,
			.sc-research-focus__paragraph,
			.sc-research-bridge__body,
			.sc-research-hero__lead,
			.sc-service-summary__description,
			.sc-contact-enquiry__aside-body,
			.sc-article__excerpt,
			.sc-text-lead,
			.sc-section__lead
		),
	:lang(ru) :is(.sc-media-hero__lead, .sc-hero__lead),
	:lang(ru)
		:is(
			.sc-entry-content,
			.sc-article__body,
			.sc-prose,
			.sc-editorial-body,
			.sc-about-overview__paragraph,
			.sc-about-bridge__body,
			.sc-split__body,
			.sc-timeline__body,
			.sc-step__body,
			.sc-callout__body,
			.sc-research-focus__paragraph,
			.sc-research-bridge__body,
			.sc-research-hero__lead,
			.sc-service-summary__description,
			.sc-contact-enquiry__aside-body,
			.sc-article__excerpt,
			.sc-text-lead,
			.sc-section__lead
		) {
		text-align: start;
	}

	/* A Persian standfirst is the one Latin-width paragraph that keeps its
	   justification on a phone: the script closes its own word gaps, so a
	   narrow measure does not open rivers in it. */
	[data-sc-font-group="persian"] .sc-section-header__lead,
	[data-sc-font-group="persian"] .sc-media-hero__lead,
	[data-sc-font-group="persian"] .sc-hero__lead {
		text-align: justify;
		text-justify: inter-word;
	}
}

/*
 * The exclusions are structural rather than a list: justification is applied
 * only through the editorial containers named above and only to their direct
 * paragraphs, so a heading, a navigation row, a button, a caption, a
 * metadata line or a short card cannot receive it in the first place. Any of
 * those can sit inside an editorial body — a callout heading, a figure caption,
 * a document link — and every one of them stays flush.
 */

a {
	color: var(--sc-color-link);
	text-decoration-thickness: max(1px, 0.06em);
	text-underline-offset: 0.15em;
	transition: color var(--sc-transition-fast);
}

a:hover {
	color: var(--sc-color-link-hover);
}

/*
 * Standalone links inside body content must be distinguishable without colour
 * alone (WCAG 1.4.1). Underline is inherited from theme.json for content links.
 */
a:not([class]) {
	text-decoration-line: underline;
}

strong,
b {
	font-weight: var(--sc-font-weight-semibold);
}

small {
	font-size: var(--sc-font-size-sm);
}

/* ---------------------------------------------------------------------------
 * Lists
 *
 * Content lists keep their markers and indentation; navigation lists are reset
 * by their own component, not globally. Blanket list resets destroy the
 * semantics of authored content.
 * ------------------------------------------------------------------------- */

ul,
ol {
	padding-inline-start: var(--sc-space-md);
}

li > ul,
li > ol {
	margin-block: var(--sc-space-3xs);
}

/* ---------------------------------------------------------------------------
 * Forms and interactive elements
 * ------------------------------------------------------------------------- */

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

button {
	cursor: pointer;
}

/*
 * Interactive elements must meet a usable target size. Applied to controls
 * only, never to inline links inside prose.
 */
button,
[role="button"],
input[type="submit"],
input[type="button"],
input[type="reset"],
input[type="checkbox"],
input[type="radio"],
select {
	min-block-size: var(--sc-touch-target);
}

input[type="checkbox"],
input[type="radio"] {
	min-block-size: auto;
	inline-size: 1.25rem;
	block-size: 1.25rem;
}

textarea {
	min-block-size: 8rem;
	resize: vertical;
}

::placeholder {
	color: var(--sc-color-text-subtle);
	opacity: 1;
}

/* ---------------------------------------------------------------------------
 * Tables
 *
 * Technical data is frequently tabular. Tables must be readable on a phone
 * without the whole page scrolling sideways, so they scroll within their own
 * region instead.
 * ------------------------------------------------------------------------- */

table {
	inline-size: 100%;
	border-collapse: collapse;

	/* `overflow` on a table element is unreliable; the wrapper handles it. */
}

th,
td {
	padding-block: var(--sc-space-xs);
	padding-inline: var(--sc-space-sm);
	border-block-end: var(--sc-border-width) solid var(--sc-color-border);
	text-align: start; /* logical: replaces left/right alignment */
	vertical-align: top;
}

th {
	font-weight: var(--sc-font-weight-semibold);
	color: var(--sc-color-heading);
}

/* ---------------------------------------------------------------------------
 * Blockquote, code, rules
 * ------------------------------------------------------------------------- */

blockquote {
	margin-inline: 0;
	margin-block: var(--sc-space-md);
	border-inline-start: var(--sc-border-width-strong) solid var(--sc-color-brand);
	padding-inline-start: var(--sc-space-lg);
}

blockquote cite {
	display: block;
	margin-block-start: var(--sc-space-2xs);
	color: var(--sc-color-text-muted);
	font-size: var(--sc-font-size-sm);
	font-style: normal;
}

code,
kbd,
samp,
pre {
	font-family: var(--sc-font-family-mono);
	font-size: 0.9em;
}

pre {
	overflow: auto;
	padding: var(--sc-space-sm);
	border-radius: var(--sc-radius-sm);
	background-color: var(--sc-color-surface-sunken);
}

hr {
	margin-block: var(--sc-space-lg);
	border: 0;
	border-block-start: var(--sc-border-width) solid var(--sc-color-border);
}

/* ---------------------------------------------------------------------------
 * Focus
 *
 * A visible focus indicator is a WCAG 2.4.7 requirement. It is never removed.
 * :focus-visible keeps it for keyboard users without flashing it on click.
 * ------------------------------------------------------------------------- */

:focus-visible {
	outline: var(--sc-focus-outline);
	outline-offset: var(--sc-focus-offset);
	border-radius: var(--sc-radius-sm);
}

/* Remove the default outline only where we replace it immediately. */
:focus:not(:focus-visible) {
	outline: none;
}

/* ---------------------------------------------------------------------------
 * Selection
 * ------------------------------------------------------------------------- */

::selection {
	background-color: var(--sc-color-brand-subtle);
	color: var(--sc-color-heading);
}

/* ---------------------------------------------------------------------------
 * Accessibility utilities
 *
 * `screen-reader-text` is the WordPress convention. It hides content visually
 * while keeping it available to assistive technology — the alternative,
 * display:none, removes it from the accessibility tree entirely.
 * ------------------------------------------------------------------------- */

.screen-reader-text {
	position: absolute !important;
	inline-size: 1px;
	block-size: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	overflow-wrap: normal;
}

/*
 * Skip link. Off-screen until focused, then fully visible. Without the focus
 * state it is technically present but practically unusable.
 */
.sc-skip-link:focus,
.sc-skip-link:focus-visible {
	position: fixed;
	inset-block-start: var(--sc-space-sm);
	inset-inline-start: var(--sc-space-sm);
	z-index: var(--sc-z-skip-link);
	inline-size: auto;
	block-size: auto;
	margin: 0;
	padding: var(--sc-space-xs) var(--sc-space-md);
	clip-path: none;
	overflow: visible;
	border-radius: var(--sc-radius-sm);
	background-color: var(--sc-color-surface);
	color: var(--sc-color-text);
	box-shadow: var(--sc-shadow-md);
	font-weight: var(--sc-font-weight-semibold);
	white-space: normal;
	text-decoration: none;
}

/* Hide content from everyone. Used only for genuinely decorative elements. */
[hidden] {
	display: none !important;
}

/* ---------------------------------------------------------------------------
 * Reduced motion
 * ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------------------------------------------------------------------------
 * Forced colours (Windows High Contrast Mode)
 *
 * The system palette must win. Background images and shadows that carry
 * meaning are replaced with borders so nothing becomes invisible.
 * ------------------------------------------------------------------------- */

@media (forced-colors: active) {
	.sc-card,
	.sc-document,
	.sc-pagination__item > * {
		border: var(--sc-border-width) solid canvastext;
	}

	:focus-visible {
		outline: 3px solid canvastext;
	}
}

/* ---------------------------------------------------------------------------
 * Print
 *
 * A technical B2B site gets printed: product data sheets, specifications and
 * contact details. Print output must be legible, not merely a screenshot.
 * ------------------------------------------------------------------------- */

@media print {
	.sc-site-header,
	.sc-site-footer,
	.sc-breadcrumbs,
	.sc-pagination,
	.sc-skip-link {
		display: none !important;
	}

	body {
		background: #ffffff;
		color: #000000;
		font-size: 11pt;
	}

	a {
		color: #000000;
		text-decoration: underline;
	}

	/* Reveal destination URLs, which are unavailable on paper. */
	a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: 0.85em;
		word-break: break-all;
	}

	/* Never split a table row or a figure across pages. */
	tr,
	table,
	figure {
		break-inside: avoid;
	}

	h1,
	h2,
	h3 {
		break-after: avoid;
	}
}

/* ---------------------------------------------------------------------------
 * Brand typeface
 *
 * The brandbook's typeface, self-hosted as a variable font (weight axis only,
 * 100–900), split by unicode range so a Latin-only page downloads one file.
 *
 * It is registered under `Sarv Display` so the stack in
 * `--sc-font-family-base` can name it ahead of the locally installed
 * `Montserrat`: without that, a machine that has Montserrat installed renders
 * every section with its own copy of the family, and a machine that does not
 * silently falls back to Helvetica. Naming the shipped file first keeps the
 * approved design on every machine and, because the file is a real variable
 * font, lets the weight axis be interpolated (Chromium snaps an installed
 * static family to its named instances, so only the shipped file can express
 * the weights the reference was drawn with).
 * ------------------------------------------------------------------------- */

@font-face {
	font-family: "Sarv Display";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("../fonts/montserrat-var-latin.woff2") format("woff2-variations");
	unicode-range:
		u+0000-00ff, u+0131, u+0152-0153, u+02bb-02bc, u+02c6, u+02da, u+02dc, u+0304, u+0308,
		u+0329, u+2000-206f, u+20ac, u+2122, u+2191, u+2193, u+2192, u+2212, u+2215, u+feff, u+fffd;
}

@font-face {
	font-family: "Sarv Display";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("../fonts/montserrat-var-latin-ext.woff2") format("woff2-variations");
	unicode-range:
		u+0100-02af, u+0300-0301, u+0303-0304, u+0308-0309, u+0323, u+0329, u+1e00-1eff, u+2020,
		u+20a0-20ab, u+20ad-20c0, u+2113, u+2c60-2c7f, u+a720-a7ff;
}

/* ---------------------------------------------------------------------------
 * Persian typeface — Vazirmatn
 *
 * The approved Persian face, self-hosted from the licensed files in
 * `resources/fonts/`. It is the variable instance (weight axis 100–900), which
 * is one request covering every weight the design system uses instead of four
 * static files, and it interpolates the weights the reference was drawn with
 * (500 and 600 included) rather than snapping to the nearest named instance.
 *
 * It is deliberately NOT split by unicode range. Vazirmatn carries the Arabic
 * script and the Latin range, and a Persian page sets its Latin brand names,
 * product codes and file names in the same face, so a Persian page needs both
 * ranges from the same file — subsetting it would trade one small saving for a
 * visible weight or shape mismatch inside the same sentence.
 *
 * The file is only ever requested by a Persian page. `--sc-font-family-fa` is
 * the only stack that names it, and that stack is only in scope when
 * `inc/multilingual.php` sets `data-sc-font-group="persian"` on `<html>`, so
 * the English and Russian pages never download it.
 *
 * @see inc/enqueue.php — the preload, emitted for Persian pages only.
 * ------------------------------------------------------------------------- */

@font-face {
	font-family: Vazirmatn;
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("../fonts/vazirmatn-var-arabic.woff2") format("woff2-variations");
}
