/**
 * Semantic tokens — Victoria Soncini (CSS Custom Properties layer).
 *
 * Complements theme.json: every value references a WordPress preset,
 * no hard-coded fallbacks (tokens-only: zero hex/px/font values here).
 * Single mode: one palette, no OS-driven remap.
 * Palette values come from the Figma UI kit (see docs/registro-frontend.md [T7]).
 */

:root {
	/* --- Color: semantic layer --- */
	--color-ink: var(--wp--preset--color--ink);
	--color-paper: var(--wp--preset--color--paper);
	--color-accent: var(--wp--preset--color--accent);
	/* The brand pink, and the one Figma calls `accent/primary`. It was in
	 * this project for a long time only as a hex baked into the SVG assets
	 * — wordmark, logo, both hero backgrounds, the circle — with nothing in
	 * the palette behind it, so any component that needed the brand pink in
	 * CSS had no token to reach for. Now it has one. On `--color-ink` it
	 * measures 8.26:1, so it carries 14px label text without help. */
	--color-accent-primary: var(--wp--preset--color--accent-primary);
	/* Sistema 01: `--color-accent-primary-strong` y
	 * `--color-accent-secondary-strong` eliminados (0 usos en código);
	 * los presets de theme.json quedan intactos (anclan Figma). */
	--color-accent-secondary: var(--wp--preset--color--accent-secondary);
	--color-highlight: var(--wp--preset--color--highlight);
	--color-highlight-celeste: var(--wp--preset--color--highlight-celeste);
	/* Sistema 01: `--color-highlight-celeste-soft` (semántico) e hilos
	 * `--color-chip-*` eliminados: los chips leen el preset directo en
	 * site.css (paridad odd/even ya expresada por el selector). */
	/* --- Nav: the item for the page you are on ---
	 * A different job from the chip tier that happens to share the colour:
	 * a chip labels a case study, this marks where you are. Named for that
	 * job rather than aliasing the chip into it, so the two can diverge
	 * without one silently changing the other.
	 *
	 * `--wp--preset--color--highlight` (#FBE2EE) with `--color-ink`
	 * measures 14.81:1, so the label keeps far more than the 4.5:1 it needs.
	 * The deep accent pinks do not work here and were never candidates:
	 * `--color-accent` measures 2.60:1 against the label colour and fails,
	 * and `--color-accent-soft` would pass at 7.19:1 but is a different
	 * pink than the one the chips use. */
	--color-nav-active-bg: var(--wp--preset--color--highlight);
	/* Dark-mode seed roles (only consumed under [data-theme="dark"]
	 * below; inert in light). */
	--color-accent-soft: var(--wp--preset--color--accent-soft);
	--color-muted-soft: var(--wp--preset--color--muted-soft);
	--color-text: var(--color-ink);
	--color-text-muted: var(--wp--preset--color--muted);
	--color-border: var(--wp--preset--color--line);
	--color-surface: var(--color-paper);
	--color-subtle: var(--wp--preset--color--subtle);
	--color-background: var(--color-paper);



	/* --- Typography: scale mirrors theme.json fontSizes.
	 * H1–H4 fluidos con clamp (máximo = valor Figma vía preset, mínimo =
	 * paso inferior); H5, body y label fijos (preferencia de usuario). --- */
	--font-size-h1: clamp(2.5rem, 1rem + 5vw, var(--wp--preset--font-size--h-1));
	--font-size-h2: clamp(2rem, 1rem + 2.8vw, var(--wp--preset--font-size--h-2));
	--font-size-h3: clamp(1.5rem, 1rem + 1.1vw, var(--wp--preset--font-size--h-3));
	--font-size-h4: clamp(1.25rem, 1rem + 0.6vw, var(--wp--preset--font-size--h-4));
	--font-size-h5: var(--wp--preset--font-size--h-5);
	--font-size-body: var(--wp--preset--font-size--body);
	--font-size-body-lg: var(--wp--preset--font-size--body-lg);
	--font-size-label: var(--wp--preset--font-size--label);

	/* --- Line-height: 150% of each font size, snapped to the 8px grid
	 * (4px fallback when the nearest multiple of 8 is more than 2px away).
	 * Fixed sizes use rem for exact px on a 16px root.
	 * Full table in docs/registro-frontend.md.
	 *
	 * H1–H4 (niveles fluidos): el line-height también interpola, con dos
	 * anclajes — 360px → mínimo (tamaño mobile × ratio) y 1024px → máximo
	 * (el valor Figma de desktop). Como el clamp satura justo en el
	 * breakpoint, de 1024px para arriba el valor computado es idéntico
	 * al que había antes (86/84/48/36): el desktop no se toca, y abajo
	 * del breakpoint el interlineado acompaña al tamaño en vez de
	 * quedar inflado (H1 llegaba a 2.15 y H2 a 2.63 antes de este cambio).
	 * H5/body/body-lg/label no se tocan: su tamaño es fijo, así que la
	 * relación es la misma en todos los anchos. */
	/* 86px exactos de Figma: excepción documentada a la grilla 8/4. */
	--font-line-height-h1: clamp(2.5rem, calc(0.94rem + 6.93vw), 5.375rem);
	--font-line-height-h2: clamp(3rem, calc(1.78rem + 5.42vw), 5.25rem);
	--font-line-height-h3: clamp(2.25rem, calc(1.84rem + 1.81vw), 3rem);
	--font-line-height-h4: clamp(1.875rem, calc(1.67rem + 0.9vw), 2.25rem);
	--font-line-height-h5: 2rem;
	/* The one level of the size scale that had no partner. `--font-size-body-lg`
	 * (1.125rem) existed with nothing to pair it with, so the two places that
	 * use that size at a smaller breakpoint — the Work type chips under
	 * 1024px — had either to approximate with the body line-height or leave a
	 * 24px glyph on a 32px leading, which keeps the chip box at full height
	 * and defeats the point of shrinking it. 1.75rem is on the 8/4 grid and
	 * gives the 18px a 1.56 ratio. */
	--font-line-height-body-lg: 1.75rem;
	--font-line-height-body: 1.5rem;
	--font-line-height-label: 1.25rem;

	/* DM Serif Display only ships weight 400: serif levels stay 400
	 * to avoid faux-bold synthesis. */
	--font-weight-h1: 400;
	--font-weight-h2: 400;
	--font-weight-h3: 400;
	--font-weight-h5: 700;
	--font-weight-semibold: 500;
	/* Inter's regular. Needed by the first non-heading sans role: the button
	 * label, which Figma sets at 400. The h1–h4 tokens above happen to be
	 * 400 too, but they name a heading level, not a weight — borrowing one
	 * for a button would make the button's weight depend on a heading's
	 * future revision. */
	--font-weight-regular: 400;

	/* Tracking Figma (tight del título hero). En em para que sea
	 * proporcional al tamaño: −0.034em da los mismos −3px a 88px de
	 * desktop y se ajusta solo cuando el clamp achica la fuente. */
	--tracking-tight: -0.034em;

	--font-sans: var(--wp--preset--font-family--inter);
	--font-serif: var(--wp--preset--font-family--serif);

	/* --- Spacing (mirrors settings.spacing.spacingSizes) --- */
	--size-1: var(--wp--preset--spacing--1);
	--size-2: var(--wp--preset--spacing--2);
	--size-3: var(--wp--preset--spacing--3);
	--size-4: var(--wp--preset--spacing--4);
	--size-5: var(--wp--preset--spacing--5);
	--size-6: var(--wp--preset--spacing--6);
	--size-7: var(--wp--preset--spacing--7);
	--size-8: var(--wp--preset--spacing--8);
	--size-9: var(--wp--preset--spacing--9);
	/* Sistema 01: sin --size-10 (era 7.5rem crudo de un solo uso; el gap
	 * que lo leía lleva el valor inline documentado). Escala 10→9 pasos. */

	/* --- Motion: shared durations + easing (CSS transitions and
	 * JS-driven effects use these; reveals use the ease-out token) --- */
	--motion-duration-fast: 0.25s;
	--motion-duration-med: 0.7s;
	/* A deliberate, drawn transition — the divider growing across the
	 * page. Above `med` but still a transition, not a loop, so it sits on
	 * this scale rather than the loop one. Same ease-out as everything
	 * else: the draw is slow, not differently shaped. */
	--motion-duration-slow: 1.1s;
	--motion-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
	/* Loops never ease: any acceleration reads as a stutter. */
	--motion-ease-linear: linear;
	--motion-reveal-distance: 1.5rem;
	--motion-reveal-stagger: 0.12s;
	/* Sistema 01: rungs del slider en `#expertise` (site.css). El script
	 * los lee por getComputedStyle sobre la sección, así que el scope
	 * propio resuelve igual. */

	/* --- Borders & outlines (single source for hairlines) --- */
	--size-border: 0.0625rem;
	--size-outline: 0.125rem;

	/* Sistema 01: `--size-toggle-bar` vive en `.header` (site.css):
	 * solo lo lee el hamburger. */
	/* --- Layout: containers --- */
	--size-content: 80rem;
	--size-wide: 90rem;
	/* Site frame on large desktop: 90% of the viewport, never wider than
	 * `--size-wide`. Read by `.container` from 1280px up; the featured media
	 * derives from it minus the container padding and the card band. */
	--size-row-wide: min(90vw, var(--size-wide));
	/* Sistema 01: `--size-bg-scale-mobile` vive en `.hero__bg` (site.css). */
	--size-reading: 45rem;
	--size-hero-copy: 47.5rem;
	--size-expertise-card: 25rem;
	--size-featured-media: 50rem;
	--size-featured-card: 39rem;
	/* Sistema 01: compact/band/overlap viven en `.featured` (site.css):
	 * solo los consume el Home. */

	/* --- Featured overlap: card offset over the media --- */
	--size-featured-card-offset: 2.5rem;

	/* --- Mobile: the card breaking out of the media grid ---
	 * Below 1024px the media gives up one step of width to a bigger margin
	 * on one side, and the card goes into that margin and over the image.
	 * Three values, one per decision.
	 *
	 * `overlap` is how far the card climbs onto the picture, measured from
	 * the image's bottom edge. 3.5rem is off the reference mock, where it
	 * measures 3.4rem; the desktop row uses its own token
	 * (`--size-overlap-panel`, 9rem) because it is a different job at a
	 * different scale, and `--size-featured-card-offset` (2.5rem) is the
	 * absolute nudge the Home card uses, not this. 3.5 is not on the
	 * spacing scale, so it gets its own token rather than a round number.
	 *
	 * `card-share` is how much of the image the card spans, as a ratio
	 * because it has to multiply a length (`calc((100% - inset) * 0.8)`)
	 * and CSS cannot multiply a length by a percentage. On the mock it
	 * measures 680/840 = 81%, so 0.8 is the mock's number, not a guess. */
	--size-media-card-overlap: 3.5rem;
	/* Ceiling for the media height on short viewports. A 4:5 portrait at
	 * 1023px wide measured 1239px — taller than the viewport itself. The
	 * cap is on the height because that is what the constraint is about,
	 * and it is applied through the 4/5 ratio as a max-width on the media,
	 * which is the only way to shorten the picture without cropping it or
	 * breaking its proportion. Viewport-relative, like the `100vh/vw`
	 * exceptions in AGENTS.md.
	 *
	 * `100vh` is the fallback and `100svh` the real value: on mobile the
	 * large viewport height is the screen with the browser chrome retracted,
	 * so a picture sized against `100vh` can end up taller than what the
	 * user can actually see once the address bar is back. Declared in this
	 * order — fallback first, then the `@supports` upgrade below — because
	 * a custom property cannot hold a fallback pair the way a property can,
	 * so the branch has to be explicit. */
	--size-featured-media-max-height: 100vh;

	/* --- Overlap: how much of a floating surface sits on top of the
	 * content behind it. Deliberately not named after a component: it
	 * describes the relationship between two surfaces, not a card. Any
	 * panel that overlaps media or text reads this token, so the inset
	 * stays identical across scenarios instead of being re-invented per
	 * component. `--size-featured-card-offset` above is a different job —
	 * a fixed nudge off the top edge, not a bottom-anchored overlap. */
	--size-overlap-panel: 9rem;

	/* Sistema 01: condense range, wordmark y toggle viven en `.header`
	 * (site.css): solo los lee la cabecera. */

	/* --- Radius (Sistema 01: lg eliminado, 0 usos; escala 7→6) --- */
	--size-radius-pill: 999px;
	--size-radius-full: 50%;
	--size-radius-xs: 0.25rem;
	--size-radius-sm: 0.375rem;
	--size-radius-md: 0.5rem;
	--size-radius-xl: 1rem;

	/* --- Shadows: a single working shadow (Sistema 01: sm/md eliminados,
	 * 0 usos reales — md solo vivía en un bloque comentado). --- */
	--shadow-lg: 0 1rem 3rem 0 rgba(22, 22, 24, 0.16);

	/* --- Z-index layers (0 = default, sin token) --- */
	--z-content: 1;
	--z-header: 10;
	--z-skip: 100;
}

