/*!
 * Sarv Catalyst — Design tokens
 *
 * Primary frontend design-token definition, participating in a verified contract
 * with theme.json. Every component, layout and utility style in this theme reads
 * its values from the custom properties below; theme.json publishes the same
 * brand values to WordPress and the block editor as editor presets.
 *
 * This file is not the only place a brand value is written. theme.json authors
 * its palette anchor values as literal hex, because WordPress editor presets are
 * resolved by PHP and the editor bundle and cannot read a CSS custom property.
 * The two files therefore hold equivalent values that must move together, and
 * scripts/verify-structure.mjs enforces that they do: it resolves every
 * `var(--sc-*)` reference in the CSS against the declared token set, and checks
 * that all 13 palette colours in theme.json are still present in this file. That
 * is a verified contract between two owners, not a single source of truth.
 *
 * Structure:
 *   1. Colour primitives (the raw ramps)
 *   2. Colour semantics (roles — what components must use)
 *   3. Typography (families, sizes, weights, line heights, letter spacing)
 *   4. Space (a single geometric scale)
 *   5. Layout (containers, grid)
 *   6. Border, radius and shadow
 *   7. Motion and z-index
 *   8. Focus
 *
 * Rules:
 *   - Components reference semantic tokens, never primitives and never hex.
 *   - Every token is namespaced `--sc-`.
 *   - Logical properties only (`margin-inline`, not `margin-left`). This is
 *     what makes Persian RTL work without a second stylesheet.
 *
 * Contrast audit (WCAG 2.2, computed):
 *   text on surface ............. 12.02:1  AAA
 *   text on surface-muted ....... 11.28:1  AAA
 *   brand on surface ............  4.96:1  AA
 *   brand-strong on surface .....  8.78:1  AAA
 *   on-brand (white on brand) ...  4.96:1  AA
 *   on-brand muted (blue-50) ....  4.57:1  AA
 *   on-accent (white on accent) .  4.70:1  AA
 *   on-inverse (white on inverse) 14.42:1  AAA
 *   brand-light .................  2.21:1  FAIL — graphic use only
 *   brand-mid ...................  3.18:1  AA-large only
 *
 * brand-light (#42BBE6) and brand-mid (#3398D6) must never carry text on a
 * light surface, and must never be a background behind white body text. They
 * are intended for large display type, graphical accents, charts and iconography.
 *
 * @see docs/ARCHITECTURE.md — "Design system"
 */

