/* =========================================================
   1. Fonts (self-hosted, no third-party requests)
   
   Open Sans, the font named by Typora's default theme (Github).
   Variable: one file per style covers weights 400-700.
   ========================================================= */

@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/opensans-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: "Open Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/opensans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Open Sans";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/opensans-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: "Open Sans";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/opensans-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* =========================================================
   2. Design tokens — change these to reskin the site
   ========================================================= */

:root {
  color-scheme: light;

  /* Light: Typora's Github palette, warmed a couple of percent so the page
     reads as paper rather than an unlit white wall. */
  --bg: #fbfaf8;
  --text: #333333;
  --text-secondary: #777777;
  --text-faint: #999999;
  --border: #dcdbd7; /* table borders, blockquote rule */
  --rule: #e5e4e1; /* <hr> */
  --heading-rule: #edece9; /* the rule Typora puts under h1/h2 */
  --pre-border: #e4e3df; /* Typora's outline around code */
  --code-bg: #f4f3f1; /* inline code */
  --pre-bg: #f7f6f4; /* code blocks, table headers, even rows */
  --selection: #b5d6fc;

  /* Font stack from Typora's default theme. Open Sans covers Latin only;
     CJK falls back to the system default. */
  --font-body: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial,
    "Segoe UI Emoji", "SF Pro", sans-serif;
  --font-mono: "Lucida Console", Consolas, "Courier", monospace;

  --content-width: 38.75rem; /* 620px — the narrow reading column */
  --gutter: 20px;

  --body-size: 1rem; /* 16px, matching Typora */
  --line-height: 1.6;
}

/* Dark: this site's own palette — Typora ships no dark theme. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #1f1e1d;
  --text: #ffffff;
  --text-secondary: #b0aea5;
  --text-faint: #87867f;
  --border: #5e5d59;
  --rule: #4a4a48;
  --heading-rule: #5e5d59;
  --pre-border: #5e5d59;
  --code-bg: rgba(255, 255, 255, 0.09);
  --pre-bg: rgba(255, 255, 255, 0.05);
  --selection: rgba(65, 131, 196, 0.45);
}

/* =========================================================
   3. Reset
   ========================================================= */

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
}

::selection {
  background: var(--selection);
  color: inherit;
}

/* =========================================================
   4. Base typography
   ========================================================= */

/* The background lives on <body>, so CSS propagates it to the whole canvas. */

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--body-size);
  line-height: var(--line-height);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* Typora: p, blockquote, ul, ol, dl, table { margin: 0.8em 0 } */
p {
  margin: 0.8em 0;
}

/* Links are told apart by the underline alone; hover lifts them 2px and
   pressing puts them back. top, not transform — links are inline boxes. */
a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.1em;
  text-decoration-thickness: 0.08em;
  position: relative;
  top: 0;
  transition: top 0.16s ease;
}

a:hover {
  top: -2px;
}

a:active {
  top: 0;
}

strong {
  font-weight: 600;
}

em {
  font-style: italic;
}

/* Typora: hr { height: 2px; margin: 16px 0; background-color: #e7e7e7; border: 0 } */
hr {
  height: 2px;
  margin: 16px 0;
  background-color: var(--rule);
  border: 0;
  box-sizing: content-box;
}

/* =========================================================
   5. Layout
   ========================================================= */

.container {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---- Header ---- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  padding-top: 15px;
  padding-bottom: 10px;
  margin-top: 15px;
  margin-bottom: 25px;
  transition: background-color 0.2s ease;
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 0.6em;
}

.site-title {
  font-size: 1.8rem; /* 1.44em x 20px = 28.8px */
  font-weight: 600;
  line-height: 1;
  margin: 0;
  text-decoration: none;
  white-space: nowrap;
}

/* Push the theme switch to the far right. */
.toggle-switch {
  position: relative;
  width: 40px;
  height: 20px;
  margin-left: auto;
  flex: none;
}

.toggle-switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.toggle-label {
  position: absolute;
  inset: 0;
  border: 1px solid var(--text);
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.toggle-label::before {
  content: "";
  position: absolute;
  left: 2px;
  bottom: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--text);
  transition: transform 0.2s ease, background-color 0.2s ease;
}

.toggle-switch input:checked + .toggle-label {
  background: var(--text);
}

.toggle-switch input:checked + .toggle-label::before {
  background: var(--bg);
  transform: translateX(20px);
}

