/* ==========================================================================
   Tyler Berggren — tylerberggren.com
   Hand-written static site. No framework, no build step.

   Theme is ported from reinstall.work: same background, same neutral grays,
   same type pairing, same component set. The one departure is the accent —
   a forest green rather than red, dark enough that it needs a lighter tint
   on dark surfaces. See --accent-lift below.
   ========================================================================== */

/* --- Fonts ---------------------------------------------------------------- */

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url('/fonts/plex-sans-var.woff2') format('woff2-variations');
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plex-mono-400.woff2') format('woff2');
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/plex-mono-500.woff2') format('woff2');
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plex-mono-600.woff2') format('woff2');
}

/* IBM Plex Serif, subset to basic latin + smart punctuation + the five
   diacritics a pronunciation respelling needs (U+014D, U+0259, U+028C,
   U+02C8, U+02CC). Used only by the dictionary entry.
   Rebuild: pyftsubset IBMPlexSerif-{Regular,SemiBold}.woff2
            --unicodes=U+0020-007E,U+00A0,U+2018-2019,U+201C-201D,U+2013-2014,U+2026,U+014D,U+0259,U+028C,U+02C8,U+02CC
            --flavor=woff2 --output-file=plex-serif-{400,600}.woff2
   No italic face is shipped: a whole cut for the part-of-speech tag cost
   10KB to render four characters. The tag is upright serif instead. */
@font-face {
  font-family: 'IBM Plex Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/plex-serif-400.woff2') format('woff2');
}

@font-face {
  font-family: 'IBM Plex Serif';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/plex-serif-600.woff2') format('woff2');
}

/* Phosphor Light, subset to the 6 glyphs this site uses:
   U+E092 arrow-up-right, U+E2EE linkedin-logo, U+E398 paper-plane-tilt,
   U+E4BC x-logo, U+E576 github-logo, U+E58C monitor-play.
   Rebuild: pyftsubset Phosphor-Light.woff2
            --unicodes=U+E092,U+E2EE,U+E398,U+E4BC,U+E576,U+E58C
            --flavor=woff2 --output-file=phosphor-light-subset.woff2 */
@font-face {
  font-family: 'Phosphor-Light';
  font-style: normal;
  font-weight: normal;
  font-display: block;
  /* ?v= must be bumped whenever the glyph set changes — /fonts/* is served
     immutable for a year, so a stale cache would drop icons silently. */
  src: url('/fonts/phosphor-light-subset.woff2?v=3') format('woff2');
}

/* Phosphor Fill, subset to the 4 social glyphs used in the About block:
   U+E2EE linkedin-logo, U+E398 paper-plane-tilt, U+E4BC x-logo,
   U+E576 github-logo.
   Rebuild: pyftsubset Phosphor-Fill.woff2
            --unicodes=U+E2EE,U+E398,U+E4BC,U+E576
            --flavor=woff2 --output-file=phosphor-fill-subset.woff2 */
@font-face {
  font-family: 'Phosphor-Fill';
  font-style: normal;
  font-weight: normal;
  font-display: block;
  src: url('/fonts/phosphor-fill-subset.woff2?v=2') format('woff2');
}

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

:root {
  /* Palette — bg, ink, and neutrals are reinstall.work's values unchanged. */
  --bg: #f2f0ed;
  --ink: #0a0a0a;
  --accent: #1b4d3e;
  --neutral: #8a8a8a;
  --dark: #1e1e1e;

  /* A forest green this deep sits at 1.7:1 against --dark — invisible as a
     button fill on the contact band, where reinstall.work's red managed 3:1.
     Same hue (162deg) and saturation, lifted to 40% lightness: 4.65:1 against
     the band, and 5.5:1 for --ink text sitting on it. Use on dark surfaces
     only; on --bg it drops to 3.15:1 and fails for body-size text. */
  --accent-lift: #35977a;

  /* Derived surfaces */
  --bg-raised: #f8f7f5;
  --rule: color-mix(in srgb, var(--neutral) 32%, transparent);
  --rule-strong: color-mix(in srgb, var(--neutral) 55%, transparent);
  --muted: #6b6b6b;

  /* Type */
  --sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --serif: 'IBM Plex Serif', ui-serif, Georgia, 'Times New Roman', serif;

  /* Layout */
  --measure: 80ch;
  --measure-prose: 62ch;
  --page: 1120px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --header-h: 4.25rem;

  --radius: 6px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Light only — there is no dark theme. Declaring it stops the browser
     from auto-darkening form controls and scrollbars. */
  color-scheme: light;
}

