/* ============================================================
   王秀文的博客 — 设计语言：仪表盘 × 中文编辑排版

   三种字体角色：
     宋体   标题（编辑感，中文的骨架）
     黑体   正文（安静、易读）
     等宽   遥测（时间、字数、状态、编号 —— 一切可测量的东西）

   只有一个重色（信号橙），只给活的东西用：当月心跳、阅读进度、hover。
   ============================================================ */

:root {
  --paper:   #FCFCFB;
  --panel:   #F2F3F2;
  --ink:     #12161B;
  --muted:   #5B6672;
  --rule:    #E2E5E4;
  --signal:  #FF4D00;
  --ok:      #17864B;

  --display: "Songti SC", "Song", "SimSun", "Noto Serif CJK SC",
             "Source Han Serif SC", "Georgia", serif;
  --body:    "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
             -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono:    ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  --measure: 34rem;   /* reading column */
  --gutter:  1.5rem;
  --content: 46rem;   /* page width; the reading pages narrow this (see body.reading-page) */
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:  #0E1216;
    --panel:  #161B21;
    --ink:    #E7EAEC;
    --muted:  #8A95A1;
    --rule:   #222A31;
    --signal: #FF5C1A;
    --ok:     #2DBE72;
  }
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }

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

.wrap { max-width: var(--content); margin: 0 auto; padding: 0 var(--gutter); }

/* On an article, the chrome narrows with the text: the wordmark, the title and
   the footer all start on the same vertical line. */
body.reading-page { --content: calc(var(--measure) + 2 * var(--gutter)); }
.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ---------- topbar ---------- */

.topbar {
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
}

.topbar-inner {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  height: 3.5rem;
  max-width: var(--content);
  margin: 0 auto;
}

.wordmark {
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: .02em;
  white-space: nowrap;
}

.topnav {
  display: flex;
  gap: 1rem;
  flex: 1;
  font-family: var(--mono);
  font-size: .75rem;
  letter-spacing: .06em;
}
.topnav a { color: var(--muted); padding: .25rem 0; }
.topnav a:hover { color: var(--signal); }

.search input {
  width: 6.5rem;
  padding: .3rem .6rem;
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  outline: none;
  transition: width .18s ease, border-color .18s ease;
}
.search input::placeholder { color: var(--muted); }
.search input:focus {
  width: 9rem;
  border-bottom-color: var(--signal);
  outline: none;
}

/* ---------- masthead + heartbeat (the signature) ---------- */

.masthead {
  padding: 4rem 0 2.25rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 1rem;
}

.masthead-title {
  font-family: var(--display);
  font-size: clamp(1.9rem, 6vw, 2.6rem);
  font-weight: 700;
  letter-spacing: .01em;
  line-height: 1.25;
  margin: 0;
}

.masthead-desc {
  color: var(--muted);
  margin: .5rem 0 2rem;
  font-size: .95rem;
}

.hb-block { margin-bottom: 2rem; }

.hb-caption {
  display: flex;
  justify-content: space-between;
  margin-top: .5rem;
  padding-top: .4rem;
  border-top: 1px solid var(--rule);
  font-size: .625rem;
  letter-spacing: .1em;
  color: var(--muted);
}

/* One bar per month. Height carries the count; the gaps carry the silences. */
/* The strip now spans the blog's whole life (2020 → now, ~69 bars) rather than a
   fixed 18-month window that happened to be entirely empty. More bars, so the gap
   tightens — at 3px the columns were wider than the data. */
.heartbeat {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 2.75rem;
}

.hb-bar {
  flex: 1;
  display: flex;
  align-items: flex-end;
  height: 100%;
  min-width: 0;
}
/* Level is expressed as opacity over --ink, not as a mixed colour: opacity
   inverts predictably with the theme, where a colour-mix can be double-darkened
   by a browser's own auto-dark pass. */
