/* ============================================
   QUIET TERMINAL DESIGN SYSTEM

   One monospace family, one flat type scale, hairline rules, square
   corners, no drop shadows, and hover states that invert foreground and
   background instead of moving anything.

   Hierarchy comes from case, weight, tone and literal markdown glyphs
   ("## ", "[tag]", "-"), not from size jumps or colour blocks.
   ============================================ */

:root {
  /* ------------------------------------------------
     Neutral ramp — the whole palette.
     A cool grey carrying a trace of the old blue-slate hue, so the site
     still reads as itself. Never pure #fff or #000: the page is paper
     with ink on it, not a light box.
     ------------------------------------------------ */
  --n-0:   #f2f4f6;
  --n-50:  #e4e7ea;
  --n-100: #d3d7dc;
  --n-200: #b4bac2;
  --n-300: #8b939d;
  --n-400: #6b737d;
  --n-500: #555c66;
  --n-600: #454b54;
  --n-700: #2a3037;
  --n-800: #191d21;
  --n-900: #15181b;
  --n-950: #0d0f11;

  /* ------------------------------------------------
     Light theme. Contrast ratios are measured against the surface the
     text actually lands on, and noted where they sit near the line.
     ------------------------------------------------ */
  --bg-primary: var(--n-50);      /* #e4e7ea */
  --bg-subtle: var(--n-100);      /* #d3d7dc — inset panels */
  --bg-inverse: var(--n-900);     /* fill behind inverted text */

  --text-primary: var(--n-900);   /* 14.9:1 on --bg-primary */
  --text-secondary: var(--n-600); /*  7.1:1 on --bg-primary */
  --text-muted: var(--n-500);     /*  5.4:1 on page, 4.7:1 on panel — the floor */
  --text-inverse: var(--n-50);

  --rule: var(--n-200);           /* hairline separator, decorative */
  --border-color: var(--n-400);   /* control border — 3.9:1 page, 3.3:1 panel */

  --scrim: rgba(13, 15, 17, 0.6);
}

[data-theme="dark"] {
  --bg-primary: var(--n-950);     /* #0d0f11 */
  --bg-subtle: var(--n-800);      /* #191d21 */
  --bg-inverse: var(--n-0);

  --text-primary: #d6dade;        /* 13.7:1 on --bg-primary */
  --text-secondary: #9aa3ad;      /*  7.5:1 on --bg-primary */
  --text-muted: #7c858f;          /*  5.1:1 on page, 4.5:1 on panel */
  --text-inverse: var(--n-950);

  --rule: var(--n-700);           /* #2a3037 */
  --border-color: #626b76;        /* 3.6:1 on page, 3.1:1 on panel */

  --scrim: rgba(13, 15, 17, 0.7);
}

/* ------------------------------------------------
   Structure. Borders are always hairline and corners are always square,
   so these are effectively constants. They stay tokens only so a single
   edit can prove that across the whole sheet.
   ------------------------------------------------ */
:root {
  --border-width: 1px;
  --border-hairline: 1px;
  --border-radius: 0;

  /* The one lift in the system, reserved for a surface that genuinely
     floats above the page: the shortcuts dialog. Hard offset, no blur. */
  --shadow-panel: 5px 5px 0 0 var(--border-color);

  /* Retired. Kept defined so any rule still asking for one resolves to
     nothing rather than to an invalid value. */
  --shadow-standard: none;
  --shadow-hover: none;
  --shadow-small: none;
  --shadow-small-hover: none;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* Dated-row geometry — the "date [type] title" rows on the homepage's
     Recent list and on /feed. The type column is right-aligned against a
     floor of this width, so the gap before a title is always one --space-3
     no matter how short the type name is: [diary] and [project] both end
     flush. The floor only stops the title's left edge from jumping between
     lists; a longer type name than "project" simply widens the column and
     the rows stay aligned with each other.

     ch, not rem: it is used on elements set in --step-sm, so it counts
     characters of the text actually rendered there. */
  --col-type: 9ch;

  /* One family, three names. The names survive so existing rules keep
     reading, but they all resolve to the same face. */
  --font-mono: 'Cascadia Mono', ui-monospace, SFMono-Regular, 'SF Mono',
               Menlo, Consolas, 'Liberation Mono', monospace;
  --font-body: var(--font-mono);
  --font-heading: var(--font-mono);

  /* Fixed measure. Every band of the page — nav, main, footer — is capped
     here, so the site is one column from top to bottom. */
  --measure: 80ch;

  --step: 0.875rem;   /* the single body/heading size */
  --step-sm: 0.78rem; /* metadata, tags, labels */
  --step-xs: 0.7rem;

  --transition: 0.15s ease;
}

