/* ============================================================================
   ALEXANDRIA LIBRARY — SITE STYLESHEET
   ----------------------------------------------------------------------------
   Every visual rule for the site lives in this one file. There is no CSS
   framework, no preprocessor and no build step: what you read here is what the
   browser gets, and `web/index.html` plus `web/design-standards.html` are the
   only two documents that consume it.

   THE DESIGN, IN ONE PARAGRAPH
   A quiet, modern document. A neutral sans (Inter) carries every heading and
   every line of prose; a monospace (IBM Plex Mono) is reserved for recorded
   values — component nicknames, port names, data types, paths, counts — where
   the reader benefits from seeing at a glance that something is a literal from
   the codebase rather than a sentence about it. Structure is carried by
   hairline rules and generous whitespace, not by heavy black bars, boxes, or
   drop shadows. Weight is used sparingly: nothing on the site is set bolder
   than 600. One deep red is the only accent, and it means "this is interactive"
   — nothing else.

   THE DESIGN IS WRITTEN DOWN
   The token names, the section numbering of this file, and the class names for
   each kind of block — .doc, .kicker, .title, .section, .disclosure, .table,
   .caption, .nav — are deliberately plain, so a rule can be found from the
   markup and back again. Where this project has a piece ordinary document
   prose does not — the component diagrams, above all — it is styled to the
   same rules rather than inventing a second idiom. Before changing type,
   colour, or rule weights, read `web/design-standards.html`: a change here is
   a change to a standard the whole site follows.

   HOW THIS FILE IS ORGANISED
      1.  Design tokens ............ every colour, font, size and spacing value
      2.  Document skeleton ........ page frame, resets, base elements
      3.  Masthead ................. title block at the top of each page
      4.  Abstract ................. the summary paragraph
      5.  Table of contents ........ the section index on the homepage
      6.  Section headings ......... "Introduction", "Installation", …
      7.  Body copy ................ paragraphs, lists, labels, captions
      8.  Rules .................... the horizontal dividers
      9.  Tables ................... data tables and their captions
     10.  Collapsible rows ......... the <details>/<summary> row one domain
                                     of the component reference sits in
     11.  Component diagrams ....... the inputs → component → outputs schematics
     12.  References .............. the link list at the foot of the page
     13.  Top navigation ........... the bar on interior pages
     14.  Design-standards page .... specimens and swatches, used on one page
     15.  Colophon ................. page footer
     16.  Responsive ............... narrow-screen overrides

   To restyle the whole site, change a token in section 1 rather than editing
   the rules below — nearly every rule is expressed in terms of those tokens.
   ========================================================================= */


/* ============================================================================
   1. DESIGN TOKENS
   Change these, not the rules further down.
   ========================================================================= */

