/* ==========================================================================
   tokens.css — the single place to change the look of blog.dicko.dev
   Every colour, face, size and spacing used by base.css / components.css /
   prose.css comes from here. Change a value here and every page follows.
   Prefix: --bs- (Beer & Servers).
   ========================================================================== */

:root {
  color-scheme: light dark;

  /* ---- Colour (light) ------------------------------------------------- */
  --bs-bg: #FCFCFA;          /* page background */
  --bs-surface: #F3F3EF;     /* inline code, tag chips, subtle panels */
  --bs-text: #161616;        /* body text */
  --bs-muted: #66665F;       /* metadata, subtitles, footer */
  --bs-rule: #161616;        /* strong rules: masthead, H2 top rule, footer */
  --bs-rule-soft: #DCDCD5;   /* thin rules between list items */
  --bs-accent: #C8102E;      /* date, active nav, link underline. Nowhere else. */
  --bs-link: var(--bs-text); /* link text colour; the accent lives in the underline */
  --bs-code-bg: #161616;     /* block code background */
  --bs-code-text: #F4F4F1;   /* block code text */
  --bs-selection: #F5D9DD;   /* ::selection background */

  /* ---- Type faces ------------------------------------------------------ */
  --bs-font-display: "Bricolage Grotesque", "Bricolage Grotesque Fallback", system-ui, sans-serif;
  --bs-font-body: "Source Sans 3", "Source Sans 3 Fallback", system-ui, sans-serif;
  --bs-font-mono: "Fira Code", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --bs-weight-display: 800;
  --bs-weight-body: 400;
  --bs-weight-body-strong: 600;
  --bs-weight-mono: 500;
  --bs-tracking-display: -0.03em;
  --bs-tracking-meta: 0.04em;
  --bs-tracking-nav: 0.06em;

  /* ---- Type scale (px, decided in round 3) ----------------------------- */
  --bs-text-body: 18.5px;
  --bs-text-small: 13px;        /* masthead tagline */
  --bs-text-meta: 12px;         /* mono date line, nav, footer */
  --bs-text-tag: 11px;          /* tag chips */
  --bs-text-code: 14px;         /* block code */
  --bs-text-code-inline: 0.88em;
  --bs-text-masthead: 24px;
  --bs-text-h1: 44px;
  --bs-text-h1-mobile: 32px;
  --bs-text-h2: 27px;
  --bs-text-h3: 21px;
  --bs-text-title: 26px;        /* post title in the list */
  --bs-text-subtitle: 22px;     /* "Or: …" on the post page */
  --bs-text-subtitle-list: 17px;/* "Or: …" in the list */
  --bs-text-quote: 21px;

  --bs-leading-body: 1.6;
  --bs-leading-tight: 1.02;
  --bs-leading-heading: 1.12;

  /* ---- Layout ---------------------------------------------------------- */
  --bs-measure: 720px;          /* reading width for masthead, list, post, footer */
  --bs-gutter: 24px;            /* side padding inside the measure */
  --bs-thumb-w: 150px;          /* list cover thumbnail width */
  --bs-thumb-ratio: 3 / 2;
  --bs-mark-size: 44px;         /* masthead logo */
  --bs-rule-w: 2px;
  --bs-rule-soft-w: 1px;
  --bs-radius: 6px;             /* mark corners; everything else is square */
  --bs-underline-w: 2px;
  --bs-underline-offset: 3px;
  --bs-breakpoint-narrow: 600px;/* informational: media queries cannot read vars */

  /* ---- Spacing ----------------------------------------------------------- */
  --bs-space-1: 4px;
  --bs-space-2: 8px;
  --bs-space-3: 12px;
  --bs-space-4: 16px;
  --bs-space-5: 24px;
  --bs-space-6: 32px;
  --bs-space-7: 48px;
}