:root {
	/* ---------------------------------------------------------------------
	 * 1. Colour primitives
	 *
	 * Brand anchors, exactly as specified:
	 *   #1476AE  primary blue
	 *   #E31D24  primary red
	 *   #42BBE6  secondary blue (light)
	 *   #3398D6  secondary blue (mid)
	 *   #425563  dark neutral
	 *   #F4F7F9  light neutral
	 *
	 * Surrounding steps are a derived ramp. They exist so that hover states,
	 * borders and muted surfaces come from the same hue family rather than
	 * being invented per component.
	 * ------------------------------------------------------------------- */

	--sc-blue-50: #eef7fc;
	--sc-blue-100: #ddeef8;
	--sc-blue-200: #b6dff7;
	--sc-blue-300: #7fc7f0;
	--sc-blue-400: #3fabe9;
	--sc-blue-500: #1476ae;
	--sc-blue-600: #0d6292;
	--sc-blue-700: #0a4f76;
	--sc-blue-800: #083c59;
	--sc-blue-900: #05293d;
	--sc-blue-950: #031a27;

	--sc-sky-50: #eef8fb;
	--sc-sky-100: #ddf1f8;
	--sc-sky-200: #b7e5f5;
	--sc-sky-300: #81d2ee;
	--sc-sky-400: #42bbe6;
	--sc-sky-500: #42bbe6;
	--sc-sky-600: #17a8dc;
	--sc-sky-700: #1287b1;
	--sc-sky-800: #0e6786;
	--sc-sky-900: #09465b;
	--sc-sky-950: #062d3b;

	--sc-azure-50: #eff6fb;
	--sc-azure-100: #dfedf6;
	--sc-azure-200: #bbddf1;
	--sc-azure-300: #88c3e7;
	--sc-azure-400: #4da5db;
	--sc-azure-500: #3398d6;
	--sc-azure-600: #207fb9;
	--sc-azure-700: #1a6695;
	--sc-azure-800: #144d71;
	--sc-azure-900: #0d354d;
	--sc-azure-950: #092232;

	--sc-red-50: #fceeef;
	--sc-red-100: #f8ddde;
	--sc-red-200: #f6b6b9;
	--sc-red-300: #ef8084;
	--sc-red-400: #e74046;
	--sc-red-500: #e31d24;
	--sc-red-600: #c01218;
	--sc-red-700: #9a0f14;
	--sc-red-800: #750b0f;
	--sc-red-900: #4f080a;
	--sc-red-950: #330507;

	--sc-neutral-50: #f3f5f7;
	--sc-neutral-100: #e7ebee;
	--sc-neutral-200: #ced7de;
	--sc-neutral-300: #a9bac6;
	--sc-neutral-400: #7e97a9;
	--sc-neutral-500: #425563;
	--sc-neutral-600: #354652;
	--sc-neutral-700: #2b3842;
	--sc-neutral-800: #212b32;
	--sc-neutral-900: #161d22;
	--sc-neutral-950: #0e1316;

	--sc-white: #ffffff;
	--sc-black: #000000;

	/* ---------------------------------------------------------------------
	 * 2. Colour semantics
	 *
	 * Components must use these. The 60/30/10 brand balance (blues / neutrals /
	 * reds) is expressed here: brands carry structure and identity, neutrals
	 * carry the bulk of the surface area, and `accent` is reserved for
	 * attention — primary actions and critical emphasis only.
	 * ------------------------------------------------------------------- */

	/* Surfaces */
	--sc-color-surface: var(--sc-white);
	--sc-color-surface-muted: #f4f7f9; /* brand light neutral, verbatim */
	--sc-color-surface-sunken: var(--sc-neutral-100);
	--sc-color-surface-raised: var(--sc-white);
	--sc-color-surface-inverse: var(--sc-neutral-800);
	--sc-color-surface-brand: var(--sc-blue-500);
	--sc-color-surface-brand-strong: var(--sc-blue-700);

	/*
	 * Tints taken from the approved homepage references. Each one is a band
	 * background only: they sit behind dark text and are never used to carry a
	 * label on their own.
	 */
	--sc-color-surface-pale: #f4f9fe;
	--sc-color-surface-finder: #f2f9fd;
	--sc-color-surface-industries: #eaf6fd;
	--sc-color-pattern-line: #a2cbe8;

	/* Text */
	--sc-color-text: #2b3842; /* 12.02:1 on white — AAA */
	--sc-color-text-muted: var(--sc-neutral-600); /* 9.77:1 on white — AAA */
	--sc-color-text-subtle: var(--sc-neutral-500); /* 7.49:1 on white — AAA */
	--sc-color-text-inverse: var(--sc-white);
	--sc-color-text-on-brand: var(--sc-white); /* 4.96:1 on brand — AA */
	--sc-color-text-on-accent: var(--sc-white); /* 4.70:1 on accent — AA */
	--sc-color-text-on-brand-muted: var(--sc-blue-50); /* secondary copy on brand bands */
	--sc-color-heading: var(--sc-neutral-800);

	/* Brand */
	--sc-color-brand: var(--sc-blue-500);
	--sc-color-brand-hover: var(--sc-blue-600);
	--sc-color-brand-strong: var(--sc-blue-700);
	--sc-color-brand-subtle: var(--sc-blue-50);
	--sc-color-brand-border: var(--sc-blue-200);

	/* Accent — reserved for primary action and critical emphasis */
	--sc-color-accent: var(--sc-red-500);
	--sc-color-accent-hover: var(--sc-red-600);
	--sc-color-accent-strong: var(--sc-red-700);
	--sc-color-accent-subtle: var(--sc-red-50);

	/* Links */
	--sc-color-link: var(--sc-blue-700); /* 8.78:1 — AAA, safe for body copy */
	--sc-color-link-hover: var(--sc-blue-800);
	--sc-color-link-visited: var(--sc-blue-800);

	/* Borders and dividers */
	--sc-color-border: var(--sc-neutral-200);
	--sc-color-border-strong: var(--sc-neutral-300);
	--sc-color-border-subtle: var(--sc-neutral-100);
	--sc-color-border-inverse: rgb(255 255 255 / 20%);

	/* Feedback */
	--sc-color-success: #1f7a4d;
	--sc-color-warning: #9a5b00;
	--sc-color-error: var(--sc-red-700);

	/* Graphic-only brand colours. Documented as unsafe for text. */
	--sc-color-graphic-light: var(--sc-sky-400);
	--sc-color-graphic-mid: var(--sc-azure-500);

	--sc-color-transparent: transparent;

	/* ---------------------------------------------------------------------
	 * 3. Typography
	 *
	 * The approved typefaces, both self-hosted:
	 *
	 *   Latin   Montserrat  — shipped as `Sarv Display`, a variable font split
	 *                         by unicode range (see base.css).
	 *   Persian Vazirmatn   — shipped as `Vazirmatn`, the licensed variable
	 *                         font (see base.css).
	 *
	 * The font group is selected by a data attribute on <html> emitted from
	 * inc/multilingual.php. Swapping either typeface is therefore a change to
	 * one variable here — no component, template or stylesheet is touched.
	 *
	 * Each stack ends in a metric-similar system fallback so a page that never
	 * receives the file still sets with the right rhythm rather than collapsing
	 * to the browser default serif.
	 * ------------------------------------------------------------------- */

	--sc-font-family-latin: "Sarv Display", Montserrat, "Helvetica Neue", Arial, sans-serif;
	--sc-font-family-base: var(--sc-font-family-latin);
	--sc-font-family-heading: var(--sc-font-family-base);
	--sc-font-family-mono:
		"SFMono-Regular", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

	/* Persian typography. Vazirmatn is bundled with the theme. */
	--sc-font-family-fa: "Vazirmatn", Tahoma, "Iranian Sans", sans-serif;

	/* Fluid type scale. min()/clamp() keeps steps reasonable across viewports
	   without introducing arbitrary breakpoints. */
	--sc-font-size-xs: 0.8125rem; /* 13px */
	--sc-font-size-sm: 0.875rem; /* 14px */
	--sc-font-size-base: 1rem; /* 16px */
	--sc-font-size-lg: 1.125rem; /* 18px */
	--sc-font-size-xl: clamp(1.25rem, 1.15rem + 0.4vw, 1.375rem);
	--sc-font-size-2xl: clamp(1.375rem, 1.22rem + 0.7vw, 1.625rem);
	--sc-font-size-3xl: clamp(1.625rem, 1.38rem + 1.1vw, 2.125rem);
	--sc-font-size-4xl: clamp(2rem, 1.6rem + 1.8vw, 3rem);

	--sc-font-weight-regular: 400;
	--sc-font-weight-medium: 500;
	--sc-font-weight-semibold: 600;
	--sc-font-weight-bold: 700;

	--sc-line-height-tight: 1.2;
	--sc-line-height-snug: 1.35;
	--sc-line-height-normal: 1.6;
	--sc-line-height-relaxed: 1.75;

	/*
	 * Persian sets need more leading and slightly more tracking. Applied only
	 * when the font group is Persian, so no duplicate rules are required.
	 */
	--sc-line-height-fa-offset: 0.15;
	--sc-letter-spacing-fa-offset: 0;

	/*
	 * Reading measure for long-form editorial body.
	 *
	 * Justification is only applied where the measure can carry it. Below the
	 * measure a justified paragraph opens rivers between its words, so the
	 * alignment rule in base.css is scoped to the editorial prose classes
	 * rather than to `p`, and this is the width it is scoped to.
	 */
	--sc-measure-justified: 62ch;
	--sc-measure-editorial: 70ch;

	--sc-letter-spacing-tight: -0.02em;
	--sc-letter-spacing-normal: 0;
	--sc-letter-spacing-wide: 0.04em;

	--sc-measure: 68ch; /* comfortable reading measure */

	/* ---------------------------------------------------------------------
	 * 4. Space
	 *
	 * One geometric scale. Every gap, pad and margin in the theme comes from
	 * here, which is what stops spacing drift as the site grows.
	 * ------------------------------------------------------------------- */

	--sc-space-3xs: 0.25rem; /*  4px */
	--sc-space-2xs: 0.5rem; /*  8px */
	--sc-space-xs: 0.75rem; /* 12px */
	--sc-space-sm: 1rem; /* 16px */
	--sc-space-md: 1.5rem; /* 24px */
	--sc-space-lg: 2rem; /* 32px */
	--sc-space-xl: 3rem; /* 48px */
	--sc-space-2xl: 4rem; /* 64px */
	--sc-space-3xl: 6rem; /* 96px */

	/* Vertical rhythm for full-width sections. Responsive, still one token. */
	--sc-space-section: clamp(3rem, 2rem + 4vw, 6rem);

	/* Minimum interactive target size — WCAG 2.2 (2.5.8) is 24px,
	   the brief's AAA-leaning target is 44px. */
	--sc-touch-target: 2.75rem;

	/* ---------------------------------------------------------------------
	 * 5. Layout
	 * ------------------------------------------------------------------- */

	--sc-container-narrow: 48rem; /* 768px */
	--sc-container-content: 45rem; /* 720px — mirrors theme.json contentSize */
	--sc-container-wide: 75rem; /* 1200px — mirrors theme.json wideSize */
	--sc-container-full: 100%;
	--sc-container-gutter: clamp(1rem, 0.5rem + 2.5vw, 2.5rem);

	--sc-grid-columns: 12;
	--sc-grid-gap: var(--sc-space-md);

	--sc-header-height: 5rem;
	--sc-sidebar-width: 18rem;

	/* ---------------------------------------------------------------------
	 * 6. Border, radius, shadow
	 * ------------------------------------------------------------------- */

	--sc-border-width: 1px;
	--sc-border-width-strong: 2px;

	--sc-radius-sm: 0.25rem;
	--sc-radius-md: 0.5rem;
	--sc-radius-lg: 1rem;
	--sc-radius-pill: 999px;

	/*
	 * The one radius every internal-page hero and content photograph is cut
	 * with. A single token rather than a per-page decision: the site's picture
	 * corners are a property of the design system, so a new page template that
	 * places a photograph inherits the treatment instead of re-choosing it.
	 *
	 * 1rem sits in the middle of the 12–18px band the design calls for, and
	 * `--sc-radius-media-sm` steps it down where the frame is short enough that
	 * 16px would read as a pill rather than as a corner.
	 */
	--sc-radius-media: 1rem;
	--sc-radius-media-sm: 0.75rem;

	/*
	 * Shadows are restrained and neutral-tinted. No coloured glow: the brand
	 * positioning is industrial and scientific, not decorative.
	 */
	--sc-shadow-sm: 0 1px 2px 0 rgb(33 43 50 / 6%);
	--sc-shadow-md: 0 4px 12px -2px rgb(33 43 50 / 10%);
	--sc-shadow-lg: 0 12px 32px -8px rgb(33 43 50 / 14%);

	--sc-button-padding-block: 0.75rem;
	--sc-button-padding-inline: 1.5rem;

	/* ---------------------------------------------------------------------
	 * 7. Motion and stacking
	 * ------------------------------------------------------------------- */

	--sc-transition-fast: 120ms ease-out;
	--sc-transition-base: 200ms ease-out;
	--sc-transition-slow: 320ms ease-out;

	/*
	 * The entrance transitions. Longer than the shared "slow" step on purpose:
	 * a section arriving is the one place the site asks to be watched, and at
	 * 320ms a 34px lift is over before the eye has registered it as movement.
	 * The easing is a decelerating curve with no overshoot, so the section
	 * settles rather than bounces.
	 *
	 * 640ms is the middle of the 550–750ms band the motion review asked for, and
	 * the travel is 2.125rem (34px) rather than the 24px that read as noise. The
	 * two numbers move together: a longer duration with no extra distance is a
	 * slower version of the same invisible effect, and extra distance on the old
	 * 520ms reads as a jump.
	 */
	--sc-transition-reveal: 720ms cubic-bezier(0.22, 0.61, 0.36, 1);

	/*
	 * How far a revealed element travels. Declared once so the section reveal,
	 * the stagger and the split reveals cannot drift apart, and so a single
	 * media query can halve all of them on a short viewport.
	 */
	--sc-reveal-distance: 2.75rem;

	/* The step between two siblings in a staggered group. 80–130ms is the band
	   the review asked for; 110ms resolves a four-item row in a third of a
	   second, which is long enough to read as a sequence and short enough that
	   the last card never arrives after the visitor has started reading it. */
	--sc-reveal-step: 130ms;

	/*
	 * How far a photograph settles inside its frame when the section arrives.
	 * 1.03 is the value the reference compositions were measured with; it is a
	 * token rather than a literal so the phone layout can bring it in, where the
	 * same 3% is a few pixels and reads as a twitch.
	 */
	--sc-reveal-scale: 1.06;

	/*
	 * The photograph's slow drift.
	 *
	 * A separate, much longer duration from the section reveal on purpose. The
	 * reveal is an arrival — it has to finish while the eye is still on it. The
	 * drift is a settle: a 6% crop relaxing back to square over nearly 1.4s, on
	 * the image alone, so the frame and the copy beside it arrive together and
	 * the picture then keeps resolving for a beat after they have stopped. That
	 * is the difference between an image that is revealed and an image that
	 * comes into focus.
	 */
	--sc-transition-drift: 1400ms cubic-bezier(0.16, 0.7, 0.28, 1);

	/*
	 * The hero entrance. A touch longer than a section reveal because a hero is
	 * the one band a visitor is guaranteed to see, so the extra 200ms buys a
	 * sequence that reads as staged rather than as a single fade — and it is
	 * still under a second, so nothing on the page is ever waiting.
	 */
	--sc-transition-hero: 880ms cubic-bezier(0.22, 0.61, 0.36, 1);

	--sc-z-base: 1;
	--sc-z-dropdown: 100;

	/*
	 * Component-set variables. These are not values a stylesheet chooses; they
	 * are the single dimension a component is parameterised by, written into the
	 * element's own `style` attribute by the template that owns the data. They
	 * are declared here so that the design-token contract — every `var()` in the
	 * theme resolves against a declared property — holds for them too, and so
	 * that a component which forgets to set one still renders a defined state
	 * rather than an invalid value.
	 */
	--sc-stat-grade: 3rem;

	--sc-z-sticky: 200;
	--sc-z-overlay: 300;
	--sc-z-modal: 400;
	--sc-z-skip-link: 500;

	/* ---------------------------------------------------------------------
	 * 8. Focus
	 *
	 * A single focus treatment, applied globally. Visible focus is an
	 * accessibility requirement, not a style preference, so it is defined once
	 * here and never removed by a component.
	 * ------------------------------------------------------------------- */

	--sc-focus-outline: 2px solid var(--sc-blue-700);
	--sc-focus-offset: 2px;

	/* ---------------------------------------------------------------------
	 * 9. Brand pattern
	 *
	 * The graphic-pattern system is a set of alpha masks, not artwork with
	 * baked-in colour. Two sizes and three opacities cover every placement, so
	 * no component invents its own scale and the pattern keeps one identity.
	 * ------------------------------------------------------------------- */

	--sc-pattern-size-lg: 34rem;
	--sc-pattern-size-md: 20rem;
	--sc-pattern-opacity: 0.1;
	--sc-pattern-opacity-strong: 0.22;

	/* A saturated blue field needs more alpha than white before the same
	   geometry reads at all. */
	--sc-pattern-opacity-on-brand: 0.3;
}