/* The terminal is no longer a black box dropped onto a light page — the
   whole site is the terminal now, so it follows the theme like everything
   else. These aliases survive because TerminalHero writes them at runtime
   onto elements it creates itself. */
:root,
[data-theme="dark"] {
  --terminal-bg: var(--bg-subtle);
  --terminal-text: var(--text-primary);
  --terminal-text-muted: var(--text-muted);
  --terminal-warning: var(--text-primary);
  --terminal-success: var(--text-muted);
  --terminal-error: var(--text-primary);
}

/* ============================================
   RESET & BASE
   ============================================ */

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

html {
  font-size: 16px;
}

body {
  font-family: var(--font-body);
  font-size: var(--step);
  line-height: 1.7;
  background-color: var(--bg-primary);
  color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
}

/* A square ring, to match every other corner. */
a:focus-visible, button:focus-visible, input:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--text-primary);
  outline-offset: 2px;
  border-radius: 0;
}

#main-content:focus {
  outline: none;
}

.skip-link {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 100;
  transform: translateY(-200%);
  padding: var(--space-3) var(--space-4);
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  border: var(--border-width) solid var(--border-color);
  font-weight: 700;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.skip-link:focus {
  transform: translateY(0);
}

/* ============================================
   TYPOGRAPHY

   The flat scale: h1 through h6 are the same size as body text. A heading
   is marked by case, weight and letter-spacing, and in prose by a literal
   "## " prefix. Do not give a heading a font-size — that single rule is
   what holds this design together.
   ============================================ */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-size: var(--step);
  font-weight: 700;
  line-height: 1.7;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-4);
}

p {
  margin-bottom: var(--space-4);
}

a {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  transition: background-color var(--transition), color var(--transition);
}

/* The site-wide hover: invert, do not move. */
a:hover {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  text-decoration: none;
}

strong, b { font-weight: 700; }

::selection {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
}

.container {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--space-5);
}

/* ============================================
   TERMINAL
   ============================================ */

.terminal {
  background-color: var(--terminal-bg);
  border: var(--border-width) solid var(--border-color);
  border-radius: var(--border-radius);
  padding: var(--space-5);
  color: var(--terminal-text);
}

.terminal-content {
  font-family: var(--font-mono);
}

.terminal-line {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.terminal-prompt {
  color: var(--text-muted);
  flex-shrink: 0;
}

.terminal-cursor {
  display: inline-block;
  width: 0.6em;
  height: 1.1em;
  background-color: var(--terminal-text);
  animation: blink 1s step-end infinite;
  vertical-align: text-bottom;
}

@keyframes blink {
  50% { opacity: 0; }
}

/* Terminal history lines — must stay unscoped. TerminalHero.astro's
   addHistoryLine() creates these elements with document.createElement()
   at runtime, so they never receive Astro's scoped data-astro-cid
   attribute. A scoped rule here would never match; keep it global.

   There is no hue left to separate these states, so they separate by
   weight and tone, and each line also carries a text prefix of its own. */
.terminal-history-line {
  display: block;
  margin-top: var(--space-2);
  color: var(--terminal-text);
}
.terminal-history-error {
  color: var(--terminal-error);
  font-weight: 700;
}
.terminal-history-warning {
  color: var(--terminal-warning);
}
.terminal-history-success {
  color: var(--terminal-success);
}

/* ============================================
   CONTROLS
   ============================================ */

.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--step-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--space-2) var(--space-4);
  background-color: transparent;
  color: var(--text-primary);
  border: var(--border-width) solid var(--border-color);
  border-radius: var(--border-radius);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--transition), color var(--transition),
              border-color var(--transition);
}

