/* ==========================================================================
   Jaydatt Khodave — design system
   Single stylesheet, mobile-first, no framework.

   Sections
   01 Tokens
   02 Reset & base
   03 Layout
   04 Typography helpers
   05 Buttons & links
   06 Header & navigation
   07 Breadcrumbs
   08 Cards & grids
   09 Prose (long-form content)
   10 Blog
   11 Post
   12 Lists, timeline, gallery, tags
   13 Forms
   14 Footer
   15 Utilities
   17 Hero
   18 Skills
   19 Projects
   20 Experience & education entries
   21 Contact CTA
   23 Motion & print

   Icon glyphs live in assets/css/fontawesome.css (self-hosted, subsetted).
   ========================================================================== */

/* --------------------------------------------------------------------------
   01 Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour — light-only by design. One accent, neutral greys. */
  --color-bg: #ffffff;
  --color-bg-alt: #f7f8fa;
  --color-bg-inset: #eef0f4;
  --color-text: #16181d;
  --color-text-soft: #4d5460;
  --color-text-faint: #6b7280;
  --color-border: #dcdfe5;
  --color-border-strong: #b9bec9;
  --color-accent: #1c3faa;
  --color-accent-strong: #16327f;
  --color-accent-soft: #eaeefb;
  /* Error red chosen to clear 4.5:1 on both --color-bg and --color-bg-alt. */
  --color-error: #b3261e;
  --color-error-soft: #fdf2f1;
  --color-inverse-bg: #14161b;
  --color-inverse-text: #f3f4f6;
  --color-inverse-soft: #a9b0bd;
  --color-inverse-border: #2d313a;
  --color-focus: #1c3faa;

  /* Typography — system stack, no web font download. */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Fluid type scale: min at 320px, max at 1280px. */
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --text-lg: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --text-xl: clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
  --text-2xl: clamp(1.375rem, 1.25rem + 0.6vw, 1.75rem);
  --text-3xl: clamp(1.625rem, 1.4rem + 1vw, 2.25rem);
  --text-4xl: clamp(1.875rem, 1.5rem + 1.7vw, 2.875rem);
  --text-5xl: clamp(2.25rem, 1.7rem + 2.6vw, 3.75rem);

  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-normal: 1.55;
  --leading-relaxed: 1.7;

  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --tracking-wide: 0.08em;

  /* Spacing scale (rem-based, 4px rhythm). */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* Fluid section padding. */
  --section-y: clamp(2.5rem, 1.5rem + 4vw, 5rem);
  --section-y-tight: clamp(1.75rem, 1.2rem + 2.5vw, 3rem);

  /* Layout */
  --container-max: 72rem;   /* 1152px */
  --measure: 68ch;          /* comfortable reading width */
  --gutter: clamp(1rem, 0.6rem + 2vw, 2rem);

  /* Borders & motion */
  --radius: 2px;
  --border: 1px solid var(--color-border);
  --transition: 150ms ease;
}

/* --------------------------------------------------------------------------
   02 Reset & base
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: var(--space-6);
}

body {
  margin: 0;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Guard against any single element forcing a horizontal scrollbar. */
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin-block: 0;
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  text-wrap: balance;
  overflow-wrap: break-word;
}

h1 { font-size: var(--text-4xl); letter-spacing: -0.02em; }
h2 { font-size: var(--text-3xl); letter-spacing: -0.015em; }
h3 { font-size: var(--text-2xl); letter-spacing: -0.01em; }
h4 { font-size: var(--text-xl); }
h5 { font-size: var(--text-lg); }
h6 { font-size: var(--text-base); }

p,
ul,
ol,
dl,
figure,
blockquote,
pre,
table {
  margin-block: 0;
}

