/**
 * SGP typography system — the single source of truth for type.
 *
 * One family (Geist Sans), seven content roles (H1–H4, P1–P3), two UI roles
 * (control, eyebrow) and four weights (400/500/600/700). Nothing else.
 *
 * Rules for anyone editing type after this:
 *  1. Never write a literal font-size, font-weight or letter-spacing in a component
 *     sheet. Use a `--sq-t-*` token, or the `.sq-t-*` class.
 *  2. Visual role and heading level are separate concerns. A card title is an <h3>
 *     because of where it sits in the document outline; it is `--sq-t-h4` because of
 *     how big it should look. Never pick a heading level to get a size.
 *  3. Long-form prose is never P3. Essential interface text is never below 14px.
 *
 * Load order matters: this sheet is enqueued before every component sheet, and the
 * legacy-alias block below re-points the older token vocabularies at these roles so
 * existing call sites land on the new scale without being rewritten one by one.
 */

/* ─── Roles ─────────────────────────────────────────────────────────────── */

:root {
	/* Family. `--wp--preset--font-family--*` come from theme.json; these are the
	   names component sheets should use. */
	--sq-font-sans: var(--wp--preset--font-family--sans, 'Geist Sans', 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
	--sq-font-mono: var(--wp--preset--font-family--mono, 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace);

	/* Size. Fluid roles interpolate between the two ends of the clamp; the browser
	   generates intermediate values, which is the only place a non-round size is
	   legitimate. */
	--sq-t-h1: clamp(2.5rem, 3.5vw + 1rem, 4rem);
	--sq-t-h2: clamp(2rem, 2vw + 1rem, 2.75rem);
	--sq-t-h3: clamp(1.5rem, 1vw + 1rem, 1.75rem);
	--sq-t-h4: clamp(1.125rem, 0.35vw + 1rem, 1.25rem);
	--sq-t-p1: clamp(1.0625rem, 0.25vw + 1rem, 1.125rem);
	--sq-t-p2: 1rem;
	--sq-t-p3: 0.875rem;
	--sq-t-control: 0.875rem;
	--sq-t-eyebrow: 0.75rem;

	/* Weight. Four, and only four. */
	--sq-w-regular: 400;
	--sq-w-medium: 500;
	--sq-w-semibold: 600;
	--sq-w-bold: 700;

	/* Leading. Unitless throughout so it scales with the element's own size. */
	--sq-lh-h1: 1.02;
	--sq-lh-h2: 1.08;
	--sq-lh-h3: 1.15;
	--sq-lh-h4: 1.3;
	--sq-lh-body: 1.6;
	--sq-lh-supporting: 1.5;
	--sq-lh-ui: 1.2;
	--sq-lh-eyebrow: 1.4;

	/* Tracking. Tightens as size grows; body and below sit at 0. */
	--sq-ls-h1: -0.035em;
	--sq-ls-h2: -0.03em;
	--sq-ls-h3: -0.02em;
	--sq-ls-h4: -0.01em;
	--sq-ls-body: 0;
	--sq-ls-eyebrow: 0.08em;

	/* Measure. 60–72 characters is the readable band.
	   Expressed in em, not ch: Geist's `0` glyph is much wider than its average
	   lowercase character, so 68ch measured out at 79 real characters. 35em lands on
	   ~68 characters and holds that count at every size in the scale. */
	--sq-measure: 35em;
}

/* ─── Legacy aliases ────────────────────────────────────────────────────── */

/*
 * Three token vocabularies predate this sheet and are referenced from roughly two
 * hundred call sites: theme.json's `--wp--custom--type--*`, the marketplace sheet's
 * `--sq-type-*` and the product sheet's `--sqpp-t-*`. WooCommerce adds a fourth via
 * its own preset sizes.
 *
 * Rather than rewrite every call site, each legacy name is re-pointed at the role it
 * should always have meant. The aliases are the migration surface: when a sheet stops
 * referencing one, its line here can go.
 */
:root {
	/* marketplace-system.css */
	--sq-type-h1: var(--sq-t-h1);
	--sq-type-h2: var(--sq-t-h2);
	--sq-type-h3: var(--sq-t-h3);
	--sq-type-h4: var(--sq-t-h4);
	--sq-type-p1: var(--sq-t-p1);
	--sq-type-p2: var(--sq-t-p2);
	--sq-type-p3: var(--sq-t-p3);
	--sq-type-p4: var(--sq-t-p3);

	/* product-detail.css */
	--sqpp-t-display: var(--sq-t-h1);
	--sqpp-t-section: var(--sq-t-h2);
	--sqpp-t-sub: var(--sq-t-h4);
	--sqpp-t-lede: var(--sq-t-p1);
	--sqpp-t-body: var(--sq-t-p2);
	--sqpp-t-small: var(--sq-t-p3);
	--sqpp-t-label: var(--sq-t-eyebrow);

	/* WooCommerce preset sizes. Pinned so cart/checkout/account inherit the scale
	   instead of Woo's own 13/16/42px ladder. */
	--wp--preset--font-size--small: var(--sq-t-p3);
	--wp--preset--font-size--normal: var(--sq-t-p2);
	--wp--preset--font-size--medium: var(--sq-t-p1);
	--wp--preset--font-size--large: var(--sq-t-h3);
	--wp--preset--font-size--x-large: var(--sq-t-h2);
}

/* ─── Family, rendering, and the anti-faux-bold rule ────────────────────── */

html {
	/* Never synthesise a weight or a slant. With a variable font every weight in
	   the 100–900 range is real, so a faux face can only mean a bug. */
	font-synthesis: none;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

body {
	font-family: var(--sq-font-sans);
	font-size: var(--sq-t-p2);
	font-weight: var(--sq-w-regular);
	line-height: var(--sq-lh-body);
	letter-spacing: var(--sq-ls-body);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

code, kbd, samp, pre, .sq-mono {
	font-family: var(--sq-font-mono);
	font-size: 0.9375em; /* mono runs optically large next to Geist Sans at the same px */
}

/* ─── Element defaults ──────────────────────────────────────────────────── */

h1, .sq-t-h1 {
	font-size: var(--sq-t-h1);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-h1);
	letter-spacing: var(--sq-ls-h1);
	text-wrap: balance;
}

h2, .sq-t-h2 {
	font-size: var(--sq-t-h2);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-h2);
	letter-spacing: var(--sq-ls-h2);
	text-wrap: balance;
}

h3, .sq-t-h3 {
	font-size: var(--sq-t-h3);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-h3);
	letter-spacing: var(--sq-ls-h3);
	text-wrap: balance;
}

