/*
 * The Destination File — base layer: fonts, reset, document, article rhythm.
 *
 * Body text is set FIRST and everything else calibrates against it. Its four
 * properties — family, size, leading, measure — determine the rest of the system.
 *
 * @package The_Destination_File
 */

/* ---------------------------------------------------------------------------
 * FONT DELIVERY — self-hosted, never an external request (§18 item 16, D-026)
 *
 * Four variable files, two families (D-059). Newsreader's roman carries both the
 * weight and the optical-size axes, so a large headline draws with finer, lighter
 * forms than the same face at text size; its italic is weight-only. Public Sans
 * ships roman and italic. Each face's SIL Open Font Licence sits beside its files in
 * assets/fonts/. The two romans are preloaded (functions.php); the italics wait for
 * first use. `font-display: swap` keeps text visible while a face is still arriving.
 *
 * The Latin subset covers U+0000–00FF plus typographic punctuation: every Spanish
 * place name the guides use — Nayarit, Bucerías, Sayulita — is inside it.
 * ------------------------------------------------------------------------ */

@font-face {
	font-family: 'Newsreader';
	src: url( '../fonts/newsreader-variable.woff2' ) format( 'woff2' );
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Newsreader';
	src: url( '../fonts/newsreader-italic-variable.woff2' ) format( 'woff2' );
	font-weight: 200 800;
	font-style: italic;
	font-display: swap;
}

@font-face {
	font-family: 'Public Sans';
	src: url( '../fonts/public-sans-variable.woff2' ) format( 'woff2' );
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Public Sans';
	src: url( '../fonts/public-sans-italic-variable.woff2' ) format( 'woff2' );
	font-weight: 100 900;
	font-style: italic;
	font-display: swap;
}

/* ---------------------------------------------------------------------------
 * RESET — only what earns its place
 * ------------------------------------------------------------------------ */

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

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd, ol, ul {
	margin: 0;
}

/*
 * Interface lists only — nav, cards, rails, breadcrumbs, filters — which all carry
 * a `tdf-` class. NOT a bare `ul[class]`: Gutenberg stamps every editorial list
 * `wp-block-list`, so the bare form stripped bullets, numbering and indent from
 * article content on every page (measured on wp-env 2026-09-12). Guarded by D-047.
 */
ol[class^="tdf-"],
ul[class^="tdf-"] {
	padding: 0;
	list-style: none;
}

img,
picture,
video {
	display: block;
	max-width: 100%;
}

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

/* ---------------------------------------------------------------------------
 * DOCUMENT
 *
 * The body is set in Public Sans (Luis's approval, 2026-09-13): a clean, open sans
 * for long reading, with Newsreader reserved for the voice of the publication —
 * titles, headings, standfirsts and quotations.
 * ------------------------------------------------------------------------ */

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

