/*
 * ▐  ▗▐                
 * ▜▀ ▄▜▀ ▌  ▌ ▞▀▖▞▀▘▞▀▘
 * ▐ ▖▐▐ ▖▐▐▐▗▖▌ ▖▝▀▖▝▀▖
 *  ▀ ▀▘▀  ▘▘▝▘▝▀ ▀▀ ▀▀ 
 *
 * tech in the woods stylesheet, where the magic happens.
 */
:root {
	color-scheme: light dark;

	/* Palette — raw brand colors */
	--titw-palette-green: #006400;
	--titw-palette-green-light: #90ee90;
	--titw-palette-green-bright: #7ed492;
	--titw-palette-brown: #664c28;
	--titw-palette-tan: #d2b48c;
	--titw-palette-sea-green: #3cb371;
	--titw-palette-cream: #f5f1e8;
	--titw-palette-forest-dark: #0e1a12;
	--titw-palette-white: #ffffff;
	--titw-palette-ink: #1a1a1a;

	/* Semantic — roles that reference the palette (light mode) */
	--titw-bg: var(--titw-palette-white);
	--titw-text: var(--titw-palette-ink);
	--titw-brand: var(--titw-palette-green);
	--titw-link: var(--titw-palette-green);
	--titw-link-visited: var(--titw-palette-brown);
	--titw-selection: var(--titw-palette-sea-green);
	--titw-selection-text: var(--titw-palette-forest-dark);
	--titw-heading: var(--titw-palette-green);
	--titw-ground: var(--titw-palette-green);
	--titw-panorama: url("/images/footer-panorama.svg");
	/* Height/width ratio of the panorama viewBox — keep in sync with the
	   image so the footer can reserve the full rendered height. */
	--titw-panorama-ratio: calc(64 / 1200);
}

/* Dark mode — remap only the semantic roles onto darker-friendly palette
   colors. The palette and every rule stay exactly the same. */
@media (prefers-color-scheme: dark) {
	:root {
		--titw-bg: var(--titw-palette-forest-dark);
		--titw-text: var(--titw-palette-cream);
		--titw-brand: var(--titw-palette-green-bright);
		--titw-link: var(--titw-palette-green-bright);
		--titw-link-visited: var(--titw-palette-tan);
		--titw-heading: var(--titw-palette-green-bright);
		--titw-ground: var(--titw-palette-ink);
		--titw-panorama: url("/images/footer-panorama-dark.svg");
	}
}

@font-face {
	font-family: 'Inter';
	src: url('/assets/fonts/InterVariable.woff2') format('woff2');
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Inter';
	src: url('/assets/fonts/InterVariable-Italic.woff2') format('woff2');
	font-weight: 100 900;
	font-style: italic;
	font-display: swap;
}

body {
	font-family: 'Inter', system-ui, Arial;
	font-size: 1.25em;
	/* dvh tracks the real visible viewport on mobile (URL bar retracted or
	   not); vh stays as the fallback for older browsers. */
	min-height: 100vh;
	min-height: 100dvh;
	margin: 0;
	background: var(--titw-bg);
	color: var(--titw-text);
	display: flex;
	flex-direction: column;
}

main {
	max-width: 70ch;
	margin: 1em auto;
	padding-inline: 1em;
}

header {
	position: relative;
}

footer {
	flex: 1;
	/* At 100% width the panorama is 100vw × ratio tall; on very wide
	   viewports that exceeds 8em, and the bottom-anchored image would lose
	   its treetops. Reserve whichever is taller. */
	min-height: max(8em, calc(100vw * var(--titw-panorama-ratio)));
	text-align: center;
	/* Forest panorama silhouette along the bottom edge, layered over a green
	   ground band. The gradient fade spans the last 8em regardless of how tall
	   the footer grows. */
	background:
		var(--titw-panorama) center bottom / 100% auto no-repeat,
		linear-gradient(to top, var(--titw-ground), var(--titw-bg) 8em);
}

h1 {
	font-size: 1.75em;
}

h2 {
	font-size: 1.5em;
}

a {
	color: var(--titw-link);
}

a:visited {
	color: var(--titw-link-visited);
}

/* Inverted "highlighter" on hover: the link color fills the background, text
   flips to the page background for contrast. color + background-color are the
   only properties browsers let :visited override. */
a:hover {
	color: var(--titw-bg);
	background-color: var(--titw-link);
	text-decoration: none;
}

a:visited:hover {
	color: var(--titw-bg);
	background-color: var(--titw-link-visited);
}

/* Pictorial links — the wordmark, the feed icon, the heading-anchor stick —
   opt out of the highlighter fill. */
.brand a:hover,
.brand a:visited:hover,
.feed-icon:hover,
.post h2 .heading-anchor:hover {
	background-color: transparent;
}

::selection {
	color: var(--titw-selection-text);
	background: var(--titw-selection);
}

nav {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	position: relative;
	padding: 3em 0 2.5em;
}