/* ---- Colour (dark) ------------------------------------------------------- */
/* Follows the OS unless the page is pinned with data-theme="light"|"dark"
   by theme.js. Same structure, different values; nothing else changes. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bs-bg: #141414;
    --bs-surface: #1D1D1C;
    --bs-text: #ECECE6;
    --bs-muted: #9F9F97;
    --bs-rule: #ECECE6;
    --bs-rule-soft: #2D2D2A;
    --bs-accent: #FF4D63;
    --bs-code-bg: #000000;
    --bs-code-text: #ECECE6;
    --bs-selection: #4A1F27;
  }
}
:root[data-theme="dark"] {
  --bs-bg: #141414;
  --bs-surface: #1D1D1C;
  --bs-text: #ECECE6;
  --bs-muted: #9F9F97;
  --bs-rule: #ECECE6;
  --bs-rule-soft: #2D2D2A;
  --bs-accent: #FF4D63;
  --bs-code-bg: #000000;
  --bs-code-text: #ECECE6;
  --bs-selection: #4A1F27;
}


/* ==========================================================================
   fonts.css — self-hosted webfonts (latin subset, variable, OFL)
   Files live in ../fonts/. No request leaves the site for type.
   Source: Google Fonts latin woff2 builds, fetched 2026-10-09.
   ========================================================================== */

@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("../fonts/bricolage-grotesque-latin.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: "Source Sans 3";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("../fonts/source-sans-3-latin.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: "Source Sans 3";
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("../fonts/source-sans-3-italic-latin.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: "Fira Code";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/fira-code-latin.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;
}

/* Metric-matched fallbacks so text does not jump when the woff2 arrives.
   Values are approximate; tune with a font-fallback tool if layout shift shows. */
@font-face {
  font-family: "Source Sans 3 Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 94%;
  ascent-override: 102%;
  descent-override: 32%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Bricolage Grotesque Fallback";
  src: local("Arial Black"), local("Arial Bold"), local("Helvetica Bold");
  size-adjust: 97%;
  ascent-override: 92%;
  descent-override: 22%;
  line-gap-override: 0%;
}


/* ==========================================================================
   base.css — reset + element defaults. Uses tokens only; no literal values.
   ========================================================================== */

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

html {
  background: var(--bs-bg);
  color: var(--bs-text);
  font-family: var(--bs-font-body);
  font-size: var(--bs-text-body);
  font-weight: var(--bs-weight-body);
  line-height: var(--bs-leading-body);
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}
body { margin: 0; min-height: 100vh; display: flex; flex-direction: column; }
main { flex: 1 0 auto; }

img, svg, video { max-width: 100%; height: auto; display: block; }
img { font-style: italic; }           /* alt text renders italic when an image fails */

h1, h2, h3, h4 {
  font-family: var(--bs-font-display);
  font-weight: var(--bs-weight-display);
  letter-spacing: var(--bs-tracking-display);
  line-height: var(--bs-leading-heading);
  margin: 0;
  overflow-wrap: anywhere;
}
p, ul, ol, blockquote, pre, figure, table { margin: 0; }
strong, b { font-weight: var(--bs-weight-body-strong); }

a { color: var(--bs-link); }
a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: var(--bs-underline-w) solid var(--bs-accent);
  outline-offset: 2px;
}
::selection { background: var(--bs-selection); }

code, kbd, samp, pre {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-variant-ligatures: none;
}
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

/* ---- Shared primitives -------------------------------------------------- */

/* One column, the reading width, centred. Every band of the page uses it. */
.container {
  max-width: calc(var(--bs-measure) + 2 * var(--bs-gutter));
  margin: 0 auto;
  padding-left: var(--bs-gutter);
  padding-right: var(--bs-gutter);
}

/* Mono metadata line: "07 JUN 2026 · 14 MIN · PLATFORM ENGINEERING" */
.meta {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-meta);
  line-height: 1.5;
  letter-spacing: var(--bs-tracking-meta);
  text-transform: uppercase;
  color: var(--bs-muted);
}
.meta__date { color: var(--bs-accent); }
.meta__sep { margin: 0 0.35em; }

/* Mono uppercase link with the accent underline (nav, "more", prev/next) */
.mono-link {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-meta);
  letter-spacing: var(--bs-tracking-nav);
  text-transform: uppercase;
  color: var(--bs-text);
  text-decoration: none;
  border-bottom: var(--bs-underline-w) solid var(--bs-accent);
  padding-bottom: 2px;
}
.mono-link:hover { border-bottom-color: var(--bs-text); }