:root {
  /* -- Colour: surfaces ----------------------------------------------------
     Beyond the page itself there is one barely-there warm tint, used behind
     small inline objects: an inline code span, a neutral tag. It is never
     used to shade a region of the page — an opened domain is set off by
     whitespace and one hairline, not by a panel colour. */
  --color-bg: #ffffff;              /* page background */
  --color-surface: #faf9f7;         /* reserved: hovered controls */
  --color-surface-hover: #f4f2ef;   /* inline code, neutral tags */

  /* -- Colour: text --------------------------------------------------------
     Three steps, in descending emphasis. Anything that is not prose — a
     caption, a port type, an eyebrow label — sits on one of the lower two,
     which is most of what keeps the page feeling light. */
  --color-text: #1c1a19;            /* body copy and headings */
  --color-text-soft: #4a4643;       /* secondary prose: descriptions, notes */
  --color-text-mute: #7a746e;       /* tertiary: captions, counts, labels */

  /* -- Colour: accent ------------------------------------------------------
     A single deep red, and the one thing on the page allowed to use it is
     something you can click. --color-accent-hover and --color-accent-wash are
     derived from it in the `body` rule in section 2, not here, so that
     overriding --color-accent on <body> carries its two derived tints with it,
     so one declaration re-themes the whole site, hover states included. */
  --color-accent: #7c1405;
  --color-selection: #ffe0d9;       /* ::selection highlight */

  /* -- Colour: rules -------------------------------------------------------
     Structure is hairlines, not bars. Both weights are 1px; they differ only
     in contrast, and even the "strong" one is a light grey. This is the single
     biggest reason the page reads lighter than the ruled technical paper it
     used to be: a divider should tell you where a section ends, not draw
     attention to itself while doing it. */
  --color-rule: #eae7e3;            /* between rows within a section */
  --color-rule-strong: #d5d0ca;     /* between major sections */

  /* -- Colour: port data types ---------------------------------------------
     The one place on the site that uses colour to carry meaning other than
     "interactive". Each Grasshopper data type has its own hue, shown as a dot
     beside a port name and as the colour of that port's type label, so a
     reader can scan the component reference for "everything that takes a
     curve" without reading every label. It is a data encoding, in the way a
     map's pin colours are, and it is confined to section 11 — nothing outside
     a diagram may use these.

     To add a type: add a token here, add a matching `.port--*` class at the
     end of section 11, and use it on the port's wrapper div in index.html. */
  --type-number:   rgb(150, 89, 28);   /* Number, Integer */
  --type-curve:    rgb(107, 58, 91);   /* Curve */
  --type-boolean:  rgb(47, 93, 107);   /* Boolean */
  --type-string:   rgb(63, 107, 63);   /* String, file path */
  --type-geometry: rgb(122, 74, 47);   /* Geometry, Brep, Box */
  --type-point:    rgb(42, 107, 99);   /* Point3d */
  --type-data:     rgb(85, 96, 107);   /* Data / DataTree */
  --type-plane:    rgb(71, 81, 124);   /* Plane */
  --type-colour:   rgb(122, 60, 60);   /* Colour */

  /* -- Type ----------------------------------------------------------------
     Both families are loaded from Google Fonts by the <link> in each
     document's <head>. The fallbacks apply if that request fails. Change the
     family here AND in both documents' <link> tags — one without the other
     silently falls back. */
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Helvetica, Arial, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* -- Type weights --------------------------------------------------------
     Three weights, and no bold. 600 is the heaviest thing on the site; the
     jump from 400 to 600 is enough to mark a heading when the type around it
     is calm. Use --weight-medium for anything that needs to be *noticed*
     without being a heading: a table header, a port name, a domain title. */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-strong: 600;

  /* -- Type scale ----------------------------------------------------------
     Sizes are smaller than the serif this site used before needed at the same
     apparent scale: Inter has a large x-height, so it reads bigger per px. */
  --size-title: 34px;               /* page title */
  --size-title-record: 27px;        /* … on an interior page */
  --size-section: 23px;             /* section heading */
  --size-subsection: 17px;          /* domain row heading */
  --size-body: 16px;                /* body paragraphs */
  --size-abstract: 16px;            /* abstract paragraph */
  --size-table: 15px;               /* table cells, list items */
  --size-data: 13px;                /* monospace data: paths, counts */
  --size-caption: 13px;             /* figure/table captions */
  --size-fine: 12px;                /* diagram descriptions, port names */
  --size-label: 11px;               /* uppercase eyebrow labels, port types */

  /* -- Letter-spacing ------------------------------------------------------
     Inter is drawn for interfaces and sets slightly loose at display sizes,
     so large type is tightened and small caps-tracked type is opened up. */
  --track-tight: -0.02em;           /* titles and section headings */
  --track-body: -0.006em;           /* running prose */
  --track-label: 0.08em;            /* uppercase eyebrow labels */

  /* -- Spacing -------------------------------------------------------------
     A coarse scale; prefer these over bare pixel values. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 18px;
  --space-5: 26px;
  --space-6: 40px;
  --space-7: 56px;

  /* -- Radius --------------------------------------------------------------
     Used only where an element is a drawn object or a control rather than a
     run of text — a diagram's component box, a button, an input. Text and
     tables stay square; rounding them would read as decoration. */
  --radius-sm: 4px;
  --radius-md: 8px;

  /* -- Measure -------------------------------------------------------------
     --measure caps the document; --measure-text caps running prose so lines
     stay readable even when the document itself is wide. */
  --measure: 1000px;
  --measure-text: 70ch;

  /* -- Page frame ----------------------------------------------------------
     The homepage's headroom and footroom. Both sit outside the --space-*
     scale on purpose: they are larger than any gap between elements, which is
     what makes the document read as a page rather than as a scrolling feed. */
  --doc-pad-top: 80px;
  --doc-pad-bottom: 120px;
  --doc-pad-x: 40px;                /* gutter between content and window edge */

  /* -- Diagram geometry ----------------------------------------------------
     Section 11 only. The port column is wide enough for a name like
     `sub_category` on one line; the arrow column is a fixed gutter so every
     diagram's component box starts at the same x, and a page of diagrams
     reads as a column rather than as ragged boxes. */
  --diagram-port-col: 132px;
  --diagram-arrow-col: 28px;
  --diagram-max: 640px;
  /* How far a diagram and its domain's count line are indented from the
     domain row that contains them. */
  --diagram-indent: var(--space-5);

  /* -- Motion --------------------------------------------------------------
     One duration, one easing, everywhere. */
  --transition: 140ms ease;
}


