/*
  Data-dense dashboard direction, confirmed via wayfinder map #17 /
  tickets #18-#19. Light/dark tokens switch on the [data-theme]
  attribute, set by the pre-paint script in base.njk.

  Contrast reverified against the actual final values (not just
  trusted from the prototype), independently for both palettes:
    light: text/bg 15.7:1, muted/bg 5.72:1, accent/bg 4.64:1
    dark:  text/bg 11.6:1, muted/panel 4.63:1, accent/bg 4.99:1
  All pass WCAG AA (4.5:1 normal text); several exceed AAA (7:1).

  :root carries the light palette as a fallback — if the pre-paint
  script never runs (JS disabled/blocked/errors before it executes),
  html gets no [data-theme] attribute and these are the values used,
  so the design (badges, toggle, skip-link) doesn't silently lose its
  styling. html[data-theme="light"] below is redundant with :root in
  that case but kept explicit for symmetry with the dark block.
*/

:root {
	--font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	--measure: 42rem;
	--color-bg: #f2f2f4;
	--color-panel: #e4e4e8;
	--color-text: #14181f;
	--color-muted: #57606a;
	--color-accent: #0969da;
	--color-border: #c7c7cf;
	/* Theme-toggle thumb icons, masked shapes (see .theme-toggle-thumb::before) —
       theme-independent, so defined once here rather than per palette block. */
	--icon-sun: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E");
	--icon-moon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E");
}

html[data-theme="light"] {
	--color-bg: #f2f2f4;
	--color-panel: #e4e4e8;
	--color-text: #14181f;
	--color-muted: #57606a;
	--color-accent: #0969da;
	--color-border: #c7c7cf;
}

html[data-theme="dark"] {
	--color-bg: #2d2d30;
	--color-panel: #3c3c41;
	--color-text: #e6e9ec;
	--color-muted: #a8a8ad;
	--color-accent: #4a9eff;
	--color-border: #4a4a50;
}

* {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-family: var(--font-body);
	color: var(--color-text);
	background: var(--color-bg);
	line-height: 1.35;
	font-size: 0.95rem;
}

a {
	color: var(--color-accent);
}

.skip-link {
	position: absolute;
	top: -3rem;
	left: 0;
	background: var(--color-accent);
	/* Use the page background as the skip-link's text color, not a
       hardcoded white — the dark-mode accent (#4a9eff) is a light
       blue meant to pair with dark text, not white; white-on-#4a9eff
       fails contrast (2.75:1). var(--color-bg) passes AA in both
       modes (4.64:1 light, 4.99:1 dark). */
	color: var(--color-bg);
	padding: 0.5rem 1rem;
	z-index: 100;
	transition: top 0.1s ease-in-out;
}

.skip-link:focus {
	top: 0;
}

.site-header,
.site-main,
.site-footer {
	max-width: var(--measure);
	margin: 0 auto;
	padding: 1.5rem 1rem;
}

/* align-items: center (was baseline) and .site-nav's flex: 1 below are
   both needed to fit the theme toggle button, which isn't text and
   doesn't have a text baseline to align against. justify-content:
   space-between was dropped since nav now grows to fill the space
   between title and toggle on its own. */
.site-header {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	border-bottom: 1px solid var(--color-border);
}

.site-title {
	font-weight: 700;
	text-decoration: none;
	color: var(--color-text);
}

/* Desktop controls: always visible above the breakpoint, hidden below
   it via a plain display:none (see media query). Independent element
   from .nav-toggle below — not the same nav/toggle shown twice via
   some clever single-markup trick, because reliably keeping content
   visible above a breakpoint while it's nested inside a <details>
   turned out not to work (native closed-content hiding isn't reliably
   overridable that way). */
.site-header-controls {
	display: flex;
	align-items: center;
	flex: 1;
}

.site-nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	flex: 1;
	justify-content: end;
}

.site-nav a {
	margin-left: 1rem;
	text-decoration: none;
}

.site-nav a:hover {
	text-decoration: underline;
}

/* An actual toggle switch (track + sliding thumb), not an icon button —
   role="switch"/aria-checked on the button (set by theme-toggle.js) is
   the correct ARIA pattern for a control that visually is a switch. */
