/* ===========================================================================
   FS — BASE
   Reset, document defaults, type scale, layout primitives, page furniture.
   Tokens only — no raw values below this line.

   Directional properties are logical (inline/block, never left/right) so a
   future /ar/ locale needs no override sheet.
   =========================================================================== */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}

body {
	margin: 0;
	background: var(--fs-bg);
	color: var(--fs-ink);
	font-family: var(--fs-font-body);
	font-size: var(--fs-t-body);
	line-height: var(--fs-lh-150);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;

	/* clip, NOT hidden - and the difference is load-bearing.

	   `overflow-x: hidden` cannot leave the other axis alone: per spec, when one
	   axis is not visible the other resolves from visible to auto, so this rule
	   was silently turning <body> into a scroll container (computed: hidden auto).
	   Anything using position: sticky inside it then sticks relative to BODY -
	   which never scrolls, because <html> is what scrolls - so sticky resolved to
	   no effect at all. .fs-stack__aside was pinned in the stylesheet and simply
	   scrolled away in the browser, with nothing in the CSS to explain why.

	   `clip` contains horizontal overflow identically but does NOT create a
	   scroll container, so it can coexist with overflow-y: visible and sticky
	   works again. Do not swap this back to hidden. */
	overflow-x: clip;
}

img,
video,
svg {
	max-width: 100%;
	height: auto;
}

/* ---------------------------------------------------------------------------
   TYPE SCALE
   Fluid via clamp(); tracking is proportional and never negative below 20px.
   --------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
	font-family: var(--fs-font-display);
	margin: 0 0 var(--fs-space-sm);
	color: var(--fs-ink);
	text-wrap: balance;
}

/* Ritovex sets every heading at bold 700 and 150% leading, and lets size
   alone carry the hierarchy. 150% is loose for display type - the hero drops
   to 130% via --fs-lh-130 - but it is the template's own value, adopted
   deliberately rather than corrected.

   Weights are 700 and 500 only. Satoshi ships 300/400/500/700/900: asking for
   600 or 800 makes the browser synthesise a face, which is heavier on some
   platforms and ignored on others. */

h1 {
	font-size: var(--fs-t-h1);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-display);
}

h2 {
	font-size: var(--fs-t-h2);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-lg);
}

h3 {
	font-size: var(--fs-t-h3);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-md);
}

h4 {
	font-size: var(--fs-t-h4);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-md);
}

h5 {
	font-size: var(--fs-t-h5);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-md);
}

h6 {
	font-size: var(--fs-t-h6);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-150);
	letter-spacing: var(--fs-track-none);
}

p {
	margin: 0 0 var(--fs-space-sm);
}

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

/* Measure. Prose 68ch, ledes 54ch, display headlines 20ch. */
.fs-prose {
	max-inline-size: 68ch;
}

.fs-lede {
	max-inline-size: 54ch;
	font-size: var(--fs-t-lede);
	line-height: var(--fs-lh-150);
	color: var(--fs-muted);
}

.fs-display {
	font-size: var(--fs-t-display);
	font-weight: var(--fs-weight-bold);
	line-height: var(--fs-lh-120);
	letter-spacing: var(--fs-track-display);
	max-inline-size: 20ch;
}

.fs-mono {
	font-family: var(--fs-font-mono);
	font-size: var(--fs-t-mono);
	letter-spacing: 0.02em;
}

.fs-small {
	font-size: var(--fs-t-small);
	color: var(--fs-muted);
}

/* ---------------------------------------------------------------------------
   LINKS + FOCUS
   Accent text uses the ink rung: --fs-rose at body size is 4.17:1 and fails AA.
   --------------------------------------------------------------------------- */

a {
	color: var(--fs-rose-ink);
	text-underline-offset: 0.2em;
	transition: color var(--fs-duration-fast) var(--fs-ease);
}

a:hover {
	color: var(--fs-rose);
}

/* Focus is never animated and never removed without a replacement. */
:focus-visible {
	outline: 2px solid var(--fs-focus);
	outline-offset: 2px;
	border-radius: var(--fs-radius-sm);
}