/* ============================================================================
   2. DOCUMENT SKELETON
   ========================================================================= */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;    /* the table of contents jumps to sections */
}

body {
  /* Derived here rather than in :root — see the note on --color-accent above.
     --color-accent-wash is the faintest possible accent tint, used behind a
     hovered button on the design-standards page. */
  --color-accent-hover: color-mix(in srgb, var(--color-accent) 72%, #000000);
  --color-accent-wash: color-mix(in srgb, var(--color-accent) 5%, #ffffff);

  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--size-body);
  font-weight: var(--weight-regular);
  line-height: 1.6;
  letter-spacing: var(--track-body);
  /* Kerning and default ligatures on; Inter's contextual alternates are left
     off, since they change letterforms mid-word in ways that read as a bug
     next to a column of identifiers. */
  font-feature-settings: 'kern' 1, 'liga' 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection { background: var(--color-selection); }

/* Links carry the accent and a hairline underline that stays put on hover —
   quieter at rest than a full-weight underline, still unmistakably a link. */
a {
  color: var(--color-accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--transition);
}

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

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

/* Inline code — a path, a filename, an identifier named inside a sentence.
   The tint is what separates it from the prose; it carries no border, which
   at this size would be most of what the eye sees. */
code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--color-surface-hover);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
}

/* A code span inside a table cell or a diagram is already in a dense column;
   the tint there stacks up into stripes, so it is dropped. */
.table code,
.diagram-box code { background: none; padding: 0; }

img { display: block; max-width: 100%; }

figure { margin: 0; }

/* `.doc` is the single centred column every page sits inside. */
.doc {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--doc-pad-top) var(--doc-pad-x) var(--doc-pad-bottom);
}

/* Interior pages (design standards) sit under a nav bar, so they need less
   headroom than the homepage. */
.doc--interior { padding-top: var(--space-6); }

/* Anchored sections stop below the point they would otherwise land, so a
   heading is never flush against the top edge of the viewport. */
[id] { scroll-margin-top: var(--space-6); }

/* Honour a reader's request for reduced motion: nothing here is meaningful
   animation, so it can all be switched off. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}


/* ============================================================================
   3. MASTHEAD
   The centred title block: eyebrow, title, subtitle, byline, dateline.
   Used at the top of the homepage; interior pages use the left-aligned
   variant at the foot of this section.
   ========================================================================= */

/* Small tracked caps above the title. Set in the body face rather than the
   monospace: mono caps at this size read as a system message, not a label. */
.kicker {
  text-align: center;
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-mute);
  margin: 0 0 var(--space-4);
}

.title {
  text-align: center;
  font-size: var(--size-title);
  font-weight: var(--weight-strong);
  line-height: 1.15;
  letter-spacing: var(--track-tight);
  margin: 0 0 var(--space-3);
}

.subtitle {
  text-align: center;
  /* Between --size-body and --size-section, and used once. A token here would
     be a name with a single caller. */
  font-size: 17px;
  font-weight: var(--weight-regular);
  color: var(--color-text-soft);
  margin: 0 0 var(--space-5);
}

.byline {
  text-align: center;
  font-size: 15px;   /* one step under the subtitle it sits below */
  color: var(--color-text-soft);
  margin: 0 0 var(--space-1);
}