body {
	margin: 0;
	background-color: var( --tdf-paper );
	color: var( --tdf-ink );
	font-family: var( --tdf-font-ui );
	font-size: var( --tdf-text-body );
	font-weight: var( --tdf-weight-body );
	line-height: var( --tdf-leading-body );
	font-synthesis-weight: none;   /* a faked bold is not a weight */
	font-synthesis-style: none;    /* a slanted roman is not an italic */
	font-feature-settings: 'kern' 1, 'liga' 1;
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

@media ( max-width: 47.99em ) {

	body {
		font-size: var( --tdf-text-body-mob );   /* 17px on phones — never below the 16px floor */
	}
}

/* ---------------------------------------------------------------------------
 * HEADINGS
 *
 * Hierarchy comes from SIZE and SPACE, not from weight escalation and never from
 * capitals. Space above exceeds space below, because a heading belongs to the
 * text that follows it. Headlines sit light; the optical-size axis does the
 * refining, so the weight never has to.
 * ------------------------------------------------------------------------ */

h1, h2, h3, h4 {
	font-family: var( --tdf-font-editorial );
	font-weight: var( --tdf-weight-heading );
	font-optical-sizing: auto;
	line-height: var( --tdf-leading-heading );
	letter-spacing: var( --tdf-tracking-heading );
	color: var( --tdf-ink-strong );
	text-wrap: balance;   /* stops a one-word orphan on the last line */
	hyphens: none;
}

h1 {
	font-size: var( --tdf-text-h1 );
	font-weight: var( --tdf-weight-display );
	line-height: var( --tdf-leading-display );
	letter-spacing: var( --tdf-tracking-display );
}

h2 { font-size: var( --tdf-text-h2 ); }

h3 {
	font-size: var( --tdf-text-h3 );
	font-weight: var( --tdf-weight-subhead );
}

h4 {
	font-size: var( --tdf-text-lede );
	font-weight: var( --tdf-weight-subhead );
}

/* ---------------------------------------------------------------------------
 * LINKS
 *
 * Underlined by default in body copy. Colour alone is not an affordance, and an
 * underline is the oldest and clearest signal a link has. The offset and
 * thickness stop it colliding with descenders.
 * ------------------------------------------------------------------------ */

a {
	color: var( --tdf-accent );
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	text-decoration-color: var( --tdf-accent-line );
	transition: color var( --tdf-duration ) var( --tdf-ease ),
	            text-decoration-color var( --tdf-duration ) var( --tdf-ease );
}

a:hover {
	color: var( --tdf-accent-deep );
	text-decoration-color: currentColor;
}

a:active {
	color: var( --tdf-accent-deep );
}

/* ---------------------------------------------------------------------------
 * FOCUS — visible on every interactive control, no exceptions
 *
 * :focus-visible so a mouse click does not leave a ring behind, but a keyboard
 * user always sees one. Removing the outline without replacing it is the single
 * most common accessibility regression in a redesign.
 * ------------------------------------------------------------------------ */

:where( a, button, input, select, textarea, summary, [tabindex] ):focus-visible {
	outline: var( --tdf-focus-width ) solid var( --tdf-focus-color );
	outline-offset: var( --tdf-focus-offset );
	border-radius: var( --tdf-radius );
}

/* Skip link: off-screen until focused, then anchored where it can be read. */
.tdf-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: var( --tdf-space-xs ) var( --tdf-space-sm );
	background-color: var( --tdf-accent );
	color: var( --tdf-on-accent );
	font-family: var( --tdf-font-ui );
	text-decoration: none;
}

.tdf-skip-link:focus {
	left: var( --tdf-space-sm );
	top: var( --tdf-space-sm );
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
	border: 0;
}

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

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

.tdf-main {
	display: block;
	padding-block: var( --tdf-section-pad );
}

/*
 * A main element that holds its own content directly, with no per-section
 * container inside it.
 *
 * .tdf-main sets vertical padding ONLY, so a template that neither nests a
 * .tdf-container nor carries this modifier runs edge-to-edge with no horizontal
 * gutter at all — on a phone the text touches the screen edge. Templates whose
 * sections manage their own width (the homepage) must NOT use this, or the gutter
 * applies twice.
 */
.tdf-main--contained {
	width: 100%;
	max-width: var( --tdf-container );
	margin-inline: auto;
	padding-inline: var( --tdf-gutter );
}

/*
 * A guide opens close under the masthead. The section padding above is right for a
 * page that begins with a heading, but a guide begins with its breadcrumb and its
 * photograph, and a hundred pixels of empty paper in front of them only delays the
 * article (Luis's brief, 2026-09-13).
 */
.tdf-main--guide {
	padding-block-start: var( --tdf-space-md );
}

/* ---------------------------------------------------------------------------
 * ARTICLE RHYTHM
 *
 * The measure is enforced on the CHILDREN, not on a wrapper, so a table can break
 * the measure deliberately while the prose never does. Every child starts on the
 * column's left edge — the same edge as the breadcrumb, the opening and the
 * sources — so the page has one left margin, not three.
 * ------------------------------------------------------------------------ */

.tdf-guide__content > * {
	max-width: var( --tdf-measure );
	margin-inline: 0;
}

/* Paragraph separation is SPACE, not indent — never both. 20px under an 18px body
 * set at 1.7: a full blank line would read as a list of separate statements, and
 * much less merges paragraphs on a dark ground (checked against the portfolio's
 * calmest dark article, THV, 2026-09-13). `pretty` keeps a lone word off a
 * paragraph's last line. */
.tdf-guide__content > p {
	margin-block: 0 calc( var( --tdf-space-sm ) + var( --tdf-space-3xs ) );
	text-wrap: pretty;
}

.tdf-guide__content > p + p {
	text-indent: 0;
}

/* A section opens on space and a short claret rule — one consistent accent detail
 * per section, drawn in CSS so the article text itself is untouched. */
.tdf-guide__content > h2 {
	position: relative;
	margin-block: var( --tdf-space-xl ) var( --tdf-space-sm );
	padding-block-start: var( --tdf-space-md );
}

.tdf-guide__content > h2::before {
	content: '';
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	width: var( --tdf-space-lg );
	border-block-start: var( --tdf-border-heavy ) solid var( --tdf-accent );
}

