/**
 * Typographic scale, rhythm and layout primitives.
 *
 * The brand reads premium through negative space and restraint, so the
 * defaults here are deliberately generous and low-contrast in weight.
 */

body {
	background-color: var(--basaran-bg);
	color: var(--basaran-text);
	font-family: var(--basaran-font-body);
	font-size: 1rem;
	line-height: 1.7;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6,
.basaran-h1, .basaran-h2, .basaran-h3 {
	font-family: var(--basaran-font-heading);
	color: var(--basaran-heading);
	font-weight: 600;
	line-height: 1.18;
	letter-spacing: var(--basaran-tracking-heading);
	margin-block: 0 var(--basaran-space-2);
	text-wrap: balance;
}

h1, .basaran-h1 { font-size: clamp(2.25rem, 1.5rem + 3vw, 3.75rem); }
h2, .basaran-h2 { font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem); }
h3, .basaran-h3 { font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem); }
h4 { font-size: 1.25rem; }

p, li { text-wrap: pretty; }

p { margin-block: 0 var(--basaran-space-2); }

a {
	color: var(--basaran-link);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	transition: color var(--basaran-transition);
}

a:hover,
a:focus-visible {
	color: var(--basaran-link-hover);
}

/* Visible focus is an AA requirement and is easy to lose to theme resets. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--basaran-focus);
	outline-offset: 3px;
	border-radius: var(--basaran-radius);
}

/* Section eyebrow — uppercase, wide tracking, echoing the wordmark lockup. */
.basaran-eyebrow {
	display: inline-block;
	font-family: var(--basaran-font-heading);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--basaran-tracking-eyebrow);
	color: var(--basaran-olive-700);
	margin-block-end: var(--basaran-space-1);
}

/* Layout primitives ------------------------------------------------------- */

.basaran-container {
	width: 100%;
	max-width: var(--basaran-container);
	margin-inline: auto;
	padding-inline: var(--basaran-space-3);
}

.basaran-container--narrow { max-width: var(--basaran-container-narrow); }

.basaran-section {
	padding-block: var(--basaran-space-5);
}

.basaran-section--tight { padding-block: var(--basaran-space-4); }

.basaran-section--sand { background-color: var(--basaran-bg-muted); }
.basaran-section--alt { background-color: var(--basaran-bg-alt); }

/* Dark surfaces -----------------------------------------------------------
   Tokens are REDEFINED at the scope rather than overriding component by
   component. Components like `.basaran-lede` and `.basaran-differentiator__text`
   set their own colour from `--basaran-text-muted`; a plain `color` on the
   section is inherited, so those explicit rules won and the text rendered dark
   olive on Deep Forest — effectively invisible.

   Rebinding the tokens means anything dropped onto a dark surface gets correct
   colours automatically, including components written later. */

.basaran-section--forest,
.basaran-footer,
.basaran-consent {
	--basaran-text: var(--basaran-ivory);
	--basaran-text-muted: var(--basaran-sand);
	--basaran-heading: var(--basaran-ivory);
	--basaran-link: var(--basaran-sand);
	--basaran-link-hover: var(--basaran-ivory);
	--basaran-hairline: rgba(245, 241, 232, 0.16);
}

.basaran-section--forest {
	background-color: var(--basaran-bg-inverse);
	color: var(--basaran-text-inverse);
}

.basaran-section--forest :where(h1, h2, h3, h4, h5, h6) { color: var(--basaran-text-inverse); }
.basaran-section--forest .basaran-eyebrow { color: var(--basaran-sand); }
.basaran-section--forest a:not(.basaran-btn) { color: var(--basaran-sand); }

/* The `hidden` attribute must actually hide -------------------------------
   The browser default is `[hidden] { display: none }` at *zero* specificity, so
   any component rule that sets `display` beats it. `.basaran-card` sets
   `display: flex`, which meant the product filters set `item.hidden = true` and
   nothing disappeared — the filter bar looked completely broken.

   `!important` is the right tool here: `hidden` is a statement of intent from
   the markup and no layout rule should be able to contradict it. */
[hidden] {
	display: none !important;
}