/* The one line of the masthead that is a recorded value, so it is the one
   line set in the data face. */
.dateline {
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--size-data);
  color: var(--color-text-mute);
  margin: 0 0 var(--space-6);
}

/* Left-aligned masthead for interior pages, where the page heads a record
   rather than opening a publication. */
.masthead--left .kicker,
.masthead--left .title,
.masthead--left .subtitle,
.masthead--left .dateline { text-align: left; }
.masthead--left .title { font-size: var(--size-title-record); margin-bottom: var(--space-2); }
.masthead--left .dateline { margin-bottom: 0; }


/* ============================================================================
   4. ABSTRACT
   The summary paragraph under the masthead. The keyword list that used to
   follow it was removed as one more line of text that told a reader nothing
   the paragraph above had not already said.
   ========================================================================= */

.abstract {
  max-width: var(--measure-text);
  margin: 0 auto var(--space-6);
}

.abstract-label {
  text-align: center;
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-mute);
  margin: 0 0 var(--space-3);
}

.abstract p {
  font-size: var(--size-abstract);
  line-height: 1.7;
  color: var(--color-text-soft);
  margin: 0 0 var(--space-3);
}

.abstract p:last-child { margin-bottom: 0; }


/* ============================================================================
   5. TABLE OF CONTENTS
   A plain index of the sections below. There are no numerals: the list order
   is the document order, which is all a numeral was telling the reader, and
   it only listed the nine domains twice — the component reference is its own
   index once its rows are on the page.
   ========================================================================= */

.toc-label {
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-mute);
  margin: 0 0 var(--space-3);
}

/* One entry per line. A wrapping row packs the labels tighter, but it also
   lets a six-item index break across two lines at some widths and not others;
   stacked, the list is the same shape on every screen and each label gets its
   own generous tap target. */
.toc {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--size-table);
}

.toc a {
  display: block;
  padding: var(--space-2) 0;
  text-decoration: none;
  color: var(--color-text-soft);
  transition: color var(--transition);
}

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


/* ============================================================================
   6. SECTION HEADINGS
   Plain labels — "Introduction", "Installation", "Component Reference".
   Nothing is numbered: the headings and the contents list carry the same
   names, which is enough to navigate by.
   ========================================================================= */

.section-heading {
  font-size: var(--size-section);
  font-weight: var(--weight-strong);
  line-height: 1.25;
  letter-spacing: var(--track-tight);
  margin: 0 0 var(--space-4);
}

/* Whatever follows a section heading gets its gap from the heading's own
   bottom margin, so elements that carry a top margin of their own drop it
   here rather than doubling up. */
.section-heading + .caption,
.section-heading + .reference-list,
.section-heading + .list,
.section-heading + .table,
.section-heading + .table-scroll,
.section-heading + .domain-list { margin-top: 0; }

/* Each top-level section opens with a hairline. The generous top margin, not
   the rule's weight, is what separates one section from the next. */
.section {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-rule-strong);
}


/* ============================================================================
   7. BODY COPY
   ========================================================================= */

.body-text {
  font-size: var(--size-body);
  line-height: 1.7;
  color: var(--color-text-soft);
  max-width: var(--measure-text);
  margin: 0 0 var(--space-4);
}

.body-text:last-child { margin-bottom: 0; }

/* Ordered and unordered lists share everything but their markers, so they
   share a class. Use <ol class="list"> where the order is the point — the
   installation steps — and <ul class="list"> where it is not. */
.list {
  font-size: var(--size-table);
  line-height: 1.7;
  color: var(--color-text-soft);
  max-width: var(--measure-text);
  margin: var(--space-3) 0 0;
  padding-left: var(--space-4);
}

.list li { margin-bottom: var(--space-2); }
.list li:last-child { margin-bottom: 0; }

/* An uppercase tracked eyebrow above a block of content. */
.label {
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-mute);
  margin: 0 0 var(--space-3);
}

/* Caption under a figure or table. Sentence case, never numbered — a caption
   describes the thing above it, and "Table 2" describes nothing. Write one
   only when it says something the table or figure does not. */
