/* Shared base styles used by both index.html and project.html.
 *
 * Includes:
 *   - @font-face declarations (EB Garamond, latin subset)
 *   - :root color variables
 *   - global reset and html/body baseline
 *   - .topbar / .brand / .topnav (header common rules)
 *   - footer common positioning + easter-egg link styling
 *
 * Page-specific styles (hero, project, mosaic, video controls,
 * featured cards, footer flex/grid layout per page) live inline in
 * each HTML file's <style> block.
 */

/* ---------------- Fonts ---------------- */
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ebgaramond-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ebgaramond-400-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ebgaramond-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ebgaramond-500-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------------- Variables ---------------- */
:root {
  --bg: #fff;
  --fg: #111;
  --muted: #333;
  --subtle: #888;
  --nav: #999;
  --footer: #bbb;
  --rule: #eee;
  --link-hover: #111;
  color-scheme: light;
}

/* ---------------- Reset + html/body baseline ---------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Chrome counts off-viewport transformed fixed elements (e.g. the
   hover .preview) toward document overflow, producing a 1–Npx
   horizontal scrollbar. `overflow-x: clip` suppresses it without
   creating a scroll container (so `position: sticky` keeps working,
   unlike `overflow-x: hidden`). `scrollbar-gutter: stable` reserves
   the vertical scrollbar gutter so 100vw / centering math doesn't
   shift the layout when the scrollbar appears (Chrome). */
html { overflow-x: clip; scrollbar-gutter: stable; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: 'EB Garamond', serif;
  position: relative;
}

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

/* ---------------- Top header (fixed-position nav) ---------------- */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 18px 38px;
  pointer-events: none;
}
/* Per-pixel inversion against media (hero video/image, mosaic
   thumbnails, inline figures). Only enabled while the header
   actually overlaps a media element — over plain page text/
   background it would produce noisy per-glyph color flicker.
   Opacity softens the blend (66% difference + 34% original pixels). */
.topbar.over-media {
  mix-blend-mode: difference;
  opacity: 0.66;
}
.topbar.over-media .brand,
.topbar.over-media .topnav a,
.topbar.over-media .topnav a:hover,
.topbar.over-media .topnav a:focus-visible,
.topbar.over-media .topnav .copy-email,
.topbar.over-media .topnav .copy-email:hover,
.topbar.over-media .topnav .copy-email:focus-visible,
.topbar.over-media .topnav .copy-toast { color: #fff; }
.topbar.over-media .topnav a[data-fade]:not(.is-visible) { color: transparent; }
.brand {
  font-size: 1.05rem;
  color: var(--fg);
  text-decoration: none;
  letter-spacing: -0.01em;
  pointer-events: auto;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.brand.is-visible { opacity: 1; }

.topnav {
  display: flex;
  gap: 24px;
  font-size: 0.85rem;
  pointer-events: auto;
}
.topnav a {
  color: var(--nav);
  text-decoration: none;
  transition: color 0.2s, opacity 0.4s ease;
}
/* The contact element is a <button> (click-to-copy email) styled to
   look and behave exactly like the surrounding nav links. It shows just
   "contact" until clicked, when the rest of the address types out. */
.topnav .copy-email {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  line-height: inherit;
  color: var(--nav);
  cursor: pointer;
  position: relative;
  display: inline-block;
  white-space: nowrap;
  transition: color 0.2s, opacity 0.4s ease;
}
/* "copied" confirmation that fades in under the button on click, so it's
   unmistakable that the address was placed on the clipboard. */
.topnav .copy-toast {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--nav);
  opacity: 0;
  transform: translateY(-2px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.topnav .copy-email.is-copied .copy-toast {
  opacity: 1;
  transform: translateY(0);
  /* Wait for the address reveal (~0.55s) to finish before confirming. */
  transition: opacity 0.2s ease 0.55s, transform 0.2s ease 0.55s;
}
/* The address remainder (e.g. "@antoinedanion.com") stays collapsed
   until `.is-copied`, then reveals letter-by-letter via a stepped
   max-width transition. `--suffix-w` is measured in JS. */
.topnav .copy-suffix {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  vertical-align: bottom;
  white-space: nowrap;
  opacity: 0;
  transition: max-width 0.5s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.4s ease;
}
.topnav .copy-email.is-copied .copy-suffix {
  max-width: var(--suffix-w, 18ch);
  opacity: 1;
  transition: max-width 0.55s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.05s ease;
}
@media (prefers-reduced-motion: reduce) {
  .topnav .copy-suffix,
  .topnav .copy-email.is-copied .copy-suffix { transition: none; }
}
/* Suppress color transitions during the brief moment the topbar swaps
   in/out of `over-media`, so we don't get a white-on-white flash. */
.topbar.no-color-transition .brand,
.topbar.no-color-transition .topnav a,
.topbar.no-color-transition .topnav .copy-email { transition: opacity 0.4s ease; }
/* `data-fade` links start invisible and fade in/out via the
   `.is-visible` class managed in the per-page brand-fade script. */
.topnav a[data-fade] { opacity: 0; }
.topnav a[data-fade].is-visible { opacity: 1; }

.topnav a:hover,
.topnav a:focus-visible,
.topnav .copy-email:hover,
.topnav .copy-email:focus-visible {
  color: var(--link-hover);
  outline: none;
}

/* ---------------- Footer common rules ----------------
 * Pinned to the viewport with the same gutters and typography on
 * every page. Each page lays out its OWN children (grid vs flex,
 * with/without socials) inline.
 */
footer {
  position: fixed;
  bottom: 28px;
  left: 38px;
  right: 38px;
  font-size: 0.8rem;
  color: var(--footer);
  pointer-events: none;
  z-index: 10;
  transition: opacity 0.075s ease;
}
footer span { pointer-events: auto; white-space: nowrap; }
/* Easter-egg link: indistinguishable from plain text. */
footer a {
  color: inherit;
  text-decoration: none;
  cursor: default;
}
/* When the viewport is too narrow, JS adds .inflow so the footer
   drops back into the document flow. Each page customises
   margin/padding/max-width inline. */
footer.inflow {
  position: static;
}
footer.is-fading { opacity: 0; }

/* ---------------- Not-found block ----------------
 * Used by /404.html (Cloudflare Pages auto-serves it for any
 * unknown route) and by the project page's notFound() helper when
 * a slug doesn't match any known project. Code + message sit
 * side-by-side on a shared baseline, anchored top-left under the
 * fixed topbar so the page reads immediately without competing
 * with the header for vertical centre.
 */
.notfound {
  /* width:100% so this stretches across the parent regardless of
     whether the parent is a block (default) or a flex/grid container
     with align-items:center (project.html's body). The inner block
     then centers consistently across pages. */
  width: 100%;
  display: flex;
  justify-content: center;
  padding: 22vh 0 0;
}
.notfound-inner {
  width: 100%;
  max-width: 760px;
  padding: 0 48px;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 56px;
}
.notfound-code {
  font-size: 6rem;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0;
}
.notfound-title {
  font-size: 1.15rem;
  font-style: italic;
  color: var(--muted);
  line-height: 1.65;
  margin: 0;
}

@media (max-width: 640px) {
  .notfound { padding: 18vh 0 0; }
  .notfound-inner { padding: 0 24px; gap: 0 32px; }
  .notfound-code { font-size: 4.5rem; }
  .notfound-title { font-size: 1.05rem; }
}
