/* =====================================================================
   DOC — the machine documentation pages (/machines/<name>/).

   Owned by the doc area. See .claude/design-language.md §9.

   LOAD ORDER
   styles.css is the pre-redesign sheet and now loads FIRST, so at
   equal specificity the rules in this file win. The three overrides
   at the end of this file are therefore written flat — they no longer
   need an extra tag or class bolted on to out-specify the legacy
   sheet, and the `html:has(.doc-page) { scroll-padding-top: 0 }` hack
   is gone entirely because styles.css stopped setting it.

   The class names stay namespaced (.doc-prose, .doc-tbl, .doc-jump,
   .dr-kicker…) because styles.css still carries live rules for the
   old names (.prose, .doc-table, .doc-rich) and sharing a name would
   mean inheriting whatever they set.

   THE LOOK
   Hairlines, square corners, no fills behind text, one reading
   measure, and nothing below 15px (§3). Body copy is 19px — these are
   long technical documents and the copy is the point. Mono is rare:
   a status word, a count, a spec value (§3).
   ===================================================================== */

.doc-page {
  /* hugo.toml [params.colors] — duplicated here because this is a
     plain stylesheet, not a template. Scoped to .doc-page rather
     than :root so the doc area cannot leak tokens into other areas. */
  --doc-surface: #ffffff;

  /* THE STICKY STACK, in one place.

     --doc-jump-row is the height of the jump bar's CONTENT box: the
     links are exactly this tall. The bar also carries a hairline top
     and bottom, and box-sizing is border-box, so what the bar
     actually occupies on screen is two pixels more than the row.
     --doc-jump-h is that true occupied height, and it is what the
     anchor offsets below have to clear.

     Getting this wrong by those two pixels is how every heading used
     to land two pixels under the bar. */
  --doc-jump-row: 3.5rem;
  --doc-jump-h: calc(var(--doc-jump-row) + 2px);

  /* The whole fixed/sticky stack a jump has to clear, and the gap we
     want between it and the heading that lands under it. */
  --doc-stack: calc(var(--bar-h) + var(--doc-jump-h));
  --doc-gap: 1.25rem;
}

/* ---------------------------------------------------------------------
   Anchors under two fixed things

   system.css already clears the top bar for every [id]. On a doc page
   with the jump bar showing there is a second sticky strip underneath
   it, so the offset grows.
   --------------------------------------------------------------------- */
/* One offset for every anchor on the page, headings included. The
   anchors now sit ON the headings (see doc-section-head.html), so this
   lands the heading itself just under whatever is sticky above it —
   the same distance every time, at every breakpoint. */
.doc-page [id] { scroll-margin-top: calc(var(--bar-h) + var(--doc-gap)); }
.doc-page.has-jump [id] {
  scroll-margin-top: calc(var(--doc-stack) + var(--doc-gap));
}

/* ---------------------------------------------------------------------
   THE JUMP BAR

   Sits flush under the fixed top bar. The bar is h-16 sm:h-20, which
   is exactly --bar-h, and this offsets from that token, so the two
   cannot fall out of register at the 640px breakpoint.

   Plain section names at reading size, divided by hairlines. The
   two-digit indices and the micro-caps mono are gone (§2, §3).
   --------------------------------------------------------------------- */
