/*
 * base.css — the theme's only always-on stylesheet.
 * Contents: token alias layer · reset · base typography · media defaults ·
 * layout primitives · accessibility (focus ring, skip link) · reduced motion.
 *
 * Loaded by inc/assets.php as the "synergi-base" handle, and registered as the
 * block editor stylesheet in inc/setup.php. Every section stylesheet depends on
 * this handle, so anything declared here is available to all of them.
 *
 * Rules: no hard-coded design values — every colour, size, radius and duration
 * resolves to a theme.json custom property (CLAUDE.md §2.7). Logical properties
 * only, never left/right (CLAUDE.md §2.11). Selectors stay flat, two levels max.
 *
 * What this file deliberately does NOT do: set body font, colour, line-height or
 * heading sizes. The "styles" block in theme.json owns those and emits them as
 * global-styles inline CSS. Restating them here would create exactly the
 * override layer CLAUDE.md §4 exists to prevent.
 */

/* ==========================================================================
   1. Token alias layer
   The single place the theme.json naming (--wp--preset--*, --wp--custom--*)
   meets the short names every other stylesheet uses. Values originate in
   theme.json; nothing new is defined here. Two reasons this layer exists:
   the design source (main.min.css) is written against short names, so the
   Stage 5 split becomes a mechanical rename rather than a rewrite; and it
   gives one file to open when asking where a value came from.
   ========================================================================== */