.theme-toggle {
	cursor: pointer;
	border: 1px solid var(--color-border);
	background: var(--color-panel);
	border-radius: 999px;
	margin-left: 1rem;
	width: 2.75rem;
	height: 1.5rem;
	padding: 0.15rem;
	position: relative;
	flex-shrink: 0;
}

.theme-toggle-thumb {
	/* block, not inline (its default as a <span>) — needed for
       width/height to apply so the ::before icon has a box to fill. */
	display: block;
	width: 1.1rem;
	height: 1.1rem;
	border-radius: 50%;
	background: var(--color-text);
	transition:
		transform 0.15s ease,
		background 0.15s ease;
}

/* Icon color is always the inverse token of the thumb's own background
   (--color-bg vs --color-text), so contrast is guaranteed correct in
   both states without a separate check — they're already verified
   near-max-contrast pairs (15.7:1 light / 11.6:1 dark, see palette
   comment at the top of this file).

   Rendered as an SVG shape via mask-image + background-color, not a
   Unicode glyph (☀/☾) with a text color — Unicode symbol glyphs are
   drawn from whatever font the browser substitutes for that codepoint,
   and those substitutes have inconsistent vertical metrics across
   browsers/platforms (a glyph centered in Firefox sat visibly off
   center in Chrome/Edge). A masked SVG has no font metrics to disagree
   about — mask-size/position are exact box percentages, so the icon
   lands in the same spot in every browser. */
.theme-toggle-thumb::before {
	content: "";
	display: block;
	width: 100%;
	height: 100%;
	background-color: var(--color-bg);
	-webkit-mask-image: var(--icon-sun);
	mask-image: var(--icon-sun);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: 65%;
	mask-size: 65%;
}

/* Travel distance: track content area (2.75rem - 2 × 0.15rem padding)
   minus the thumb's own width = 2.45rem - 1.1rem = 1.35rem.

   Deliberately keyed off html[data-theme="dark"], NOT [aria-checked] —
   data-theme is set by the pre-paint inline script in base.njk, before
   first paint, so the switch's visual state always matches the actual
   page theme immediately. aria-checked is only corrected once
   theme-toggle.js runs; if it were the visual source of truth too, a
   dark-mode page load would flash the switch showing "off" (or show
   it wrong permanently if that script failed to run) even though the
   page itself was already correctly dark. */
html[data-theme="dark"] .theme-toggle {
	background: var(--color-accent);
}

html[data-theme="dark"] .theme-toggle-thumb {
	transform: translateX(1.35rem);
	background: var(--color-bg);
}

html[data-theme="dark"] .theme-toggle-thumb::before {
	background-color: var(--color-text);
	-webkit-mask-image: var(--icon-moon);
	mask-image: var(--icon-moon);
}

/* Mobile controls: hidden entirely above the breakpoint. <details> is
   the natural fit here (not fighting its behavior, using it exactly
   as intended — content shown only when [open]) since this only ever
   needs to behave normally within a single breakpoint. */
.nav-toggle {
	display: none;
}

.nav-toggle-summary {
	cursor: pointer;
	list-style: none;
	width: 2rem;
	height: 2rem;
	align-items: center;
	justify-content: center;
	background: var(--color-panel);
	border: 1px solid var(--color-border);
	border-radius: 4px;
}

/* Safari/WebKit renders its own marker outside the list-style mechanism
   (same fix as .about-section's summary, see below) */
.nav-toggle-summary::-webkit-details-marker {
	display: none;
}

@media (max-width: 640px) {
	/* With .site-header-controls hidden, only the title and the
       hamburger remain — neither has flex-grow, so without this
       they'd sit adjacent at the start instead of at opposite ends. */
	.site-header {
		justify-content: space-between;
	}

	.site-header-controls {
		display: none;
	}

	.nav-toggle {
		display: block;
		position: relative;
	}

	.nav-toggle-summary {
		display: inline-flex;
	}

	/* position: absolute so the open panel overlays the page instead
       of pushing .site-header's height — it must not grow the header
       when expanded. */
	.nav-toggle-panel {
		display: none;
		position: absolute;
		top: calc(100% + 0.5rem);
		right: 0;
		flex-direction: column;
		align-items: flex-start;
		gap: 0.5rem;
		min-width: 10rem;
		background: var(--color-panel);
		border: 1px solid var(--color-border);
		border-radius: 4px;
		padding: 0.75rem;
		z-index: 10;
	}

	.nav-toggle[open] .nav-toggle-panel {
		display: flex;
	}

	.nav-toggle-panel .site-nav {
		flex-direction: column;
	}

	.nav-toggle-panel .site-nav a {
		margin-left: 0;
		padding: 0.5rem 0;
	}

	.nav-toggle-panel .theme-toggle {
		margin-left: 0;
	}
}