.caption {
  font-size: var(--size-caption);
  color: var(--color-text-mute);
  line-height: 1.55;
  margin: var(--space-3) 0 0;
  max-width: var(--measure-text);
}

/* Monospace run of recorded data inside prose: a path, a count, a version. */
.data {
  font-family: var(--font-mono);
  font-size: var(--size-data);
  color: var(--color-text-mute);
  font-variant-numeric: tabular-nums;   /* digits line up between rows */
}


/* ============================================================================
   8. RULES
   Both weights are hairlines; they differ in contrast, not thickness.
   ========================================================================= */

/* Major division — under the masthead, above the colophon. */
.rule {
  border: none;
  border-top: 1px solid var(--color-rule-strong);
  margin: 0 0 var(--space-6);
}

/* Row-level division within a block. */
.rule-soft {
  border: none;
  border-top: 1px solid var(--color-rule);
  margin: 0 0 var(--space-5);
}


/* ============================================================================
   9. TABLES
   Hairline horizontal rules only — no verticals, no zebra striping, no outer
   border. A table should look like aligned text, not like a spreadsheet.
   ========================================================================= */

.table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--space-4) 0 0;
  font-size: var(--size-table);
}

/* Header row: small tracked caps, medium weight. It is distinguished from the
   body by case and colour rather than by a heavy rule above and below it. */
.table th {
  text-align: left;
  padding: 0 var(--space-4) var(--space-3) 0;
  border-bottom: 1px solid var(--color-rule-strong);
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-mute);
  white-space: nowrap;
}

.table td {
  padding: var(--space-3) var(--space-4) var(--space-3) 0;
  vertical-align: top;
  border-bottom: 1px solid var(--color-rule);
  color: var(--color-text-soft);
}

/* The last cell keeps a small trailing gutter rather than sitting flush with
   the table's edge. */
.table th:last-child,
.table td:last-child { padding-right: var(--space-3); }

/* The first column of a two-column reference table — a path, a metric name —
   is the row's label, so it takes the full text colour while the description
   beside it stays a step down. */
.table .key-cell {
  color: var(--color-text);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}

/* Right-align numeric columns. The alignment applies to the whole column … */
.table .num-cell { text-align: right; }

/* … but only the cells carry the data face. A numeric column's header is
   still a header, and setting it in mono at the data size made it read a
   size larger than the headers beside it. */
.table td.num-cell {
  font-family: var(--font-mono);
  font-size: var(--size-data);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--color-text-mute);
}

/* Let a wide table scroll inside its own box rather than forcing the whole
   page sideways. Wrap every .table in one of these. */
.table-scroll { overflow-x: auto; margin-top: var(--space-4); }
.table-scroll .table { margin-top: 0; }


/* ============================================================================
   10. COLLAPSIBLE ROWS
   Native <details>/<summary>. There is one kind: a row in a list, which the
   Component Reference is made of — one row per domain, opening in place to
   that domain's component diagrams. No JavaScript is involved; opening and
   closing is the browser's.

   The rows are closed on load on purpose. All nine open at once is thirty-nine
   diagrams and several screens of scrolling before the reader reaches the
   development notes; closed, the section is an index of the nine domains and
   the reader opens the one they came for.
   ========================================================================= */

.domain-list { margin-top: var(--space-5); }

.disclosure { margin: 0; }

/* The hairline belongs to the whole row, not to the summary's text, so the
   list reads as ruled entries rather than as underlined headings. */
.disclosure > summary {
  cursor: pointer;
  list-style: none;          /* hide the default triangle … */
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-rule);
}
.disclosure > summary::-webkit-details-marker { display: none; }  /* … in Safari */

/* An open row's rule moves to the foot of its body, below, so the row and
   what it opened are closed off once rather than twice. */
.disclosure[open] > summary { border-bottom-color: transparent; }

.disclosure > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

/* The clickable heading row: domain name on the left, show/hide hint on the
   right. Tracking is neutral rather than the body's slight negative: this is
   a name, not a line of prose. */
.disclosure-heading {
  display: flex;
  gap: var(--space-4);
  align-items: baseline;
  font-size: var(--size-subsection);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
}