/* Media never overflows its container. */
img,
picture,
video,
canvas,
svg,
iframe {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

svg {
  fill: currentColor;
}

a {
  color: var(--color-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
  transition: color var(--transition);
}

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

strong,
b {
  font-weight: var(--weight-semibold);
}

small {
  font-size: var(--text-sm);
}

hr {
  height: 0;
  margin-block: var(--space-6);
  border: 0;
  border-block-start: var(--border);
}

code,
kbd,
samp,
pre {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

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

/* Visible, consistent focus for every interactive element. */
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* Long unbroken strings (URLs, IDs) must not blow out narrow viewports. */
p,
li,
dd,
dt,
figcaption,
blockquote,
td,
th {
  overflow-wrap: break-word;
}

/* Email addresses and URLs used as link text have no break opportunities,
   so they need the more aggressive rule. */
a[href^="mailto:"],
a[href^="tel:"] {
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   03 Layout
   -------------------------------------------------------------------------- */

.container {
  width: min(100% - (var(--gutter) * 2), var(--container-max));
  margin-inline: auto;
}

.section {
  padding-block: var(--section-y);
}

.section--tight {
  padding-block: var(--section-y-tight);
}

.section--alt {
  background-color: var(--color-bg-alt);
}

.section--bordered {
  border-block-end: var(--border);
}

.site-main {
  display: block;
}

/* <main> carries tabindex="-1" so the skip link can move focus into it.
   It is a programmatic focus target, never reached by tabbing, so it should
   not draw a focus ring around the whole page. */
.site-main:focus {
  outline: none;
}

/* Two-column split that collapses to one column on small screens. */
.split {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 62rem) {
  .split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-7);
  }

  .split--center {
    align-items: center;
  }
}

.stack > * + * {
  margin-block-start: var(--space-4);
}

.stack-lg > * + * {
  margin-block-start: var(--space-5);
}

/* --------------------------------------------------------------------------
   04 Typography helpers
   -------------------------------------------------------------------------- */

.eyebrow {
  margin-block-end: var(--space-3);
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.section-head {
  max-width: var(--measure);
  margin-block-end: var(--space-6);
}

.section-title {
  font-size: var(--text-3xl);
}

.section-lede {
  margin-block-start: var(--space-4);
  color: var(--color-text-soft);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  max-width: var(--measure);
}

.lede {
  color: var(--color-text-soft);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
}

.text-soft {
  color: var(--color-text-soft);
}

.measure {
  max-width: var(--measure);
}

/* --------------------------------------------------------------------------
   05 Buttons & links
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 2.75rem; /* 44px touch target */
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition),
    color var(--transition);
}

.btn:hover {
  background-color: var(--color-bg-alt);
  color: var(--color-text);
}

.btn--primary {
  border-color: var(--color-accent);
  background-color: var(--color-accent);
  color: #ffffff;
}

.btn--primary:hover {
  border-color: var(--color-accent-strong);
  background-color: var(--color-accent-strong);
  color: #ffffff;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block-start: var(--space-6);
}

/* Full-width buttons on the narrowest screens. */
@media (max-width: 26rem) {
  .btn-row {
    flex-direction: column;
  }

  .btn-row .btn {
    width: 100%;
  }
}

.link-strong {
  font-weight: var(--weight-semibold);
}

/* --------------------------------------------------------------------------
   06 Header & navigation
   -------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  inset-inline-start: var(--space-4);
  inset-block-start: 0;
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-text);
  color: #ffffff;
  font-weight: var(--weight-semibold);
  text-decoration: none;
  transform: translateY(-120%);
  transition: transform var(--transition);
}

.skip-link:focus {
  color: #ffffff;
  transform: translateY(0);
}

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background-color: var(--color-bg);
  border-block-end: var(--border);
}

.header-inner {
  /* No positioning context here on purpose: the mobile menu panel is
     positioned against .site-header so it spans the full viewport width. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 4rem;
  padding-block: var(--space-3);
}

.header-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text);
  text-decoration: none;
  /* Keep the brand from squashing the nav on mid-size screens. */
  min-width: 0;
}

.header-brand:hover {
  color: var(--color-text);
}

.header-logo {
  flex-shrink: 0;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius);
}