:root {
	/* Palette — the 11 editor colours. */
	--syn-navy: var(--wp--preset--color--navy);
	--syn-navy-deep: var(--wp--preset--color--navy-deep);
	--syn-ink: var(--wp--preset--color--ink);
	--syn-cyan: var(--wp--preset--color--cyan);
	--syn-cyan-soft: var(--wp--preset--color--cyan-soft);
	--syn-mint: var(--wp--preset--color--mint);
	--syn-text: var(--wp--preset--color--text);
	--syn-text-soft: var(--wp--preset--color--text-soft);
	--syn-white: var(--wp--preset--color--white);
	--syn-paper: var(--wp--preset--color--paper);
	--syn-paper-blue: var(--wp--preset--color--paper-blue);

	/* Utility colours — kept out of the editor picker on purpose (CLAUDE.md §3). */
	--syn-border: var(--wp--custom--color--border);
	--syn-border-dark: var(--wp--custom--color--border-dark);
	--syn-focus: var(--wp--custom--color--focus);
	--syn-success: var(--wp--custom--color--success);

	/*
	 * The hero scrim base. Every hero photograph on the site is read through a
	 * gradient of this colour: the homepage hero (sections/hero.css §2) and the
	 * page-header hero band (parts/page-header.css §3), which is the one on all
	 * the other pages. One token so the two can never drift apart.
	 *
	 * #192029 is not a new brand colour and is not eyeballed. It is Ink mixed
	 * 35% into Text — color-mix(in srgb, #071a31 35%, #232324) — both §3 palette
	 * colours, resolved to a literal here only because theme.json takes no
	 * comments and the custom.color block next to it is written in literals too.
	 *
	 * Why it exists at all (1 Sep): the scrim used to be Ink straight, and Ink
	 * is a strongly blue navy (its blue channel is 42 above its red). Over a
	 * photograph at the 86-97% these gradients run, that read as a blue wash on
	 * every hero rather than as a photograph. Mixing toward Text keeps the same
	 * darkness and drops the blue cast by 62%, so the picture keeps its own
	 * colour. Darkness is what the contrast depends on, so nothing regressed:
	 * white over the scrim measures 16.41:1 (was 17.48:1) and mint 10.30:1 (was
	 * 10.97:1), both far above the 4.5:1 floor in CLAUDE.md §9.
	 *
	 * Keep the darkness if this is ever retuned. The stop percentages, not this
	 * colour, are what hold the fixed transparent header legible over an
	 * editor-chosen photograph — see the note at parts/page-header.css §3.
	 */
	--syn-scrim: var(--wp--custom--color--scrim);

	--syn-gradient-brand: var(--wp--preset--gradient--brand);
	--syn-gradient-brand-deep: var(--wp--preset--gradient--brand-deep);

	/*
	 * Type scale — steps -1 to 4, matching the design source's --step-* names.
	 *
	 * The two largest slugs are "xxl"/"xxxl", not "2xl"/"3xl": core runs every
	 * preset slug through _wp_to_kebab_case() when it builds the custom property,
	 * which inserts a dash between a digit and a letter. A "2xl" slug therefore
	 * emits --wp--preset--font-size--2-xl, and every reference written as
	 * --wp--preset--font-size--2xl silently resolves to nothing. Verified on
	 * staging 25 Aug: h1 and h2 were rendering at the browser default size
	 * because of exactly that. Never start a preset slug with a digit.
	 */
	--syn-step--1: var(--wp--preset--font-size--sm);
	--syn-step-0: var(--wp--preset--font-size--base);
	--syn-step-1: var(--wp--preset--font-size--lg);
	--syn-step-2: var(--wp--preset--font-size--xl);
	--syn-step-3: var(--wp--preset--font-size--xxl);
	--syn-step-4: var(--wp--preset--font-size--xxxl);

	--syn-font-brand: var(--wp--preset--font-family--brand);

	/* Spacing steps 1–8. Step 8 is the section rhythm. */
	--syn-space-1: var(--wp--preset--spacing--20);
	--syn-space-2: var(--wp--preset--spacing--30);
	--syn-space-3: var(--wp--preset--spacing--40);
	--syn-space-4: var(--wp--preset--spacing--50);
	--syn-space-5: var(--wp--preset--spacing--60);
	--syn-space-6: var(--wp--preset--spacing--70);
	--syn-space-7: var(--wp--preset--spacing--80);
	--syn-section-space: var(--wp--preset--spacing--90);

	/* Layout. --syn-container mirrors the wideSize in theme.json; keep them equal. */
	--syn-container: 82rem;
	--syn-container-narrow: var(--wp--custom--container-narrow);
	--syn-gutter: var(--wp--custom--gutter);
	--syn-header-height: var(--wp--custom--header-height);

	--syn-radius-sm: var(--wp--custom--radius--sm);
	--syn-radius-md: var(--wp--custom--radius--md);
	--syn-radius-lg: var(--wp--custom--radius--lg);
	--syn-radius-xl: var(--wp--custom--radius--xl);

	--syn-shadow-soft: var(--wp--preset--shadow--soft);
	--syn-shadow-card: var(--wp--preset--shadow--card);

	--syn-ease-out: var(--wp--custom--motion--ease-out);
	--syn-duration-fast: var(--wp--custom--motion--duration-fast);
	--syn-duration: var(--wp--custom--motion--duration);
	--syn-duration-slow: var(--wp--custom--motion--duration-slow);

	/*
	 * One accent gradient per service line. These are the only design values in
	 * the theme that cannot be derived from the §3 palette — their hues (teal,
	 * gold, violet, rose) are deliberately outside it, so a section stylesheet
	 * cannot reach them with color-mix() the way it reaches every white and ink
	 * shade. They live in theme.json under settings.custom rather than in the
	 * colour palette, so they are tokens without being offered to editors.
	 * Used by the services deck (section 02) and, from Stage 6, by the service
	 * page templates.
	 */
	--syn-service-accounting: var(--wp--custom--service-accent--accounting);
	--syn-service-human-resources: var(--wp--custom--service-accent--human-resources);
	--syn-service-procurement: var(--wp--custom--service-accent--procurement);
	--syn-service-technology-ai: var(--wp--custom--service-accent--technology-ai);
	--syn-service-marketing: var(--wp--custom--service-accent--marketing);
	--syn-service-project-management: var(--wp--custom--service-accent--project-management);
}

/*
 * Two responsive token overrides carried over from the design source, which
 * sets them inside media queries that theme.json cannot express.
 * The source has a third step (--gutter: 0.85rem below 22rem/352px); it is
 * dropped because the narrow clamp already resolves to about 16px there — a 2px
 * difference, below every width the theme is tested at.
 */
