/*
 * dev.arman.ac
 *
 * The spectrum from arman.ac is used as an instrument, not a decoration:
 * each post's tick takes its hue from where it sits in time, and on a post
 * the spectrum fills as you read. Everything else stays quiet so the writing
 * and the code lead.
 */

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

:root {
  --font-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --font-text: "Atkinson Hyperlegible Next", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --bg: #fcfcfc;
  --surface: #f2f2f1;
  --ink: #111111;
  --ink-2: #474747;
  --ink-3: #6b6b6b;
  --rule: #e2e2e0;
  --accent: #2456d3;
  --spec-s: 88%;
  --spec-l: 47%;

  /* Syntax */
  --syn-comment: #8a8a86;
  --syn-keyword: #5a3fd0;
  --syn-string: #17774a;
  --syn-number: #a14d00;
  --syn-func: #1f5ccc;
  --syn-type: #b23f12;
  --syn-builtin: #a3246f;

  /* hue(p) = 20 + 300p: orange → yellow → green → blue → violet → magenta */
  --spectrum: linear-gradient(
    90deg,
    hsl(20 var(--spec-s) var(--spec-l)),
    hsl(80 var(--spec-s) var(--spec-l)) 20%,
    hsl(140 var(--spec-s) var(--spec-l)) 40%,
    hsl(200 var(--spec-s) var(--spec-l)) 60%,
    hsl(260 var(--spec-s) var(--spec-l)) 80%,
    hsl(320 var(--spec-s) var(--spec-l))
  );

  --measure: 41rem;
  --gutter: 7rem;
  --pad: 1.25rem;

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #000000;
    --surface: #0d0d0d;
    --ink: #ececec;
    --ink-2: #a6a6a6;
    --ink-3: #868686;
    --rule: #1d1d1d;
    --accent: #7aa2ff;
    --spec-s: 100%;
    --spec-l: 64%;

    --syn-comment: #737373;
    --syn-keyword: #a99cff;
    --syn-string: #84dca2;
    --syn-number: #ffd970;
    --syn-func: #84abff;
    --syn-type: #ffa36b;
    --syn-builtin: #ff8fd2;
  }
}

/* ---------- Base ---------- */

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

html {
  /* Reserve the scrollbar's space so pages don't shift when it appears. */
  scrollbar-gutter: stable;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 400 1.0625rem/1.7 var(--font-text);
  font-feature-settings: "kern";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main {
  flex: 1;
}

::selection {
  background: color-mix(in srgb, var(--accent) 28%, transparent);
}

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

a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  text-underline-offset: 0.2em;
  transition: text-decoration-color 0.15s ease;
}

a:hover {
  text-decoration-color: currentColor;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: var(--pad);
  top: -3rem;
  padding: 0.4rem 0.8rem;
  background: var(--ink);
  color: var(--bg);
  z-index: 20;
}

.skip:focus {
  top: 0.75rem;
}

/*
 * Every block is a three-column grid: a gutter on each side and the reading
 * measure in the middle. Prose sits in the measure; code, tables and figures
 * break out into the gutters, because code lines run longer than sentences.
 */
.frame,
.prose {
  display: grid;
  align-content: start;
  grid-template-columns:
    [full-start] minmax(var(--pad), 1fr)
    [wide-start] minmax(0, var(--gutter))
    [text-start] min(var(--measure), 100% - 2 * var(--pad))
    [text-end] minmax(0, var(--gutter))
    [wide-end] minmax(var(--pad), 1fr)
    [full-end];
}

.frame > *,
.prose > * {
  grid-column: text;
  /* Long code lines must scroll inside their block, not widen the grid. */
  min-width: 0;
}

.prose {
  grid-column: full;
}

/* ---------- Header & footer ---------- */

.site-head__inner,
.site-foot__inner {
  grid-column: wide;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
}

.site-head {
  padding-block: 1.75rem 0;
}

.wordmark {
  font: 600 1.0625rem/1 var(--font-display);
  letter-spacing: -0.01em;
  text-decoration: none;
}