.btn:hover,
.btn:focus-visible {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  border-color: var(--bg-inverse);
}

/* A badge is a label, not a control, so it is a plain inverted block with
   no border and no animation. */
.badge-new {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--step-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 0 var(--space-2);
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  border-radius: var(--border-radius);
}

/* Every remaining control shares one skin. */
.theme-toggle,
.clear-all,
.tag-filter,
.shortcuts-close,
.shortcuts-trigger,
.scroll-to-top,
.social-link {
  font-family: var(--font-body);
  background-color: transparent;
  color: var(--text-primary);
  border: var(--border-width) solid var(--border-color);
  border-radius: var(--border-radius);
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition),
              border-color var(--transition);
}

.theme-toggle:hover,
.clear-all:hover,
.tag-filter:hover,
.shortcuts-close:hover,
.shortcuts-trigger:hover,
.scroll-to-top:hover,
.social-link:hover {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  border-color: var(--bg-inverse);
}

/* ============================================
   LISTS

   .grid is a single column at every width. An 80ch measure has no room
   for a card grid, and a dated list reads faster than a wall of boxes.
   The class name is unchanged because every list page and every homepage
   section renders through it.
   ============================================ */

.grid {
  display: flex;
  flex-direction: column;
  border-top: var(--border-hairline) solid var(--rule);
}

/* A card is a row now: no border of its own, no fill, no shadow. The
   hairline between rows does all the separating.

   --space-4 is the shared row rhythm: .card, .recent-item and .feed-item
   all use it, so a homepage section, a list page and /feed scroll at the
   same cadence. A card holds four lines to a Recent row's one, but its
   own internal margins already do that spacing — adding more here is what
   made the homepage read as two different rhythms stacked. */
.card {
  display: flex;
  flex-direction: column;
  padding: var(--space-4) 0;
  border-bottom: var(--border-hairline) solid var(--rule);
  background-color: transparent;
}

.card-title {
  font-size: var(--step);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-1);
}

.card-title a { text-decoration: none; }

.card-meta {
  font-size: var(--step-sm);
  color: var(--text-muted);
  letter-spacing: 0.04em;
  margin-bottom: var(--space-3);
  font-variant-numeric: tabular-nums;
}

.card-content {
  flex-grow: 1;
  color: var(--text-secondary);
  margin-bottom: var(--space-3);
}

.card-actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
}

.card-eyebrow {
  display: inline-block;
  margin-bottom: var(--space-2);
}

/* Tags are bracketed text, the way a shell would print them — no pill,
   no border, no fill. */
.tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--step-sm);
  font-weight: 400;
  text-transform: lowercase;
  letter-spacing: 0;
  color: var(--text-muted);
}

.tag::before { content: "["; }
.tag::after { content: "]"; }

/* A rule with its name sitting on it, like a section break in a man page. */
.section-separator {
  position: relative;
  margin: var(--space-8) 0;
  border: none;
  border-top: var(--border-hairline) solid var(--rule);
}