.hb-bar > i {
  display: block;
  width: 100%;
  height: 2px;                       /* an empty month is a flat line, not a hole */
  background: var(--ink);
  opacity: .12;
  border-radius: 1px;
  transition: background-color .15s ease, opacity .15s ease;
}
.hb-bar.lv1 > i { height: 25%;  opacity: .30; }
.hb-bar.lv2 > i { height: 45%;  opacity: .48; }
.hb-bar.lv3 > i { height: 70%;  opacity: .66; }
.hb-bar.lv4 > i { height: 100%; opacity: .85; }

.hb-bar:hover > i { background: var(--signal); opacity: 1; }
.hb-bar.hb-now > i { background: var(--signal); opacity: 1; }   /* this month is live */
.hb-bar.hb-now.lv0 > i { opacity: .5; }

/* Status readout: the numbers, as instrument data. */
.readout {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  margin: 0;
  font-family: var(--mono);
}
.readout div { display: flex; flex-direction: column; gap: .15rem; }
.readout dt {
  font-size: .6875rem;
  letter-spacing: .1em;
  color: var(--muted);
}
.readout dd {
  margin: 0;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
}

/* ---------- entry list ---------- */

.page-heading {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  margin: 3rem 0 2rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--rule);
}

.entries { display: flex; flex-direction: column; }

.entry {
  display: grid;
  grid-template-columns: 6rem 1fr;
  gap: 1.5rem;
  padding: 2rem 0;
  border-bottom: 1px solid var(--rule);
}
.entry:last-child { border-bottom: 0; }

.entry-rail {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .4rem;
  padding-top: .35rem;
}
.entry-rail time {
  font-size: .75rem;
  color: var(--muted);
  letter-spacing: .02em;
}

.entry-title {
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1.45;
  margin: 0 0 .5rem;
  letter-spacing: .01em;
}
.entry-title a { background-image: linear-gradient(var(--signal), var(--signal));
  background-size: 0 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size .25s ease, color .15s ease;
}
.entry-title a:hover { color: var(--signal); background-size: 100% 1px; }

.entry-excerpt {
  color: var(--muted);
  margin: 0 0 1rem;
  font-size: .9375rem;
  line-height: 1.7;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.entry-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.metric { font-size: .6875rem; color: var(--muted); letter-spacing: .04em; white-space: nowrap; }

/* ---------- tags ---------- */

.tags { display: flex; flex-wrap: wrap; gap: .375rem; }

.tag {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .03em;
  color: var(--muted);
  padding: .1rem .5rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  transition: color .15s ease, border-color .15s ease;
}
.tag:hover { color: var(--signal); border-color: var(--signal); }
.tag.cat { color: var(--ink); border-color: color-mix(in srgb, var(--ink) 30%, transparent); }

.chip {
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .08em;
  padding: .05rem .375rem;
  border-radius: 2px;
  border: 1px solid var(--rule);
  color: var(--muted);
}
.chip.draft { border-style: dashed; }

/* ---------- article ---------- */

.progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 30;
}

.post-head {
  padding: 4rem 0 0;
  margin-bottom: 2.5rem;
}

.post-title {
  font-family: var(--display);
  font-size: clamp(1.75rem, 5.5vw, 2.35rem);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: .01em;
  margin: 0 0 1.5rem;
}

/* The telemetry block: label above value, hairline-separated, like a gauge row. */
.post-telemetry {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 0;
  padding: .875rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.post-telemetry > div {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  padding: 0 1.125rem;
  border-left: 1px solid var(--rule);
}
.post-telemetry > div:first-child { padding-left: 0; border-left: 0; }
.post-telemetry dt {
  font-size: .625rem;
  letter-spacing: .1em;
  color: var(--muted);
}
.post-telemetry dd {
  margin: 0;
  font-size: .8125rem;
  font-variant-numeric: tabular-nums;
}
.post-telemetry dd a:hover { color: var(--signal); }
.post-telemetry .is-draft { color: var(--signal); }

/* ---------- prose ---------- */

.prose { font-size: 1.0625rem; line-height: 1.9; }

.prose > * + * { margin-top: 1.5em; }

.prose h2, .prose h3, .prose h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: .01em;
  margin-top: 2.75em;
  margin-bottom: -.4em;    /* the `* + *` rule adds the rest */
}
.prose h2 { font-size: 1.375rem; }
.prose h3 { font-size: 1.15rem; }
.prose h4 { font-size: 1rem; }