.fs-section--dark :focus-visible {
	outline-color: var(--fs-rose-lift);
}

/* ---------------------------------------------------------------------------
   LAYOUT PRIMITIVES
   --------------------------------------------------------------------------- */

.fs-container {
	width: 100%;
	max-inline-size: var(--fs-container);
	margin-inline: auto;
	padding-inline: var(--fs-gutter);
}

.fs-container--wide {
	max-inline-size: var(--fs-container-wide);
}

.fs-container--text {
	max-inline-size: var(--fs-container-text);
}

.fs-section {
	padding-block: var(--fs-section-base);
}

.fs-section--compact {
	padding-block: var(--fs-section-compact);
}

.fs-section--feature {
	padding-block: var(--fs-section-feature);
}

.fs-section--alt {
	background: var(--fs-bg-alt);
}

.fs-main {
	display: block;
	min-block-size: 50vh;
}

.fs-content {
	padding-block: var(--fs-section-base);
}

/* Grid: 12 columns, fluid gutter. */
.fs-grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	gap: var(--fs-space-md);
}

@media (max-width: 1023px) {
	.fs-grid {
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}
}

@media (max-width: 767px) {
	.fs-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ---------------------------------------------------------------------------
   SKIP LINK — first in tab order, visible the moment it receives focus.
   --------------------------------------------------------------------------- */

.fs-skip-link {
	position: absolute;
	inset-inline-start: -9999px;
	inset-block-start: 0;
	z-index: 100;
	padding: var(--fs-space-xs) var(--fs-space-sm);
	background: var(--fs-ink);
	color: var(--fs-white);
	border-radius: var(--fs-radius-sm);
	text-decoration: none;
}

.fs-skip-link:focus {
	inset-inline-start: var(--fs-space-sm);
	inset-block-start: var(--fs-space-sm);
	color: var(--fs-white);
}

/* ---------------------------------------------------------------------------
   REVEAL — driven by the shared observer in assets/js/reveal.js
   8px, not 40px: large reveal distances make a page feel like it is
   assembling itself under the visitor.
   --------------------------------------------------------------------------- */

.fs-reveal {
	opacity: 0;
	transform: translateY(8px);
	transition:
		opacity var(--fs-duration-slow) var(--fs-ease),
		transform var(--fs-duration-slow) var(--fs-ease);
}

.fs-reveal.is-visible {
	opacity: 1;
	transform: none;
}

/* Content must never depend on JS to become visible. */
.no-js .fs-reveal {
	opacity: 1;
	transform: none;
}

/* ---------------------------------------------------------------------------
   HEADER / FOOTER
   Moved to chrome.css on 2026-08-02. Page furniture grew dropdowns, a mega
   menu and a mobile panel, which is more than a reset sheet should carry.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   ENTRIES — minimal blog/archive styling so index.php is not unstyled.
   --------------------------------------------------------------------------- */

.fs-entry + .fs-entry {
	margin-block-start: var(--fs-space-lg);
	padding-block-start: var(--fs-space-lg);
	border-block-start: 1px solid var(--fs-border);
}

.fs-entry__media {
	margin: 0 0 var(--fs-space-sm);
}

.fs-entry__media img {
	border-radius: var(--fs-radius-card);
}

.pagination {
	margin-block-start: var(--fs-space-lg);
}

.pagination .page-numbers {
	margin-inline-end: var(--fs-space-xs);
}

/* ---------------------------------------------------------------------------
   RTL — English-only at launch, but the hooks are here so Arabic is a
   translation job rather than a rewrite.
   --------------------------------------------------------------------------- */

[dir="rtl"] .fs-btn__arrow {
	scale: -1 1;
}

/* ---------------------------------------------------------------------------
   REDUCED MOTION
   The contract: movement is removed, information never is.
   --------------------------------------------------------------------------- */

@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;
	}

	.fs-reveal {
		opacity: 1;
		transform: none;
	}
}