.toggle-switch input:focus-visible + .toggle-label {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

/* ---- Main ---- */

.page-main {
  padding-bottom: 3em;
}

/* =========================================================
   6. Home page
   ========================================================= */

/* ---- Category blocks: posts / course / research ---- */

.section {
  margin-top: 1.3em;
}

.section--last {
  margin-bottom: 3em;
}

.section-title {
  font-size: 1.5rem; /* 1.2em x 20px = 24px */
  font-weight: 600;
  line-height: 1.2;
  margin: 0 0 0.7em;
}

/* The heading is a button, styled as the plain heading it looks like. */

.section-toggle {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}

.section-toggle__chevron {
  width: 0.6em;
  height: 0.6em;
  flex: none;
  opacity: 0.4;
  transition: transform 0.25s ease, opacity 0.2s ease;
}

.section-toggle:hover .section-toggle__chevron,
.section-toggle:focus-visible .section-toggle__chevron {
  opacity: 1;
}

.section.is-collapsed .section-toggle__chevron {
  transform: rotate(-90deg);
}

/* ---- Folding a category away ----
   The same 0fr to 1fr grid trick the intro's "More" block uses. */

.section-body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.3s ease, margin-block 0.3s ease;
  /* Room for the hover lift; the negative margin hands the space back. */
  margin-block: -0.5em;
}

.section-body__inner {
  overflow: hidden;
  padding-block: 0.5em;
  transition: padding-block 0.3s ease;
}

/* Collapse padding and negative margin too, or the padding box keeps a
   sliver of the timeline visible. */
.section.is-collapsed .section-body {
  grid-template-rows: 0fr;
  margin-block: 0;
}

.section.is-collapsed .section-body__inner {
  padding-block: 0;
}

/* ---- The link list, drawn as a timeline ----
   Each entry is a row of year | spine | title. */

.link-list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}

/* The spine: one line down the whole list. */
.link-list::before {
  content: "";
  position: absolute;
  left: 4.25em;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
}

.link-list > li {
  display: grid;
  /* year | the strip the spine runs down | title */
  grid-template-columns: 3.5em 1.5em minmax(0, 1fr);
  align-items: baseline;
  padding-block: 0.45em;
}

/* The year, to the left of the spine. */
.entry-meta {
  grid-column: 1;
  text-align: right;
  color: inherit;
}

.link-list > li > a {
  grid-column: 3;
  justify-self: start;
}

/* ---- The "More" expander on the home page ---- */

.intro > p {
  margin-bottom: 0;
}

.intro-more {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}

/* overflow:hidden makes this a BFC, so the margins of the paragraphs inside
   count towards its height. */
.intro-more > div {
  overflow: hidden;
}

.intro-more > div > p:first-child {
  margin-top: 1em;
}

.intro.is-open .intro-more {
  grid-template-rows: 1fr;
}

.intro.is-open .intro-ellipsis {
  display: none;
}

.intro-toggle {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.1em;
  text-decoration-thickness: 0.08em;
  transition: color 0.2s linear;
}

.intro-toggle:hover {
  color: var(--text-secondary);
}

/* =========================================================
   7. Article page
   
   Sizes, line heights and spacing follow Typora's default theme (Github).
   Baseline: html 16px, body 1rem.
   ========================================================= */

/* Typora: h1 { font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid #eee } */
.article-title {
  font-size: 2.25em;
  font-weight: 700;
  line-height: 1.2;
  margin: 1rem 0;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--heading-rule);
  text-wrap: balance;
}

.article-date {
  color: var(--text-secondary);
  font-size: 0.9em;
  margin: 0 0 2em;
}

.article-body {
  /* Both of these come from Typora's #write. */
  overflow-wrap: break-word;
  word-break: normal;
}

/* Typora: h1..h6 { margin: 1rem 0; font-weight: bold; line-height: 1.4 } */
.article-body h1,
.article-body h2,
.article-body h3,
.article-body h4,
.article-body h5,
.article-body h6 {
  margin: 1rem 0;
  font-weight: 700;
  line-height: 1.4;
}

.article-body h1 {
  font-size: 2.25em;
  line-height: 1.2;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--heading-rule);
}

.article-body h2 {
  font-size: 1.75em;
  line-height: 1.225;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--heading-rule);
}

.article-body h3 {
  font-size: 1.5em;
  line-height: 1.43;
}

.article-body h4 {
  font-size: 1.25em;
}

.article-body h5 {
  font-size: 1em;
}

.article-body h6 {
  font-size: 1em;
  color: var(--text-secondary);
}

/* Typora: p, blockquote, ul, ol, dl, table { margin: 0.8em 0 } */
.article-body p,
.article-body blockquote,
.article-body ul,
.article-body ol,
.article-body dl,
.article-body table {
  margin: 0.8em 0;
}

.article-body ul,
.article-body ol {
  padding-left: 30px;
}

.article-body li > ul,
.article-body li > ol {
  margin: 0;
}

/* Typora: blockquote { border-left: 4px solid #dfe2e5; padding: 0 15px; color: #777 } */
.article-body blockquote {
  border-left: 4px solid var(--border);
  padding: 0 15px;
  color: var(--text-secondary);
}

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

/* An image at the end of a paragraph gets its own line; one sitting
   mid-sentence stays inline. */
.article-body p > img:last-child {
  display: block;
  margin: 1.2em auto;
}