@media (max-width: 74rem) {

	:root {
		--syn-header-height: var(--wp--custom--header-height-compact);
	}
}

@media (max-width: 47.99rem) {

	:root {
		--syn-gutter: var(--wp--custom--gutter-narrow);
	}
}

/* ==========================================================================
   2. Reset
   ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	scroll-behavior: smooth;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

body {
	margin: 0;
	min-block-size: 100vh;
	-webkit-font-smoothing: antialiased;
}

/*
 * Headings and paragraphs arrive with user-agent margins that fight blockGap
 * and the section rhythm. Vertical spacing is set by whichever container owns
 * the element, never inherited from the browser.
 */
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd,
ol,
ul {
	margin-block: 0;
}

ol,
ul {
	padding-inline-start: 0;
}

/* Lists inside editor-authored content (.syn-entry-content, set by page.php and
   index.php) keep their markers and their indent. */
.syn-entry-content ol,
.syn-entry-content ul {
	padding-inline-start: var(--syn-space-4);
}

/* ==========================================================================
   3. Base typography
   theme.json sets family, size, weight, colour and line-height. Only the rules
   it cannot express live here.
   ========================================================================== */

h1,
h2,
h3 {
	text-wrap: balance;
}

p {
	text-wrap: pretty;
}

::selection {
	background-color: var(--syn-cyan-soft);
	color: var(--syn-ink);
}

hr {
	border: 0;
	border-block-start: 1px solid var(--syn-border);
	margin-block: var(--syn-space-5);
}

code,
pre,
kbd,
samp {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 0.9em;
}

/* ==========================================================================
   4. Media and form defaults
   ========================================================================== */

img,
picture,
video,
canvas,
svg,
iframe {
	display: block;
	max-inline-size: 100%;
}

img,
video,
canvas {
	block-size: auto;
}

/* Inherit the brand font rather than the user agent's control font. */
input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

textarea {
	resize: vertical;
}

/* ==========================================================================
   5. Layout primitives
   The only two width containers the theme has. Sections and templates compose
   from these; no section defines a max-width of its own.
   ========================================================================== */

.syn-container {
	inline-size: 100%;
	max-inline-size: var(--syn-container);
	margin-inline: auto;
	padding-inline: var(--syn-gutter);
}

.syn-container--narrow {
	max-inline-size: var(--syn-container-narrow);
}

/*
 * Core alignments for editor-authored content. alignleft and alignright are
 * left to core: they are float-based and physical by definition, so the theme
 * does not restate them (CLAUDE.md §2.11).
 */
.syn-entry-content > .alignwide {
	max-inline-size: var(--syn-container);
	margin-inline: auto;
}

.syn-entry-content > .alignfull {
	max-inline-size: none;
	/* Cancels the container gutter so a full-bleed block reaches the viewport edge. */
	margin-inline: calc(var(--syn-gutter) * -1);
}

.syn-entry-content > .aligncenter {
	margin-inline: auto;
}

/*
 * Vertical rhythm for editor-authored content.
 *
 * theme.json's blockGap cannot do this job here: core only emits blockGap rules
 * for the block-layout wrappers a block theme generates, and a classic template
 * calling the_content() has none of them. The reset above stripped the user
 * agent's margins, so without these rules post content would run together.
 *
 * Headings take a larger step above than below, so a heading reads as attached
 * to the text it introduces rather than floating between two blocks.
 */
.syn-entry-content {
	padding-block: var(--syn-space-6);
}

.syn-entry-content > * + * {
	margin-block-start: var(--syn-space-4);
}

.syn-entry-content > * + h2,
.syn-entry-content > * + h3,
.syn-entry-content > * + h4 {
	margin-block-start: var(--syn-space-6);
}

.syn-entry-content > :first-child {
	margin-block-start: 0;
}

/* Multi-page posts and pages, from wp_link_pages(). */
.syn-page-links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--syn-space-2);
	margin-block-start: var(--syn-space-5);
}

/* ==========================================================================
   6. Accessibility
   ========================================================================== */