.prose a {
  color: var(--ink);
  border-bottom: 1px solid var(--signal);
  transition: color .15s ease, background-color .15s ease;
}
.prose a:hover { color: var(--signal); }

.prose strong { font-weight: 600; }

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

.prose blockquote {
  margin-left: 0;
  margin-right: 0;
  padding-left: 1.25rem;
  border-left: 2px solid var(--signal);
  color: var(--muted);
}
.prose blockquote > * + * { margin-top: 1em; }

.prose code {
  font-family: var(--mono);
  font-size: .85em;
  background: var(--panel);
  padding: .1em .35em;
  border-radius: 2px;
}

.prose pre {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1rem 1.125rem;
  overflow-x: auto;
  line-height: 1.65;
}
.prose pre code { background: none; padding: 0; font-size: .8125rem; }

.prose ul, .prose ol { padding-left: 1.25rem; }
.prose li + li { margin-top: .4em; }

/* GFM task lists sit flush, checkbox inline with its text. */
.prose li input[type=checkbox] {
  width: auto;
  margin: 0 .4rem 0 0;
  vertical-align: middle;
  accent-color: var(--signal);
}
.prose li:has(> input[type=checkbox]) { list-style: none; margin-left: -1.25rem; }

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: .9375rem;
  display: block;
  overflow-x: auto;
}
.prose th, .prose td {
  border-bottom: 1px solid var(--rule);
  padding: .55rem .75rem;
  text-align: left;
}
.prose th {
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .06em;
  color: var(--muted);
  border-bottom: 1px solid var(--ink);
}
.prose tbody tr:last-child td { border-bottom: 0; }

.prose hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 3em 0;
}

.post-tags { margin-top: 3rem; }

/* ---------- prev / next ---------- */

.post-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  margin-top: 4rem;
  border-top: 1px solid var(--rule);
  background: var(--rule);
}

.pn {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: 1.5rem 0;
  background: var(--paper);
}
.pn.next { text-align: right; align-items: flex-end; padding-left: 1.25rem; }
.pn.prev { padding-right: 1.25rem; }
.pn:only-child { grid-column: 1 / -1; }

.pn-label { font-size: .625rem; letter-spacing: .12em; color: var(--muted); }
.pn-title {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
  transition: color .15s ease;
}
.pn:hover .pn-title { color: var(--signal); }

/* ---------- pagination ---------- */

/* Prev / numbers / next. The numbers are a window (see buildPager) — printing all
   29 pages, as this used to, is wallpaper rather than navigation. */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 3rem 0 0;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}

.pg-step {
  flex: 0 0 auto;
  padding: .4rem .7rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  font-size: .8125rem;
  color: var(--muted);
  white-space: nowrap;
}
.pg-step:hover { color: var(--signal); border-color: var(--signal); }

/* Kept in the layout rather than hidden: the row shouldn't reflow as you page. */
.pg-step.disabled { opacity: .3; pointer-events: none; }

.pg-nums {
  display: flex;
  align-items: center;
  gap: .25rem;
  flex-wrap: wrap;
  justify-content: center;
}

.pg-num {
  min-width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: .8125rem;
  color: var(--muted);
  border: 1px solid transparent;
  border-radius: 3px;
}
.pg-num:hover { color: var(--signal); border-color: var(--signal); }
.pg-num.current { color: var(--paper); background: var(--ink); }

.pg-gap {
  min-width: 1.25rem;
  text-align: center;
  color: var(--rule);
  user-select: none;
}

.pg-caption {
  margin: .75rem 0 0;
  text-align: center;
  font-size: .75rem;
  color: var(--muted);
}

/* On a phone the number window is the first thing to go — the prev/next buttons
   are what a thumb actually uses. */
@media (max-width: 34rem) {
  .pg-nums { display: none; }
  .pagination { justify-content: space-between; }
}

/* ---------- archive ---------- */

.arc-group { margin-bottom: 3rem; scroll-margin-top: 5rem; }

