/* ==========================================================================
   dyttyr.com
   One stylesheet for the whole site.

   Design rules this file holds itself to:
   - One accent colour (amber), used identically in both themes. Deliberately
     off the default SaaS-blue: warm enough to sit with the site's warm
     greys. --warn below is shifted toward yellow, a good 18-20 degrees of
     hue off the accent, so the two are never mistaken for each other in a
     status line.
   - Two corner radii and nothing else: 6px for controls and tags, 10px for
     cards and panels. Documented here so it stays consistent.
   - Both themes clear WCAG AA for body text. Muted text is 6.4:1 on light
     and 7.4:1 on dark; link colour is 5.4:1 and 9.9:1.
   - Motion is hover, focus and one short page fade. Nothing loops, nothing
     moves on scroll, and everything collapses under prefers-reduced-motion.
   ========================================================================== */

/* ------------------------------------------------------------------ fonts */
/* Self-hosted so there are no third-party requests and no layout shift.
   Drop the .woff2 files into src/fonts and the build copies them across.
   If they are absent the fallback stack below takes over cleanly. */

@font-face {
  font-family: 'Geist';
  src: url('/assets/fonts/Geist-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('/assets/fonts/Geist-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('/assets/fonts/Geist-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Geist Mono';
  src: url('/assets/fonts/GeistMono-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ----------------------------------------------------------------- tokens */

:root {
  color-scheme: light;

  --bg: #fbfbfa;
  --bg-subtle: #f4f4f2;
  --bg-inset: #ecece9;
  --border: #dddcd8;
  --border-strong: #c3c2bd;

  --text: #1b1b19;
  --text-muted: #5c5c57;

  --accent: #9a5b0a;
  --accent-hover: #7c4708;
  --accent-wash: #fbeed9;
  --accent-contrast: #ffffff;

  --ok: #146c43;
  --warn: #766c00;
  --error: #b42318;

  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo,
    Consolas, 'Liberation Mono', monospace;

  /* Two radii, no more. Controls and tags use sm, cards and panels use md. */
  --r-sm: 6px;
  --r-md: 10px;

  --shell: 68rem;
  --measure: 68ch;

  /* Shadows are tinted toward the page ground, never pure black. */
  --shadow-card: 0 1px 2px rgb(27 27 25 / 0.04), 0 6px 20px rgb(27 27 25 / 0.05);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

[data-theme='dark'] {
  color-scheme: dark;

  --bg: #131315;
  --bg-subtle: #1a1a1d;
  --bg-inset: #222226;
  --border: #2e2e33;
  --border-strong: #43434a;

  --text: #ebebe9;
  --text-muted: #a3a3a0;

  --accent: #f2b155;
  --accent-hover: #f7c67e;
  --accent-wash: #3a2a12;
  --accent-contrast: #1a1206;

  --ok: #5fd39a;
  --warn: #e8d03c;
  --error: #f27a72;

  --shadow-card: 0 1px 2px rgb(0 0 0 / 0.3), 0 6px 20px rgb(0 0 0 / 0.28);
}

/* ------------------------------------------------------------------ reset */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem; /* clears the sticky header on anchor jumps */
}

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

p {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color 0.15s var(--ease);
}

a:hover {
  color: var(--accent-hover);
}

img,
svg {
  max-width: 100%;
  height: auto;
  display: block;
}

code,
kbd,
samp,
pre {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

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

::selection {
  background: var(--accent-wash);
  color: var(--text);
}

/* --------------------------------------------------------------- skeleton */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

main {
  flex: 1 0 auto;
  padding-block: 3.5rem 5rem;
}

/* One short fade as a page settles. This is the whole "page transition":
   deliberately quiet, and skipped entirely under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .page-enter {
    animation: page-in 0.26s var(--ease) both;
  }
  @keyframes page-in {
    from {
      opacity: 0;
      transform: translateY(4px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.65rem 1rem;
  background: var(--accent);
  color: var(--accent-contrast);
  border-radius: 0 0 var(--r-sm) 0;
  font-weight: 500;
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

/* ----------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--border);
}

@supports not (backdrop-filter: blur(1px)) {
  .site-header {
    background: var(--bg);
  }
}

.header-inner {
  height: 4rem; /* 64px, comfortably inside the 80px cap */
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  /* Reads as roughly 7.5px between the mark and the d, once the glyph's own
     left bearing is counted. Half the mark height is the usual lockup gap. */
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
}

/* The supplied logo, shown as is. Never restyle the artwork itself.

   logo.svg has a squared viewBox tightened to the artwork, so this box size is
   effectively the mark size and no negative-margin correction is needed.

   At 1.25rem the mark renders about 18.8px wide and 16px tall. The wordmark
   beside it has an 11px cap height and a 15px full extent from the top of the
   d to the bottom of the y, which puts the mark at 1.45 times cap height and
   just above the word's own height. That is the balanced range for a mark set
   next to a wordmark; much larger and it starts to dominate the name. */
.wordmark-mark {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  display: block;
  object-fit: contain;
}

/* An inlined SVG logo fills with currentColor, so it follows the theme through
   ordinary inheritance and needs nothing here.

   A bitmap logo cannot do that, so dark-ink artwork gets inverted instead.
   Inverting flips lightness only: shape, proportion and spacing are untouched.
   Scoped to img so it never double-applies to the inline SVG.

   A bitmap logo must have a TRANSPARENT background. With white baked in, this
   rule turns that white into a black block. */
[data-theme='dark'] img.wordmark-mark {
  filter: invert(1);
}

.wordmark:hover {
  color: var(--accent);
}

.nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-inline-start: auto;
}

.nav-link {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.9375rem;
  white-space: nowrap;
}

.nav-link:hover {
  color: var(--accent);
}

.nav-link.is-current {
  color: var(--text);
  font-weight: 500;
}

.theme-toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.125rem;
  height: 2.125rem;
  padding: 0;
  font: inherit;
  color: var(--text-muted);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease),
    background-color 0.15s var(--ease);
}

.theme-toggle svg {
  width: 1.0625rem;
  height: 1.0625rem;
  display: block;
}

/* The button shows the theme it will switch you TO, which is why light mode
   shows a moon. Both icons ship in the markup and css picks one, so the right
   icon is on screen before any script runs rather than flashing after it.

   These selectors are deliberately scoped to .theme-toggle. A bare .icon-sun
   would lose to the .theme-toggle svg rule above on specificity and both icons
   would show at once. */
.theme-toggle .icon-sun {
  display: none;
}

[data-theme='dark'] .theme-toggle .icon-moon {
  display: none;
}

[data-theme='dark'] .theme-toggle .icon-sun {
  display: block;
}

.theme-toggle:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-wash);
}

