/*
Theme Name: Batavia
Theme URI: https://hairil.com/batavia
Author: Hairil
Author URI: https://hairil.com
Description: A precise block theme for a personal site: home page, notes, selected work and a rate card, built entirely from core blocks. IBM Plex Sans and Plex Mono are self-hosted, the palette reads like ink on paper, and dark mode follows the visitor's system preference. Your name, contact details and social profiles are entered once under Appearance and read by every pattern that mentions them. No custom post types, no external requests.
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 7.4
Version: 1.5.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: batavia
Tags: accessibility-ready, block-patterns, block-styles, blog, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, full-width-template, grid-layout, one-column, portfolio, sticky-post, template-editing, threaded-comments, translation-ready, wide-blocks

Batavia is distributed under the terms of the GNU GPL v2 or later.
Bundled font files are licensed separately under the SIL Open Font License 1.1;
see assets/fonts/LICENSE-IBM-Plex.txt and the Credits section of readme.txt.
*/

/*
 * Batavia keeps nearly all styling in theme.json so users can override it from
 * the Styles interface. This file holds only what theme.json cannot express:
 * pseudo-elements, focus behaviour, and the custom block styles registered in
 * functions.php. Dark mode lives in assets/css/color-scheme.css.
 */

/* -------------------------------------------------------------------------
 * 1. Skip link
 * WordPress 7.0+ inserts the skip link server-side in _block_template_add_skip_link(),
 * but only when the template contains a MAIN element -- every Batavia template
 * therefore wraps its content in a <main> group. Core ships its own skip-link
 * stylesheet whose load order relative to the theme's is not guaranteed, so the
 * :root prefix below raises specificity to (0,4,0) and wins either way.
 * ---------------------------------------------------------------------- */

:root .skip-link.screen-reader-text {
	background-color: var(--wp--preset--color--ink);
	border: 0;
	border-radius: 0;
	box-shadow: none;
	clip-path: inset(50%);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	height: 1px;
	inset-inline-start: -9999px;
	letter-spacing: 0.04em;
	line-height: normal;
	margin: 0;
	overflow: hidden;
	padding: 0.75rem 1.25rem;
	position: absolute;
	text-decoration: none;
	width: 1px;
	z-index: 100000;
}

:root .skip-link.screen-reader-text:focus {
	clip-path: none;
	height: auto;
	inset-inline-start: var(--wp--preset--spacing--20);
	top: var(--wp--preset--spacing--20);
	width: auto;
}

/* -------------------------------------------------------------------------
 * 2. Focus
 * A single, unmistakable focus ring. Uses :focus-visible so pointer clicks
 * stay quiet, with a :focus fallback for browsers that lack support.
 * ---------------------------------------------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
	outline: none;
}

/* -------------------------------------------------------------------------
 * 3. Global refinements
 * ---------------------------------------------------------------------- */

/* Batavia is built on a sharp grid; nothing is rounded by default. */
.wp-block-image img,
.wp-block-post-featured-image img,
.wp-block-cover {
	border-radius: 0;
}

/* Mono text is used for figures and dates, so keep digits on a fixed pitch. */
.wp-block-post-date,
.wp-block-query-pagination,
.is-style-batavia-label,
.is-style-batavia-figure {
	font-variant-numeric: tabular-nums;
}

/* Headings read as spec headings, not marketing headlines. */
h1, h2, h3,
.wp-block-post-title,
.wp-block-site-title {
	text-wrap: balance;
}

/* Long identifiers (package names, class names) should never overflow. */
.wp-block-code,
.wp-block-preformatted {
	overflow-x: auto;
}

/*
 * core/template-part carries no spacing support of its own, so header and
 * footer cannot be told to skip the root layout's blockGap directly. That
 * gap is set with :where(), specificity zero, so any ordinary selector
 * overrides it -- here, back to each template part supplying its own
 * padding rather than stacking a second gap on top.
 */
.wp-block-template-part {
	margin-block-start: 0;
}

/*
 * Visually hidden, still announced. Used for the heading that gives the blog
 * index a level-one heading without repeating it on screen.
 */
.screen-reader-text {
	border: 0;
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	white-space: nowrap;
	width: 1px;
}

/*
 * Core's outline button style hard-codes a 2px border and its own padding.
 * Batavia keeps every control on the same 1px hairline grid, and states the
 * hover and focus colours explicitly so they do not depend on load order.
 */
.wp-block-button.is-style-outline > .wp-block-button__link {
	background-color: transparent;
	border-width: 1px;
	color: var(--wp--preset--color--ink);
	padding: 0.75rem 1.25rem;
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover,
.wp-block-button.is-style-outline > .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
}

/* -------------------------------------------------------------------------
 * 4. Custom block styles
 * Registered in functions.php via register_block_style().
 * ---------------------------------------------------------------------- */