/* --- Reset / base --------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  /* Anchor targets clear the sticky header */
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
  -webkit-text-size-adjust: 100%;
}

@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;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  font-weight: 400;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

strong {
  font-weight: 700;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- Layout primitives ---------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: clamp(4rem, 9vw, 7.5rem);
  border-top: 1px solid var(--rule);
}

.section__head {
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}

.eyebrow {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.9rem;
}

.eyebrow--muted {
  color: var(--neutral);
}

h2 {
  font-size: clamp(1.9rem, 1.3rem + 2.4vw, 3rem);
}

h3 {
  font-size: clamp(1.15rem, 1.05rem + 0.4vw, 1.35rem);
}

.lede {
  max-width: var(--measure);
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
  color: var(--muted);
  margin-top: 1rem;
}

.prose {
  max-width: var(--measure);
  display: grid;
  gap: 1.15em;
}

/* `:not(.btn)` matters — a .btn placed inside .prose would otherwise inherit
   accent text, which on the solid-accent button is green-on-green. */
.prose a:not(.btn) {
  color: var(--accent);
  font-weight: 500;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
}

.prose a:not(.btn):hover {
  text-decoration-color: currentColor;
}

.prose em {
  font-style: italic;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--bg);
  padding: 0.75rem 1.25rem;
  font-family: var(--mono);
  font-size: 0.875rem;
  text-decoration: none;
}

.skip-link:focus {
  left: 0.5rem;
  top: 0.5rem;
}

/* --- Header --------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(12px);
  -webkit-backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid var(--rule);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  width: 100%;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  flex-shrink: 0;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

/* 2.5rem against a 4.25rem header leaves ~14px of breathing room top and
   bottom. Going larger starts crowding the rule under the header. */
.brand img {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  flex-shrink: 0;
}

/* --- Nav ------------------------------------------------------------------ */

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 1.75rem);
}

.nav a:not(.btn) {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--muted);
  text-decoration: none;
  padding-block: 0.35rem;
  position: relative;
  transition: color 0.18s var(--ease);
  white-space: nowrap;
}

.nav a:not(.btn)::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.24s var(--ease);
}

.nav a:not(.btn):hover {
  color: var(--ink);
}

.nav a:not(.btn)[aria-current='true'] {
  color: var(--ink);
}

.nav a:not(.btn)[aria-current='true']::after {
  transform: scaleX(1);
}

/* Shown at every width: compact in the desktop bar, full-width at the foot
   of the mobile panel (see the mobile block). */
.nav__cta {
  padding: 0.6rem 1rem;
  margin-left: 0.35rem;
}

/* Mobile nav */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-right: -0.5rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

/* 760px is enough here — two nav links plus the CTA, where reinstall.work
   had five and needed 900px. */
@media (min-width: 760px) {
  .nav-toggle {
    display: none;
  }
}

@media (max-width: 759px) {
  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
    padding: 0.5rem var(--gutter) 1.5rem;
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transition: opacity 0.2s var(--ease), transform 0.2s var(--ease),
      visibility 0.2s;
  }

  .nav[data-open='true'] {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
  }

  .nav a:not(.btn) {
    padding-block: 0.85rem;
    font-size: 0.9375rem;
    border-bottom: 1px solid var(--rule);
  }

  /* The last text link sits directly above the CTA — its divider would read
     as a stray second rule between them. */
  .nav a:not(.btn):has(+ .btn) {
    border-bottom: none;
  }

  .nav__cta {
    justify-content: center;
    margin: 0.75rem 0 0;
    padding-block: 0.85rem;
  }

  .nav a:not(.btn)::after {
    display: none;
  }
}

/* --- Icons ---------------------------------------------------------------- */

/* Minimal stand-in for the Phosphor web stylesheet — we ship 7 glyphs, so
   there is no reason to carry the full ~87KB of icon classes. */