.theme-toggle:active {
  transform: translateY(1px);
}

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

.site-footer {
  border-top: 1px solid var(--border);
  padding-block: 2rem;
  margin-top: auto;
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: baseline;
  justify-content: space-between;
}

.footer-note,
.footer-nav {
  font-size: 0.875rem;
  color: var(--text-muted);
}

.footer-nav {
  display: flex;
  gap: 1.25rem;
}

/* ------------------------------------------------------------------- home */

.intro {
  padding-top: 1.5rem; /* hero sits high, well under the pt-24 cap */
  padding-bottom: 4.5rem;
}

/* The header mark is a terminal prompt glyph; this line says so instead of
   leaving it as a 20px icon nobody reads. */
.intro-prompt {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 1.1rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.intro-cursor {
  display: inline-block;
  width: 0.5em;
  height: 1em;
  background: var(--accent);
  vertical-align: text-bottom;
}

@media (prefers-reduced-motion: no-preference) {
  .intro-cursor {
    animation: cursor-blink 1.05s step-end infinite;
  }
}

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

.intro-title {
  font-size: clamp(2.125rem, 5vw, 3.25rem);
  letter-spacing: -0.03em;
  line-height: 1.08;
  max-width: 26ch;
}

.intro-lede {
  margin-top: 1.25rem;
  max-width: 46ch;
  font-size: 1.0625rem;
  color: var(--text-muted);
}

.intro-actions {
  margin-top: 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.home-terminal {
  padding-block: 3rem;
  border-top: 1px solid var(--border);
}

/* A decorative macOS-style window chrome around the filterable tools/notes
   list. The traffic-light dots are fixed brand colours, not theme tokens:
   that's what makes them read as "real" window controls in both themes. */
.term-window {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.term-titlebar {
  display: flex;
  align-items: center;
  padding: 0.65rem 1rem;
  background: var(--bg-inset);
  border-bottom: 1px solid var(--border);
}

.term-dots {
  display: flex;
  flex: none;
  gap: 0.4rem;
}

.term-dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
}

.term-dot-red {
  background: #ff5f57;
}

.term-dot-yellow {
  background: #febc2e;
}

.term-dot-green {
  background: #28c840;
}

.term-titlebar-name {
  flex: 1;
  margin-inline-end: 2.7rem; /* balances the dot cluster so the name reads centred */
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.term-body {
  padding: 1.25rem 1.5rem 1.5rem;
}

.term-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.875rem;
}

.term-line .prompt-cmd {
  color: var(--text);
}

.term-results {
  list-style: none;
  margin-top: 1.25rem;
  border-top: 1px solid var(--border);
}

.term-result {
  border-bottom: 1px solid var(--border);
}

.term-result a {
  display: block;
  padding-block: 0.75rem;
  text-decoration: none;
  transition: color 0.15s var(--ease);
}

.term-result a:hover .term-result-title {
  color: var(--accent);
}

.term-result-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  font-size: 0.875rem;
}

.term-result-type {
  flex: none;
  width: 3.25rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.term-result-title {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-weight: 500;
  transition: color 0.15s var(--ease);
}

.term-result-date {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.term-result-desc {
  margin-top: 0.3rem;
  margin-inline-start: calc(3.25rem + 0.75rem);
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.term-more {
  margin-top: 1rem;
  display: flex;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
}

.term-more-sep {
  color: var(--border-strong);
}

.colophon {
  padding-top: 3rem;
  border-top: 1px solid var(--border);
}

.colophon-title {
  font-size: 1.25rem;
  margin-bottom: 1rem;
}

/* --------------------------------------------------------- page furniture */

.page-head {
  max-width: 58ch;
  margin-bottom: 3rem;
}

.page-title {
  font-size: clamp(1.875rem, 3.6vw, 2.5rem);
  letter-spacing: -0.025em;
}

.page-lede {
  margin-top: 1rem;
  color: var(--text-muted);
  font-size: 1.0625rem;
}

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.breadcrumb a {
  text-decoration: none;
}

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

/* Muted rather than border-coloured: as a visible glyph it has to clear AA
   like any other text, even though it is aria-hidden. */
.breadcrumb-sep {
  color: var(--text-muted);
}

.group {
  margin-bottom: 3.5rem;
}

.group:last-child {
  margin-bottom: 0;
}

.group-title {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-muted);
  padding-bottom: 0.75rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap; /* a CTA never wraps to a second line */
  padding: 0.6rem 1.1rem;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease),
    color 0.15s var(--ease), transform 0.1s var(--ease);
}

.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-contrast);
}