/* 4.1 Spec label -- a mono micro-heading trailed by a hairline rule. */
.is-style-batavia-label {
	align-items: center;
	color: var(--wp--preset--color--muted);
	display: flex;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	gap: 0.875rem;
	letter-spacing: 0.1em;
	line-height: 1.4;
	text-transform: uppercase;
}

.is-style-batavia-label::after {
	background-color: var(--wp--preset--color--rule);
	content: "";
	flex: 1 1 auto;
	height: 1px;
	min-width: 2rem;
}

/* 4.2 Panel -- a hairline-boxed group, the theme's default container. */
.is-style-batavia-panel {
	border: 1px solid var(--wp--preset--color--rule);
	padding: var(--wp--preset--spacing--40);
}

/* 4.3 Timeline -- a ruled rail with a tick against each direct child. */
.is-style-batavia-timeline {
	border-inline-start: 1px solid var(--wp--preset--color--rule);
	padding-inline-start: var(--wp--preset--spacing--40);
}

.is-style-batavia-timeline > * {
	position: relative;
}

.is-style-batavia-timeline > *::before {
	background-color: var(--wp--preset--color--accent);
	content: "";
	height: 1px;
	inset-inline-start: calc(-1 * var(--wp--preset--spacing--40) - 1px);
	position: absolute;
	top: 0.6em;
	width: calc(var(--wp--preset--spacing--20) + 1px);
}

/*
 * 4.3.1 Company mark -- a circle that holds either a logo photo or initials,
 * the same shape as a profile picture. Fixed against flex shrinking so a
 * long job title cannot squash it.
 */
.is-style-batavia-mark {
	align-items: center;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 50%;
	display: flex;
	flex: 0 0 auto;
	height: 4.5rem;
	justify-content: center;
	overflow: hidden;
	width: 4.5rem;
}

.is-style-batavia-mark > * {
	color: var(--wp--preset--color--muted);
	margin: 0;
}