.ph-light,
.ph-fill {
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  letter-spacing: normal;
  line-height: 1;
  display: inline-block;
  speak: never;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.ph-light {
  font-family: 'Phosphor-Light' !important;
}

.ph-fill {
  font-family: 'Phosphor-Fill' !important;
}

/* Codepoints are identical across Phosphor weights — only the family differs. */
.ph-monitor-play::before {
  content: '\e58c';
}

.ph-arrow-up-right::before {
  content: '\e092';
}

.ph-linkedin-logo::before {
  content: '\e2ee';
}

.ph-paper-plane-tilt::before {
  content: '\e398';
}

.ph-x-logo::before {
  content: '\e4bc';
}

.ph-github-logo::before {
  content: '\e576';
}

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  /* Sans, always — buttons stay in the sans voice even where surrounding
     chrome (nav, eyebrows, footer) is mono. */
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1;
  white-space: nowrap;
  padding: 0.9rem 1.4rem;
  border-radius: var(--radius);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--bg);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease),
    color 0.18s var(--ease), transform 0.18s var(--ease);
}

.btn:hover {
  background: color-mix(in srgb, var(--accent) 86%, #000);
  border-color: color-mix(in srgb, var(--accent) 86%, #000);
  transform: translateY(-1px);
}

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}

.btn--ghost:hover {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}

.btn--sm {
  padding: 0.6rem 1rem;
  font-size: 0.8125rem;
}

.btn i {
  font-size: 1.35em;
  line-height: 1;
  flex-shrink: 0;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
}

.btn-row--close {
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}

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

.hero {
  padding-block: clamp(3.5rem, 8vw, 6.5rem) clamp(3rem, 7vw, 5.5rem);
  border-top: 0;

  /* One shared measure for the headline and the subhead beneath it, so the
     two blocks occupy the same column instead of breaking at different
     points. It has to be absolute: the two are set at different font sizes,
     so an identical `ch` value would resolve to different pixel widths and
     the blocks would not actually line up. 63rem is the 30ch the headline
     needs at its largest size (1008px), and it also clears the subhead's
     813px with room to spare. The 1120px page cap constrains both before
     this does; below ~910px the container wins and they wrap, as intended. */
  --hero-measure: 63rem;
}

.hero h1 {
  font-size: clamp(2.125rem, 1.3rem + 3.1vw, 3.5rem);
  letter-spacing: -0.03em;
  max-width: var(--hero-measure);
}

.hero .lede {
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem);
  max-width: var(--hero-measure);
}

.hero__media {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  border-radius: calc(var(--radius) * 2);
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--dark);
  aspect-ratio: 16 / 9;
}

.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Dictionary entry ------------------------------------------------------ */

/* A definition block, set as a dictionary pastiche: serif for the entry head
   (headword + pronunciation + part of speech), sans for the definition. */
.dictionary .wrap {
  max-width: var(--page);
}

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

.dfn__word {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.9rem, 1.3rem + 2.4vw, 3rem);
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.dfn__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.6rem;
  font-family: var(--serif);
  font-size: 1.0625rem;
  color: var(--muted);
}

/* The part-of-speech tag. Upright rather than italic — see the @font-face
   note above on why no italic cut ships. */
.dfn__pos {
  color: var(--accent);
  font-weight: 600;
}

.dfn__sense {
  display: flex;
  gap: 0.9rem;
  margin-top: clamp(1.5rem, 3vw, 2rem);
}

/* The sense number sits in the serif so it reads as part of the entry
   apparatus, not as body copy. */
.dfn__num {
  flex-shrink: 0;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--accent);
}

.dfn__body {
  font-family: var(--sans);
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
  line-height: 1.6;
}

/* --- About ---------------------------------------------------------------- */

.about {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
}

@media (min-width: 900px) {
  .about {
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
    align-items: start;
  }
}

.about__portrait {
  width: clamp(7rem, 20vw, 12rem);
  border-radius: 50%;
}

/* The longest single block of body copy on the site — tighter measure than
   the rest of the page. */
.about .prose {
  max-width: var(--measure-prose);
}

.about__meta {
  margin-top: 1.25rem;
  display: grid;
  gap: 0.35rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted);
}