.section-label {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  background-color: var(--bg-primary);
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: var(--step-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  padding-right: var(--space-3);
}

.section {
  margin-bottom: var(--space-7);
}

.section-header {
  margin-bottom: var(--space-4);
}

/* The NEW badge sits on the heading's baseline row. This lived as an inline
   style on three near-identical homepage sections, each with its own
   hardcoded gap. */
.section-header h2 {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* The "View all" / "Everything, by year" line that closes a list. Left,
   like everything else in a one-column layout — it used to be centred on
   the three homepage sections only, which read as a stray indent under a
   flush-left list. */
.view-all {
  margin-top: var(--space-4);
}

/* ============================================
   NAVIGATION
   ============================================ */

.nav {
  padding: var(--space-5) 0;
  border-bottom: var(--border-hairline) solid var(--rule);
  margin-bottom: var(--space-6);
}

.nav-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

.nav-brand {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--step);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  text-decoration: none;
}

.nav-links {
  display: flex;
  gap: var(--space-4);
  list-style: none;
}

.nav-link {
  font-family: var(--font-body);
  font-size: var(--step-sm);
  text-transform: lowercase;
  letter-spacing: 0.04em;
  text-decoration: none;
  color: var(--text-secondary);
  padding: 0 var(--space-1);
  transition: background-color var(--transition), color var(--transition);
}

.nav-link:hover,
.nav-brand:hover {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
}

.nav-link[aria-current="page"] {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
}

.theme-toggle {
  padding: var(--space-1) var(--space-3);
  font-size: var(--step-sm);
  text-transform: lowercase;
  letter-spacing: 0.04em;
  min-width: 4.5rem;
  text-align: center;
}

.theme-toggle .theme-label-light { display: none; }
[data-theme="dark"] .theme-toggle .theme-label-dark { display: none; }
[data-theme="dark"] .theme-toggle .theme-label-light { display: inline; }

@media (max-width: 768px) {
  .nav-container {
    flex-wrap: wrap;
    gap: var(--space-3);
  }

  .nav-links {
    gap: var(--space-3);
    flex-wrap: wrap;
  }
}

@media (max-width: 480px) {
  .container { padding: 0 var(--space-4); }
  .terminal { padding: var(--space-4); }
}

/* ============================================
   FOOTER
   ============================================ */

.footer {
  margin-top: var(--space-8);
  padding: var(--space-6) 0;
  border-top: var(--border-hairline) solid var(--rule);
  font-size: var(--step-sm);
  color: var(--text-muted);
}

.footer-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.social-links {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
}

.social-link svg {
  width: 16px;
  height: 16px;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.footer-link {
  color: var(--text-muted);
  text-decoration: none;
  font-size: var(--step-sm);
  transition: background-color var(--transition), color var(--transition);
}

.footer-link:hover {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
}

.scroll-to-top {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  width: 34px;
  height: 34px;
  font-size: var(--step);
  font-weight: 700;
  background-color: var(--bg-primary);
  opacity: 0;
  visibility: hidden;
  z-index: 1000;
  transition: opacity var(--transition), visibility var(--transition),
              background-color var(--transition), color var(--transition);
}

.scroll-to-top.visible {
  opacity: 1;
  visibility: visible;
}

@media (max-width: 480px) {
  .scroll-to-top {
    bottom: var(--space-4);
    right: var(--space-4);
  }
}

/* ============================================
   SITE HEALTH

   The one place a large number is allowed. A metric is data being read as
   a quantity, not a heading, so the flat scale does not apply to it.
   ============================================ */

.site-health {
  margin-top: var(--space-8);
  padding: var(--space-6) 0;
  border-top: var(--border-hairline) solid var(--rule);
}

.site-health .section-title {
  font-size: var(--step);
  margin-bottom: var(--space-2);
}

.site-health .section-description {
  color: var(--text-muted);
  margin-bottom: var(--space-5);
  font-size: var(--step-sm);
}

.health-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6);
}

.health-card {
  background-color: transparent;
  padding: 0;
}