/* A logo dropped in place of the initials fills the circle, cropping to fit. */
.is-style-batavia-mark img {
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/*
 * 4.3.2 Article entry -- a thumbnail beside a column of text.
 * A grid, not a flex row: flex only reserves the thumbnail's column when a
 * post actually has one, so a post without a featured image had its text
 * column start flush against the left edge instead of lining up with every
 * other entry's title. Grid's empty first track keeps that column reserved
 * either way. Collapses to one column under 640px, where there is no room
 * for a fixed-width thumbnail beside a readable line of text.
 *
 * `body` is not decoration: WordPress's own layout CSS sets `display: flex`
 * on `body .is-layout-flex`, at specificity (0,1,1) -- one point ahead of a
 * bare class selector -- so overriding `display` here needs the same shape
 * to actually win rather than silently losing to a same-specificity rule
 * that merely loads later.
 */
body .is-style-batavia-entry {
	display: grid;
	grid-template-columns: 12rem 1fr;
}

.is-style-batavia-entry > .wp-block-group {
	grid-column: 2;
	min-width: 0;
}

.is-style-batavia-entry > .wp-block-post-featured-image {
	grid-column: 1;
	margin-block: 0;
}

.is-style-batavia-entry > .wp-block-post-featured-image img {
	width: 100%;
}

@media (max-width: 640px) {
	body .is-style-batavia-entry {
		grid-template-columns: 1fr;
	}

	.is-style-batavia-entry > .wp-block-group,
	.is-style-batavia-entry > .wp-block-post-featured-image {
		grid-column: 1;
	}
}

/*
 * 4.3.3 Project card -- a screenshot with a rule under it that shifts to
 * Accent on hover, so the whole card reads as interactive without a shadow
 * or a zoom. The rule lives on the image rather than the card, so hovering
 * the title -- also a link, to the same post -- highlights it too.
 */
.is-style-batavia-project .wp-block-post-featured-image {
	border-bottom: 1px solid var(--wp--preset--color--rule);
	margin-block-end: 0;
	transition: border-color 150ms ease;
}

.is-style-batavia-project:hover .wp-block-post-featured-image,
.is-style-batavia-project:focus-within .wp-block-post-featured-image {
	border-color: var(--wp--preset--color--accent);
}

/*
 * 4.3.4 Featured image placeholder -- a diagonal hairline fill standing in
 * for a post's missing photo, from batavia_post_featured_image_placeholder()
 * in inc/media.php. Kept to the same rule and surface colours as everything
 * else, so an empty slot reads as deliberate rather than broken.
 */
.batavia-featured-image-placeholder {
	background-color: var(--wp--preset--color--surface);
	background-image: repeating-linear-gradient(
		135deg,
		var(--wp--preset--color--rule) 0,
		var(--wp--preset--color--rule) 1px,
		transparent 1px,
		transparent 10px
	);
	border: 1px solid var(--wp--preset--color--rule);
	display: block;
	width: 100%;
}

/* 4.4 Ruled list -- entries separated by hairlines, no bullets. */
.is-style-batavia-ruled {
	list-style: none;
	margin-inline-start: 0;
	padding-inline-start: 0;
}

.is-style-batavia-ruled li {
	border-bottom: 1px solid var(--wp--preset--color--rule);
	padding-bottom: 0.5rem;
	padding-top: 0.5rem;
}

.is-style-batavia-ruled li:last-child {
	border-bottom: 0;
}

/* The same treatment on a Details block, so a run of questions reads as a list. */
.wp-block-details.is-style-batavia-ruled {
	border-bottom: 1px solid var(--wp--preset--color--rule);
	padding-bottom: var(--wp--preset--spacing--20);
}

.wp-block-details.is-style-batavia-ruled summary {
	cursor: pointer;
	font-weight: 500;
}

/* 4.5 Mono list -- for tech-stack columns and spec sheets. */
.is-style-batavia-mono {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
	line-height: 2;
	list-style: none;
	margin-inline-start: 0;
	padding-inline-start: 0;
}

/* 4.6 Dotted rule. */
.wp-block-separator.is-style-batavia-dotted {
	background: none;
	border: 0;
	border-top: 1px dashed currentColor;
	height: 0;
	opacity: 1;
}

/* 4.7 Logo mark -- neutralised until hovered, so a logo strip stays quiet. */
.is-style-batavia-logo img {
	filter: grayscale(100%);
	opacity: 0.55;
	transition: opacity 150ms ease, filter 150ms ease;
}

.is-style-batavia-logo:hover img,
.is-style-batavia-logo:focus-within img {
	filter: grayscale(0%);
	opacity: 1;
}

/* 4.8 Quote -- an accent rail on the leading edge.
   This lives here rather than in theme.json because theme.json borders are
   physical: a border-left stays on the left in a right-to-left language. */
.wp-block-quote {
	border-inline-start: 2px solid var(--wp--preset--color--accent);
	padding-inline-start: var(--wp--preset--spacing--30);
}

/* 4.9 Figure -- a large mono number, for prices and metrics. */
.is-style-batavia-figure {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 400;
	letter-spacing: -0.03em;
	line-height: 1.1;
}

/* 4.10 Spec sheet -- a table of values, ruled rather than boxed. */
.wp-block-table.is-style-batavia-spec table {
	border-collapse: collapse;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
	font-variant-numeric: tabular-nums;
}

.wp-block-table.is-style-batavia-spec td,
.wp-block-table.is-style-batavia-spec th {
	border: 0;
	border-bottom: 1px solid var(--wp--preset--color--rule);
	padding: 0.5rem 0;
}

.wp-block-table.is-style-batavia-spec tr:last-child td,
.wp-block-table.is-style-batavia-spec tr:last-child th {
	border-bottom: 0;
}

/* The first cell of a row is its label, so it recedes like one. */
.wp-block-table.is-style-batavia-spec td:first-child {
	color: var(--wp--preset--color--muted);
	padding-inline-end: var(--wp--preset--spacing--30);
}

/* 4.11 Numbered steps -- ruled entries with the number as an accent. */
.is-style-batavia-steps {
	list-style: decimal;
	padding-inline-start: 2.5rem;
}

.is-style-batavia-steps li {
	border-bottom: 1px solid var(--wp--preset--color--rule);
	padding-bottom: 0.75rem;
	padding-top: 0.75rem;
}

.is-style-batavia-steps li:last-child {
	border-bottom: 0;
}

.is-style-batavia-steps li::marker {
	color: var(--wp--preset--color--accent);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
}

/* 4.12 Tag chips -- each term as its own hairline-bordered pill. */
.is-style-batavia-tags {
	column-gap: var(--wp--preset--spacing--10);
	display: flex;
	flex-wrap: wrap;
	row-gap: var(--wp--preset--spacing--10);
}

.is-style-batavia-tags a {
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 999px;
	color: var(--wp--preset--color--ink);
	display: inline-block;
	font-size: var(--wp--preset--font-size--x-small);
	padding: 0.25rem 0.625rem;
	text-decoration: none;
}

.is-style-batavia-tags a:hover,
.is-style-batavia-tags a:focus {
	background-color: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
}

/*
 * 4.13 Post navigation as a button -- core/post-navigation-link carries no
 * button style option of its own, so Previous/Next borrow the outline
 * button's look directly rather than reading as bare links beside it.
 */
.wp-block-post-navigation-link.is-style-outline > a {
	border: 1px solid var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ink);
	display: inline-block;
	padding: 0.75rem 1.25rem;
	text-decoration: none;
}

.wp-block-post-navigation-link.is-style-outline > a:hover,
.wp-block-post-navigation-link.is-style-outline > a:focus {
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
}

/* -------------------------------------------------------------------------
 * 5. Motion
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-duration: 0.01ms !important;
	}
}