.arc-month {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  margin: 0 0 .75rem;
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--rule);
  font-weight: 400;
}
.arc-y { font-size: 1.125rem; }
.arc-m {
  font-size: 1.125rem;
  color: var(--signal);
}
.arc-m::before { content: "/"; color: var(--rule); margin: 0 .1rem; }
.arc-n { margin-left: auto; font-size: .6875rem; color: var(--muted); letter-spacing: .06em; }

.arc-list { list-style: none; margin: 0; padding: 0; }
.arc-list li {
  display: grid;
  grid-template-columns: 5.5rem 1fr auto;
  gap: 1rem;
  align-items: baseline;
  padding: .5rem 0;
}
.arc-list time { font-size: .75rem; color: var(--muted); }
.arc-list a { transition: color .15s ease; }
.arc-list a:hover { color: var(--signal); }

/* ---------- status page (404) ---------- */

.status-page { padding: 8rem 0; text-align: center; }
.status-code {
  font-size: 4rem;
  font-weight: 500;
  letter-spacing: .06em;
  color: var(--signal);
  line-height: 1;
}
.status-msg { color: var(--muted); margin: 1.25rem 0 .5rem; }
.status-actions { font-family: var(--mono); font-size: .8125rem; }
.status-actions a { color: var(--ink); border-bottom: 1px solid var(--signal); }
.status-actions a:hover { color: var(--signal); }
.status-actions .dot { color: var(--rule); margin: 0 .5rem; }

.empty {
  padding: 5rem 0;
  text-align: center;
  color: var(--muted);
}
.empty a { border-bottom: 1px solid var(--signal); }

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

.footer {
  margin-top: 6rem;
  border-top: 1px solid var(--rule);
  padding: 2rem 0 3rem;
}
.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  font-size: .75rem;
  color: var(--muted);
  max-width: var(--content);
  margin: 0 auto;
}
.footer-links { display: flex; gap: 1.25rem; font-family: var(--mono); }
.footer-links a:hover { color: var(--signal); }

/* ---------- responsive ---------- */

@media (max-width: 640px) {
  .entry { grid-template-columns: 1fr; gap: .625rem; }
  .entry-rail { flex-direction: row; align-items: center; padding-top: 0; }
  .arc-list li { grid-template-columns: 4.5rem 1fr; }
  .arc-list .metric { display: none; }
  .post-nav { grid-template-columns: 1fr; }
  .pn.next { text-align: left; align-items: flex-start; padding-left: 0; }
  .readout { gap: 1.25rem; }
  .post-telemetry > div { padding: .35rem .875rem; }
  .post-telemetry > div:first-child { padding-left: 0; }
  .topnav { gap: .75rem; }
  .search input { width: 4.5rem; }
}

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

/* ============================================================
   后台 —— 同一套语言，但更密、更像控制台。
   正文区留白让位给信息密度：写东西的人要的是掌控感。
   ============================================================ */

body.admin { background: var(--panel); }

.admin-header {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 0;
  z-index: 20;
}
.admin-header .header-inner {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  height: 3.5rem;
  max-width: 72rem;
  margin: 0 auto;
}
.admin-header .brand {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
}
.admin-header nav {
  display: flex;
  gap: 1rem;
  flex: 1;
  font-family: var(--mono);
  font-size: .75rem;
  letter-spacing: .06em;
}
.admin-header nav a { color: var(--muted); }
.admin-header nav a:hover { color: var(--signal); }

