/* yoanfaure.com
   Monochrome. Inter for everything that is read; JetBrains Mono only for code,
   the log's hash and date, and the backdrop field. Nothing decorative except
   the field. Tokens first, then base, backdrop, shell, content, log, home. */

/* ---------- fonts ---------- */

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

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

@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/JetBrainsMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ---------- */

:root {
  --bg: #f4efe4;
  --fg: #262523;
  --muted: #6b675f;
  --rule: #ddd6c8;

  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --gutter: clamp(1rem, 4vw, 2.5rem);
  --header-h: 3.5rem;

  /* The page column: header, main and footer share one width, centred, on
     every page, so the brand never moves. 38rem of text is about 68 characters
     of Inter at the entry body size. In rem, not ch, because the footer has a
     smaller font and its ch would be narrower. */
  --column: calc(38rem + 2 * var(--gutter));

  /* What the column is painted with. Inner pages: opaque paper with hairline
     edges, so the field only shows in the side margins. Home: nothing. */
  --paper: var(--bg);
  --edge: var(--rule);
  --halo: none;

  color-scheme: light;
}

/* No data-theme: follow the system. data-theme forces a theme. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #1e1d1b;
    --fg: #ece6d9;
    --muted: #9a958b;
    --rule: #34322f;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: #1e1d1b;
  --fg: #ece6d9;
  --muted: #9a958b;
  --rule: #34322f;

  color-scheme: dark;
}

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

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

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: 4.5rem;
}

@media (min-width: 960px) {
  html {
    font-size: 17px;
  }
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Home: the field shows behind everything. Text keeps a soft halo of the
   background colour, so a line of the field never cuts through a word. */
body[data-page="home"] {
  --paper: transparent;
  --edge: transparent;
  --halo: 0 0 0.25em var(--bg), 0 0 0.5em var(--bg), 0 0 0.5em var(--bg);
}

main {
  flex: 1 0 auto;
  padding-bottom: clamp(3rem, 8vw, 5rem);
}

::selection {
  background: var(--fg);
  color: var(--bg);
}

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

a[href]:hover,
a[href]:focus-visible,
button:hover,
button:focus-visible {
  background: var(--fg);
  color: var(--bg);
}

:focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 2px;
}

h1,
h2,
h3,
h4 {
  font-weight: 700;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h1 {
  margin: 0 0 1.25rem;
  font-size: clamp(1.875rem, 1.3rem + 2.2vw, 2.5rem);
  line-height: 1.12;
  letter-spacing: -0.03em;
}

/* The only mono in the text. One weight ships, so nothing is faked. */
code,
pre,
kbd {
  font-family: var(--font-mono);
  font-weight: 400;
  font-style: normal;
  font-variant-ligatures: none;
  font-feature-settings: "calt" 0;
}

.visually-hidden,
.skip-link:not(:focus) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: fixed;
  top: 0.75rem;
  left: var(--gutter);
  z-index: 100;
  padding: 0.35rem 0.75rem;
  background: var(--fg);
  color: var(--bg);
}

/* ---------- backdrop: the field ---------- */

/* A fixed, full-viewport layer behind the page (field.js draws into it).
   The shell sits above it; inner pages paint an opaque column over it.
   field.js builds its character grid from this element's computed font, so the
   field says "mono" itself instead of inheriting the sans from the body. */
.field {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1;
  color: var(--fg);
}

.field-canvas {
  position: absolute;
  inset: 0;
  display: block;
}

/* ---------- shell: the column ---------- */

.site-header,
main,
.site-footer {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--column);
  margin-inline: auto;
  background: var(--paper);
  box-shadow: 1px 0 0 var(--edge), -1px 0 0 var(--edge);
  text-shadow: var(--halo);
}

/* an inverted link or button is its own background: no halo on it */
.site-header a[href]:is(:hover, :focus-visible),
.site-header button:is(:hover, :focus-visible),
main a[href]:is(:hover, :focus-visible),
.site-footer a[href]:is(:hover, :focus-visible) {
  text-shadow: none;
}

/* ---------- shell: header ---------- */

/* The name on the left, the theme toggle on the right. Nothing else. */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: var(--header-h);
  padding: 0 var(--gutter);
}

.brand {
  margin-left: -0.3em;
  padding: 0 0.3em;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-decoration: none;
}

.theme-toggle {
  margin: 0 -0.4rem 0 0;
  padding: 0.45rem 0.4rem;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  line-height: 0;
  cursor: pointer;
}

.theme-toggle__icon {
  display: inline-block;
  width: 1.05rem;
  height: 1.05rem;
  border: 2px solid currentColor;
  border-radius: 50%;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
}

/* ---------- shell: footer ---------- */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 2rem;
  padding: 1.75rem var(--gutter) 2.25rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.875rem;
}

.site-footer p {
  margin: 0;
}

/* ---------- pages: entry, 404 ---------- */

.prose,
.not-found {
  padding: clamp(2.5rem, 7vw, 5rem) var(--gutter) 0;
}

.meta {
  margin: 0 0 1rem;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.5;
}

.project .tagline {
  margin: -0.25rem 0 0.75rem;
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.015em;
}

.back {
  margin: 3.5rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
}

.empty {
  color: var(--muted);
}

/* markdown body: a reading column (the page column sets the measure, about 68
   characters), with room between paragraphs and headings */

.prose {
  font-size: 1.125rem;
  line-height: 1.7;
}