.btn-primary:hover {
  background: var(--accent-hover);
  color: var(--accent-contrast);
}

.btn-quiet {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}

.btn-quiet:hover {
  background: var(--accent-wash);
  border-color: var(--accent);
  color: var(--accent);
}

.btn-small {
  padding: 0.4rem 0.7rem;
  font-size: 0.8125rem;
}

.btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn[disabled]:active {
  transform: none;
}

/* ------------------------------------------------------------ tools index */

.category-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.75rem;
}

.category-jump a {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  padding: 0.3rem 0.65rem;
  border-radius: var(--r-sm);
  background: var(--bg-inset);
  color: var(--text-muted);
  text-decoration: none;
}

.category-jump a:hover {
  color: var(--accent);
  background: var(--accent-wash);
}

.tool-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.tool-card {
  display: block;
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  text-decoration: none;
  transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease),
    transform 0.15s var(--ease);
}

.tool-card:hover {
  border-color: var(--accent);
  background: var(--bg-inset);
  transform: translateY(-2px);
}

.tool-card-title {
  font-size: 1rem;
  color: var(--text);
  transition: color 0.15s var(--ease);
}

.tool-card:hover .tool-card-title {
  color: var(--accent);
}

.tool-card-desc {
  margin-top: 0.4rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* ------------------------------------------------------------ notes index */

.note-list {
  list-style: none;
}

.note-row {
  border-bottom: 1px solid var(--border);
}

.note-row:last-child {
  border-bottom: 0;
}

.note-row-link {
  display: block;
  padding-block: 1.1rem;
  text-decoration: none;
}

.note-row-title {
  font-size: 1.0625rem;
  color: var(--text);
  transition: color 0.15s var(--ease);
}

.note-row-link:hover .note-row-title {
  color: var(--accent);
}

.note-row-desc {
  margin-top: 0.35rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
  max-width: 62ch;
}

.note-row-meta,
.note-meta {
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.meta-sep::before {
  content: '';
  display: inline-block;
  width: 1px;
  height: 0.8em;
  margin-right: 0.75rem;
  background: var(--border-strong);
  vertical-align: -0.05em;
}

.row-tags,
.note-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding-bottom: 1.1rem;
}

.note-tags {
  margin-top: 1rem;
  padding-bottom: 0;
}

.tag {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  padding: 0.15rem 0.45rem;
  border-radius: var(--r-sm);
  background: var(--bg-inset);
  color: var(--text-muted);
}

/* ------------------------------------------------------------- note pages */

.note {
  max-width: var(--measure);
}

.note-head {
  padding-bottom: 1.75rem;
  margin-bottom: 2.25rem;
  border-bottom: 1px solid var(--border);
}

.contents {
  padding: 1.25rem 1.5rem;
  margin-bottom: 2.5rem;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.contents-title {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: 0.65rem;
}

.contents-list {
  list-style: none;
  display: grid;
  gap: 0.4rem;
  font-size: 0.9375rem;
}

.contents-list a {
  text-decoration: none;
}

.contents-list a:hover {
  color: var(--accent);
  text-decoration: underline;
}

.nearby {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-top: 4rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
  max-width: var(--measure);
}

.nearby-link {
  display: block;
  padding: 1rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  text-decoration: none;
  color: var(--text);
  font-size: 0.9375rem;
  transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease),
    color 0.15s var(--ease);
}

.nearby-link:hover {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--accent);
}