.admin-main { max-width: 72rem; margin: 0 auto; padding: 2rem var(--gutter) 5rem; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: .5rem 1rem;
  font-family: var(--mono);
  font-size: .75rem;
  letter-spacing: .06em;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .15s ease, color .15s ease;
}
.btn:hover { border-color: var(--signal); color: var(--signal); }
.btn.primary {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.btn.primary:hover { background: var(--signal); border-color: var(--signal); color: #fff; }
.btn.ghost { background: transparent; }
.btn.small { padding: .3rem .6rem; font-size: .6875rem; }

button.link {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--mono);
  font-size: .6875rem;
  color: var(--muted);
  cursor: pointer;
}
button.link:hover { color: var(--signal); }
button.link.danger:hover { color: var(--signal); }

/* ---------- forms ---------- */

input:not([type=checkbox]):not([type=radio]), textarea, select {
  width: 100%;
  padding: .5rem .625rem;
  font-family: var(--body);
  font-size: .875rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 2px;
  outline: none;
  transition: border-color .15s ease;
}
input:focus, textarea:focus, select:focus { border-color: var(--signal); }

label {
  display: block;
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .08em;
  color: var(--muted);
}
label input, label select, label textarea { margin-top: .35rem; }

.hint { display: block; margin-top: .3rem; font-size: .6875rem; color: var(--muted); }
.muted { color: var(--muted); }
.small { font-size: .8125rem; }

.alert {
  padding: .625rem .875rem;
  margin-bottom: 1.25rem;
  border-radius: 2px;
  border: 1px solid var(--rule);
  border-left: 2px solid var(--rule);
  font-family: var(--mono);
  font-size: .75rem;
}
.alert.ok { border-left-color: var(--ok); color: var(--ok); }
.alert.error { border-left-color: var(--signal); color: var(--signal); }

/* ---------- login ---------- */

.login-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1.25rem;
}
.login-card {
  width: 100%;
  max-width: 20rem;
  display: flex;
  flex-direction: column;
  gap: .875rem;
  padding: 2.25rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
}
.login-card h1 { font-family: var(--display); font-size: 1.25rem; margin: 0; }
.login-card p { margin: 0; }
.login-card .btn { width: 100%; margin-top: .35rem; }
.login-card .muted.small a { border-bottom: 1px solid var(--signal); }

/* ---------- toolbar + table ---------- */

.admin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.stats {
  display: flex;
  gap: 1.5rem;
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--muted);
  letter-spacing: .06em;
}
.stats strong { color: var(--ink); font-size: .9375rem; margin-right: .2rem; }

.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
  font-size: .875rem;
}
.admin-table th {
  font-family: var(--mono);
  font-size: .625rem;
  font-weight: 500;
  letter-spacing: .1em;
  color: var(--muted);
  text-align: left;
  padding: .625rem .875rem;
  border-bottom: 1px solid var(--rule);
}
.admin-table td {
  padding: .75rem .875rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}
.admin-table tr:last-child td { border-bottom: 0; }
.admin-table tr:hover td { background: color-mix(in srgb, var(--panel) 60%, transparent); }

.title-cell a { font-weight: 500; }
.title-cell a:hover { color: var(--signal); }
.title-cell .id {
  font-family: var(--mono);
  font-size: .6875rem;
  color: var(--muted);
  margin-left: .4rem;
}
.badge {
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .08em;
  padding: .1rem .4rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--muted);
}
.badge.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }

.actions {
  display: flex;
  gap: .875rem;
  align-items: center;
  justify-content: flex-end;
  font-family: var(--mono);
  font-size: .6875rem;
}
.actions form { display: inline; }
.actions a { color: var(--muted); }
.actions a:hover { color: var(--signal); }

/* ---------- editor ---------- */

.editor { display: flex; flex-direction: column; gap: 1rem; }

.title-input {
  font-family: var(--display) !important;
  font-size: 1.5rem !important;
  font-weight: 700;
  padding: .75rem .875rem !important;
}

.editor-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

.editor-pane {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
}
.pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .5rem .75rem;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .1em;
  color: var(--muted);
}
.editor-pane textarea {
  border: 0;
  border-radius: 0;
  min-height: 30rem;
  resize: vertical;
  font-family: var(--mono);
  font-size: .8125rem;
  line-height: 1.8;
}
.preview {
  padding: 1rem 1.125rem;
  min-height: 30rem;
  overflow-y: auto;
  font-size: .9375rem;
}

.editor-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .875rem;
  padding: 1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
}

.editor-actions { display: flex; gap: .625rem; align-items: center; }

/* ---------- cards ---------- */

.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; align-items: start; }