.prose :is(p, ul, ol, pre, table, blockquote, figure) {
  margin: 0 0 1.35em;
}

.prose h2 {
  margin: 2.75rem 0 0.8rem;
  font-size: 1.5rem;
  line-height: 1.25;
}

.prose h3 {
  margin: 2.25rem 0 0.6rem;
  font-size: 1.2rem;
  line-height: 1.35;
}

.prose h4 {
  margin: 1.75rem 0 0.5rem;
  font-size: 1.125rem;
  line-height: 1.4;
}

.prose ul,
.prose ol {
  padding-left: 1.4em;
}

.prose li + li {
  margin-top: 0.4em;
}

.prose li > :is(ul, ol) {
  margin: 0.4em 0 0;
}

.prose :not(pre) > code {
  padding: 0.12em 0.35em;
  background: var(--rule);
  font-size: 0.85em;
}

.prose pre {
  padding: 1rem 1.25rem;
  overflow-x: auto;
  border: 1px solid var(--rule);
  font-size: 0.875rem;
  line-height: 1.6;
  tab-size: 2;
}

.prose pre code {
  padding: 0;
  background: none;
  font-size: inherit;
}

.prose blockquote {
  padding-left: 1.25em;
  border-left: 2px solid var(--fg);
  font-style: italic;
}

.prose blockquote > :last-child {
  margin-bottom: 0;
}

.prose hr {
  margin: 2.75rem 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

.prose img {
  max-width: 100%;
  height: auto;
}

.prose strong {
  font-weight: 650;
}

/* heading permalinks (empty anchors added by the Markdown renderer) */

.prose .anchor {
  margin-left: 0.4em;
  color: var(--muted);
  font-weight: 400;
  text-decoration: none;
  visibility: hidden;
}

.prose .anchor::before {
  content: "#";
}

.prose :is(h2, h3, h4):hover .anchor,
.prose :is(h2, h3, h4):focus-within .anchor {
  visibility: visible;
}

/* footnotes */

.prose sup {
  line-height: 0;
}

.prose sup a,
.prose .footnote-backref {
  text-decoration: none;
}

.prose .footnotes {
  margin-top: 3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.875rem;
}

.prose .footnotes ol {
  margin: 0;
}

.prose .footnotes p {
  margin: 0 0 0.5rem;
}

/* tables: ruled, no boxes */

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95em;
}

.prose :is(th, td) {
  padding: 0.7em 2ch 0.7em 0;
  border-top: 1px solid var(--rule);
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}

.prose :is(th, td):last-child {
  padding-right: 0;
}

.prose th {
  border-top: 0;
  border-bottom: 1px solid var(--fg);
  color: var(--muted);
  font-weight: 650;
}

.prose tbody tr:last-child td {
  border-bottom: 1px solid var(--rule);
}

.prose td:first-child {
  color: var(--muted);
}

/* 404: a terminal (its lines are <pre>, so they are mono) */

.not-found {
  padding-top: clamp(3rem, 14vw, 9rem);
}

.not-found pre {
  margin: 0;
  font-size: clamp(0.95rem, 0.8rem + 0.8vw, 1.25rem);
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.not-found .prompt {
  margin-top: 0.5rem;
}

.not-found .prompt::before {
  content: "% ";
  color: var(--muted);
}

/* ---------- the log ---------- */

/* Hash and date are mono and sized by their own `ch`, so they line up whatever
   the row's font is. Type and title are Inter, so the type gets a fixed track
   (in em) and the title takes the rest. */
.log {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule);
  list-style: none;
}

.log-row {
  display: grid;
  grid-template-columns: max-content max-content 3.75em minmax(0, 1fr);
  column-gap: 1.25em;
  align-items: baseline;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--rule);
}

.log-hash,
.log-date {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.8em;
  font-variant-ligatures: none;
}

.log-hash {
  width: 7ch;
}

.log-date {
  width: 10ch;
}

.log-type {
  color: var(--muted);
}

.log-hash:not([href]) {
  text-decoration: none;
}

.log-title {
  font-weight: 600;
  overflow-wrap: anywhere;
}

@media (max-width: 599.98px) {
  .log-row {
    grid-template-columns: 4em minmax(0, 1fr);
    column-gap: 1em;
    padding: 0.7rem 0;
  }

  .log-hash {
    grid-area: 1 / 1;
  }

  .log-date {
    grid-area: 1 / 2;
  }

  .log-type {
    grid-area: 2 / 1;
  }

  .log-title {
    grid-area: 2 / 2;
  }
}

/* ---------- home ---------- */

/* One centred column: a quiet intro, then the log, which carries the page. */
.intro {
  padding: clamp(2rem, 6vw, 3.5rem) var(--gutter) 0;
}

.intro h1 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.3;
  letter-spacing: -0.02em;
}

.intro p {
  max-width: 38rem;
  margin: 0 0 0.7rem;
  color: var(--muted);
  font-size: 0.9375rem;
}

.intro .tagline {
  margin: 0.1rem 0 1.25rem;
  color: var(--fg);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.intro .contact {
  margin: 1.25rem 0 0;
}

.log-section {
  padding: clamp(2.5rem, 7vw, 4rem) var(--gutter) 0;
}

.log-section h2 {
  margin: 0 0 0.85rem;
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0;
}

.log-section .log {
  font-size: 1.125rem;
}

.log-section .log-row {
  padding: 0.95rem 0;
}