.header-brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.header-brand-name {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.header-brand-subtitle {
  color: var(--color-text-faint);
  font-size: var(--text-xs);
  line-height: 1.3;
  /* Hidden on very small screens to protect the header from wrapping. */
  display: none;
}

@media (min-width: 26rem) {
  .header-brand-subtitle {
    display: block;
  }
}

.desktop-nav {
  display: none;
}

.desktop-nav a {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  color: var(--color-text-soft);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  white-space: nowrap;
}

.desktop-nav a:hover {
  color: var(--color-text);
  background-color: var(--color-bg-alt);
}

.desktop-nav a[aria-current="page"] {
  color: var(--color-accent);
  font-weight: var(--weight-semibold);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.header-cta {
  display: none;
}

/* Mobile navigation: native <details> disclosure, so it needs no JavaScript. */
.mobile-nav {
  position: static;
}

.mobile-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  color: var(--color-text);
  cursor: pointer;
  /* Remove the native disclosure triangle; the icon conveys state. */
  list-style: none;
}

.mobile-menu-toggle::-webkit-details-marker {
  display: none;
}

.mobile-menu-toggle::marker {
  content: "";
}

.mobile-menu-toggle:hover {
  background-color: var(--color-bg-alt);
}

.mobile-menu-toggle > i {
  font-size: 1.125rem;
}

/* Swap the bars/close glyphs from the open state — no JS class juggling. */
.mobile-menu-toggle .icon-close { display: none; }
.mobile-nav[open] .mobile-menu-toggle .icon-close { display: inline-block; }
.mobile-nav[open] .mobile-menu-toggle .icon-menu { display: none; }

/* The panel is positioned against the header, not the toggle, so it spans
   the full width below the header bar. */
.mobile-menu {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  z-index: 40;
  border-block: var(--border);
  background-color: var(--color-bg);
}

/* When the disclosure is closed the panel must not be laid out at all.
   Without this, browsers still compute geometry for the hidden slot, which
   both wastes layout work and makes the links measurable by tooling. */
.mobile-nav:not([open]) .mobile-menu {
  display: none;
}

.mobile-menu-inner {
  display: flex;
  flex-direction: column;
  padding-block: var(--space-3);
}

.mobile-menu-inner a {
  padding: var(--space-3) 0;
  border-block-end: var(--border);
  color: var(--color-text);
  font-weight: var(--weight-medium);
  text-decoration: none;
}

.mobile-menu-inner a:last-child {
  border-block-end: 0;
}

.mobile-menu-inner a[aria-current="page"] {
  color: var(--color-accent);
  font-weight: var(--weight-semibold);
}

/* Desktop navigation takes over at 60rem (960px). */
@media (min-width: 60rem) {
  .desktop-nav {
    display: flex;
    align-items: center;
    gap: var(--space-1);
  }

  .header-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.5rem;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius);
    background-color: var(--color-accent);
    color: #ffffff;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    text-decoration: none;
  }

  .header-cta:hover {
    background-color: var(--color-accent-strong);
    color: #ffffff;
  }

  .mobile-nav {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   07 Breadcrumbs
   -------------------------------------------------------------------------- */

.breadcrumbs {
  padding-block-start: var(--space-5);
  font-size: var(--text-sm);
}

.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  padding: 0;
  margin: 0;
  list-style: none;
  color: var(--color-text-faint);
}

.breadcrumbs a {
  color: var(--color-text-faint);
}

.breadcrumbs a:hover {
  color: var(--color-text);
}

.breadcrumbs [aria-current="page"] {
  color: var(--color-text);
  font-weight: var(--weight-medium);
}

.breadcrumbs-sep {
  /* Uses text-faint rather than a lighter border colour so the visible glyph
     still meets WCAG AA contrast (4.5:1) against the page background. */
  color: var(--color-text-faint);
}

/* --------------------------------------------------------------------------
   08 Cards & grids
   -------------------------------------------------------------------------- */