.site-footer {
	color: var(--color-muted);
	font-size: 0.875rem;
	border-top: 1px solid var(--color-border);
}

h1,
h2,
h3,
h4 {
	line-height: 1.25;
}

.tagline {
	color: var(--color-muted);
	margin-top: -0.5rem;
}

.job {
	margin-bottom: 0.75rem;
}

.job h3 {
	margin-bottom: 0.25rem;
}

.job .where {
	font-weight: 400;
	color: var(--color-muted);
}

.job .dates {
	display: inline-block;
	background: var(--color-panel);
	border: 1px solid var(--color-border);
	border-radius: 4px;
	padding: 0.05rem 0.4rem;
	font-size: 0.75rem;
	font-family: ui-monospace, "SF Mono", Consolas, monospace;
	color: var(--color-muted);
	margin-top: 0;
}

.skill-group {
	margin-bottom: 0.75rem;
}

.skill-group h3 {
	margin-bottom: 0.25rem;
	font-size: 1rem;
}

.skill-group p {
	display: inline-block;
	background: var(--color-panel);
	border: 1px solid var(--color-border);
	border-radius: 4px;
	padding: 0.35rem 0.5rem;
	font-size: 0.85rem;
	color: var(--color-muted);
	margin-top: 0;
}

/* Shared disclosure-triangle treatment for both About's and Resume's
   collapsible sections — visually identical, they differ only in
   default open/closed state (set via the `open` attribute per
   instance in the markup) and which script persists that state
   (about-sections.js vs resume-sections.js), not in appearance. */
.about-section,
.resume-section {
	margin-bottom: 1rem;
}

.about-section > summary,
.resume-section > summary {
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

/* Safari/WebKit renders its own marker outside the list-style mechanism */
.about-section > summary::-webkit-details-marker,
.resume-section > summary::-webkit-details-marker {
	display: none;
}

/* Custom marker, guaranteed centered against the heading via flexbox
   align-items — the native marker doesn't scale/center against a
   larger nested heading's font metrics, this does. */
.about-section > summary::before,
.resume-section > summary::before {
	content: "▶";
	display: inline-block;
	font-size: 0.75em;
	color: var(--color-muted);
	transition: transform 0.15s ease;
}

.about-section[open] > summary::before,
.resume-section[open] > summary::before {
	transform: rotate(90deg);
}

.about-section > summary h2,
.resume-section > summary h2 {
	display: inline;
	margin: 0;
}

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

.post-list li {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 0.25rem 1rem;
	padding: 0.5rem 0;
	border-bottom: 1px solid var(--color-border);
}

.post-date,
time {
	color: var(--color-muted);
	font-size: 0.9rem;
}

/* Print support for the Resume page (guntherjh/guntherjh.github.io#35)
   — scoped to pages containing .resume-section via :has(), rather
   than unconditionally hiding chrome on every page's print output,
   since that wasn't asked for and isn't this stylesheet's call to
   make for pages other than Resume. */
@media print {
	body:has(.resume-section) .site-header,
	body:has(.resume-section) .site-footer,
	body:has(.resume-section) .skip-link {
		display: none;
	}

	/* The disclosure triangle is a screen-only interaction affordance,
       meaningless on paper. */
	.resume-section > summary::before {
		display: none;
	}

	/* A printed page can't carry interactive toggle state — show every
       Resume section's content regardless of whether a visitor had
       collapsed it on screen. Overrides the browser's own UA rule that
       hides a closed <details>'s content. */
	.resume-section:not([open]) > *:not(summary) {
		display: block !important;
	}
}