.wordmark__sub {
  color: var(--ink-3);
  font-weight: 500;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  font: 500 0.9375rem/1.4 var(--font-display);
}

.site-nav a {
  color: var(--ink-2);
  text-decoration: none;
}

.site-nav a:hover,
.site-nav a[aria-current="page"] {
  color: var(--ink);
}

.site-foot {
  margin-top: 6rem;
  padding-block: 1.5rem 2.5rem;
  color: var(--ink-3);
  font-size: 0.875rem;
}

.site-foot__inner {
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
}

.site-foot .site-nav {
  font: inherit;
}

/* ---------- Homepage ---------- */

/* Post list: dates hang in the left gutter so titles line up with prose. */
.entries {
  grid-column: wide;
  list-style: none;
  margin: clamp(2.5rem, 7vw, 4.5rem) 0 0;
  padding: 0;
}

.entry {
  display: grid;
  grid-template-columns: var(--gutter) minmax(0, var(--measure));
  padding-block: 1.5rem;
  border-top: 1px solid var(--rule);
}

.entry:last-child {
  border-bottom: 1px solid var(--rule);
}

.entry__date {
  position: relative;
  padding-left: 0.875rem;
  font: 400 0.8125rem/2.15 var(--font-mono);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* The post's own colour, matching its line on the spectrum. */
.entry__date::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 2px;
  height: 1.05em;
  background: hsl(calc(20 + var(--p) * 300) var(--spec-s) var(--spec-l));
  transition: height 0.2s ease;
}

.entry:hover .entry__date::before {
  height: 1.6em;
  top: 0.3em;
}