.health-card-title {
  font-size: var(--step-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: var(--border-hairline) solid var(--rule);
  font-family: var(--font-heading);
}

.health-metrics {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
}

.metric {
  display: flex;
  flex-direction: column;
  padding: 0;
}

.metric-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
  font-family: var(--font-heading);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.metric-value.high { color: var(--text-primary); }

.metric-label {
  font-size: var(--step-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: var(--space-1);
}

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

.check-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  font-size: var(--step-sm);
  color: var(--text-secondary);
}

.check-icon {
  color: var(--text-muted);
  font-weight: 700;
}

/* No `color` here: it would duplicate the base `a` rule while tying
   `a:hover` on specificity and winning on source order, which would pin the
   text colour while the hover inverts the background behind it. */
.check-item a {
  text-decoration: underline;
}

@media (max-width: 768px) {
  .health-grid { grid-template-columns: 1fr; }
  .health-metrics { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================
   FILTERS
   ============================================ */

.collection-filters {
  padding: var(--space-5) 0;
  margin-bottom: var(--space-5);
  border-top: var(--border-hairline) solid var(--rule);
  border-bottom: var(--border-hairline) solid var(--rule);
}

.filter-section { margin-bottom: var(--space-4); }
.filter-section:last-child { margin-bottom: 0; }

.filter-label {
  display: block;
  font-size: var(--step-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: var(--space-2);
  font-family: var(--font-heading);
}

.filter-help {
  font-size: var(--step-xs);
  color: var(--text-muted);
  margin: var(--space-1) 0 0;
}

.search-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

/* A prompt glyph, so the field reads as somewhere you type a command. */
.search-wrapper::before {
  content: "\276F";
  position: absolute;
  left: var(--space-3);
  color: var(--text-muted);
  pointer-events: none;
}

.search-input {
  width: 100%;
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-6);
  border: var(--border-width) solid var(--border-color);
  border-radius: var(--border-radius);
  background-color: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--step);
  transition: border-color var(--transition);
}

.search-input::placeholder { color: var(--text-muted); }

/* No outline:none — the site-wide :focus-visible ring is the only focus
   cue left, now that nothing lifts or shifts on interaction. */
.search-input:focus {
  border-color: var(--text-primary);
}

.tag-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.tag-filter {
  padding: 0 var(--space-2);
  font-size: var(--step-sm);
  text-transform: lowercase;
}

.tag-filter.active,
.tag-filter[aria-pressed="true"] {
  background-color: var(--bg-inverse);
  color: var(--text-inverse);
  border-color: var(--bg-inverse);
}

.active-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  margin-bottom: var(--space-4);
  border-bottom: var(--border-hairline) solid var(--rule);
}

.active-filters-label {
  font-size: var(--step-sm);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.active-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  flex: 1;
}

.active-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--step-sm);
  color: var(--text-primary);
}

.remove-filter {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--step-sm);
  line-height: 1;
  color: var(--text-muted);
  transition: color var(--transition);
}

.remove-filter:hover { color: var(--text-primary); }

.clear-all {
  padding: 0 var(--space-2);
  font-size: var(--step-sm);
  text-transform: lowercase;
}

.results-count {
  font-size: var(--step-sm);
  color: var(--text-muted);
}

@media (max-width: 768px) {
  .active-filters {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================
   KEYBOARD SHORTCUTS OVERLAY
   ============================================ */

.shortcuts-overlay {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background-color: var(--scrim);
}

.shortcuts-overlay[hidden] { display: none; }

/* The one surface that genuinely floats, so it keeps the one hard shadow. */
.shortcuts-panel {
  width: min(640px, 100%);
  max-height: 85vh;
  overflow-y: auto;
  padding: var(--space-5);
  background-color: var(--bg-primary);
  border: var(--border-width) solid var(--border-color);
  border-radius: var(--border-radius);
  box-shadow: var(--shadow-panel);
}

.shortcuts-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--rule);
}

.shortcuts-header h2 { margin: 0; }

.shortcuts-close {
  width: 1.9rem;
  height: 1.9rem;
  font-size: var(--step);
  line-height: 1;
  flex-shrink: 0;
}

.shortcuts-groups {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

@media (min-width: 768px) {
  .shortcuts-groups { grid-template-columns: 1fr 1fr; }
}

.shortcuts-group h3 {
  font-size: var(--step-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}

.shortcuts-group ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.shortcuts-group li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--step-sm);
}

kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.6rem;
  padding: 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--step-sm);
  background-color: var(--bg-subtle);
  color: var(--text-primary);
  border: var(--border-hairline) solid var(--border-color);
  border-radius: var(--border-radius);
}

.shortcuts-note {
  margin: var(--space-5) 0 0;
  font-size: var(--step-sm);
  color: var(--text-muted);
}

.shortcuts-trigger {
  position: fixed;
  left: var(--space-4);
  bottom: var(--space-4);
  z-index: 90;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-size: var(--step-sm);
  color: var(--text-muted);
  background-color: var(--bg-primary);
}

@media (max-width: 768px) {
  .shortcuts-trigger { display: none; }
}

/* ============================================
   TAG INDEX (/tags)
   ============================================ */

.tag-index {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  border-top: var(--border-hairline) solid var(--rule);
}

.tag-index-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  padding: var(--space-3) 0;
  border-bottom: var(--border-hairline) solid var(--rule);
}