/*
 * One visible focus ring for everything (CLAUDE.md §9). theme.json declares the
 * same ring on links and buttons; this catches every other focusable element.
 * :focus-visible only, so a mouse click never paints a ring — but the ring is
 * never removable: outline: none without a replacement is a bug here.
 */
:focus-visible {
	outline: 3px solid var(--syn-focus);
	outline-offset: 2px;
	border-radius: var(--syn-radius-sm);
}

/*
 * Skip link — the first focusable element on every page, targeting
 * #main-content in header.php. Off-screen until focused, then pinned to the
 * start of the viewport.
 */
.syn-skip-link {
	position: absolute;
	inset-block-start: -100%;
	inset-inline-start: var(--syn-gutter);
	z-index: 999;
	padding: var(--syn-space-2) var(--syn-space-4);
	background-color: var(--syn-navy);
	color: var(--syn-white);
	border-radius: var(--syn-radius-md);
	text-decoration: none;
}

.syn-skip-link:focus {
	inset-block-start: var(--syn-space-2);
}

/* Screen-reader-only text, for labels that must exist but not be seen. */
.syn-visually-hidden {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ==========================================================================
   7. Reduced motion
   Applied theme-wide so no section has to remember it (CLAUDE.md §6). Content
   stays visible — reduced motion means no movement, never hidden content.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

	html {
		scroll-behavior: auto;
	}

	/*
	 * !important is required here: this rule has to beat every animation
	 * declaration in every section stylesheet, including ones written later.
	 * This rule and the two plugin overrides in instagram.css are the only
	 * !important declarations the theme ships (CLAUDE.md §2.12).
	 */
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
		/*
		 * The delays go too, or a zero-duration transition still waits. why.css
		 * holds a 300ms delay before a card's words appear and shared-services
		 * staggers its float by up to 2.6s; without these two lines reduced motion
		 * turns those into blank pauses instead of removing them.
		 */
		animation-delay: -1ms !important;
		transition-delay: 0ms !important;
	}
}

/* ==========================================================================
   8. Buttons
   The design's shared button, promoted here in Stage 5 because sections need
   it and it also appears in editor content and on 404.php. Stage 3 wrote the
   header CTA's geometry out inline rather than inventing this early; that CTA
   has since been removed, so this is the only copy.

   The asymmetric radius (square leading edge, rounded trailing edge) is the
   design's, not a mistake — it is what makes the brand's buttons recognisable.
   It is written logically so it mirrors correctly in Arabic.
   ========================================================================== */

.syn-button {
	display: inline-flex;
	min-block-size: 3.25rem;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	padding-block: 0.8rem;
	padding-inline: 1.35rem;
	border: 1px solid transparent;
	border-start-start-radius: 0;
	border-end-start-radius: 0;
	border-start-end-radius: 1.25rem;
	border-end-end-radius: 1.25rem;
	font-size: var(--syn-step--1);
	font-weight: 700;
	letter-spacing: 0.025em;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	transition:
		transform var(--syn-duration-fast) var(--syn-ease-out),
		box-shadow var(--syn-duration-fast),
		background-color var(--syn-duration-fast),
		border-color var(--syn-duration-fast),
		color var(--syn-duration-fast),
		filter var(--syn-duration-fast);
}

.syn-button:hover {
	transform: translateY(-2px);
}

/* Solid brand gradient. The primary action in any group. */
.syn-button--primary {
	background-image: var(--syn-gradient-brand);
	color: var(--syn-white);
	box-shadow: 0 0.5rem 1.4rem color-mix(in srgb, var(--syn-navy) 28%, transparent);
}

.syn-button--primary:hover {
	color: var(--syn-white);
	box-shadow: 0 0.7rem 1.8rem color-mix(in srgb, var(--syn-navy) 34%, transparent);
	filter: brightness(1.12);
}

/*
 * Outlined, for use on a LIGHT surface — the Instagram section's "Follow
 * Synergi". Its opposite number is --light below; the two are not
 * interchangeable, and the source proves why: it puts its light-surface
 * outline button on the closing CTA's near-black panel, where navy text on ink
 * measures 1.3:1 and the button is effectively invisible. Section 12 uses
 * --light instead.
 */