.doc-jump {
  position: sticky;
  top: var(--bar-h);
  z-index: 30;
  min-height: var(--doc-jump-h);   /* row + its two hairlines */
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.doc-jump-scroll {
  display: flex;
  align-items: stretch;
  overflow-x: auto;
  scrollbar-width: none;
}
.doc-jump-scroll::-webkit-scrollbar { display: none; }

.doc-jump-link {
  display: inline-flex;
  align-items: center;
  flex: none;
  height: var(--doc-jump-row);
  padding: 0 1.25rem;
  border-left: 1px solid var(--line);
  color: var(--muted);
  font-size: 1.0625rem;
  line-height: 1;
  white-space: nowrap;
  transition: color var(--t) var(--ease);
}
.doc-jump-link:first-child { padding-left: 0; border-left: 0; }
.doc-jump-link:hover { color: var(--maroon); }

/* ---------------------------------------------------------------------
   SECTION HEAD

   A hairline across the content column with the name under it. That
   one rule is the whole boundary between sections: the sections
   themselves no longer carry a bottom border, and the decorative gold
   tick that used to register against the left end of the rule is gone
   (§2, §6).
   --------------------------------------------------------------------- */
.doc-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  padding-top: 1.5rem;
  margin-bottom: 3rem;
  border-top: 1px solid var(--line);
}

/* ---------------------------------------------------------------------
   SPEC STRIP

   Target numbers across the top of the page. Columns divided by
   hairlines rather than boxed into cards — the values are a row of
   readings, so they are set as one. The value is mono because it is a
   measurement; the label is not.
   --------------------------------------------------------------------- */
.doc-specs {
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--line);
}

@media (min-width: 640px) {
  .doc-specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .doc-specs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.doc-specs > div {
  padding: 1.25rem 1.5rem 1.5rem 0;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 640px) {
  .doc-specs > div { border-left: 1px solid var(--line); padding-left: 1.5rem; }
  .doc-specs > div:nth-child(2n + 1) { border-left: 0; padding-left: 0; }
}
@media (min-width: 1024px) {
  .doc-specs > div:nth-child(2n + 1) { border-left: 1px solid var(--line); padding-left: 1.5rem; }
  .doc-specs > div:nth-child(4n + 1) { border-left: 0; padding-left: 0; }
}

.doc-specs dt {
  font-size: 1.0625rem;
  line-height: 1.4;
  color: var(--muted);
}

.doc-specs .doc-specs-target {
  margin-top: 0.75rem;
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 1.375rem;
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--ink);
}

.doc-specs .doc-specs-now {
  margin-top: 0.375rem;
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 1.0625rem;
  line-height: 1.3;
  color: var(--muted);
}

/* ---------------------------------------------------------------------
   READINGS — the Overview's row of key numbers

   Each number hangs under its own short rule, so the row reads as a
   set of graduations rather than as a strip of cards.
   --------------------------------------------------------------------- */
.doc-readings {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 2.5rem 3rem;
}

/* A flex column with the label pushed to the bottom, so the labels
   stay on one line across the row even when a value wraps. */
.doc-readings > div {
  display: flex;
  flex-direction: column;
  padding-top: 1rem;
  border-top: 1px solid var(--ink);
}

.doc-readings dt {
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 2.5rem;
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.doc-readings dd {
  margin-top: auto;
  padding-top: 0.75rem;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--muted);
}

/* ---------------------------------------------------------------------
   PROCESS STEPS — the Overview's numbered sequence

   An ordinary ordered list: the browser's own numbering carries the
   sequence, so there is no hand-set "01" numeral any more (§2).
   --------------------------------------------------------------------- */
.doc-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 2.5rem 3rem;
  list-style: decimal;
}

