@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,600;1,400&family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap");

/* Arbiter / Trace tokens — two themes from one source. Light is the warm-neutral
   default; dark is graphite. Orange is action/current state, never severity. */
:root {
  --canvas: #F5F3ED;
  --surface: #FCFBF7;
  --surface-raised: #FFFFFF;
  --code: #ECEAE2;
  --ink: #171A1F;
  --muted: #5C6470;
  --line: #8A857B;
  --line-soft: #C8C4BA;
  --accent: #C2410C;
  --accent-hover: #9A3412;
  --accent-ink: #FFFFFF;
  --status-pass: #1F6B45;

  --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --text-h2: 24px;
  --text-h3: 18px;

  --radius-compact: 2px;
  --radius: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;

  --motion-control: 150ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  color-scheme: light;
}

/* An explicit choice, applied to <html> by the head script before first paint. */
:root[data-theme="dark"] {
  --canvas: #111316;
  --surface: #191C21;
  --surface-raised: #22262D;
  --code: #0C0E11;
  --ink: #F2F0E8;
  --muted: #A8AFB8;
  --line: #747D89;
  --line-soft: #59616C;
  --accent: #FB923C;
  --accent-hover: #FDBA74;
  --accent-ink: #1A1005;
  --status-pass: #65C890;

  color-scheme: dark;
}

/* No explicit choice: follow the OS. Covers the JavaScript-disabled visitor too. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --canvas: #111316;
    --surface: #191C21;
    --surface-raised: #22262D;
    --code: #0C0E11;
    --ink: #F2F0E8;
    --muted: #A8AFB8;
    --line: #747D89;
    --line-soft: #59616C;
    --accent: #FB923C;
    --accent-hover: #FDBA74;
    --accent-ink: #1A1005;
    --status-pass: #65C890;

    color-scheme: dark;
  }
}

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

/* The design carries box-sizing inline on exactly these four boxes and nowhere
   else. It must not be global: .btn and .input are sized by height and width, so
   a universal border-box shrinks every button by 2px and the email field by 26px. */
.site-header, .site-main, .site-footer, .consent-row { box-sizing: border-box; }

/* The background lives on <html> so it paints the whole viewport, including the
   overscroll area, before the body box is laid out. */
html { background: var(--canvas); }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

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

.rule { border: 0; border-top: 1px solid var(--line-soft); margin: 0; }

/* ---------- controls ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  padding: 0 var(--space-4);
  height: 40px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--motion-control) var(--ease),
              border-color var(--motion-control) var(--ease),
              color var(--motion-control) var(--ease);
}
.btn:hover { text-decoration: none; }
/* An author `display` beats the UA's [hidden] rule regardless of specificity, so
   a button the page hides would otherwise stay on screen. */
.btn[hidden] { display: none; }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
/* components.css sets only the background here. "Book a call" is an <a>, so the
   global a:hover colour (0,1,1) would outrank .btn-primary's (0,1,0) and paint the
   label accent-hover on an accent-hover background — invisible. Pin the colour. */
.btn-primary:hover { background: var(--accent-hover); color: var(--accent-ink); }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--line); }
.btn-secondary:hover { background: var(--surface-raised); border-color: var(--ink); }
.btn-sm { height: 32px; padding: 0 var(--space-3); font-size: 13px; }

.input {
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  height: 40px;
  padding: 0 var(--space-3);
  transition: border-color var(--motion-control) var(--ease);
}
.input:hover { border-color: var(--ink); }
.input:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }

/* ---------- site header ---------- */

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: 1040px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 32px;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.brand:hover { text-decoration: none; }
.brand-name { font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); }
.site-nav { display: flex; align-items: center; gap: 16px; }

.nav-link, .nav-current {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.nav-link { color: var(--muted); text-decoration: none; }
.nav-link:hover { color: var(--ink); text-decoration: none; }
.nav-current { color: var(--ink); border-bottom: 1px solid var(--accent); padding-bottom: 2px; }

.theme-btn {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-compact);
  padding: 6px 10px;
  cursor: pointer;
  transition: border-color var(--motion-control) var(--ease),
              color var(--motion-control) var(--ease);
}
.theme-btn:hover { border-color: var(--line); color: var(--ink); }
/* The button ships `hidden` and is revealed once script has wired it. Any class
   rule that set `display` would out-specify the UA's [hidden] rule and show it
   anyway — the same trap `.consent` documents one section down. It does not set
   `display` today; this states the requirement so a later one cannot break it. */
.theme-btn[hidden] { display: none; }

/* ---------- main column ---------- */

.site-main {
  flex: 1;
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
  padding: 48px 32px 0;
  font-size: 15px;
  line-height: 1.6;
}

h1 {
  margin: 0;
  font-size: 32px;
  line-height: 1.2;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--ink);
}