h4, .sq-t-h4 {
	font-size: var(--sq-t-h4);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-h4);
	letter-spacing: var(--sq-ls-h4);
	text-wrap: balance;
}

/* H5/H6 exist for outline correctness, not for a smaller look. They render at the
   supporting and eyebrow roles so a deep outline stays legible. */
h5, .sq-t-h5 {
	font-size: var(--sq-t-p3);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-eyebrow);
	letter-spacing: var(--sq-ls-body);
}

h6, .sq-t-h6 {
	font-size: var(--sq-t-eyebrow);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-eyebrow);
	letter-spacing: var(--sq-ls-eyebrow);
}

p, li, dd, dt, blockquote, figcaption {
	text-wrap: pretty;
}

/*
 * <small> and friends default to 0.8333em, which lands on 13.33px and reintroduces a
 * size the system does not have. Pin them to the supporting role.
 */
small, .sq-small {
	font-size: var(--sq-t-p3);
	line-height: var(--sq-lh-supporting);
}

sub, sup {
	font-size: 0.75em; /* relative on purpose: a superscript tracks its parent's size */
	line-height: 0;
}

/* Screen-reader-only text is clipped, so it should never introduce a size of its own. */
.sgp-visually-hidden,
.screen-reader-text {
	font-size: inherit;
}

/*
 * Form controls do not inherit type from the document by default: a bare <button>
 * renders at the UA's 13.33px/normal, which is both below the 14px interface floor
 * and a size the system does not contain.
 *
 * Text inputs sit at the body role rather than the control role on purpose — iOS
 * zooms the viewport when a focused input is under 16px.
 */
button,
[type='button'],
[type='submit'],
[type='reset'],
.wp-element-button {
	font-family: var(--sq-font-sans);
	font-size: var(--sq-t-control);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-ui);
	letter-spacing: var(--sq-ls-body);
}

input,
select,
textarea,
optgroup {
	font-family: var(--sq-font-sans);
	font-size: var(--sq-t-p2);
	font-weight: var(--sq-w-regular);
	line-height: var(--sq-lh-body);
	letter-spacing: var(--sq-ls-body);
}

::placeholder {
	font-size: inherit;
	letter-spacing: inherit;
}

label,
legend {
	font-size: var(--sq-t-p3);
	line-height: var(--sq-lh-supporting);
}

/* ─── Content roles ─────────────────────────────────────────────────────── */

.sq-t-p1 {
	font-size: var(--sq-t-p1);
	font-weight: var(--sq-w-regular);
	line-height: var(--sq-lh-body);
	letter-spacing: var(--sq-ls-body);
	text-wrap: pretty;
}

.sq-t-p2 {
	font-size: var(--sq-t-p2);
	font-weight: var(--sq-w-regular);
	line-height: var(--sq-lh-body);
	letter-spacing: var(--sq-ls-body);
	text-wrap: pretty;
}

.sq-t-p3 {
	font-size: var(--sq-t-p3);
	font-weight: var(--sq-w-regular);
	line-height: var(--sq-lh-supporting);
	letter-spacing: var(--sq-ls-body);
}