.nearby-end {
  text-align: right;
}

.nearby-dir {
  display: block;
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 0.25rem;
}

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

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

.prose-narrow {
  max-width: var(--measure);
}

.prose > * + * {
  margin-top: 1.25rem;
}

.prose h2 {
  margin-top: 2.75rem;
  font-size: 1.375rem;
}

.prose h3 {
  margin-top: 2rem;
  font-size: 1.125rem;
}

.prose h2 + *,
.prose h3 + * {
  margin-top: 0.75rem;
}

.prose ul,
.prose ol {
  padding-inline-start: 1.35rem;
}

.prose li + li {
  margin-top: 0.4rem;
}

.prose li::marker {
  color: var(--text-muted);
}

.prose strong {
  font-weight: 600;
}

.prose code {
  padding: 0.12em 0.35em;
  border-radius: 4px;
  background: var(--bg-inset);
  color: var(--text);
}

.prose pre {
  margin-top: 1.25rem;
  padding: 1rem 1.1rem;
  overflow-x: auto;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: 0.875rem;
  line-height: 1.6;
}

.prose pre code {
  padding: 0;
  background: none;
  font-size: inherit;
}

.prose blockquote {
  margin: 1.75rem 0;
  padding-left: 1.25rem;
  border-left: 2px solid var(--accent);
  color: var(--text-muted);
}

.prose blockquote p + p {
  margin-top: 0.75rem;
}

.prose hr {
  margin-block: 2.5rem;
  border: 0;
  border-top: 1px solid var(--border);
}

.prose figure {
  margin: 2rem 0;
}