.tdf-guide__content > h2:first-child {
	margin-block-start: 0;
}

.tdf-guide__content > h3 {
	margin-block: var( --tdf-space-lg ) var( --tdf-space-xs );
}

/* A contents link lands with the heading a breath below the top edge, never under
 * anything. */
.tdf-guide__content :is( h2, h3 )[id] {
	scroll-margin-top: var( --tdf-space-lg );
}

/* Lists sit on the SAME measure as paragraphs so the text edges align; the item
 * text is indented by the marker only. The wide measure is for tables. */
.tdf-guide__content > ul,
.tdf-guide__content > ol {
	margin-block: 0 var( --tdf-space-md );
	padding-inline-start: var( --tdf-space-md );
	max-width: var( --tdf-measure );
}

.tdf-guide__content > ul li,
.tdf-guide__content > ol li {
	margin-block-end: var( --tdf-space-2xs );
}

/* Nested lists: indent one step from the parent item, no extra gap above. */
.tdf-guide__content li > ul,
.tdf-guide__content li > ol {
	margin-block: var( --tdf-space-2xs ) 0;
	padding-inline-start: var( --tdf-space-md );
}

/* In-article images are optional and sit on the reading column (D-056). Their box
 * is visible before the pixels land, in the appearance's own recessed tone — never
 * a white rectangle on a dark page. */
.tdf-guide__content > figure {
	max-width: var( --tdf-measure );
	margin-block: var( --tdf-space-xl );
}

.tdf-guide__content figure img {
	width: 100%;
	height: auto;
	border-radius: var( --tdf-radius-media );
	background-color: var( --tdf-paper-sunk );
}

.tdf-guide__content figcaption {
	max-width: var( --tdf-measure );
	margin-block-start: var( --tdf-space-2xs );
	font-family: var( --tdf-font-ui );
	font-size: var( --tdf-text-meta );
	line-height: var( --tdf-leading-tight );
	color: var( --tdf-ink-muted );
}

/* Emphasis: italic OR bold, never both, and used sparingly. Both families ship a
 * true italic, which is why font-synthesis is off above. */
.tdf-guide__content em { font-style: italic; }
.tdf-guide__content strong { font-weight: 650; }

/* ---------------------------------------------------------------------------
 * BLOCKQUOTE / PULL QUOTE
 *
 * The indent and the rule signal the quotation. Quotation marks on top of that
 * are redundant, and a giant decorative glyph is decoration pretending to be
 * typography. A quotation speaks in the publication's own voice: Newsreader.
 * ------------------------------------------------------------------------ */

.tdf-guide__content > blockquote {
	max-width: var( --tdf-measure-narrow );
	margin-block: var( --tdf-space-xl );
	padding-inline-start: var( --tdf-space-md );
	border-inline-start: var( --tdf-border-heavy ) solid var( --tdf-accent );
	font-family: var( --tdf-font-editorial );
	font-size: var( --tdf-text-lede );
	line-height: 1.45;
	color: var( --tdf-ink-strong );
}

.tdf-guide__content > blockquote cite {
	display: block;
	margin-block-start: var( --tdf-space-2xs );
	font-family: var( --tdf-font-ui );
	font-size: var( --tdf-text-meta );
	font-style: normal;
	color: var( --tdf-ink-muted );
}

/* ---------------------------------------------------------------------------
 * TABLES — data makes its own grid; borders are clutter
 * ------------------------------------------------------------------------ */

.tdf-guide__content table {
	width: 100%;
	max-width: var( --tdf-measure-wide );
	border-collapse: collapse;
	margin-block: var( --tdf-space-lg );
	font-family: var( --tdf-font-ui );
	font-size: var( --tdf-text-meta );
	font-variant-numeric: tabular-nums lining-nums;
}

.tdf-guide__content th {
	text-align: start;
	font-weight: 600;
	border-block-end: var( --tdf-border ) solid var( --tdf-rule-strong );
}

.tdf-guide__content th,
.tdf-guide__content td {
	padding: var( --tdf-space-2xs ) var( --tdf-space-sm );
	border-block-end: var( --tdf-border ) solid var( --tdf-rule );
}

/* A wide table scrolls in its own box rather than making the PAGE scroll
 * sideways — a horizontally scrolling document is a layout failure. */
.tdf-table-scroll {
	overflow-x: auto;
	max-width: 100%;
}

hr {
	max-width: var( --tdf-measure );
	margin: var( --tdf-space-xl ) 0;
	border: 0;
	border-block-start: var( --tdf-border ) solid var( --tdf-rule-strong );
}