/* ─── UI roles ──────────────────────────────────────────────────────────── */

.sq-t-control {
	font-size: var(--sq-t-control);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-ui);
	letter-spacing: var(--sq-ls-body);
}

.sq-t-eyebrow {
	font-size: var(--sq-t-eyebrow);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-eyebrow);
	letter-spacing: var(--sq-ls-eyebrow);
}

/*
 * Numerics. Tabular figures so a column of prices, ratings or counts aligns on the
 * decimal and does not reflow as digits change.
 */
.sq-t-num,
.sgp-card__price,
.sgp-price,
.woocommerce-Price-amount,
.sq-price {
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum' 1;
	font-weight: var(--sq-w-semibold);
}

/* ─── Prose ─────────────────────────────────────────────────────────────── */

/*
 * The article template's reading setting was the one part of the old system worth
 * keeping. It maps onto P1 at a 1.75 leading — close to the 18px/31.5px it measured
 * before — and holds a 60–72 character measure.
 */
.sq-prose {
	font-size: var(--sq-t-p1);
	font-weight: var(--sq-w-regular);
	line-height: 1.75;
	letter-spacing: var(--sq-ls-body);
}

.sq-prose > p,
.sq-prose > ul,
.sq-prose > ol,
.sq-prose > blockquote {
	max-width: var(--sq-measure);
	text-wrap: pretty;
}

/* Prose is never supporting-sized, whatever a nested rule tries. */
.sq-prose p,
.sq-prose li {
	font-size: inherit;
}

/* ─── Guard rails ───────────────────────────────────────────────────────── */

/*
 * Third-party product copy — vendor descriptions, imported changelogs, Elementor
 * output — arrives with its own inline font stacks and sizes. It may keep its
 * structure; it may not introduce a family or an arbitrary size.
 *
 * `font: inherit` on the family alone (rather than blanket !important on size) keeps
 * legitimate emphasis and headings intact inside imported markup.
 */
.sq-prose [style*='font-family'],
.sq-vendor-copy [style*='font-family'],
.sgp-imported [style*='font-family'],
.entry-content [style*='font-family'] {
	font-family: var(--sq-font-sans) !important;
}

.sq-prose font[face],
.sq-vendor-copy font[face],
.sgp-imported font[face],
.entry-content font[face] {
	font-family: var(--sq-font-sans) !important;
}

/*
 * Imported copy is floored at the body role and capped at H3, so a vendor cannot
 * ship 9px legal text or a 96px shout inside a product description.
 */
.sq-prose [style*='font-size'],
.sq-vendor-copy [style*='font-size'],
.sgp-imported [style*='font-size'],
.entry-content [style*='font-size'] {
	font-size: clamp(var(--sq-t-p2), 1em, var(--sq-t-h3)) !important;
}

/*
 * WooCommerce's block CSS sets its product grid to a 12px base, which drags the product
 * title and the add-to-cart button below the 14px interface floor. A product title and
 * a buy button are the two things on that grid that must not be small.
 *
 * The selectors mirror Woo's own specificity rather than reaching for !important.
 */
.wc-block-grid__product {
	/* The body role, not the supporting one: Woo sizes several children at 0.875em, and
	   anchoring the grid at 16px makes those land exactly on the 14px floor instead of
	   an off-scale 12.25px. */
	font-size: var(--sq-t-p2);
}

.wc-block-grid__product .wc-block-grid__product-title {
	font-size: var(--sq-t-p2);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-h4);
}

.wc-block-grid__product .wc-block-grid__product-price {
	font-size: var(--sq-t-p3);
	font-variant-numeric: tabular-nums;
	font-weight: var(--sq-w-semibold);
}

.wc-block-grid__product-add-to-cart.wp-block-button .wp-block-button__link,
.wc-block-grid__product .wp-block-button__link {
	font-size: var(--sq-t-control);
	font-weight: var(--sq-w-semibold);
	line-height: var(--sq-lh-ui);
}

/* ─── Accessibility ─────────────────────────────────────────────────────── */

/*
 * WCAG 1.4.12 text spacing. Users overriding these must not clip content, so anything
 * that sets a fixed height around text is asked to grow instead. Kept narrow: only
 * the containers that were found to clip under the override.
 */
@media (prefers-reduced-motion: no-preference) {
	.sq-t-h1, .sq-t-h2, h1, h2 { }
}

@supports (text-wrap: balance) {
	/* Balance only helps short display lines; on a long heading it costs more than it
	   gains, so it is dropped past a few lines' worth of text. */
	h1, h2, h3, h4 { text-wrap: balance; }
}

/* Respect the user's own font size: every role is rem- or em-based, so a 200% zoom
   or a larger default size scales the whole system. Nothing here is px. */