/*
 * ---------------------------------------------------------------------------
 * Persian (RTL) adjustments
 *
 * Only token values change. No layout, spacing or component rule is
 * duplicated, because every rule in the theme uses logical properties and the
 * cascade already handles direction.
 * ------------------------------------------------------------------------- */

[data-sc-font-group="persian"] {
	--sc-font-family-base: var(--sc-font-family-fa);
	--sc-font-family-heading: var(--sc-font-family-fa);
	--sc-line-height-normal: calc(1.6 + var(--sc-line-height-fa-offset));
	--sc-line-height-relaxed: calc(1.75 + var(--sc-line-height-fa-offset));
	--sc-letter-spacing-tight: var(--sc-letter-spacing-normal);
}

/* ---------------------------------------------------------------------------
 * Dark surface context
 *
 * Applied by templates that place content on the inverse surface. Redefining
 * the semantic tokens means descendants need no special-casing: they keep
 * referencing --sc-color-text and get the correct contrast automatically.
 * ------------------------------------------------------------------------- */

.sc-surface-inverse,
[data-sc-context="inverse"] {
	--sc-color-text: var(--sc-white);
	--sc-color-text-muted: var(--sc-neutral-300);
	--sc-color-text-subtle: var(--sc-neutral-400);
	--sc-color-heading: var(--sc-white);
	--sc-color-link: var(--sc-blue-200);
	--sc-color-link-hover: var(--sc-white);
	--sc-color-border: var(--sc-color-border-inverse);
	--sc-color-border-subtle: var(--sc-color-border-inverse);

	color: var(--sc-color-text);
	background-color: var(--sc-color-surface-inverse);
}