/* Responsive safety net ---------------------------------------------------
   Tested at 360 / 768 / 1024 / 1440 (PRD Section 12). The 360 breakpoint is
   where these matter: a single unbreakable string or an unwrapped table is
   enough to make the whole page scroll sideways. */

html {
	/* `clip` rather than `hidden`: hidden on the root turns position:sticky
	   into position:static, which would break the sticky header. */
	overflow-x: clip;
}

/* Long unbroken strings — email addresses, spec codes, pasted URLs. */
.basaran-prose,
.basaran-footer__contact,
.basaran-card__excerpt,
.basaran-lede {
	overflow-wrap: anywhere;
}

/* Grid and flex children default to min-width:auto, which lets wide content
   push the track wider than its column instead of shrinking. */
.basaran-grid > *,
.basaran-header__inner > *,
.basaran-cta-band > * {
	min-width: 0;
}

/* Wide content scrolls inside its own box, never the page. */
.basaran-table-scroll {
	overflow-x: auto;
	max-width: 100%;
	/* The last table row intentionally has no bottom border, so without this the
	   spec table runs straight into the next heading and reads as truncated. */
	margin-block-end: var(--basaran-space-3);
	/* Momentum scrolling on iOS, and a visible focus ring since the region is
	   keyboard-reachable. */
	-webkit-overflow-scrolling: touch;
}

.basaran-table-scroll:focus-visible {
	outline: 2px solid var(--basaran-focus);
	outline-offset: 2px;
}

.basaran-grid {
	display: grid;
	gap: var(--basaran-space-3);
	grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}

.basaran-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

.basaran-stack > * + * { margin-block-start: var(--basaran-space-2); }

.basaran-lede {
	font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
	color: var(--basaran-text-muted);
	max-width: 62ch;
}

/* Media — explicit dimensions are set in PHP; this protects the aspect ratio. */
img, video {
	max-width: 100%;
	height: auto;
}

.basaran-media {
	display: block;
	overflow: hidden;
	background-color: var(--basaran-sand-100);
	border-radius: var(--basaran-radius);
}

.basaran-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Make the ratio boxes above actually hold their image.
 *
 * Every `__media` box sets an `aspect-ratio` and every one told its image
 * `height: 100%` — and none of them won. Elementor's reset ships
 * `.elementor img { height: auto }`, which is specificity (0,1,1), exactly the
 * same as `.basaran-card__media img`; its stylesheet is enqueued after the
 * theme's, so source order decided it. The image then laid out at its own
 * natural ratio inside a fixed-ratio box and left a strip of card background
 * beneath it — 40px under each 4:3 species photo in a 1:1 tile, measured.
 *
 * It read as intermittent because it is invisible whenever the asset ratio and
 * the box ratio coincide: the 640x480 product shots in a 4/3 box looked correct
 * while the 320x200 category thumbnails in the same box did not.
 *
 * The class is repeated to reach (0,2,1) and win on specificity instead of on
 * load order, which is the same technique the hero text cap in sections.css
 * uses and the reason neither needs `!important`. Listed explicitly rather than
 * as `[class*="__media"] img` so a new media box is a deliberate addition here.
 */
.basaran-media.basaran-media img,
.basaran-card__media.basaran-card__media img,
.basaran-species-card__media.basaran-species-card__media img,
.basaran-article-card__media.basaran-article-card__media img,
.basaran-product__media.basaran-product__media img,
.basaran-page__media.basaran-page__media img,
.basaran-thermowood__media.basaran-thermowood__media img,
.basaran-hero__media.basaran-hero__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Visually hidden, still announced.
   The bare `.screen-reader-text` is aliased deliberately: WordPress core markup
   emits it, and so does Elementor. Owning the rule here means a "hidden" label
   can never render as visible text because some other stylesheet was dequeued. */
.basaran-screen-reader-text,
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* …but a skip link must become visible when focused. */
.basaran-screen-reader-text:focus-visible,
.screen-reader-text:focus-visible {
	position: fixed;
	width: auto;
	height: auto;
	margin: 0;
	overflow: visible;
	clip-path: none;
}