.entry__title {
  margin: 0;
  font: 600 1.375rem/1.25 var(--font-display);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.entry__title a {
  text-decoration: none;
}

.entry__title a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

/* Make the whole row clickable without nesting block content in a link. */
.entry {
  position: relative;
}

.entry__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.entry__desc {
  margin: 0.4rem 0 0;
  color: var(--ink-2);
  line-height: 1.55;
  text-wrap: pretty;
}

.entry__meta {
  margin: 0.5rem 0 0;
  font: 400 0.8125rem/1 var(--font-mono);
  color: var(--ink-3);
}

.empty {
  margin-top: clamp(2.5rem, 7vw, 4.5rem);
  color: var(--ink-2);
}

/* ---------- Article ---------- */

.article {
  grid-column: full;
  display: grid;
  grid-template-columns: subgrid;
}

.article > * {
  grid-column: text;
}

.article > .prose {
  grid-column: full;
}

.article__head {
  padding-block: clamp(3rem, 9vw, 6rem) 2.5rem;
}

.article__meta {
  margin: 0 0 1.25rem;
  display: flex;
  gap: 0.6rem;
  font: 400 0.8125rem/1 var(--font-mono);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.article__title {
  margin: 0;
  font: 600 clamp(2rem, 5.4vw, 3rem)/1.08 var(--font-display);
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.article__lede {
  margin: 1.25rem 0 0;
  color: var(--ink-2);
  font-size: 1.1875rem;
  line-height: 1.55;
  text-wrap: pretty;
}

.page--post .article__head {
  border-bottom: 1px solid var(--rule);
  margin-bottom: 2.5rem;
}

/* Reading progress, drawn with the same spectrum. Pure CSS where supported. */
.progress {
  position: fixed;
  inset: 0 0 auto;
  height: 2px;
  background: var(--spectrum);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 10;
}

@supports (animation-timeline: scroll()) {
  .progress {
    animation: progress linear both;
    animation-timeline: scroll(root);
  }
}

@keyframes progress {
  to {
    transform: scaleX(1);
  }
}

/* ---------- Prose ---------- */

.prose > * {
  margin-block: 0 1.25rem;
}

.prose p,
.prose li {
  text-wrap: pretty;
  overflow-wrap: break-word;
}

.prose h2,
.prose h3,
.prose h4 {
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  text-wrap: balance;
  scroll-margin-top: 1.5rem;
}

.prose h2 {
  margin-block: 3.25rem 1rem;
  font-size: 1.625rem;
  line-height: 1.2;
}

.prose h3 {
  margin-block: 2.25rem 0.75rem;
  font-size: 1.25rem;
  line-height: 1.3;
}

.prose h4 {
  margin-block: 1.75rem 0.5rem;
  font-size: 1.0625rem;
}

/* Section links, added by main.js. They sit in the left gutter. */
.anchor {
  position: absolute;
  right: 100%;
  padding-right: 0.5rem;
  color: var(--ink-3);
  font-weight: 500;
  text-decoration: none;
  opacity: 0;
  transition: opacity 0.15s ease;
}

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

.prose a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
}

.prose a:hover {
  text-decoration-color: var(--accent);
}

.prose strong {
  font-weight: 600;
}

.prose ul,
.prose ol {
  padding-left: 1.25rem;
}

.prose li + li,
.prose li > ul,
.prose li > ol {
  margin-top: 0.35rem;
}

.prose li::marker {
  color: var(--ink-3);
}

.prose blockquote {
  margin-inline: 0;
  padding-left: 1.25rem;
  border-left: 2px solid var(--rule);
  color: var(--ink-2);
}

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

.prose hr {
  width: 100%;
  height: 0;
  margin-block: 3rem;
  border: 0;
  border-top: 1px solid var(--rule);
}

.prose img,
.prose video {
  display: block;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
}

.prose p:has(> img:only-child),
.prose figure {
  grid-column: wide;
  margin-block: 2rem;
}

.prose figure {
  margin-inline: 0;
}

.prose figcaption {
  margin-top: 0.75rem;
  color: var(--ink-3);
  font-size: 0.875rem;
  text-align: center;
}

/* Proofs end with a tombstone; so do posts. */
.prose--post > p:last-child::after,
.prose--post > p:has(+ .footnotes)::after {
  content: "\220E";
  margin-left: 0.5em;
  color: var(--ink-3);
}

/* Footnotes (kramdown) */
.prose sup a {
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 0.75em;
  padding-inline: 0.1em;
}

.prose .reversefootnote {
  font-variant-emoji: text;
  text-decoration: none;
}

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

/* Table of contents: write `* TOC` then `{:toc}` in a post. */
.prose #markdown-toc {
  padding: 1rem 0 1rem 1.25rem;
  border-left: 2px solid var(--rule);
  list-style: none;
  font-size: 0.9375rem;
}

.prose #markdown-toc ul {
  list-style: none;
  padding-left: 1rem;
}

.prose #markdown-toc a {
  color: var(--ink-2);
  text-decoration: none;
}

.prose #markdown-toc a:hover {
  color: var(--ink);
}

/* Tables */
.prose table {
  display: block;
  max-width: 100%;
  width: max-content;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
}

.prose th,
.prose td {
  padding: 0.5rem 1.5rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  vertical-align: top;
}

.prose th {
  font: 600 0.8125rem/1.4 var(--font-display);
  color: var(--ink-2);
  border-bottom-color: var(--ink-3);
}

/* Math (KaTeX, loaded only for posts with `math: true`) */
.prose .math-block {
  margin-block: 1.5rem;
}

.prose .katex-display {
  margin: 0;
  padding-block: 0.25rem;
  overflow-x: auto;
  overflow-y: hidden;
}

/* ---------- Code ---------- */

code,
kbd,
pre {
  font-family: var(--font-mono);
  font-variant-ligatures: none;
}

.prose :not(pre) > code {
  padding: 0.12em 0.35em;
  border-radius: 4px;
  background: var(--surface);
  font-size: 0.875em;
}

/* Keep short commands like `git rebase --onto` on one line where there is room. */
@media (min-width: 48rem) {
  .prose :not(pre) > code {
    white-space: nowrap;
  }
}

.prose kbd {
  padding: 0.1em 0.4em;
  border: 1px solid var(--rule);
  border-bottom-width: 2px;
  border-radius: 4px;
  font-size: 0.8125em;
}