.prose figcaption {
  margin-top: 0.6rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.prose img {
  border-radius: var(--r-md);
  border: 1px solid var(--border);
}

/* Wide tables scroll inside their own box; the page never scrolls sideways. */
.prose .table-scroll,
.table-scroll {
  overflow-x: auto;
  margin-top: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.prose table,
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.prose table {
  display: block;
  overflow-x: auto;
}

.prose th,
.prose td,
table.data th,
table.data td {
  text-align: left;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.prose tbody tr:last-child td,
table.data tbody tr:last-child td {
  border-bottom: 0;
}

.prose th,
table.data th {
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--text-muted);
  background: var(--bg-subtle);
}

table.data td.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- 404 */

.notfound {
  max-width: 50ch;
  padding-block: 2rem 4rem;
}

.notfound-code {
  font-family: var(--font-mono);
  font-size: 0.875rem;
  color: var(--text-muted);
  margin-bottom: 1rem;
}

/* ==========================================================================
   Tool primitives

   Every tool page is built from these, so a new tool is markup plus a small
   script rather than new CSS. Keep additions here rather than inline.
   ========================================================================== */

.tool-panel {
  padding: 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
}

.tool-panel + .tool-panel {
  margin-top: 1.25rem;
}

.tool-notes {
  max-width: var(--measure);
  margin-top: 3.5rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
}

.tool-notes-title {
  font-size: 1.0625rem;
  margin-bottom: 1rem;
}

/* fields ------------------------------------------------------------------ */

.field-row {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

.field {
  display: grid;
  gap: 0.4rem;
  min-width: 0;
}

.field > label,
.field-label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text);
}

.field input[type='text'],
.field input[type='number'],
.field input[type='password'],
.field select,
.field textarea,
.input {
  width: 100%;
  padding: 0.55rem 0.7rem;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.field textarea,
textarea.input {
  font-family: var(--font-mono);
  font-size: 0.875rem;
  line-height: 1.6;
  min-height: 8rem;
  resize: vertical;
}

.field input.mono,
.field select.mono,
.input.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.field input:hover,
.field select:hover,
.field textarea:hover,
.input:hover {
  border-color: var(--accent);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible,
.input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

/* Placeholder contrast is checked: this sits above 4.5:1 on both grounds. */
.field ::placeholder,
.input::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.field-hint {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.field-error {
  font-size: 0.8125rem;
  color: var(--error);
  font-weight: 500;
}

.field-error:empty {
  display: none;
}

.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-color: var(--error);
}

/* checkbox and radio rows ------------------------------------------------- */

.check-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
}

.check {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.9375rem;
  cursor: pointer;
  transition: color 0.15s var(--ease);
}

.check:hover {
  color: var(--accent);
}

.check input {
  accent-color: var(--accent);
  width: 1rem;
  height: 1rem;
  margin: 0;
  cursor: pointer;
}

/* actions ---------------------------------------------------------------- */

.tool-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.25rem;
}

.tool-actions .spacer {
  margin-inline-start: auto;
}

/* results ---------------------------------------------------------------- */

.result {
  margin-top: 1.25rem;
}

.result-grid {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}

.result-item {
  padding: 0.85rem 1rem;
  background: var(--bg);
}

.result-label {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 0.25rem;
}

.result-value {
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  word-break: break-word;
}

.result-value.lg {
  font-size: 1.25rem;
}

.output {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: 0.875rem;
  line-height: 1.65;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  min-height: 3rem;
}

/* empty and status states ------------------------------------------------ */

.empty {
  padding: 1.75rem 1rem;
  text-align: center;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text-muted);
  font-size: 0.9375rem;
}

.status {
  margin-top: 0.85rem;
  font-size: 0.875rem;
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
}

.status:empty {
  display: none;
}

.status[data-state='ok'] {
  color: var(--ok);
}

.status[data-state='warn'] {
  color: var(--warn);
}

.status[data-state='error'] {
  color: var(--error);
}

/* role lookup: search-and-browse list beside a detail panel. Generic enough
   under the .role- prefix that a second reference tool could reuse it. ---- */

.risk-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.risk-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  padding: 0.35rem 0.75rem;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.risk-filter-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.risk-filter-btn[data-risk='all'][aria-current='true'] {
  color: var(--accent);
  background: var(--accent-wash);
  border-color: var(--accent);
}

.risk-filter-btn.risk-high[aria-current='true'] {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 14%, transparent);
  border-color: var(--error);
}

.risk-filter-btn.risk-medium[aria-current='true'] {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  border-color: var(--warn);
}

.risk-filter-btn.risk-low[aria-current='true'] {
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 14%, transparent);
  border-color: var(--ok);
}

.role-layout {
  display: grid;
  grid-template-columns: 16rem 1fr;
  gap: 1.25rem;
  align-items: start;
  margin-top: 1.25rem;
}

.role-list {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  height: 32rem;
  overflow-y: auto;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
}