/* ---- Tables ----
   Typora: th, td { border: 1px solid #dfe2e5; padding: 6px 13px }
           th { font-weight: bold; border-bottom: 0 }
           tr:nth-child(2n), thead { background-color: #f8f8f8 } */

.article-body table {
  width: 100%;
  border-collapse: collapse;
}

.article-body th,
.article-body td {
  text-align: left;
  vertical-align: top;
  border: 1px solid var(--border);
  padding: 6px 13px;
}

.article-body th {
  font-weight: 700;
  border-bottom: 0;
}

.article-body tr:nth-child(2n),
.article-body thead {
  background-color: var(--pre-bg);
}

/* ---- Code ----
   Typora: .md-fences, code, tt { border: 1px solid #e7eaed;
                                  background-color: #f8f8f8;
                                  border-radius: 3px; font-size: 0.9em }
           code { background-color: #f3f4f4; padding: 0 2px }
           .md-fences { margin: 15px 0; padding-top: 8px; padding-bottom: 6px } */

.article-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--code-bg);
  border: 1px solid var(--pre-border);
  border-radius: 3px;
  padding: 0 2px;
}

.article-body pre {
  background: var(--pre-bg);
  border: 1px solid var(--pre-border);
  border-radius: 3px;
  margin: 15px 0;
  padding: 8px 12px 6px;
  font-size: 0.9em;
  overflow-x: auto;
}

.article-body pre code {
  background: none;
  border: 0;
  padding: 0;
  font-size: 1em;
}

/* Keep a jumped-to heading from hiding under the sticky header. */
.article-body h2,
.article-body h3 {
  scroll-margin-top: 4.5rem;
}

/* ---- Task lists ---- */

.article-body .contains-task-list {
  list-style: none;
  padding-left: 0;
}

.article-body .task-list-item {
  list-style: none;
}

.article-body .task-list-item-checkbox {
  margin-right: 0.5em;
}

/* ---- Footnotes ---- */

.article-body .footnotes {
  margin-top: 2em;
  font-size: 0.9em;
  color: var(--text-secondary);
}

.article-body .footnotes-sep {
  margin: 2.5em 0 1.5em;
}

.article-body .footnote-ref a,
.article-body .footnote-backref {
  text-decoration: none;
}

.article-body .footnote-item {
  margin-bottom: 0.4em;
}

/* =========================================================
   8. Table of contents (generated by typora2site.py)
   
   A fixed sidebar down the left edge. The toggle is a plain icon button in
   the header. Opening it moves nothing: the 620px article is centred, so
   the sidebar lands in the empty margin beside it.
   ========================================================= */

:root {
  /* Tracks the empty margin left of the article, floor of 140px. */
  --toc-width: clamp(140px, calc((100vw - var(--content-width)) / 2), 240px);
}

/* ---- The sidebar itself ---- */

.toc {
  display: none;
  font-size: 1.0625rem; /* 17px, one step up from the body text */
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 4; /* below the header's 5, so the header always covers it */
  width: var(--toc-width);
  overflow-y: auto;
  margin: 0;
  padding: 100px 20px 40px;
  background: var(--bg);
  /* Fades with the page when the theme changes. */
  transition: background-color 0.2s ease;
  scrollbar-width: none;
}

.toc::-webkit-scrollbar {
  display: none;
}

/* Always collapsed by default; only the button opens it. */
html[data-toc="open"] .toc {
  display: block;
}

/* No .page-main margin: opening the sidebar moves nothing. */

.toc-title {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 0.7em;
}

.toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.toc-item {
  margin: 0 0 0.42em;
  line-height: 1.45;
}

/* No underlines; opacity does the ranking. */
.toc-link {
  text-decoration: none;
  opacity: 0.5;
  /* top is the lift every link gets; opacity is this list's own hover. */
  transition: opacity 0.2s ease, top 0.16s ease;
}

.toc-link:hover,
.toc-link.is-active {
  opacity: 1;
}

.toc-level-3 {
  padding-left: 1.1em;
  font-size: 0.92em;
}

/* ---- The icon button in the header ----
   The sticky header is already positioned, so it is the containing block,
   and absolute positioning keeps the button out of flow. */

.toc-toggle {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.toc-toggle:hover {
  opacity: 1;
}

.toc-toggle:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 1px;
}

.toc-icon {
  display: none;
  width: 26px;
  height: 26px;
}

/* Shift the header content right when the name would collide with the button.
   :has() keeps this to pages that have one. */

@media (max-width: 700px) {
  .site-header__inner:has(.toc-toggle) {
    padding-left: 54px;
  }
}

/* Hamburger when collapsed (the default), X when open. */

.toc-icon--menu {
  display: block;
}

html[data-toc="open"] .toc-icon--menu {
  display: none;
}

html[data-toc="open"] .toc-icon--close {
  display: block;
}

/* =========================================================
   9. Small screens
   ========================================================= */

@media (max-width: 600px) {
  .article-title {
    font-size: 1.7rem;
  }
}

/* Respect the OS "reduce motion" setting. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