/* Brand */
.brand {
	display: flex;
	flex-direction: column;
	align-items: center;
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	padding-top: 1em;
}

.brand a {
	font-size: clamp(2rem, 11vw, 3.25rem);
	font-weight: bold;
	text-decoration: none;
	color: var(--titw-brand);
	/* Keep the wordmark on one line. Absolute positioning caps its width at
	   ~50% of the viewport, which the 3.25rem max exceeds in the 641-880px
	   range (e.g. phones in landscape), forcing a wrap. */
	white-space: nowrap;
}

/* Of the highlighter opt-outs, only the wordmark has visible text — keep it
   in the brand color on hover. */
.brand a:hover,
.brand a:visited:hover {
	color: var(--titw-brand);
}

.brand a .rock {
	height: 0.75em;
	vertical-align: middle;
}

.tagline {
	font-size: 1rem;
	white-space: normal;
	text-align: center;
	align-self: flex-end;
	transform: translate(0%, -30%);
}

/* Posts */
.post h1 {
	margin-top: 0.25em;
	margin-bottom: 0;
}

.post h2 {
	color: var(--titw-heading);
	margin-bottom: 0.15em;
	/* Positioning context for the hanging heading-anchor stick. */
	position: relative;
}

/* Stick (🪵) before a post heading on hover: a deep link to the heading,
   added by heading-anchors.js. Always laid out (just invisible) so the
   heading doesn't reflow when it fades in. */
.post h2 .heading-anchor::before {
	content: "\1FAB5";
}

.post h2 .heading-anchor {
	/* Hang the stick in the left gutter: out of flow, right edge pinned just
	   left of the heading, so the text stays flush with the body and the
	   glyph can never overlap it whatever the platform emoji's width. */
	position: absolute;
	right: 100%;
	margin-right: 0.25em;
	text-decoration: none;
	opacity: 0;
	transition: opacity 0.15s ease-in;
}

.post h2:hover .heading-anchor,
.post h2 .heading-anchor:focus-visible {
	opacity: 1;
}

/* Tuck a section's opening paragraph up against its heading. The h2's own
   bottom margin must go too, or it collapses into the gap this removes. */
.post h2 + p {
	margin-top: 0;
}

/* Tag cloud: each tag scales with how many posts carry it, via the
   --tag-count variable the tags index template sets inline. Logarithmic:
   every doubling of posts adds 0.25em, so early growth is visible but a
   prolific tag can't shout down the page (capped at 2em ≈ 16 posts). */
.tag-cloud {
	list-style-type: none;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.25em 0.75em;
}

.tag-cloud a {
	font-size: min(calc(1em + log(var(--tag-count, 1), 2) * 0.25em), 2em);
	text-decoration: none;
}

.post-tags {
	text-align: left;
}

.post-tags a {
	text-decoration: none;
}

.post-tags ul {
	list-style-type: none;
	padding: 0;
}

.post-date {
	margin: 0;
}

.latest-posts, .latest-links, .latest-reads {
	list-style-type: none;
	padding-left: 0;
	margin: 1em;
}

.latest-reads li {
	padding-top: 1em;
}

.latest-reads li:first-child {
	padding-top: 0;
}

.latest-posts p, .latest-links p, .latest-reads p {
	margin-top: 0.5em;
}

/* RSS icon beside the "latest posts" heading */
.feed-icon img {
	height: 0.75em;
	vertical-align: middle;
}

/* Post date separator: a bullet between the title and date (inline). */
.post-meta::before {
	content: "\2022";
	margin: 0 0.4em;
}

.post-meta {
	font-style: italic;
}

/* Mobile: take the brand out of absolute positioning so it can't overlap
   content, center it, and trim the large nav padding. */
@media (max-width: 40em) {
	/* Compact panorama for narrow screens — the wide one shrinks to an
	   illegible strip. */
	:root {
		--titw-panorama: url("/images/footer-panorama-mobile.svg");
		--titw-panorama-ratio: calc(80 / 360);
	}

	nav {
		padding: 1.5em 0;
		justify-content: center;
	}

	/* No gutter for the hanging stick here, and no hover to reveal it on
	   touch anyway — in-flow it would just reserve a blank gap before the
	   heading, so drop it entirely. */
	.post h2 .heading-anchor {
		display: none;
	}

	/* Drop the post date onto its own line below the title. */
	.post-meta {
		display: block;
	}

	.post-meta::before {
		content: none;
	}
	
	.brand {
		position: static;
		transform: none;
		left: auto;
	}
	
	.tagline {
		align-self: center;
		transform: none;
	}
}

/* Dark mode on narrow screens — compact night panorama. Comes after the
   plain mobile block so it wins for dark + mobile together. */
@media (max-width: 40em) and (prefers-color-scheme: dark) {
	:root {
		--titw-panorama: url("/images/footer-panorama-dark-mobile.svg");
	}
}
