/* tzafrir.net
   One page, two readings: typeset for people, Markdown for agents.
   Both views are drawn from the same markup; the Markdown syntax is
   generated by the rules at the bottom of this file. */

:root {
  --paper: #f1f2ee;
  --ink: #1d1f25;
  --graphite: #5d616a;
  --rule: #cdd0c9;
  --pencil: #2c52cf;

  --serif: "Spectral", "Iowan Old Style", Georgia, serif;
  --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  /* Typeset scale (Bringhurst): 14 / 19 / 24 / 48 on a 28px line. */
  --body: 1.1875rem;
  --line: 1.75rem;
  --gutter: 5.5rem;
  --measure: 34rem;

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #191b20;
    --ink: #e3e4df;
    --graphite: #9a9ea7;
    --rule: #34373f;
    --pencil: #93a9ff;
  }
}
:root[data-theme="dark"] {
  --paper: #191b20;
  --ink: #e3e4df;
  --graphite: #9a9ea7;
  --rule: #34373f;
  --pencil: #93a9ff;
}

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

html {
  background: var(--paper);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0 auto;
  max-width: calc(var(--gutter) + var(--measure) + 2rem);
  padding: calc(var(--line) * 2) 1rem calc(var(--line) * 3);
  background: var(--paper);
  font-family: var(--serif);
  font-size: var(--body);
  line-height: var(--line);
  font-variant-numeric: oldstyle-nums proportional-nums;
  font-kerning: normal;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, ul, pre { margin: 0; }
ul { padding: 0; list-style: none; }

a {
  color: var(--pencil);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
a:hover { text-decoration-thickness: 2px; }

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

/* Masthead ---------------------------------------------------------- */

.masthead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: calc(var(--line) * 4);
  padding-left: var(--gutter);
}

/* Breadcrumb: where this page sits on the site. */
.crumbs { font-style: italic; color: var(--graphite); }
.crumbs a { color: inherit; text-decoration: none; }
.crumbs a:hover { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; }
.crumbs [aria-current] { color: var(--ink); }
.crumbs .sep { padding: 0 0.35em; }

.view-toggle {
  font: inherit;
  font-size: 0.875rem;
  line-height: var(--line);
  color: var(--pencil);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.view-toggle:hover { text-decoration-thickness: 2px; }

/* Content ----------------------------------------------------------- */

main > section,
.colophon { padding-left: var(--gutter); }

main > section + section,
main > .demo + section { margin-top: calc(var(--line) * 3); }

h1 {
  font-size: 3rem;
  line-height: calc(var(--line) * 2);
  font-weight: 200;
  letter-spacing: -0.01em;
  margin-bottom: var(--line);
}

.lede {
  text-wrap: pretty;
  font-size: 1.5rem;
  line-height: calc(var(--line) * 1.25);
  max-width: 30rem;
}

h2 {
  font-size: var(--body);
  font-weight: 400;
  font-style: italic;
  color: var(--graphite);
  margin-bottom: var(--line);
}

h3 {
  font-size: var(--body);
  font-weight: 500;
}

.project + .project { margin-top: calc(var(--line) * 1.5); }

.project {
  position: relative;
  max-width: var(--measure);
}

/* Year hangs in the left gutter, in the serif's own old-style figures. */
.when {
  position: absolute;
  left: calc(var(--gutter) * -1);
  width: calc(var(--gutter) - 1.5rem);
  font-style: italic;
  color: var(--graphite);
}

:is(.project, .prose) p { max-width: var(--measure); text-wrap: pretty; }
.project p + p,
.prose > * + * { margin-top: calc(var(--line) / 2); }
.prose { max-width: var(--measure); }
.prose ul { list-style: "\2013\00a0\00a0"; padding-left: 1.25em; }

/* Commands and code are the only typeset text that is literally for
   machines, so they are the only place the monospace appears here. */
:not(pre) > code { font-family: var(--mono); font-size: 0.8em; }

main pre {
  margin-top: calc(var(--line) / 2);
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: calc(var(--line) * 0.75);
  color: var(--graphite);
  overflow-x: auto;
}

.project-list:has(li) + .empty { display: none; }
.empty { color: var(--graphite); max-width: var(--measure); }

/* Demos: the README GIFs, re-encoded as silent looping video. On a mod
   page the demo leaves the text column and takes the gutter too. */
.demo { margin: calc(var(--line) / 2) 0 0; }
main > .demo { margin-top: calc(var(--line) * 2); }
.demo video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border-radius: 3px;
  background: #282c34;
}
.demo video:not([controls]) { cursor: pointer; }

.colophon {
  margin-top: calc(var(--line) * 5);
  font-size: 0.875rem;
  color: var(--graphite);
}

/* Narrow screens: the gutter folds away and the year sits above. */
@media (max-width: 40rem) {
  :root { --gutter: 0rem; --body: 1.125rem; }
  body { padding-top: var(--line); }
  .masthead { margin-bottom: calc(var(--line) * 2.5); }
  h1 { font-size: 2.25rem; line-height: calc(var(--line) * 1.5); }
  .lede { font-size: 1.25rem; line-height: calc(var(--line) * 1.1); }
  .when { position: static; width: auto; }
}

/* ===================================================================
   Markdown view
   The same DOM, reset onto a character grid. Every block is one line
   or a whole number of lines tall, and the syntax is drawn with
   generated content so the two views can never drift apart.
   =================================================================== */

[data-view="markdown"] {
  --line: 1.5rem;
  --gutter: 0rem;
  --measure: 72ch;
}

[data-view="markdown"] body {
  font-family: var(--mono);
  font-size: 0.9375rem;
  font-variant-numeric: normal;
  max-width: calc(72ch + 2rem);
}

[data-view="markdown"] .view-toggle { font-family: inherit; font-size: inherit; }

[data-view="markdown"] :is(h1, h2, h3, .lede, main pre, .colophon, code) {
  font-family: inherit;
  font-size: inherit;
  line-height: var(--line);
  letter-spacing: 0;
  font-style: normal;
  color: var(--ink);
}

[data-view="markdown"] :is(h1, h2, h3) { font-weight: 700; }
[data-view="markdown"] h1 { margin-bottom: var(--line); }
[data-view="markdown"] .lede { max-width: none; }
[data-view="markdown"] main > section + section { margin-top: calc(var(--line) * 2); }
[data-view="markdown"] .project + .project { margin-top: calc(var(--line) * 2); }
/* In Markdown the year reads after its heading, one blank line apart. */
[data-view="markdown"] .project { display: flex; flex-direction: column; gap: var(--line); }
[data-view="markdown"] .project h3 { order: -1; }
[data-view="markdown"] .project pre { margin-top: 0; }
[data-view="markdown"] .when { position: static; width: auto; color: var(--ink); }
[data-view="markdown"] .crumbs { font-style: normal; }
[data-view="markdown"] .project p + p,
[data-view="markdown"] .prose > * + * { margin-top: var(--line); }
[data-view="markdown"] main > .demo { margin-top: var(--line); }
[data-view="markdown"] main > .demo + section { margin-top: calc(var(--line) * 2); }
[data-view="markdown"] .prose ul { list-style: none; padding-left: 0; }
[data-view="markdown"] :not(pre) > code::before,
[data-view="markdown"] :not(pre) > code::after { content: "`"; color: var(--graphite); }
[data-view="markdown"] strong::before,
[data-view="markdown"] strong::after { content: "**"; color: var(--graphite); }
[data-view="markdown"] .demo { margin-top: 0; }
[data-view="markdown"] .demo video { display: none; }
[data-view="markdown"] .demo::before {
  content: attr(data-md);
  color: var(--graphite);
  overflow-wrap: anywhere;
}
[data-view="markdown"] .masthead { margin-bottom: calc(var(--line) * 2); }
[data-view="markdown"] .colophon { margin-top: calc(var(--line) * 3); color: var(--graphite); }
[data-view="markdown"] .empty { color: var(--ink); }

[data-view="markdown"] h1::before { content: "# "; color: var(--graphite); }
[data-view="markdown"] h2::before { content: "## "; color: var(--graphite); }
[data-view="markdown"] h3::before { content: "### "; color: var(--graphite); }

[data-view="markdown"] .when::before,
[data-view="markdown"] .when::after { content: "_"; color: var(--graphite); }

[data-view="markdown"] main a,
[data-view="markdown"] .colophon a { text-decoration: none; }
[data-view="markdown"] main a::before,
[data-view="markdown"] .colophon a::before { content: "["; color: var(--graphite); }
[data-view="markdown"] main a::after,
[data-view="markdown"] .colophon a::after {
  content: "](" attr(href) ")";
  color: var(--graphite);
  overflow-wrap: anywhere;
}
[data-view="markdown"] main a:hover { text-decoration: underline; }

[data-view="markdown"] main li:not(.project)::before { content: "- "; color: var(--graphite); }

[data-view="markdown"] main pre::before { content: "```" attr(data-lang) "\A"; color: var(--graphite); }[data-view="markdown"] main pre::after { content: "\A```"; color: var(--graphite); }
[data-view="markdown"] main pre { white-space: pre-wrap; }

@media (prefers-reduced-motion: no-preference) {
  body.switching main,
  body.switching .colophon { animation: settle 180ms ease-out; }
  @keyframes settle { from { opacity: 0.25; } }
}