.syn-button--outline {
	border-color: var(--syn-navy);
	background-color: transparent;
	color: var(--syn-navy);
}

.syn-button--outline:hover {
	border-color: transparent;
	background-image: var(--syn-gradient-brand);
	color: var(--syn-white);
}

/* Outlined, for use on a dark surface — the hero and the closing CTA. */
.syn-button--light {
	border-color: color-mix(in srgb, var(--syn-white) 55%, transparent);
	background-color: transparent;
	color: var(--syn-white);
}

.syn-button--light:hover {
	border-color: var(--syn-white);
	background-color: var(--syn-white);
	color: var(--syn-navy);
}

/* ==========================================================================
   9. Scroll reveal
   Shared by every homepage section; assets/js/main.js drives it.

   The resting state is applied only inside (scripting: enabled), the same guard
   header.css uses for the nav panel. Without it a browser with JavaScript off
   would be left holding the whole homepage permanently invisible, which is the
   worst failure a decorative animation can have. Gating on a class set by
   main.js would not do: the script is deferred, so the class lands after first
   paint and the content would visibly flash in and then hide.
   ========================================================================== */

@media (scripting: enabled) {

	.syn-reveal {
		opacity: 0;
		transform: translateY(1.25rem);
		transition:
			opacity var(--syn-duration-slow) var(--syn-ease-out),
			transform var(--syn-duration-slow) var(--syn-ease-out);
	}

	.syn-reveal.syn-is-visible {
		opacity: 1;
		transform: translateY(0);
	}

	/* Already on screen when it was reached: no fade, just present. */
	.syn-reveal.syn-is-instant {
		transition: none;
	}
}

/* Reduced motion: present, in place, no movement (CLAUDE.md §6). */
@media (prefers-reduced-motion: reduce) {

	.syn-reveal {
		opacity: 1;
		transform: none;
	}
}

/* ==========================================================================
   10. Shared section elements
   The eyebrow label and the arrow text link appear in most homepage sections,
   so they are defined once here rather than repeated in each section file.
   A section that needs a variant overrides it in its own stylesheet — which is
   a component being adjusted in context, not the override layer CLAUDE.md §4
   warns about, because there is still exactly one place these are defined.
   ========================================================================== */

/* Small uppercase label above a section heading, with a short cyan rule
   before it. Tried stacked above the label earlier on 2 Sep; the decision
   that stuck is beside it, but at 1.5rem — the design source's own smaller
   variant — instead of the original 2.25rem, so the label starts closer to
   the container line. */
.syn-eyebrow {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin-block-end: 1rem;
	color: var(--syn-navy);
	font-size: var(--syn-step--1);
	font-weight: 700;
	letter-spacing: 0.13em;
	line-height: 1.3;
	text-transform: uppercase;
}

.syn-eyebrow::before {
	inline-size: 1.5rem;
	block-size: 2px;
	background-color: var(--syn-cyan);
	content: "";
}

/* "Explore X →" — the arrow slides on hover. */
.syn-text-link {
	display: inline-flex;
	align-items: center;
	gap: 0.75rem;
	color: var(--syn-navy);
	font-size: var(--syn-step--1);
	font-weight: 700;
	text-decoration: none;
}

.syn-text-link span {
	transition: transform var(--syn-duration-fast);
}

.syn-text-link:hover span {
	transform: translateX(0.25rem);
}

/*
 * Section rhythm. The design applies this to every section except the hero,
 * which sets its own full-viewport height — expressed here as an opt-out class
 * rather than :not(.syn-hero), so a future section can decline it too.
 */
.syn-section {
	position: relative;
	padding-block: var(--syn-section-space);

	/*
	 * The header is fixed, so a jump to #services would otherwise land with the
	 * section's first line underneath it. The design source only does this
	 * below 48rem, which leaves the same bug on every larger screen; the header
	 * is fixed at every width, so this is too.
	 */
	scroll-margin-block-start: var(--syn-header-height);
}