.about__meta strong {
  color: var(--ink);
  font-weight: 600;
}

.about__links {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

.about__links a {
  display: inline-flex;
  color: var(--accent);
  text-decoration: none;
  transition: opacity 0.18s var(--ease);
}

.about__links a:hover {
  opacity: 0.55;
}

.about__links i {
  font-size: 1.3rem;
  line-height: 1;
}

/* --- Work cards ----------------------------------------------------------- */

/* Three projects — one row on desktop, two up at tablet, stacked on phones. */
.cards {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

@media (min-width: 620px) {
  .cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 960px) {
  .cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The whole card is the link — each project has exactly one destination, so
   this beats a nested link and gives a much larger hit target.
   No padding on the card itself: the image is full-bleed to the card edge,
   so the inset lives on .card__body instead. */
a.card {
  display: flex;
  flex-direction: column;
  background: var(--bg-raised);
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) * 1.5);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}

a.card:hover {
  border-color: var(--rule-strong);
  transform: translateY(-2px);
}

/* Full-width banner cropped to a fixed height, flush with the card's top edge
   — the treatment carried over from the previous build of this site. `cover`
   matters here: the sources have different aspect ratios (squares and a wide
   screenshot) and all crop to the same band, rather than letterboxing at
   different visual weights the way `contain` did. */
.card__image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  margin: 0;
  /* The card's own overflow:hidden already clips this, but the explicit radius
     keeps the corners right if the card ever loses its clip. */
  border-radius: calc(var(--radius) * 1.5) calc(var(--radius) * 1.5) 0 0;
}

.card__body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  flex: 1;
  padding: clamp(1.1rem, 2.2vw, 1.5rem);
}

a.card p {
  font-size: 0.9375rem;
  color: var(--muted);
  line-height: 1.6;
}

a.card p em {
  font-style: italic;
}

/* Pushed to the bottom row so the arrows line up across cards of unequal
   text length — the grid stretches them to a common height. */
.card__go {
  margin-top: auto;
  padding-top: 0.35rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.card__go i {
  font-size: 1.15em;
  transition: transform 0.2s var(--ease);
}

a.card:hover .card__go i {
  transform: translate(2px, -2px);
}

/* --- Contact band --------------------------------------------------------- */

.band {
  background: var(--dark);
  color: var(--bg);
  border-top: 0;
}

.band .lede {
  color: color-mix(in srgb, var(--bg) 70%, transparent);
}

.band h2 {
  max-width: 22ch;
}

/* --accent is 1.7:1 against this band — a solid-accent button would read as a
   dark smudge on near-black. The lifted tint carries the same hue at 4.65:1,
   with --ink text on it rather than --bg. */
.band .btn {
  background: var(--accent-lift);
  border-color: var(--accent-lift);
  color: var(--ink);
}

.band .btn:hover {
  background: color-mix(in srgb, var(--accent-lift) 88%, #fff);
  border-color: color-mix(in srgb, var(--accent-lift) 88%, #fff);
}

.band .btn--ghost {
  background: transparent;
  color: var(--bg);
  border-color: color-mix(in srgb, var(--bg) 35%, transparent);
}

.band .btn--ghost:hover {
  background: transparent;
  border-color: var(--bg);
  color: var(--bg);
}

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

.footer {
  background: var(--dark);
  color: color-mix(in srgb, var(--bg) 62%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--bg) 14%, transparent);
  padding-block: 2.5rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
}

.footer__brand {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.footer__social {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
}

.footer__social a {
  display: inline-flex;
  /* Optical alignment — the glyphs sit slightly high against the baseline. */
  margin-top: 1px;
}

.footer__social i {
  font-size: 1.25rem;
  line-height: 1;
}

.footer a {
  color: inherit;
  text-decoration: none;
  transition: color 0.18s var(--ease);
}

.footer a:hover {
  color: var(--bg);
}

/* --- 404 ------------------------------------------------------------------ */

.notfound {
  min-height: calc(100vh - var(--header-h));
  display: grid;
  align-content: center;
  border-top: 0;
}

.notfound .eyebrow {
  justify-content: flex-start;
}

/* --- Reveal on scroll ----------------------------------------------------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
  }
}