.doc-steps > li {
  margin-left: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.doc-steps > li::marker {
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 1.0625rem;
  color: var(--maroon);
}

/* ---------------------------------------------------------------------
   PROSE

   The readability baseline for everything written in markdown: the
   machine's Background, the Overview text, and the student write-ups.
   19px, relaxed, one measure. Headings are large enough to carry the
   document's structure without numerals or rails beside them.
   --------------------------------------------------------------------- */
.doc-prose {
  font-size: 1.1875rem;
  line-height: 1.7;
  color: var(--muted);
}

.doc-prose > :first-child { margin-top: 0; }
.doc-prose > :last-child { margin-bottom: 0; }

.doc-prose p { margin: 0 0 1.4rem; }

.doc-prose strong { font-weight: 650; color: var(--ink); }

.doc-prose em { font-style: italic; }

.doc-prose a {
  color: var(--maroon);
  text-decoration: underline;
  text-decoration-color: rgba(122, 0, 25, 0.35);
  text-underline-offset: 0.2em;
  transition: text-decoration-color var(--t) var(--ease);
}
.doc-prose a:hover { text-decoration-color: var(--maroon); }

.doc-prose h2,
.doc-prose h3,
.doc-prose h4 {
  font-family: Fraunces, Georgia, serif;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--ink);
}
.doc-prose h2 { font-size: 2rem;      margin: 4rem 0 1.25rem; }
.doc-prose h3 { font-size: 1.5rem;    margin: 2.75rem 0 0.85rem; }
.doc-prose h4 { font-size: 1.25rem;   margin: 2rem 0 0.6rem; }

/* Lists sit in the margin, so the text block keeps one left edge. */
.doc-prose ul,
.doc-prose ol { margin: 0 0 1.4rem; padding-left: 1.4rem; }
.doc-prose ul { list-style: square; }
.doc-prose ol { list-style: decimal; }
.doc-prose li { margin-bottom: 0.55rem; }
.doc-prose li::marker { color: var(--line); }
.doc-prose ol li::marker {
  font-family: "Courier Prime", ui-monospace, monospace;
  color: var(--muted);
}
.doc-prose li > ul,
.doc-prose li > ol { margin: 0.55rem 0 0.3rem; }

.doc-prose code {
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 0.95em;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}

.doc-prose pre {
  margin: 0 0 1.4rem;
  padding: 1.125rem 1.25rem;
  overflow-x: auto;
  background: var(--doc-surface);
  border: 1px solid var(--line);
  border-left: 2px solid var(--ink);
  font-size: 1.0625rem;
  line-height: 1.6;
}
.doc-prose pre code { border: 0; font-size: inherit; }

/* A quote is set off by a rule in the margin, not by a filled panel. */
.doc-prose blockquote {
  margin: 2rem 0;
  padding-left: 1.5rem;
  border-left: 1px solid var(--maroon);
  color: var(--ink);
}
.doc-prose blockquote p:last-child { margin-bottom: 0; }

.doc-prose hr {
  margin: 3rem 0;
  border: 0;
  border-top: 1px solid var(--line);
}

/* Tables written in markdown get the same treatment as the data
   tables below, minus the frame. */
.doc-prose table {
  width: 100%;
  margin: 0 0 1.4rem;
  border-collapse: collapse;
  font-size: 1.0625rem;
}
.doc-prose th {
  padding: 0 1rem 0.75rem 0;
  border-bottom: 1px solid var(--ink);
  font-weight: 600;
  text-align: left;
  color: var(--ink);
}
.doc-prose td {
  padding: 0.8125rem 1rem 0.8125rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.doc-prose th:last-child,
.doc-prose td:last-child { padding-right: 0; }

/* A markdown table wider than the measure scrolls instead of
   squeezing. Emitted by doc-writeup-rich.html. */
.doc-scroll {
  margin: 0 0 1.4rem;
  overflow-x: auto;
  border-top: 1px solid var(--ink);
}
.doc-scroll table { min-width: 34rem; margin: 0; }
.doc-scroll th { border-bottom: 1px solid var(--line); padding-top: 0.75rem; }

/* Milestone / stop-gate bullets. A rule in the margin and a label —
   no highlighter fill behind the text (§4). */
.doc-prose li.doc-flag {
  list-style: none;
  margin-left: -1.4rem;
  padding-left: 1.125rem;
  border-left: 1px solid var(--line);
}
.doc-prose li.doc-flag > strong:first-child {
  display: block;
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 1.0625rem;
  font-weight: 400;
  letter-spacing: 0.08em;
}
.doc-prose li.doc-flag-milestone { border-left-color: var(--gold); }
.doc-prose li.doc-flag-milestone > strong:first-child { color: #8A6400; }
.doc-prose li.doc-flag-stop { border-left-color: var(--maroon); }
.doc-prose li.doc-flag-stop > strong:first-child { color: var(--maroon); }

/* "Week 3", "Stage 1", "Phase 2" pulled out of a ### heading — a
   schedule marker is machine data, so it stays mono (§3). */
.dr-kicker {
  display: block;
  margin-bottom: 0.4rem;
  font-family: "Courier Prime", ui-monospace, monospace;
  font-size: 1.0625rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--maroon);
}

/* ---------------------------------------------------------------------
   DATA TABLES — the parts list and anything like it
   --------------------------------------------------------------------- */
.doc-tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: 1.0625rem;
}