/* `.disclosure-title` carries no rules here, and that is deliberate. It names
   the title text inside a summary line so a rule has something to attach to if
   a row ever needs to be marked out from its neighbours — selected, current,
   filtered. A domain has no such state: it is open or closed, and nothing
   outside it can open it. The class stays in the markup so every summary line
   is built the same way; it simply inherits. */

/* "Show" / "Hide" affordance at the end of the summary line. It states the
   action only — a count here would repeat the meta line directly under it. */
.disclosure-hint {
  margin-left: auto;
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-accent);
  white-space: nowrap;
  align-self: center;
  transition: color var(--transition);
}

.disclosure > summary:hover .disclosure-hint { color: var(--color-accent-hover); }

/* Swap the hint text depending on open state. Both labels are in the markup;
   CSS decides which one is visible, so no script is needed to keep them in
   step with the row. */
.disclosure > summary .hint-open { display: none; }
.disclosure[open] > summary .hint-open { display: inline; }
.disclosure[open] > summary .hint-closed { display: none; }

.disclosure-body {
  margin-top: var(--space-3);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--color-rule);
}

/* The line under a row's heading, in the monospace the site keeps for
   recorded values: the domain's source folder and how many components are in
   it. Both are literals from the repository, which is why they are set in the
   data face rather than written out as a sentence. */
.disclosure-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--size-data);
  color: var(--color-text-mute);
  margin: 0 0 var(--space-4);
  padding-left: var(--diagram-indent);
}


/* ============================================================================
   11. COMPONENT DIAGRAMS
   One schematic per component: input ports on the left, the component box in
   the centre, output ports on the right — or, for a component whose whole
   purpose is a side effect (baking geometry, writing a CSV), a note in the
   box instead of an output column.

   Nothing else on the site is a drawing, so this is the place the language had
   to be extended beyond ordinary document prose. The extension follows the same
   rules as everything else: hairline borders, no fill, the data face for
   anything that is a literal from a script, prose sizes for anything that is a
   sentence about one. Two deliberate consequences of that:

     · The arrow between the columns is muted, not accented. The accent means
       "you can click this", and an arrow in a diagram is not clickable.
     · The box is a hairline outline with no background. The old design gave it
       a solid black border, which on a page of six diagrams read as six boxes
       before it read as six components.

   The one exception to the palette is the port dot and its type label, which
   carry per-data-type colour — see --type-* in section 1.
   ========================================================================= */

figure.diagram {
  margin: 0 0 var(--space-5) var(--diagram-indent);
  max-width: var(--diagram-max);
}

figure.diagram:last-child { margin-bottom: 0; }

.diagram-row {
  display: flex;
  align-items: stretch;
}

/* Fixed-width port columns, so every component box in a domain starts and ends
   at the same x and the column of boxes reads as a list. */