@media (min-width: 768px) {
  .tag-index-row { grid-template-columns: 1fr auto auto; }
}

.tag-index-name {
  font-weight: 700;
  font-family: var(--font-heading);
}

.tag-index-count {
  color: var(--text-muted);
  font-size: var(--step-sm);
  font-variant-numeric: tabular-nums;
}

.tag-index-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  grid-column: 1 / -1;
}

@media (min-width: 768px) {
  .tag-index-links { grid-column: auto; }
}

.tag-index-link {
  font-family: var(--font-mono);
  font-size: var(--step-sm);
  color: var(--text-muted);
}

/* ============================================
   SEARCH (/search)
   ============================================ */

.search-results {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  border-top: var(--border-hairline) solid var(--rule);
}

.search-result {
  padding: var(--space-4) 0;
  border-bottom: var(--border-hairline) solid var(--rule);
}

.search-result-link {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--step);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.search-result-type {
  margin-left: var(--space-3);
  font-size: var(--step-sm);
  font-weight: 400;
  color: var(--text-muted);
  text-transform: lowercase;
  letter-spacing: 0;
}

.search-result-type::before { content: "["; }
.search-result-type::after { content: "]"; }

.search-result-description {
  margin: var(--space-2) 0 0;
  color: var(--text-secondary);
}

.search-empty {
  padding: var(--space-6) 0;
  color: var(--text-muted);
}

/* ============================================
   PROSE — rendered markdown

   The one markdown surface: diary and fanfic entries, /changelog and
   /colophon. Slightly larger than UI text and generously led, because
   this is the only place on the site meant for sustained reading.
   ============================================ */

.prose {
  font-size: 0.9375rem;
  line-height: 1.85;
  margin-bottom: var(--space-7);
  color: var(--text-secondary);
}

.prose h2,
.prose h3,
.prose h4 {
  color: var(--text-primary);
}

.prose h2 {
  margin-top: var(--space-7);
  margin-bottom: var(--space-4);
}

.prose h3 {
  margin-top: var(--space-6);
  margin-bottom: var(--space-3);
}

/* Headings carry their markdown level as a visible glyph, since they no
   longer carry it as a size. */
.prose h2::before,
.prose h3::before,
.prose h4::before {
  color: var(--text-muted);
  font-weight: 400;
}

.prose h2::before { content: "## "; }
.prose h3::before { content: "### "; }
.prose h4::before { content: "#### "; }

.prose p { margin-bottom: var(--space-5); }

.prose ol {
  margin-bottom: var(--space-5);
  padding-left: var(--space-5);
}

.prose ul {
  list-style: none;
  margin-bottom: var(--space-5);
  padding-left: var(--space-4);
}

.prose li { margin-bottom: var(--space-2); }

.prose ul > li {
  position: relative;
}

.prose ul > li::before {
  content: "-";
  position: absolute;
  left: calc(-1 * var(--space-4));
  color: var(--text-muted);
}

.prose pre {
  background-color: var(--bg-subtle);
  border: var(--border-hairline) solid var(--rule);
  border-radius: var(--border-radius);
  padding: var(--space-4);
  overflow-x: auto;
  margin-bottom: var(--space-5);
  font-size: var(--step-sm);
  line-height: 1.6;
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.95em;
  background-color: var(--bg-subtle);
  padding: 0.1em 0.35em;
  border-radius: 0;
}

.prose pre code {
  background-color: transparent;
  padding: 0;
}

.prose blockquote {
  border-left: var(--border-width) solid var(--border-color);
  padding-left: var(--space-4);
  margin: var(--space-5) 0;
  color: var(--text-muted);
}

.prose hr {
  border: none;
  border-top: var(--border-hairline) solid var(--rule);
  margin: var(--space-6) 0;
}

.prose table {
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  margin-bottom: var(--space-5);
  font-size: var(--step-sm);
}

.prose th,
.prose td {
  border: var(--border-hairline) solid var(--rule);
  padding: var(--space-2) var(--space-3);
  text-align: left;
}

.prose th {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

/* ============================================
   UTILITIES
   ============================================ */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .terminal-cursor { animation: none; }
}