.doc-tbl th {
  padding: 0 1rem 0.875rem;
  border-bottom: 1px solid var(--ink);
  font-weight: 600;
  text-align: left;
  color: var(--ink);
  white-space: nowrap;
}

.doc-tbl td {
  padding: 1.0625rem 1rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  line-height: 1.5;
}

.doc-tbl tfoot td {
  padding-top: 1.125rem;
  border-top: 1px solid var(--ink);
  border-bottom: 0;
}

/* Numerals are data: right-aligned, in the typewriter face (§3). */
.doc-tbl .num {
  text-align: right;
  font-family: "Courier Prime", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* First and last cells sit flush with the content column. */
.doc-tbl th:first-child,
.doc-tbl td:first-child { padding-left: 0; }
.doc-tbl th:last-child,
.doc-tbl td:last-child { padding-right: 0; }

/* ---------------------------------------------------------------------
   TIMELINE RAIL

   A vertical hairline with square ticks on it. The tick's fill is the
   milestone's state; the word beside it says the same thing, so colour
   is never carrying it alone (§10).
   --------------------------------------------------------------------- */
.doc-rail { position: relative; }
.doc-rail::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.7rem;
  bottom: 0.7rem;
  width: 1px;
  background: var(--line);
}

.doc-rail-item { position: relative; padding-left: 2.25rem; }

.doc-rail-tick {
  position: absolute;
  left: 0;
  top: 0.55rem;
  width: 9px;
  height: 9px;
  border: 1px solid var(--line);
  background: var(--paper);
  box-sizing: border-box;
}
.doc-rail-tick.is-done { background: var(--ink); border-color: var(--ink); }
.doc-rail-tick.is-active { background: var(--gold); border-color: #8A6400; }

/* A square progress meter. Width is the only animated property (§7). */
.doc-meter {
  height: 3px;
  background: var(--line);
}
.doc-meter > span {
  display: block;
  height: 100%;
  background: var(--ink);
  transition: width var(--t) var(--ease);
}

/* ---------------------------------------------------------------------
   SEEDED-EXAMPLE NOTICE
   --------------------------------------------------------------------- */
.doc-note {
  padding-left: 1.25rem;
  border-left: 1px solid var(--maroon);
}

/* ---------------------------------------------------------------------
   FIGURES

   A hairline frame on white, because a diagram with a transparent
   background needs something to sit on. No radius, no shadow. The
   image is the link to the full-size file; there is no label saying so
   (§2).
   --------------------------------------------------------------------- */
.doc-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--doc-surface);
  border: 1px solid var(--line);
  transition: border-color var(--t) var(--ease);
}
.doc-frame:hover { border-color: var(--maroon); }

/* A caption is a sentence about the picture, set at reading size. The
   short gold measure rule that used to tie it to the figure is gone
   (§2, §4). */
.doc-cap {
  display: block;
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--muted);
}

/* ---------------------------------------------------------------------
   LEGACY OVERRIDES

   styles.css loads first now, so these win on source order at equal
   specificity. They exist only to undo things §4 and §6 prohibit.
   --------------------------------------------------------------------- */