/* Grid items don't collapse margins, so the top margin stays small. */
.prose .highlighter-rouge:has(pre),
.prose > pre {
  grid-column: wide;
  margin-block: 0.5rem 1.75rem;
}

.prose pre {
  margin: 0;
  padding: 1.125rem 1.25rem;
  overflow-x: auto;
  background: var(--surface);
  border-radius: 6px;
  font-size: 0.875rem;
  line-height: 1.65;
  tab-size: 4;
}

/* Language label and copy button, added by main.js above the code. */
.code-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 2.25rem;
  padding: 0.375rem 0.5rem 0 1.25rem;
  background: var(--surface);
  border-radius: 6px 6px 0 0;
  font: 400 0.75rem/1 var(--font-mono);
  color: var(--ink-3);
}

.code-bar + .highlight pre {
  padding-top: 0.5rem;
  border-radius: 0 0 6px 6px;
}

.code-copy {
  margin-left: auto;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--bg);
  color: var(--ink-2);
  font: inherit;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.highlighter-rouge:hover .code-copy,
.code-copy:focus-visible,
.code-copy[data-state] {
  opacity: 1;
}

@media (hover: none) {
  .code-copy {
    opacity: 1;
  }
}

/* Rouge token classes */
.highlight .c,
.highlight .ch,
.highlight .cm,
.highlight .cp,
.highlight .cpf,
.highlight .c1,
.highlight .cs {
  color: var(--syn-comment);
  font-style: italic;
}

.highlight .k,
.highlight .kc,
.highlight .kd,
.highlight .kn,
.highlight .kp,
.highlight .kr,
.highlight .ow {
  color: var(--syn-keyword);
}

.highlight .s,
.highlight .sa,
.highlight .sb,
.highlight .sc,
.highlight .dl,
.highlight .sd,
.highlight .s2,
.highlight .se,
.highlight .sh,
.highlight .si,
.highlight .sx,
.highlight .sr,
.highlight .s1,
.highlight .ss {
  color: var(--syn-string);
}

.highlight .m,
.highlight .mb,
.highlight .mf,
.highlight .mh,
.highlight .mi,
.highlight .il,
.highlight .mo,
.highlight .mx {
  color: var(--syn-number);
}

.highlight .nf,
.highlight .fm,
.highlight .nd {
  color: var(--syn-func);
}

.highlight .kt,
.highlight .nc,
.highlight .nn,
.highlight .ne {
  color: var(--syn-type);
}

.highlight .nb,
.highlight .bp,
.highlight .vg,
.highlight .no {
  color: var(--syn-builtin);
}

.highlight .gd {
  color: var(--syn-type);
}

.highlight .gi {
  color: var(--syn-string);
}

.highlight .gh,
.highlight .gu {
  color: var(--ink-3);
}

.highlight .err {
  color: inherit;
}

/* ---------- Pager ---------- */

.pager {
  grid-column: text;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

.pager__link {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  text-decoration: none;
}

.pager__link--next {
  grid-column: 2;
  text-align: right;
}

.pager__label {
  font: 400 0.8125rem/1 var(--font-mono);
  color: var(--ink-3);
}

.pager__title {
  font: 600 1.0625rem/1.3 var(--font-display);
  letter-spacing: -0.01em;
}

.pager__link:hover .pager__title {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

/* ---------- Small screens ---------- */

@media (max-width: 47.99rem) {
  :root {
    --gutter: 0rem;
  }

  .entry {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.35rem;
  }

  .entry__date {
    line-height: 1.6;
  }

  .entry__date::before {
    top: 0.3em;
  }

  .anchor {
    display: none;
  }

  .prose .highlighter-rouge:has(pre) {
    margin-inline: calc(-1 * var(--pad));
  }

  .prose pre,
  .code-bar,
  .code-bar + .highlight pre {
    border-radius: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
  }
}

@media print {
  .site-head,
  .site-foot,
  .progress,
  .code-bar,
  .anchor,
  .pager {
    display: none;
  }

  body {
    background: #fff;
    color: #000;
  }
}