/* Auto-fitting grid: no media queries needed, never overflows. */
.card-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.card-grid--wide {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.section--alt .card {
  background-color: var(--color-bg);
}

.card-title {
  font-size: var(--text-xl);
}

.card-title a {
  color: inherit;
  text-decoration: none;
}

.card-title a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.card-text {
  margin: 0;
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.card-meta {
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.panel {
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
}

.section--alt .panel {
  background-color: var(--color-bg);
}

/* Definition-list "quick facts". */
.facts {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  padding: 0;
  margin: 0;
}

.fact {
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.fact dt,
.fact-label {
  font-weight: var(--weight-bold);
}

.fact dd,
.fact-value {
  margin: var(--space-2) 0 0;
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

/* --------------------------------------------------------------------------
   09 Prose (long-form Markdown content)
   -------------------------------------------------------------------------- */

.prose {
  max-width: var(--measure);
}

.prose > * + * {
  margin-block-start: var(--space-5);
}

.prose h2 {
  margin-block-start: var(--space-7);
  font-size: var(--text-2xl);
}

.prose h3 {
  margin-block-start: var(--space-6);
  font-size: var(--text-xl);
}

.prose h4 {
  margin-block-start: var(--space-5);
  font-size: var(--text-lg);
}

.prose > h2:first-child,
.prose > h3:first-child {
  margin-block-start: 0;
}

.prose p,
.prose li {
  line-height: var(--leading-relaxed);
}

.prose ul,
.prose ol {
  padding-inline-start: var(--space-5);
}

.prose li + li {
  margin-block-start: var(--space-2);
}

.prose blockquote {
  padding-inline-start: var(--space-5);
  border-inline-start: 3px solid var(--color-border-strong);
  color: var(--color-text-soft);
  font-style: normal;
}

.prose img {
  border-radius: var(--radius);
}

.prose figcaption {
  margin-block-start: var(--space-2);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

/* Code blocks scroll internally instead of widening the page. */
.prose pre,
.highlight pre,
pre.highlight {
  max-width: 100%;
  padding: var(--space-4);
  overflow-x: auto;
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
  line-height: var(--leading-normal);
  -webkit-overflow-scrolling: touch;
  /* Preserve code formatting — never collapse whitespace. */
  white-space: pre;
  tab-size: 2;
}

.prose :not(pre) > code {
  padding: 0.15em 0.35em;
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
  /* Inline code may wrap so it cannot overflow. */
  overflow-wrap: break-word;
}

.prose pre code {
  padding: 0;
  border: 0;
  background: none;
}

/* Tables get a horizontal scroll container. */
.table-wrap {
  max-width: 100%;
  overflow-x: auto;
  border: var(--border);
  border-radius: var(--radius);
}

/* Highlighted answer/summary block used inside article bodies. */
.callout {
  padding: var(--space-5);
  border: var(--border);
  border-inline-start: 3px solid var(--color-accent);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
}

.callout > * + * {
  margin-block-start: var(--space-3);
}

.callout .eyebrow {
  margin-block-end: 0;
}

/* In-article table of contents. */
.post-toc {
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
}

.post-toc > h2 {
  margin-block-start: 0;
  font-size: var(--text-lg);
}

.post-toc ol {
  margin-block-start: var(--space-3);
  padding-inline-start: var(--space-5);
}

.post-toc li + li {
  margin-block-start: var(--space-2);
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.prose th,
.prose td {
  padding: var(--space-3) var(--space-4);
  border-block-end: var(--border);
  text-align: start;
  vertical-align: top;
}

.prose th {
  background-color: var(--color-bg-alt);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.prose tr:last-child td {
  border-block-end: 0;
}

/* --------------------------------------------------------------------------
   10 Blog
   -------------------------------------------------------------------------- */

.page-hero {
  border-block-end: var(--border);
}

.page-hero-inner {
  max-width: var(--measure);
  padding-block: var(--section-y);
}

.page-hero h1 {
  font-size: var(--text-4xl);
}

.page-hero .lede {
  margin-block-start: var(--space-5);
}

.blog-shell {
  padding-block: var(--section-y);
}

.blog-header {
  max-width: var(--measure);
  margin-block-end: var(--space-6);
}

.blog-kicker {
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin-block-end: var(--space-3);
}

.blog-title {
  font-size: var(--text-4xl);
}

.blog-description {
  margin-block-start: var(--space-4);
  color: var(--color-text-soft);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
}

.blog-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3);
  padding-block: var(--space-5);
  border-block: var(--border);
  margin-block-end: var(--space-6);
}

.blog-filters-label {
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.blog-filters-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.blog-filters-list a {
  padding: var(--space-2) var(--space-3);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-text-soft);
  font-size: var(--text-sm);
  text-decoration: none;
}

.blog-filters-list a:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.blog-featured,
.blog-listing {
  margin-block-start: var(--space-7);
}

.blog-featured > h2,
.blog-listing > h2 {
  margin-block-end: var(--space-5);
  font-size: var(--text-2xl);
}

.blog-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.blog-card {
  display: flex;
  flex-direction: column;
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  overflow: hidden;
}

.blog-card-image {
  display: block;
  border-block-end: var(--border);
}

/* Fixed aspect ratio prevents layout shift while images load. */
.blog-card-image img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background-color: var(--color-bg-inset);
}

.blog-card-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
}

.blog-card-category {
  color: var(--color-accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.blog-card-title {
  font-size: var(--text-xl);
}

.blog-card-title a {
  color: inherit;
  text-decoration: none;
}

.blog-card-title a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.blog-card-excerpt {
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.blog-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.blog-card-meta > span + span::before {
  content: "·";
  margin-inline-end: var(--space-3);
  color: var(--color-text-faint);
}

.blog-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.blog-card-tag {
  padding: 0.1rem var(--space-2);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
}

.blog-card-read {
  margin-block-start: auto;
  font-weight: var(--weight-semibold);
}

/* --------------------------------------------------------------------------
   11 Post
   -------------------------------------------------------------------------- */

.post-shell {
  padding-block: var(--section-y);
}

.post-header {
  max-width: var(--measure);
  margin-block-end: var(--space-6);
}

.post-kicker {
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin-block-end: var(--space-3);
}

.post-title {
  font-size: var(--text-4xl);
}

.post-description {
  margin-block-start: var(--space-4);
  color: var(--color-text-soft);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
}

.post-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin-block-start: var(--space-5);
  padding-block: var(--space-3);
  border-block: var(--border);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.post-meta > span + span::before {
  content: "·";
  margin-inline-end: var(--space-3);
  color: var(--color-text-faint);
}

.post-featured-image {
  margin-block-start: var(--space-6);
}

.post-featured-image img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-inset);
}

.author-box {
  margin-block-start: var(--space-7);
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
}

.author-box-inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: flex-start;
}

.author-box-image {
  flex-shrink: 0;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  object-fit: cover;
  background-color: var(--color-bg-inset);
}

.author-box-title {
  font-size: var(--text-xl);
}

.author-box-role {
  margin-block-start: var(--space-1);
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.author-box-bio {
  margin-block-start: var(--space-3);
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.author-box-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-block-start: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.post-related {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-6);
  border-block-start: var(--border);
}

.post-related > h2 {
  margin-block-end: var(--space-5);
  font-size: var(--text-2xl);
}

.post-related-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.post-navigation {
  display: grid;
  gap: var(--space-4);
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-6);
  border-block-start: var(--border);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.post-navigation-link {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-text);
  text-decoration: none;
}

.post-navigation-link:hover {
  border-color: var(--color-accent);
  color: var(--color-text);
}

.post-navigation-link span {
  color: var(--color-text-faint);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.post-navigation-link strong {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
}

/* --------------------------------------------------------------------------
   12 Lists, timeline, gallery, tags
   -------------------------------------------------------------------------- */

.list-plain {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  list-style: none;
}

.link-list {
  display: grid;
  gap: var(--space-3);
  padding: 0;
  margin: 0;
  list-style: none;
}

.hero-figure img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-inset);
}

.hero-tagline {
  margin-block-start: var(--space-4);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
}

.hero-tagline + .lede {
  margin-block-start: var(--space-4);
}

/* FAQ disclosure list — native <details>, no JS. */
.faq-list {
  display: grid;
  gap: var(--space-3);
}

.faq-item {
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.faq-item > summary {
  padding: var(--space-4);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  /* Keep the native disclosure marker: it conveys expanded state. */
}

.faq-item > summary:focus-visible {
  outline-offset: -2px;
}

.faq-item > p {
  padding: 0 var(--space-4) var(--space-4);
  margin: 0;
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

/* Timeline: a simple bordered rail, no decorative excess. */
.timeline {
  display: grid;
  gap: var(--space-6);
  padding: 0;
  margin: 0;
  list-style: none;
}

.timeline-item {
  padding-inline-start: var(--space-5);
  border-inline-start: 2px solid var(--color-border);
}

.timeline-date {
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.timeline-title {
  margin-block-start: var(--space-2);
  font-size: var(--text-xl);
}

.timeline-text {
  margin-block-start: var(--space-2);
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.gallery {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  padding: 0;
  margin: 0;
  list-style: none;
}

.gallery-item {
  border: var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.gallery-item img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background-color: var(--color-bg-inset);
}

.gallery-caption {
  padding: var(--space-4);
  color: var(--color-text-soft);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  list-style: none;
}

.tag {
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: var(--space-1) var(--space-3);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-text-soft);
  font-size: var(--text-sm);
  text-decoration: none;
}

.tag:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.term-group {
  padding-block: var(--space-6);
  border-block-end: var(--border);
}

.term-group:last-child {
  border-block-end: 0;
}

.term-heading {
  font-size: var(--text-2xl);
}

.term-count {
  margin-inline-start: var(--space-2);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  font-weight: var(--weight-normal);
}

/* Compact post rows (Categories / Tags index). */
.post-rows {
  display: grid;
  gap: 0;
  padding: 0;
  margin-block-start: var(--space-5);
  list-style: none;
}

.post-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  align-items: baseline;
  justify-content: space-between;
  padding-block: var(--space-3);
  border-block-end: var(--border);
}

.post-row:last-child {
  border-block-end: 0;
}

.post-row-title {
  flex: 1 1 16rem;
  font-weight: var(--weight-medium);
  text-decoration: none;
}

.post-row-title:hover {
  text-decoration: underline;
}

.post-row-date {
  flex-shrink: 0;
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

/* Achievement card icon + filter buttons. */
.card-icon {
  width: 1.5rem;
  height: 1.5rem;
  color: var(--color-accent);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin-block-end: var(--space-6);
  list-style: none;
}

.filter-button {
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition),
    color var(--transition);
}

.filter-button:hover {
  background-color: var(--color-bg-alt);
}

.filter-button[aria-pressed="true"],
.filter-button.is-active {
  border-color: var(--color-accent);
  background-color: var(--color-accent);
  color: #ffffff;
}

.achievement-list {
  padding: 0;
  margin: 0;
  list-style: none;
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.achievement-list > li[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   13 Forms
   -------------------------------------------------------------------------- */

.form {
  display: grid;
  gap: var(--space-5);
  max-width: 36rem;
}

.form-field {
  display: grid;
  gap: var(--space-2);
}

.form-label {
  font-weight: var(--weight-semibold);
}

.form-hint {
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.form-input,
.form-textarea,
.form-select {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  font-size: var(--text-base);
}

.form-textarea {
  min-height: 9rem;
  resize: vertical;
}

.form-input:focus-visible,
.form-textarea:focus-visible,
.form-select:focus-visible {
  border-color: var(--color-accent);
}

/* Required marker — never colour alone; the text note explains the asterisk. */
.req {
  color: var(--color-accent);
  font-weight: var(--weight-bold);
}

.form-required-note {
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

/* Inline field error. Uses an icon + text, not colour alone. */
.form-error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  color: var(--color-error);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.form-error[hidden] {
  display: none;
}

.form-error::before {
  content: "\26A0";  /* warning sign */
  font-weight: var(--weight-bold);
}

/* Submit-time summary, announced via role="alert". */
.form-error-summary {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-error);
  border-inline-start-width: 3px;
  border-radius: var(--radius);
  background-color: var(--color-error-soft);
  color: var(--color-error);
  font-weight: var(--weight-medium);
}

.form-error-summary[hidden] {
  display: none;
}

.form-input[aria-invalid="true"],
.form-textarea[aria-invalid="true"] {
  border-color: var(--color-error);
  border-width: 2px;
}

/* Honeypot.
   `display: none` is what Formspree documents for its `_gotcha` field. It also
   means the field creates no geometry at all and is absent from the
   accessibility tree, so screen reader users never encounter it. (An
   off-screen `left: -9999px` field would still be laid out.) */
.form-honeypot {
  display: none;
}

/* --------------------------------------------------------------------------
   14 Footer
   -------------------------------------------------------------------------- */

.site-footer {
  margin-block-start: var(--space-8);
  border-block-start: var(--border);
  background-color: var(--color-inverse-bg);
  color: var(--color-inverse-text);
}

.footer-grid {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--section-y);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.footer-logo {
  width: 3rem;
  height: 3rem;
  margin-block-end: var(--space-4);
  border-radius: var(--radius);
}

.footer-title {
  font-size: var(--text-lg);
  margin-block-end: var(--space-4);
}

.footer-title--sub {
  margin-block-start: var(--space-5);
  font-size: var(--text-base);
}

.footer-brand-name {
  font-size: var(--text-xl);
  margin-block-end: var(--space-2);
}

.footer-brand-role {
  margin-block-end: var(--space-3);
  color: var(--color-inverse-soft);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.footer-summary {
  color: var(--color-inverse-soft);
  line-height: var(--leading-relaxed);
}

.site-footer a {
  color: var(--color-inverse-soft);
  text-decoration: none;
}

.site-footer a:hover {
  color: #ffffff;
  text-decoration: underline;
}

.site-footer a:focus-visible {
  outline-color: #ffffff;
}

.footer-address {
  font-style: normal;
  color: var(--color-inverse-soft);
  line-height: var(--leading-relaxed);
  /* The email address is a single long unbreakable token; allow it to break
     so it cannot push the footer grid past the viewport. */
  overflow-wrap: anywhere;
}

.social-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: 0;
  margin-block-start: var(--space-4);
  list-style: none;
}

.social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--color-inverse-border);
  border-radius: var(--radius);
}

.social-link:hover {
  border-color: var(--color-inverse-soft);
}

/* Labelled variant (icon + name), used on the contact page. */
.social-list--labelled {
  gap: var(--space-2);
}

.social-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-4);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
}

.social-chip:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  text-decoration: none;
}

.social-link > i {
  font-size: 1.0625rem;
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-5);
  border-block-start: 1px solid var(--color-inverse-border);
  color: var(--color-inverse-soft);
  font-size: var(--text-sm);
}

/* --------------------------------------------------------------------------
   15 Utilities
   -------------------------------------------------------------------------- */

/* Accessible visually-hidden text. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Font Awesome icons inherit colour and sit inline; these helpers only adjust
   size/spacing. The glyph itself is styled in assets/css/fontawesome.css. */
.link-arrow {
  margin-inline-start: var(--space-1);
  font-size: 0.85em;
  transition: transform var(--transition);
}

a:hover > .link-arrow {
  transform: translateX(2px);
}

.link-ext {
  margin-inline-start: var(--space-1);
  font-size: 0.75em;
  opacity: 0.8;
}

.nav-icon {
  width: 1.25em;
  margin-inline-end: var(--space-3);
  color: var(--color-text-faint);
  text-align: center;
}

.subsection-title {
  margin-block-start: var(--space-7);
  font-size: var(--text-2xl);
}

/* --------------------------------------------------------------------------
   17 Hero
   -------------------------------------------------------------------------- */

.hero-greeting {
  color: var(--color-text-faint);
  font-size: var(--text-lg);
}

.hero-name {
  margin-block-start: var(--space-2);
  font-size: var(--text-5xl);
  letter-spacing: -0.03em;
}

.hero-role {
  margin-block-start: var(--space-4);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
}

.hero-role + .lede {
  margin-block-start: var(--space-4);
}

.hero-social {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: var(--border);
}

.hero-social-label {
  margin-block-end: var(--space-3);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.hero-social .social-list {
  margin-block-start: 0;
}

/* On the hero the icon buttons sit on white, so they need a visible border. */
.hero-social .social-link {
  border-color: var(--color-border);
  color: var(--color-text-soft);
}

.hero-social .social-link:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.hero-figure img {
  max-width: 30rem;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   18 Skills
   -------------------------------------------------------------------------- */

.skills-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.skill-group {
  display: flex;
  flex-direction: column;
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.skill-group-title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-xl);
}

.skill-icon {
  flex-shrink: 0;
  width: 1.75rem;
  font-size: 1.125rem;
  color: var(--color-accent);
  text-align: center;
}

.skill-group-text {
  margin-block-start: var(--space-3);
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.skill-items {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  margin-block-start: var(--space-4);
  list-style: none;
}

.skill-items > li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.skill-tick {
  flex-shrink: 0;
  margin-block-start: 0.28em;
  font-size: 0.8em;
  color: var(--color-accent);
}

/* --------------------------------------------------------------------------
   19 Projects
   -------------------------------------------------------------------------- */

.project-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}

.project-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.project-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.project-icon {
  font-size: 1.125rem;
  color: var(--color-accent);
}

.project-category {
  color: var(--color-accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.project-title {
  font-size: var(--text-xl);
}

.project-text {
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
}

.tech-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  list-style: none;
}

.tech-tag {
  padding: 0.1rem var(--space-2);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
  color: var(--color-text-soft);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.project-status {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.project-status .fa-circle-check {
  color: var(--color-accent);
}

.project-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-block-start: auto;
  padding-block-start: var(--space-3);
  border-block-start: var(--border);
}

.project-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.25rem;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-decoration: none;
}

.project-link:hover {
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   20 Experience & education entries
   -------------------------------------------------------------------------- */

.entry-list {
  display: grid;
  gap: var(--space-5);
  padding: 0;
  margin: 0;
  list-style: none;
}

.entry {
  padding: var(--space-5);
  border: var(--border);
  border-inline-start: 3px solid var(--color-accent);
  border-radius: var(--radius);
  background-color: var(--color-bg);
}

.entry-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}

.entry-icon {
  flex-shrink: 0;
  width: 2.5rem;
  height: 2.5rem;
  border: var(--border);
  border-radius: var(--radius);
  color: var(--color-accent);
  font-size: 1rem;
  line-height: 2.5rem;
  text-align: center;
}

.entry-title {
  font-size: var(--text-xl);
}

.entry-org {
  margin-block-start: var(--space-1);
  color: var(--color-text-soft);
  font-weight: var(--weight-medium);
}

.entry-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: center;
  margin-block-start: var(--space-4);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
}

.entry-period,
.entry-location {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.entry-type,
.entry-field {
  padding: 0.1rem var(--space-2);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg-alt);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.entry-text {
  margin-block-start: var(--space-4);
  color: var(--color-text-soft);
  line-height: var(--leading-relaxed);
  max-width: var(--measure);
}

.entry-highlights {
  display: grid;
  gap: var(--space-2);
  padding: 0;
  margin-block-start: var(--space-4);
  list-style: none;
}

.entry-highlights > li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  line-height: var(--leading-relaxed);
  max-width: var(--measure);
}

/* --------------------------------------------------------------------------
   21 Contact CTA
   -------------------------------------------------------------------------- */

.contact-cta {
  background-color: var(--color-bg-alt);
}

.contact-cta .section-head {
  margin-block-end: 0;
}

.contact-cta .btn-row {
  margin-block-start: var(--space-5);
}

/* --------------------------------------------------------------------------
   22 Scroll state & section reveal
   -------------------------------------------------------------------------- */

/* Subtle cue that the page has scrolled beneath the sticky header.
   Added by JavaScript; the default (unscrolled) state needs no class. */
.site-header.is-scrolled {
  border-block-end-color: var(--color-border-strong);
}

/*
   Section reveal.

   IMPORTANT: the *visible* state is the default. `.reveal-pending` is only
   ever added by JavaScript, and only when the browser supports
   IntersectionObserver AND the user has not requested reduced motion. So with
   JS disabled, JS broken, or reduced motion on, content is simply visible —
   it can never get stuck hidden.
*/
.reveal-pending {
  opacity: 0;
  transform: translateY(8px);
}

.is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity 400ms ease, transform 400ms ease;
}


/* Strip list semantics' default styling while keeping the element a list. */
.list-reset {
  padding: 0;
  margin: 0;
  list-style: none;
}

/* Bordered figure used on the About page. */
.framed-figure {
  margin: 0;
  border: var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.framed-figure img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--color-bg-inset);
}

.framed-figure figcaption {
  padding: var(--space-4);
  border-block-start: var(--border);
  color: var(--color-text-soft);
  font-size: var(--text-sm);
}

/* Definition list of contact rows. */
.contact-list {
  display: grid;
  gap: var(--space-1) var(--space-4);
  margin-block-start: var(--space-5);
}

.contact-list dt {
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.contact-list dd {
  margin: 0 0 var(--space-3);
  overflow-wrap: anywhere;
}

@media (min-width: 34rem) {
  .contact-list {
    grid-template-columns: minmax(8rem, auto) 1fr;
    align-items: baseline;
  }

  .contact-list dd {
    margin-block-end: var(--space-2);
  }
}

.note {
  padding: var(--space-4);
  margin-block-start: var(--space-5);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--color-bg);
  color: var(--color-text-soft);
}

/* Icon + label chip. */
.tag--icon {
  gap: var(--space-2);
}

.card-link {
  margin-block-start: auto;
  font-weight: var(--weight-semibold);
}

/* Centred 404 block. */
.error-page {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
}

.error-page .lede {
  margin-block-start: var(--space-5);
}

.error-page .btn-row {
  justify-content: center;
}

/* --------------------------------------------------------------------------
   23 Motion & print
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

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

  /* Belt-and-braces: JavaScript already skips the reveal when reduced motion
     is requested, but if the class is ever present it must not hide content. */
  .reveal-pending {
    opacity: 1;
    transform: none;
  }
}

/* Respect users who ask for higher contrast. */
@media (prefers-contrast: more) {
  :root {
    --color-text-soft: #2b3038;
    --color-text-faint: #3d434d;
    --color-border: #9aa0ad;
    --color-border-strong: #6b7280;
  }
}

@media print {
  .site-header,
  .site-footer,
  .breadcrumbs,
  .blog-filters,
  .post-navigation,
  .post-related,
  .skip-link {
    display: none;
  }

  body {
    color: #000;
    background: #fff;
    font-size: 11pt;
  }

  a {
    color: #000;
    text-decoration: underline;
  }

  .prose {
    max-width: none;
  }
}