/* Tag chips */
.tags { display: flex; flex-wrap: wrap; gap: var(--bs-space-2); list-style: none; margin: 0; padding: 0; }
.tags > li { display: contents; }
.tag {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-tag);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--bs-tracking-meta);
  color: var(--bs-muted);
  text-decoration: none;
  border: var(--bs-rule-soft-w) solid var(--bs-rule-soft);
  padding: 5px 7px 4px;
}
a.tag:hover { color: var(--bs-text); border-color: var(--bs-text); }

/* Rules */
.rule { border: 0; border-top: var(--bs-rule-w) solid var(--bs-rule); margin: 0; }
.rule--soft { border-top-width: var(--bs-rule-soft-w); border-top-color: var(--bs-rule-soft); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}


/* ==========================================================================
   components.css — the page furniture: masthead, nav, theme toggle,
   post list, post header, post footer nav, archive, site footer.
   Class names are BEM (block__element--modifier). Tokens only.
   ========================================================================== */

/* ---- Masthead ------------------------------------------------------------ */
.masthead { border-bottom: var(--bs-rule-w) solid var(--bs-rule); }
.masthead__inner {
  display: flex; align-items: center; gap: var(--bs-space-4);
  padding-top: 22px; padding-bottom: 14px;
}
.masthead__mark {
  flex: none;
  width: var(--bs-mark-size); height: var(--bs-mark-size);
  border-radius: var(--bs-radius);
}
.masthead__brand { display: block; color: inherit; text-decoration: none; min-width: 0; }
.masthead__name {
  font-family: var(--bs-font-display);
  font-weight: var(--bs-weight-display);
  font-size: var(--bs-text-masthead);
  line-height: 1;
  letter-spacing: var(--bs-tracking-display);
  white-space: nowrap;
}
.masthead__name em { font-style: normal; color: var(--bs-accent); }
.masthead__tagline {
  font-size: var(--bs-text-small);
  line-height: 1.3;
  color: var(--bs-muted);
  margin-top: 5px;
}
.masthead__end { margin-left: auto; display: flex; align-items: center; gap: var(--bs-space-4); }

/* ---- Nav ------------------------------------------------------------------- */
.nav { display: flex; gap: var(--bs-space-4); }
.nav__link {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-meta);
  letter-spacing: var(--bs-tracking-nav);
  text-transform: uppercase;
  color: var(--bs-muted);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: var(--bs-underline-w) solid transparent;
}
.nav__link:hover { color: var(--bs-text); }
.nav__link--active, .nav__link[aria-current="page"] {
  color: var(--bs-text);
  border-bottom-color: var(--bs-accent);
}

/* ---- Theme toggle ------------------------------------------------------- */
/* A 22px square button. Shows a sun on dark, a moon on light. theme.js wires it. */
.theme-toggle {
  flex: none; width: 22px; height: 22px; display: grid; place-items: center;
  color: var(--bs-muted); border-radius: 50%;
}
.theme-toggle:hover { color: var(--bs-text); }
.theme-toggle svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.theme-toggle__moon { display: block; }
.theme-toggle__sun { display: none; }
:root[data-theme="dark"] .theme-toggle__moon { display: none; }
:root[data-theme="dark"] .theme-toggle__sun { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle__moon { display: none; }
  :root:not([data-theme="light"]) .theme-toggle__sun { display: block; }
}

/* ---- Post list (home) ------------------------------------------------- */
.post-list { list-style: none; padding: 0; margin: 0; }
.post-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--bs-thumb-w);
  gap: var(--bs-space-5);
  align-items: start;
  padding: 26px 0;
  border-bottom: var(--bs-rule-soft-w) solid var(--bs-rule-soft);
}
.post-item__body { min-width: 0; }
.post-item__title {
  font-size: var(--bs-text-title);
  margin: var(--bs-space-2) 0 6px;
}
.post-item__title a { color: inherit; text-decoration: none; }
.post-item__title a:hover { text-decoration: underline; text-decoration-color: var(--bs-accent); text-decoration-thickness: var(--bs-underline-w); text-underline-offset: var(--bs-underline-offset); }
.post-item__subtitle {
  font-style: italic;
  font-size: var(--bs-text-subtitle-list);
  line-height: 1.45;
  color: var(--bs-muted);
}
.post-item__tags { margin-top: 10px; }
.post-item__cover {
  width: var(--bs-thumb-w);
  aspect-ratio: var(--bs-thumb-ratio);
  object-fit: cover;
}
/* Archive variant: no thumbnails, tighter rows */
.post-list--compact .post-item { grid-template-columns: 1fr; padding: 18px 0; }
.post-list--compact .post-item__cover { display: none; }
.post-list--compact .post-item__title { font-size: var(--bs-text-h3); }
.post-list--compact .post-item__subtitle { font-size: 16px; }