.diagram-ports {
  flex: 0 0 var(--diagram-port-col);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Inputs read right-to-left into the box; outputs read left-to-right out of
   it. Each column's dots therefore sit against the box, and the names run
   away from it. */
.diagram-ports-in { text-align: right; }

.diagram-port {
  margin-bottom: var(--space-2);
  /* The port's data-type colour. A `.port--*` class at the foot of this
     section overrides it; the dot and the type label both read it via
     `currentColor`, so one class colours both. */
  color: var(--color-text-mute);
}

.diagram-port:last-child { margin-bottom: 0; }

.diagram-port-head {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.diagram-ports-in .diagram-port-head { justify-content: flex-end; }
.diagram-ports-out .diagram-port-head { justify-content: flex-start; }

/* The port's name as it appears on the component in Grasshopper — a literal,
   so the data face, and medium weight so it holds its own against the type
   label under it without reaching for bold. */
.diagram-port-name {
  font-family: var(--font-mono);
  font-size: var(--size-fine);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  line-height: 1.3;
}

/* The type swatch. `currentColor` means the port's `.port--*` class is the
   only thing that has to be set. */
.diagram-port-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  display: inline-block;
  flex: 0 0 auto;
}

.diagram-port-type {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  line-height: 1.35;
  margin-top: 2px;
  color: inherit;            /* the port's data-type colour */
}

/* The gutter between a port column and the box. Muted, per the note at the
   head of this section. */
.diagram-arrow {
  flex: 0 0 var(--diagram-arrow-col);
  font-size: 15px;
  color: var(--color-text-mute);
  text-align: center;
  align-self: center;
}

/* The component itself. A hairline outline and no fill — the border says
   "this is one object", and nothing more is needed. */
.diagram-box {
  flex: 1 1 0;
  min-width: 0;
  border: 1px solid var(--color-rule-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
}

.diagram-box-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* The nickname is what appears on the canvas, so it is the box's title and is
   set in the data face. */
.diagram-box-nick {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

/* The full component name beside it — the same object under its other name,
   so it sits a step down rather than competing. */
.diagram-box-full {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  color: var(--color-text-mute);
}

/* One sentence, from the component's own docstring. Prose about the
   component, so it is set in the body face. */
.diagram-box-desc {
  font-size: var(--size-fine);
  line-height: 1.55;
  color: var(--color-text-soft);
  margin-top: var(--space-2);
}

/* An aside about one component, carried inside its own box because the page
   has no footnotes. Two things go here: the result when it is a side effect
   rather than an output — baked geometry, a written file, updated canvas
   parameters, in which case the note stands in for the output column — and a
   caveat about a component that does have outputs, such as one not yet
   packaged as a User Object. It is separated by a hairline rather than by
   italics: the old design italicised it, which at 11px read as damaged type
   rather than as an aside. */
.diagram-box-note {
  font-size: var(--size-label);
  line-height: 1.5;
  color: var(--color-text-mute);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-rule);
}

/* -- Port data-type classes ------------------------------------------------
   One per --type-* token in section 1. Put the class on the `.diagram-port`
   wrapper; the dot and the type label both follow from it. A port with no
   class falls back to the muted text colour set on `.diagram-port` above. */
.port--number   { color: var(--type-number); }
.port--curve    { color: var(--type-curve); }
.port--boolean  { color: var(--type-boolean); }
.port--string   { color: var(--type-string); }
.port--geometry { color: var(--type-geometry); }
.port--point    { color: var(--type-point); }
.port--data     { color: var(--type-data); }
.port--plane    { color: var(--type-plane); }
.port--colour   { color: var(--type-colour); }

/* -- Type legend (design-standards page) -----------------------------------
   The same dots, listed once with their type names, so the encoding used
   thirty-nine times on the homepage is written down in one place. */
.type-legend {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: grid;
  /* Wide enough for the longest pair — "Geometry, Brep, Box" beside
     --type-geometry — so no row wraps. A narrower track fits more columns in
     but breaks two of the eight rows over two lines, and a legend whose rows
     are different heights stops reading as a table of equivalents. */
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: var(--space-3) var(--space-5);
}

.type-legend li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--size-data);
  color: var(--color-text-soft);
  white-space: nowrap;
}

/* The token's name, pushed to the end of its row so the tokens line up in a
   column of their own. */
.type-legend .token {
  color: var(--color-text-mute);
  margin-left: auto;
  padding-left: var(--space-4);
}


/* ============================================================================
   12. REFERENCES
   A plain list of links with a short description each. Nothing here is
   numbered and nothing in the prose points at it with a bracketed marker:
   these are the repository's other documents, gathered at the foot of the
   page, not citations a sentence depends on. Where the prose needs to send a
   reader to one of them, it links the words that name it.
   ========================================================================= */

.reference-list {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  font-size: var(--size-table);
}

/* Each entry is its own row, separated by a hairline, so a long description
   never runs into the next link. */
.reference-list li {
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-rule);
  line-height: 1.65;
}

.reference-list li:first-child { padding-top: 0; }
.reference-list li:last-child { border-bottom: none; }

/* The link is the entry's heading, so it carries the medium weight. */
.reference-list a {
  font-weight: var(--weight-medium);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--transition), color var(--transition);
}

.reference-list a:hover { border-bottom-color: var(--color-accent); }

/* A path is a literal, so a reference whose name *is* a path is set in the
   data face. Applied to the <a>, alongside the rules above. */
.reference-list a.path { font-family: var(--font-mono); font-size: 0.92em; }

/* The description sits under the link on its own line: side by side, the two
   compete, and the link stops looking clickable. */
.reference-list .desc {
  display: block;
  color: var(--color-text-mute);
  font-size: var(--size-caption);
  margin-top: var(--space-1);
}