/* ---------------------------------------------------------------------------
 * Brand surface context
 *
 * The brand-blue counterpart to the block above, and the reason sections on
 * `--sc-color-surface-brand` are readable at all. On that surface the
 * light-surface heading and muted-text roles would resolve to #2b3842 and
 * #425563 against #1476AE — 2.4:1 and 1.9:1. Both are redefined here to the
 * lightest blue tints, which measure 4.96:1 and 4.57:1.
 *
 * Only white and near-white tints clear AA on this surface, so the muted role
 * cannot stay visually muted here; hierarchy on a brand band has to come from
 * size and weight instead of colour.
 *
 * `--sc-color-brand-strong` is deliberately NOT redefined. It is the text
 * colour of `.sc-button--inverse`, so remapping it to white would render the
 * primary action on this surface invisible.
 * ------------------------------------------------------------------------- */

[data-sc-context="brand"] {
	--sc-color-text: var(--sc-white);
	--sc-color-text-muted: var(--sc-blue-50);
	--sc-color-text-subtle: var(--sc-blue-50);
	--sc-color-heading: var(--sc-white);
	--sc-color-link: var(--sc-white);
	--sc-color-link-hover: var(--sc-blue-50);
	--sc-color-border: var(--sc-color-border-inverse);
	--sc-color-border-subtle: var(--sc-color-border-inverse);

	color: var(--sc-color-text);
	background-color: var(--sc-color-surface-brand);
}

/* ---------------------------------------------------------------------------
 * Reduced motion
 *
 * Respects the user's operating-system preference. Transitions collapse to a
 * negligible duration rather than being removed, so any transitionend listener
 * still fires.
 * ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	:root {
		--sc-transition-fast: 1ms;
		--sc-transition-base: 1ms;
		--sc-transition-slow: 1ms;

		/* The entrance durations too. The motion layer already forces every
		   revealed element to its resting state under this preference, so these
		   two only matter for the elements that are transformed by a rule the
		   motion layer does not name — and a duration left at 720ms there would
		   be a transition a vestibular-sensitive visitor asked not to receive. */
		--sc-transition-reveal: 1ms;
		--sc-transition-drift: 1ms;
		--sc-transition-hero: 1ms;

		--sc-reveal-distance: 0rem;
		--sc-reveal-scale: 1;
	}
}