.post-list__more { padding: 22px 0 6px; }

/* Year heading on the archive page */
.archive__year {
  font-size: var(--bs-text-h2);
  padding-top: var(--bs-space-3);
  margin-top: var(--bs-space-6);
  border-top: var(--bs-rule-w) solid var(--bs-rule);
}
.archive__year:first-child { margin-top: var(--bs-space-2); }

/* ---- Post page ------------------------------------------------------------ */
.post { padding-top: 36px; padding-bottom: var(--bs-space-7); }
.post__meta { margin-bottom: 14px; }
.post__title {
  font-size: var(--bs-text-h1);
  line-height: var(--bs-leading-tight);
  margin-bottom: var(--bs-space-3);
}
.post__subtitle {
  font-style: italic;
  font-size: var(--bs-text-subtitle);
  line-height: 1.4;
  color: var(--bs-muted);
  margin-bottom: var(--bs-space-5);
}
.post__cover { width: 100%; aspect-ratio: var(--bs-thumb-ratio); object-fit: cover; margin-bottom: 28px; }
.post__tags { margin-top: var(--bs-space-6); }

/* Previous / next */
.post-nav {
  margin-top: var(--bs-space-6);
  padding-top: 14px;
  border-top: var(--bs-rule-soft-w) solid var(--bs-rule-soft);
  display: flex; justify-content: space-between; gap: var(--bs-space-4);
}
.post-nav__item {
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-meta);
  line-height: 1.5;
  letter-spacing: var(--bs-tracking-meta);
  text-transform: uppercase;
  color: var(--bs-muted);
  max-width: 48%;
}
.post-nav__item--next { text-align: right; margin-left: auto; }
.post-nav__item a { color: var(--bs-text); text-decoration: none; display: block; }
.post-nav__item a:hover { text-decoration: underline; text-decoration-color: var(--bs-accent); text-decoration-thickness: var(--bs-underline-w); text-underline-offset: var(--bs-underline-offset); }

/* ---- Plain page (About, 404) ------------------------------------------ */
.page { padding-top: 36px; padding-bottom: var(--bs-space-7); }
.page__title { font-size: var(--bs-text-h1); line-height: var(--bs-leading-tight); margin-bottom: var(--bs-space-5); }

/* ---- Site footer -------------------------------------------------------- */
.footer { border-top: var(--bs-rule-w) solid var(--bs-rule); margin-top: auto; }
.footer__inner {
  display: flex; flex-wrap: wrap; gap: var(--bs-space-4) 18px; align-items: center;
  padding-top: 18px; padding-bottom: 18px;
  font-family: var(--bs-font-mono);
  font-weight: var(--bs-weight-mono);
  font-size: var(--bs-text-meta);
  letter-spacing: var(--bs-tracking-nav);
  text-transform: uppercase;
  color: var(--bs-muted);
}
.footer__link { color: var(--bs-text); text-decoration: none; }
.footer__link:hover { border-bottom: var(--bs-underline-w) solid var(--bs-accent); }
.footer__copy { margin-left: auto; }

/* ---- Narrow screens ----------------------------------------------------- */
@media (max-width: 600px) {
  .masthead__inner { flex-wrap: wrap; row-gap: var(--bs-space-3); }
  .masthead__end { margin-left: 0; width: 100%; justify-content: space-between; }
  .nav { gap: var(--bs-space-3); }
  .post-item { grid-template-columns: 1fr; }
  .post-item__cover-link { order: -1; }       /* cover above the text on phones */
  .post-item__cover { width: 100%; }
  .post__title, .page__title { font-size: var(--bs-text-h1-mobile); }
  .footer__copy { margin-left: 0; width: 100%; }
}