.card {
  padding: 1.25rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
}
.card h2 {
  font-family: var(--mono);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .12em;
  color: var(--muted);
  margin: 0 0 1rem;
}
.stack { display: flex; flex-direction: column; gap: .875rem; }
.stack .btn { align-self: flex-start; }
.inline-form { display: flex; gap: .5rem; margin-bottom: 1rem; }

.admin-list { list-style: none; margin: 0; padding: 0; font-size: .875rem; }
.admin-list li {
  display: flex;
  align-items: center;
  gap: .625rem;
  padding: .5rem 0;
  border-bottom: 1px solid var(--rule);
}
.admin-list li:last-child { border-bottom: 0; }
.admin-list li > a { flex: 1; }
.admin-list li > a:hover { color: var(--signal); }
.admin-list .count { font-family: var(--mono); font-size: .6875rem; color: var(--muted); }
.tag-cloud { display: flex; flex-wrap: wrap; gap: .375rem; }

@media (max-width: 900px) {
  .editor-grid { grid-template-columns: 1fr; }
  .two-col { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  .admin-table thead { display: none; }
  .admin-table td { display: block; border: 0; padding: .25rem .875rem; }
  .admin-table tr { display: block; border-bottom: 1px solid var(--rule); padding: .75rem 0; }
  .actions { justify-content: flex-start; padding: .5rem .875rem; }
}

/* ---------- browse by category (front page) ---------- */

/* With 288 posts, ten reverse-chronological entries aren't a way in. These chips
   are. They replaced the cadence strip here — that strip is a timeline, so it now
   lives on /archive next to the months it indexes. */
.browse {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-top: 1.75rem;
}

.chip-cat {
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
  padding: .3rem .6rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  font-size: .8125rem;
  color: var(--ink);
  background: var(--paper);
  line-height: 1.4;
}
.chip-cat:hover { border-color: var(--signal); color: var(--signal); }

.chip-n {
  font-size: .6875rem;
  color: var(--muted);
}
.chip-cat:hover .chip-n { color: var(--signal); }

/* The way out of the chips and into everything. */
.chip-more {
  border-style: dashed;
  color: var(--muted);
}


/* ---------- code highlighting (chroma, rendered server-side) ---------- */

/* Emitted as classes by goldmark-highlighting, so the same HTML restyles for the
   dark theme without re-rendering a single post. The palette is GitHub's, which
   is what most of these posts were written against. */

/* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 }
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
/* LineHighlight */ .chroma .hl { background-color: #e5e5e5 }
/* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* Line */ .chroma .line { display: flex; }
/* Keyword */ .chroma .k { color: #000000; font-weight: bold }
/* KeywordConstant */ .chroma .kc { color: #000000; font-weight: bold }
/* KeywordDeclaration */ .chroma .kd { color: #000000; font-weight: bold }
/* KeywordNamespace */ .chroma .kn { color: #000000; font-weight: bold }
/* KeywordPseudo */ .chroma .kp { color: #000000; font-weight: bold }
/* KeywordReserved */ .chroma .kr { color: #000000; font-weight: bold }
/* KeywordType */ .chroma .kt { color: #445588; font-weight: bold }
/* NameAttribute */ .chroma .na { color: #008080 }
/* NameBuiltin */ .chroma .nb { color: #0086b3 }
/* NameBuiltinPseudo */ .chroma .bp { color: #999999 }
/* NameClass */ .chroma .nc { color: #445588; font-weight: bold }
/* NameConstant */ .chroma .no { color: #008080 }
/* NameDecorator */ .chroma .nd { color: #3c5d5d; font-weight: bold }
/* NameEntity */ .chroma .ni { color: #800080 }
/* NameException */ .chroma .ne { color: #990000; font-weight: bold }
/* NameFunction */ .chroma .nf { color: #990000; font-weight: bold }
/* NameLabel */ .chroma .nl { color: #990000; font-weight: bold }
/* NameNamespace */ .chroma .nn { color: #555555 }
/* NameTag */ .chroma .nt { color: #000080 }
/* NameVariable */ .chroma .nv { color: #008080 }
/* NameVariableClass */ .chroma .vc { color: #008080 }
/* NameVariableGlobal */ .chroma .vg { color: #008080 }
/* NameVariableInstance */ .chroma .vi { color: #008080 }
/* LiteralString */ .chroma .s { color: #dd1144 }
/* LiteralStringAffix */ .chroma .sa { color: #dd1144 }
/* LiteralStringBacktick */ .chroma .sb { color: #dd1144 }
/* LiteralStringChar */ .chroma .sc { color: #dd1144 }
/* LiteralStringDelimiter */ .chroma .dl { color: #dd1144 }
/* LiteralStringDoc */ .chroma .sd { color: #dd1144 }
/* LiteralStringDouble */ .chroma .s2 { color: #dd1144 }
/* LiteralStringEscape */ .chroma .se { color: #dd1144 }
/* LiteralStringHeredoc */ .chroma .sh { color: #dd1144 }
/* LiteralStringInterpol */ .chroma .si { color: #dd1144 }
/* LiteralStringOther */ .chroma .sx { color: #dd1144 }
/* LiteralStringRegex */ .chroma .sr { color: #009926 }
/* LiteralStringSingle */ .chroma .s1 { color: #dd1144 }
/* LiteralStringSymbol */ .chroma .ss { color: #990073 }
/* LiteralNumber */ .chroma .m { color: #009999 }
/* LiteralNumberBin */ .chroma .mb { color: #009999 }
/* LiteralNumberFloat */ .chroma .mf { color: #009999 }
/* LiteralNumberHex */ .chroma .mh { color: #009999 }
/* LiteralNumberInteger */ .chroma .mi { color: #009999 }
/* LiteralNumberIntegerLong */ .chroma .il { color: #009999 }
/* LiteralNumberOct */ .chroma .mo { color: #009999 }
/* Operator */ .chroma .o { color: #000000; font-weight: bold }
/* OperatorWord */ .chroma .ow { color: #000000; font-weight: bold }
/* Comment */ .chroma .c { color: #999988; font-style: italic }
/* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic }
/* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic }
/* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic }
/* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic }
/* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold; font-style: italic }
/* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold; font-style: italic }
/* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd }
/* GenericEmph */ .chroma .ge { color: #000000; font-style: italic }
/* GenericError */ .chroma .gr { color: #aa0000 }
/* GenericHeading */ .chroma .gh { color: #999999 }
/* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd }
/* GenericOutput */ .chroma .go { color: #888888 }
/* GenericPrompt */ .chroma .gp { color: #555555 }
/* GenericStrong */ .chroma .gs { font-weight: bold }
/* GenericSubheading */ .chroma .gu { color: #aaaaaa }
/* GenericTraceback */ .chroma .gt { color: #aa0000 }
/* GenericUnderline */ .chroma .gl { text-decoration: underline }
/* TextWhitespace */ .chroma .w { color: #bbbbbb }

@media (prefers-color-scheme: dark) {
  /* Error */ .chroma .err { color: #ff0000 }
  /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
  /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
  /* LineHighlight */ .chroma .hl { background-color: #191919 }
  /* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #727272 }
  /* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #727272 }
  /* Line */ .chroma .line { display: flex; }
  /* Keyword */ .chroma .k { color: #ffffff; font-weight: bold }
  /* KeywordConstant */ .chroma .kc { color: #ffffff; font-weight: bold }
  /* KeywordDeclaration */ .chroma .kd { color: #ffffff; font-weight: bold }
  /* KeywordNamespace */ .chroma .kn { color: #ffffff; font-weight: bold }
  /* KeywordPseudo */ .chroma .kp { color: #ffffff; font-weight: bold }
  /* KeywordReserved */ .chroma .kr { color: #ffffff; font-weight: bold }
  /* KeywordType */ .chroma .kt { color: #ffffff; font-weight: bold }
  /* NameAttribute */ .chroma .na { color: #007f7f }
  /* NameBuiltin */ .chroma .nb { color: #ffffff; font-weight: bold }
  /* NameTag */ .chroma .nt { font-weight: bold }
  /* LiteralDate */ .chroma .ld { color: #ffff00; font-weight: bold }
  /* LiteralString */ .chroma .s { color: #00ffff; font-weight: bold }
  /* LiteralStringAffix */ .chroma .sa { color: #00ffff; font-weight: bold }
  /* LiteralStringBacktick */ .chroma .sb { color: #00ffff; font-weight: bold }
  /* LiteralStringChar */ .chroma .sc { color: #00ffff; font-weight: bold }
  /* LiteralStringDelimiter */ .chroma .dl { color: #00ffff; font-weight: bold }
  /* LiteralStringDoc */ .chroma .sd { color: #00ffff; font-weight: bold }
  /* LiteralStringDouble */ .chroma .s2 { color: #00ffff; font-weight: bold }
  /* LiteralStringEscape */ .chroma .se { color: #00ffff; font-weight: bold }
  /* LiteralStringHeredoc */ .chroma .sh { color: #00ffff; font-weight: bold }
  /* LiteralStringInterpol */ .chroma .si { color: #00ffff; font-weight: bold }
  /* LiteralStringOther */ .chroma .sx { color: #00ffff; font-weight: bold }
  /* LiteralStringRegex */ .chroma .sr { color: #00ffff; font-weight: bold }
  /* LiteralStringSingle */ .chroma .s1 { color: #00ffff; font-weight: bold }
  /* LiteralStringSymbol */ .chroma .ss { color: #00ffff; font-weight: bold }
  /* LiteralNumber */ .chroma .m { color: #ffff00; font-weight: bold }
  /* LiteralNumberBin */ .chroma .mb { color: #ffff00; font-weight: bold }
  /* LiteralNumberFloat */ .chroma .mf { color: #ffff00; font-weight: bold }
  /* LiteralNumberHex */ .chroma .mh { color: #ffff00; font-weight: bold }
  /* LiteralNumberInteger */ .chroma .mi { color: #ffff00; font-weight: bold }
  /* LiteralNumberIntegerLong */ .chroma .il { color: #ffff00; font-weight: bold }
  /* LiteralNumberOct */ .chroma .mo { color: #ffff00; font-weight: bold }
  /* Comment */ .chroma .c { color: #007f7f }
  /* CommentHashbang */ .chroma .ch { color: #007f7f }
  /* CommentMultiline */ .chroma .cm { color: #007f7f }
  /* CommentSingle */ .chroma .c1 { color: #007f7f }
  /* CommentSpecial */ .chroma .cs { color: #007f7f }
  /* CommentPreproc */ .chroma .cp { color: #00ff00; font-weight: bold }
  /* CommentPreprocFile */ .chroma .cpf { color: #00ff00; font-weight: bold }
  /* GenericHeading */ .chroma .gh { font-weight: bold }
  /* GenericStrong */ .chroma .gs { font-weight: bold }
  /* GenericSubheading */ .chroma .gu { font-weight: bold }
  /* GenericUnderline */ .chroma .gl { text-decoration: underline }
}

/* ---------- vditor host ---------- */

/* Vditor brings its own chrome; it just needs a frame that matches the admin. */
#vditor {
  margin-bottom: 1.5rem;
  border-radius: 4px;
}
.vditor-reset { font-family: var(--body); }

/* The login link sits in the footer with the other utility links, deliberately
   quiet: it's a door for one person, not a call to action. */
.footer-admin { color: var(--muted); }
.footer-admin:hover { color: var(--signal); }

/* ---------- wangeditor host ---------- */

#toolbar-container { border: 1px solid var(--rule); border-bottom: 0; border-radius: 4px 4px 0 0; }
#editor-container  { border: 1px solid var(--rule); border-radius: 0 0 4px 4px; height: 560px; margin-bottom: 1.5rem; }

/* A converted post changes storage format on save. Say so before, not after. */
.notice {
  margin-bottom: 1.25rem;
  padding: .75rem 1rem;
  border: 1px solid var(--signal);
  border-left-width: 3px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--signal) 6%, transparent);
  font-size: .875rem;
  line-height: 1.7;
}
.notice code { font-family: var(--mono); font-size: .8125rem; }