/* --- Dark mode seed (inert architecture, Prompt [U]).
 * Applies only under [data-theme="dark"], which no markup sets and no
 * toggle ships: light renders pixel-identical. Neutrals invert wholesale
 * (paper<->ink), roles remap to the seed presets, and self-contained
 * surfaces stay put: pastels keep ink text (14.8+ AA), line borders stay
 * visible on ink (12.66), ink-based shadows stay decorative. Header
 * backdrop (color-mix over --color-paper) follows the inversion alone.
 * Verified dark pairs: text 17.01, muted-soft 7.21, accent-soft 7.19
 * (accent/strong would fail on ink: 2.60/3.48, hence the remap). */
:root[data-theme="dark"] {
	--color-ink: var(--wp--preset--color--paper);
	--color-paper: var(--wp--preset--color--ink);
	--color-background: var(--wp--preset--color--ink);
	--color-surface: var(--wp--preset--color--ink);
	--color-subtle: var(--wp--preset--color--ink);
	--color-text: var(--wp--preset--color--paper);
	--color-text-muted: var(--color-muted-soft);
	--color-accent: var(--color-accent-soft);
}

/* `100svh` for the mobile media ceiling, where the browser knows how much of
 * the viewport is genuinely visible with its own chrome retracted. Feature-
 * gated so the `100vh` declared in the `:root` above stays the value in
 * engines without it — the same progressive-enhancement shape the rest of
 * the token layer uses. */
@supports (height: 100svh) {
	:root {
		--size-featured-media-max-height: 100svh;
	}
}