/* ==========================================================================
   prose.css — everything the Markdown body of a post can contain.
   Scope: .prose. The generator wraps rendered post.md in <div class="prose">.
   ========================================================================== */

.prose > * + * { margin-top: 22px; }

.prose h2 {
  font-size: var(--bs-text-h2);
  line-height: 1.15;
  margin-top: 36px;
  padding-top: var(--bs-space-3);
  border-top: var(--bs-rule-w) solid var(--bs-rule);
}
.prose h3 { font-size: var(--bs-text-h3); margin-top: var(--bs-space-6); }
.prose h4 { font-size: var(--bs-text-body); margin-top: var(--bs-space-5); }
.prose h2 + *, .prose h3 + *, .prose h4 + * { margin-top: var(--bs-space-3); }

.prose a {
  color: var(--bs-link);
  text-decoration: underline;
  text-decoration-color: var(--bs-accent);
  text-decoration-thickness: var(--bs-underline-w);
  text-underline-offset: var(--bs-underline-offset);
}
.prose a:hover { text-decoration-color: var(--bs-text); }

.prose ul, .prose ol { padding-left: 1.4em; }
.prose li + li { margin-top: 6px; }
.prose li > ul, .prose li > ol { margin-top: 6px; }

.prose blockquote {
  padding-left: 18px;
  border-left: 3px solid var(--bs-accent);
  font-family: var(--bs-font-display);
  font-weight: calc(var(--bs-weight-display) - 100);
  font-size: var(--bs-text-quote);
  line-height: 1.4;
  letter-spacing: -0.01em;
}
.prose blockquote p + p { margin-top: var(--bs-space-3); }
.prose blockquote cite { display: block; margin-top: var(--bs-space-2); font: var(--bs-weight-mono) var(--bs-text-meta) var(--bs-font-mono); letter-spacing: var(--bs-tracking-meta); text-transform: uppercase; color: var(--bs-muted); font-style: normal; }

.prose pre {
  background: var(--bs-code-bg);
  color: var(--bs-code-text);
  padding: 16px 18px;
  font-size: var(--bs-text-code);
  line-height: 1.5;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.prose pre code { background: none; padding: 0; font-size: inherit; color: inherit; }
.prose code {
  background: var(--bs-surface);
  padding: 0.1em 0.35em;
  font-size: var(--bs-text-code-inline);
}

.prose img { width: 100%; }
.prose figure { margin-left: 0; margin-right: 0; }
.prose figcaption { margin-top: var(--bs-space-2); font-size: var(--bs-text-small); color: var(--bs-muted); text-align: center; }

.prose hr { border: 0; border-top: var(--bs-rule-soft-w) solid var(--bs-rule-soft); margin: var(--bs-space-6) 0; }

.prose table { width: 100%; border-collapse: collapse; font-size: 16px; }
.prose th, .prose td { text-align: left; padding: 8px 10px; border-bottom: var(--bs-rule-soft-w) solid var(--bs-rule-soft); vertical-align: top; }
.prose th { font: var(--bs-weight-mono) var(--bs-text-meta) var(--bs-font-mono); letter-spacing: var(--bs-tracking-meta); text-transform: uppercase; color: var(--bs-muted); border-bottom: var(--bs-rule-w) solid var(--bs-rule); }
.prose .table-scroll { overflow-x: auto; }

.prose kbd { font-size: 0.85em; background: var(--bs-surface); border: var(--bs-rule-soft-w) solid var(--bs-rule-soft); padding: 0.1em 0.4em; }
.prose mark { background: var(--bs-selection); color: inherit; }
.prose em { font-style: italic; }
.prose sup { line-height: 0; }

/* Footnotes (markdown-it / remark style) */
.prose .footnotes { margin-top: var(--bs-space-7); padding-top: var(--bs-space-4); border-top: var(--bs-rule-soft-w) solid var(--bs-rule-soft); font-size: 16px; color: var(--bs-muted); }