/* ============================================================================
   13. TOP NAVIGATION
   Shown on interior pages only; the homepage uses its table of contents.
   ========================================================================= */

.nav {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-4) var(--doc-pad-x);
  border-bottom: 1px solid var(--color-rule-strong);
}

.nav-brand {
  font-weight: var(--weight-strong);
  font-size: var(--size-table);
  letter-spacing: var(--track-tight);
  color: var(--color-text);
  text-decoration: none;
  margin-right: auto;
  transition: color var(--transition);
}

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

.nav a:not(.nav-brand) {
  font-size: var(--size-caption);
  text-decoration: none;
}

.nav a:not(.nav-brand):hover { text-decoration: underline; }

/* A back-link above an interior page's masthead. */
.backlink {
  display: inline-block;
  font-size: var(--size-caption);
  text-decoration: none;
  margin-bottom: var(--space-5);
}

.backlink:hover { text-decoration: underline; }


/* ============================================================================
   14. DESIGN-STANDARDS PAGE
   Specimens and swatches. Nothing in this section appears on the homepage; it
   exists so the standard can be shown in the design it describes rather than
   only described in prose.
   ========================================================================= */

/* -- Rule specimens -------------------------------------------------------- */
.specimens { margin-top: var(--space-4); }
.specimen { margin-bottom: var(--space-5); }
.specimen:last-child { margin-bottom: 0; }
.specimen hr { width: 220px; margin: 0; }

/* -- Colour swatches ------------------------------------------------------- */
.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.swatch {
  height: 48px;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-sm);
}

/* -- Text button ----------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-accent);
  background: none;
  border: 1px solid var(--color-rule-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: border-color var(--transition), background-color var(--transition),
    color var(--transition);
}

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

.btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }


/* ============================================================================
   15. COLOPHON
   ========================================================================= */

.colophon {
  margin-top: var(--space-7);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-rule-strong);
  font-size: var(--size-caption);
  line-height: 1.6;
  color: var(--color-text-mute);
}


/* ============================================================================
   16. RESPONSIVE
   One breakpoint. Below it: tighter page padding, smaller display type, and
   each diagram's three columns stack into one.
   ========================================================================= */

@media (max-width: 640px) {
  /* Display type steps down by redefining the tokens, so every rule that
     already reads from them follows without being restated here. Only rules
     with no token behind them need a line of their own below. */
  :root {
    --size-title: 27px;
    --size-title-record: 22px;
    --size-section: 20px;
    --size-subsection: 16px;
    --doc-pad-top: 44px;
    --doc-pad-bottom: 80px;
    --doc-pad-x: 24px;
    --diagram-indent: var(--space-3);
  }

  .doc { padding: var(--doc-pad-top) var(--doc-pad-x) var(--doc-pad-bottom); }
  .doc--interior { padding-top: var(--space-5); }

  .nav { padding: var(--space-3) var(--doc-pad-x); }

  /* Headers stop refusing to wrap, so a long column label costs height
     rather than forcing the whole table to scroll. */
  .table th { white-space: normal; }

  /* A path in the first column can be broken rather than widening the table
     past the screen. */
  .table .key-cell { white-space: normal; overflow-wrap: anywhere; }

  /* Columns sit closer together. The gutter between the page and the window
     is worth more than the gutter between two columns, so on a phone the
     table gives up the second to protect the first.

     Note this deliberately does NOT touch the last column: the :last-child
     rule in section 9 is the more specific selector and still wins here. */
  .table th, .table td { padding-right: var(--space-2); }

  /* A diagram becomes one column: inputs, then the component, then outputs,
     top to bottom, with the arrows rotated to point down the stack. The port
     columns give up their fixed width and their right alignment — at this
     width there is nothing to align them against. */
  .diagram-row { flex-direction: column; align-items: stretch; }

  .diagram-ports { flex: none; text-align: left; }

  .diagram-ports-in .diagram-port-head,
  .diagram-ports-out .diagram-port-head { justify-content: flex-start; }

  .diagram-arrow { transform: rotate(90deg); padding: var(--space-1) 0; }

  .diagram-box { margin: var(--space-1) 0; }
}