.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.tag {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--muted);
  background: var(--code);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-compact);
  padding: 2px 7px;
}
/* Preview-only marker: a draft never reaches the published site. */
.draft-marker { font-family: var(--font-mono); font-size: 12px; font-weight: 400; color: var(--accent); }

/* ---------- index: post rows ---------- */

.post-list { margin-top: 48px; border-top: 1px solid var(--line-soft); }
.post-row { padding: 24px 0; border-bottom: 1px solid var(--line-soft); }
.post-row h2 {
  margin: 0;
  font-size: 19px;
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: -.01em;
}
.post-row h2 a { color: var(--accent); text-decoration: none; }
.post-row h2 a:hover { color: var(--accent-hover); text-decoration: underline; }
.post-row p {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 62ch;
}

/* ---------- index: subscribe panel ---------- */

.subscribe {
  margin-top: 48px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 24px;
}
.subscribe-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.subscribe h2 { margin: 0; font-size: 17px; font-weight: 600; color: var(--ink); }
.subscribe p { margin: 4px 0 0; font-size: 14px; line-height: 1.5; color: var(--muted); }
.subscribe-form { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.subscribe-form .input { width: 210px; }
.subscribe-ok { font-family: var(--font-mono); font-size: 13px; color: var(--status-pass); }
.rss-link { font-family: var(--font-mono); font-size: 12px; color: var(--muted); }
.rss-link:hover { color: var(--ink); }

/* ---------- post page ---------- */

article :is(p, ul, ol, blockquote, pre, table) { margin: 1em 0; }
article h2 {
  font-size: 21px;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 1.6em 0 .6em;
}
/* A markdown body may open with `# Heading`. Without this it would inherit the
   page-title reset — 32px, no margins, flush against the prose and indistinguishable
   from the post's own title. */
article h1 {
  font-size: var(--text-h2);
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 1.6em 0 .6em;
}

/* The design's article CSS stops at h2; goldmark can emit deeper headings, so
   these follow the design system's --text-h3 rather than an invented size. */
article h3, article h4, article h5, article h6 {
  font-size: var(--text-h3);
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 1.4em 0 .5em;
}
article pre {
  background: var(--code);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 14px;
  overflow: auto;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
}
article code { font-family: var(--font-mono); font-size: .9em; }
article :not(pre) > code {
  background: var(--code);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-compact);
  padding: 1px 5px;
}
/* goldmark wraps a fenced block as <pre><code>, so the inline .9em shrink would
   compound with the block's own 13px. The block sets the size; the code element
   inherits it and drops the inline chrome. */
article pre code { font-size: inherit; background: none; border: 0; padding: 0; }
article ul, article ol { padding-left: 24px; }
article li { margin: 4px 0; }
article blockquote {
  border-left: 3px solid var(--line-soft);
  padding-left: 14px;
  margin-left: 0;
  color: var(--muted);
}
article table { border-collapse: collapse; }
article th, article td { border: 1px solid var(--line-soft); padding: 6px 10px; text-align: left; }
article img { max-width: 100%; height: auto; }
article hr { border: 0; border-top: 1px solid var(--line-soft); margin: 2em 0; }

.post-title { text-wrap: balance; }
.post-rule { margin: 24px 0; }
.post-nav-rule { margin: 48px 0 0; }
.post-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  padding: 24px 0 0;
}
.post-nav a { font-family: var(--font-mono); font-size: 12px; color: var(--muted); }
.post-nav .all-posts:hover { color: var(--accent); }

/* ---------- site footer ---------- */

.site-footer {
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
  padding: 48px 32px 32px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.site-footer span, .footer-links a {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
}
.footer-links { display: flex; gap: 20px; flex-wrap: wrap; }
.footer-links a { text-decoration: none; }
.footer-links a:hover { color: var(--ink); text-decoration: none; }
/* The control that reopens the consent notice. A button, not a link: it
   navigates nowhere, and nothing on these pages may issue a request the visitor
   did not ask for. It reads as one of the footer's links. */
.footer-btn {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.footer-btn:hover { color: var(--ink); }

/* ---------- consent banner ---------- */

/* The banner is fixed to the bottom and overlays the footer on a short page.
   That is the designed behavior and it stays: the banner is up only until the
   visitor answers, so reserving permanent bottom padding for it would deform
   every page to accommodate one transient one.

   It is hidden by default and shown only when the blocking head script has
   stamped data-consent="ask" on the root. Deciding in CSS, before first paint,
   is what keeps a fixed bar from appearing under the cursor of a visitor who
   already answered — and a visitor with no JavaScript, who can neither answer
   nor have an answer honoured, never sees it at all. */
.consent {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
  background: var(--surface);
  border-top: 1px solid var(--line-soft);
}
[data-consent="ask"] .consent { display: block; }
.consent-row {
  max-width: 1040px;
  margin: 0 auto;
  padding: 16px 32px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.consent p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink); max-width: 62ch; }
.consent-actions { display: flex; align-items: center; gap: 12px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
