/* PlanForge website stylesheet.
 *
 * Written for this site. There is no framework, no reset library, no web font
 * and no icon set; the one icon, the GitHub mark in the header, is inlined in
 * the page. Every page loads four files: its own HTML, this one, the logo and
 * the favicon. The pages are ordered so that they still read correctly
 * with no stylesheet at all.
 *
 * Colours are picked so that every text and background pair is above the WCAG
 * 2.1 AA contrast ratio of 4.5:1, in the light scheme and in the dark one.
 */

:root {
  --bg: #ffffff;
  --shade: #f4f4f1;
  --border: #ccccc4;
  --text: #1a1c1f;
  --muted: #4a5057;
  --link: #0b4f8f;
  --visited: #6a2a8c;
  --code: #0d3a63;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16181b;
    --shade: #21252a;
    --border: #3a4147;
    --text: #e6e8ea;
    --muted: #a9b1b8;
    --link: #7cc0ff;
    --visited: #d4a8f0;
    --code: #b8d4ea;
  }
}

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

html {
  scroll-padding-top: 1rem;
}

body {
  max-width: 64rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 3rem;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
}

/* The skip link is off screen until it takes focus. */

.skip {
  position: absolute;
  left: -10000px;
}

.skip:focus {
  left: 0.5rem;
  top: 0.5rem;
  background: var(--bg);
  border: 2px solid var(--link);
  padding: 0.4rem 0.6rem;
}

/* Header and navigation. */

/* Top bar: logo on the left, repository link on the right. */

header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.7rem;
  margin-bottom: 2rem;
}

.repo {
  margin: 0;
  font-size: 0.9rem;
}

.repo a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--muted);
  text-decoration: none;
}

.repo a:visited {
  color: var(--muted);
}

.repo a:hover,
.repo a:focus-visible {
  color: var(--link);
  text-decoration: underline;
}

.repo svg {
  flex: none;
}

/* The logo carries the site name, so there is no separate text title. Sizing by
   width only, with height left automatic, keeps the aspect ratio the SVG
   declares. The intrinsic width and height on the img reserve the box before the
   file loads, so the nav below it does not jump. */

.logo {
  display: inline-block;
}

.logo img {
  display: block;
  width: 17rem;
  height: auto;
}

/* Two columns: the site menu on the left of the page, the page beside it.
   min-width: 0 on main is load-bearing. Without it a wide table or a long line
   inside a pre block sets the flex item's minimum size to its own content
   width, which pushes the whole layout wider than the page and produces a
   horizontal scrollbar on the document instead of inside the table. */

.page {
  display: flex;
  align-items: flex-start;
  gap: 2.5rem;
}

.page nav {
  flex: 0 0 11rem;
  position: sticky;
  top: 1rem;
}

.page main {
  flex: 1 1 auto;
  min-width: 0;
}

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.9rem;
}

nav li {
  display: block;
  margin: 0 0 0.5rem;
}

nav a {
  color: var(--muted);
  text-decoration: none;
}

nav a:visited {
  color: var(--muted);
}

nav a:hover,
nav a:focus-visible {
  color: var(--link);
  text-decoration: underline;
}

nav a[aria-current="page"] {
  color: var(--text);
  font-weight: 700;
}

/* Text. */

h1 {
  font-size: 1.7rem;
  line-height: 1.2;
  margin: 0 0 0.8rem;
}

h2 {
  font-size: 1.3rem;
  line-height: 1.25;
  margin: 2.4rem 0 0.6rem;
}

h3 {
  font-size: 1.05rem;
  margin: 1.5rem 0 0.4rem;
}

h4 {
  font-size: 1rem;
  margin: 1.2rem 0 0.3rem;
}

p,
ul,
ol,
dl,
pre {
  margin: 0 0 0.9rem;
}

ul,
ol {
  padding-left: 1.4rem;
}

dt {
  font-weight: 700;
  margin-top: 0.7rem;
}

dd {
  margin: 0 0 0 1.4rem;
}

a {
  color: var(--link);
}

a:visited {
  color: var(--visited);
}

:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
}

/* Code. */

code,
pre {
  font-family: ui-monospace, "DejaVu Sans Mono", monospace;
  font-size: 0.9em;
}

/* Inline code carries no background. Some pages mention code hundreds of times
   in running prose, and a shaded box around each one turns the page into a rash
   of grey rectangles. The monospace face is enough to mark it.

   Identifiers do not wrap. A browser treats a hyphen as a break opportunity, so
   `--search` in running prose otherwise splits across two lines and reads as `-`
   then `-search`, and no reader can tell how many hyphens the real option has.
   That is a correctness problem in documentation, not a cosmetic one.

   Inline code that contains a space is a message or a phrase rather than an
   identifier, and it is marked .wrap so it can still break. Without that the
   longest of them, around ninety characters, would run off the column. */

:not(pre) > code {
  color: var(--code);
  white-space: nowrap;
}

:not(pre) > code.wrap {
  white-space: normal;
}

pre {
  background: var(--shade);
  border: 1px solid var(--border);
  padding: 0.7rem 0.8rem;
  overflow-x: auto;
  line-height: 1.45;
}


/* Tables. A table that is wider than the page scrolls inside this wrapper
   instead of widening the page. */

.scroll {
  overflow-x: auto;
  margin-bottom: 0.9rem;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9rem;
}

caption {
  text-align: left;
  color: var(--muted);
  padding-bottom: 0.3rem;
}

th,
td {
  border: 1px solid var(--border);
  padding: 0.3rem 0.5rem;
  text-align: left;
  vertical-align: top;
}

th {
  background: var(--shade);
}

td.num {
  text-align: right;
}

/* Footer. */

footer {
  border-top: 1px solid var(--border);
  margin-top: 2.5rem;
  padding-top: 0.8rem;
  color: var(--muted);
  font-size: 0.9rem;
}

footer p {
  margin: 0 0 0.4rem;
}

/* Narrow screens: one column, with the menu as a row above the page. */

@media (max-width: 58rem) {
  .page {
    display: block;
  }

  .page nav {
    position: static;
    border-bottom: 1px solid var(--border);
    padding-bottom: 0.7rem;
    margin-bottom: 1.75rem;
  }

  nav li {
    display: inline;
    margin: 0 1.1rem 0 0;
  }

  /* The longest identifier on the site is 55 characters, which is wider than a
     phone column. Since it must not break mid-token, let it scroll inside its
     own box instead. Without this it widens the document and every page gets a
     horizontal scrollbar on a phone. */

  :not(pre) > code {
    display: inline-block;
    max-width: 100%;
    overflow-x: auto;
    vertical-align: bottom;
  }
}