.role-list-item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  min-height: 3.4rem;
  padding: 0.55rem 0.65rem;
  font: inherit;
  font-size: 0.875rem;
  line-height: 1.3;
  text-align: left;
  color: var(--text);
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: color 0.15s var(--ease), background-color 0.15s var(--ease);
}

.role-list-item:hover {
  background: var(--accent-wash);
  color: var(--accent);
}

.role-list-item[aria-current='true'] {
  background: var(--accent-wash);
  color: var(--accent);
  font-weight: 500;
}

.role-risk-dot {
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  border-radius: 50%;
}

.role-risk-dot.risk-high {
  background: var(--error);
}

.role-risk-dot.risk-medium {
  background: var(--warn);
}

.role-risk-dot.risk-low {
  background: var(--ok);
}

.role-detail {
  height: 32rem;
  overflow-y: auto;
  padding: 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg);
}

.role-detail-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem 1.25rem;
}

.role-detail-title {
  font-size: 1.25rem;
}

.role-detail-desc {
  margin-top: 0.6rem;
  color: var(--text-muted);
  font-size: 0.9375rem;
  max-width: var(--measure);
}

.risk-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: none;
  padding: 0.3rem 0.65rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: 999px;
}

.risk-badge::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: currentColor;
}

.risk-badge.risk-high {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 14%, transparent);
}

.risk-badge.risk-medium {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 16%, transparent);
}

.risk-badge.risk-low {
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 14%, transparent);
}

.role-section {
  margin-top: 1.5rem;
}

.role-section-label {
  margin-bottom: 0.6rem;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.role-cap-list {
  list-style: none;
  display: grid;
  gap: 0.45rem;
}

.role-cap-list li {
  position: relative;
  padding-left: 1.1rem;
  font-size: 0.9375rem;
}

.role-cap-list li::before {
  content: '\2013';
  position: absolute;
  left: 0;
  color: var(--text-muted);
}

.role-use-case {
  font-size: 0.9375rem;
  max-width: var(--measure);
}

.role-alt-list {
  list-style: none;
  display: grid;
  gap: 0.6rem;
}

.role-alt-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.6rem;
}

.role-alt-chip {
  flex: none;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  padding: 0.3rem 0.7rem;
  color: var(--text);
  background: var(--bg-subtle);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  cursor: pointer;
}

.role-alt-chip:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.role-alt-reason {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.role-alt-empty {
  font-size: 0.875rem;
  color: var(--text-muted);
}

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

@media (max-width: 480px) {
  .term-titlebar-name {
    display: none;
  }
}

@media (max-width: 768px) {
  main {
    padding-block: 2.5rem 3.5rem;
  }

  .shell {
    padding-inline: 1.25rem;
  }

  /* High-variance layouts collapse to a single column below 768px. */
  .tool-grid,
  .nearby,
  .result-grid,
  .field-row,
  .role-layout {
    grid-template-columns: 1fr;
  }

  .role-list {
    height: 16rem;
  }

  .role-detail {
    height: auto;
    overflow-y: visible;
  }

  .nearby-end {
    text-align: left;
  }

  .intro-title {
    font-size: clamp(1.875rem, 8vw, 2.25rem);
  }

  .page-head {
    margin-bottom: 2.25rem;
  }

  .tool-panel {
    padding: 1.1rem;
  }

  .footer-inner {
    flex-direction: column;
    gap: 0.75rem;
  }
}

@media (max-width: 560px) {
  .header-inner {
    gap: 0.85rem;
  }

  .nav {
    gap: 1rem;
  }

  .nav-link {
    font-size: 0.875rem;
  }

  .theme-toggle {
    width: 2rem;
    height: 2rem;
  }

  .btn {
    width: 100%;
  }

  .intro-actions {
    flex-direction: column;
  }
}

/* At the narrowest widths the wordmark yields so nav stays on one line. */
@media (max-width: 380px) {
  .wordmark {
    font-size: 0.9375rem;
  }
}

/* --------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .tool-card:hover,
  .btn:active,
  .theme-toggle:active {
    transform: none;
  }
}

/* ------------------------------------------------------------------ print */

@media print {
  .site-header,
  .site-footer,
  .nearby,
  .skip-link,
  .tool-actions {
    display: none;
  }

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