/* .machine-card carries a white-to-cream gradient, a 1.5px tinted
   border and a hover lift from the pre-redesign sheet. Flat fill, one
   hairline, and the hover moves the border colour only. */
.machine-card {
  background-image: none;
  background-color: transparent;
  border-width: 1px;
  border-color: var(--line);
  border-radius: 0;
  transform: none;
  transition: border-color var(--t) var(--ease),
              background-color var(--t) var(--ease);
}
.machine-card:hover,
.machine-card:focus-visible,
.machine-card:active {
  transform: none;
  border-color: var(--maroon);
  background-color: var(--doc-surface, #fff);
}

/* Markdown images (layouts/_default/_markup/render-image.html) are
   framed by styles.css with a 12px radius, and their captions set at
   14px behind a gold measure rule. Square the frame, bring the
   caption up to the 17px floor, drop the rule. */
.doc-prose .md-figure-frame {
  border-radius: 0;
  text-decoration: none;
}
.doc-page .md-figure-caption {
  display: block;
  font-size: 1.0625rem;
  line-height: 1.55;
}
.doc-page .md-figure-caption::before { content: none; }

/* ---------------------------------------------------------------------
   Reduced motion
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .doc-meter > span { transition: none; }
}


/* ---------------------------------------------------------------------
   EVERY ANCHOR MUST BE ABLE TO REACH THE TOP

   scroll-margin-top only works if the page can actually scroll that
   far. Click the last section on a short page and the document hits
   its end first, so the heading stops halfway down the screen — which
   is the "it doesn't align" everybody notices and nobody can
   reproduce on a long page.

   Now that every machine shows four sections and most of them are a
   two-line note, this is the common case, not the edge case. The
   guard: the last thing on the page is tall enough that the final
   heading can always be pulled up under the sticky stack.

   100svh, not 100vh — on iOS vh is the tallest the viewport ever
   gets, which would reserve more room than exists and leave dead
   space under the page.
   --------------------------------------------------------------------- */
.doc-page > nav[aria-label="More in this band"] {
  min-height: calc(100svh - var(--doc-stack));
}

/* ---------------------------------------------------------------------
   NOT WRITTEN YET (partials/doc-placeholder.html)

   A mono status word over one sentence saying what the section will
   hold. No box, no tint, no icon — a panel here would give an empty
   section more presence than a written one (§2).

   The left hairline is the one mark it gets. It separates the note
   from the section heading above it, which is the kind of rule §2
   allows: without it the note reads as the section's first
   paragraph, i.e. as content.
   --------------------------------------------------------------------- */
.doc-wip {
  max-width: 42rem;
  border-left: 1px solid var(--line);
  padding-left: 1.5rem;
}

.doc-wip-mark {
  font-size: 0.9375rem;      /* the 15px floor, §3 */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--maroon);
  margin: 0;
}

.doc-wip-say {
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--muted);
  margin: 0.75rem 0 0;
}

/* ---------------------------------------------------------------------
   A SECTION THAT HOLDS ONLY THE NOTE GETS LESS AIR

   The written sections run on py-28 / lg:py-40 because they hold long
   technical copy and need the room. Around a heading and two lines of
   "work in progress" that same rhythm reads as a broken page: twenty
   rems of padding above and below eight rems of content, four times
   over.

   This pulls those sections in. It deliberately leaves the written
   ones alone, so a machine someone has documented still breathes, and
   the difference in density is itself a signal about which pages have
   work in them.

   :has() on the padded wrapper, not a class from the template,
   because three different partials emit that wrapper and they would
   each need the same flag kept in step by hand.
   --------------------------------------------------------------------- */
.doc-page section > div:has(> .doc-wip) {
  padding-top: 4.5rem;
  padding-bottom: 4.5rem;
}

@media (min-width: 1024px) {
  .doc-page section > div:has(> .doc-wip) {
    padding-top: 5.5rem;
    padding-bottom: 5.5rem;
  }
}
