/* The instance's own stylesheet.
 *
 * Flat ink on flat paper: no radius, no shadow, no gradient. Separation is
 * by hairline and by the three paper levels. Colour is earned — only a
 * human commitment, a machine proof and a refutation are allowed any — so
 * everything else here is ink, weight and texture.
 *
 * Three faces, three jobs: serif for mathematics and for prose a person
 * signed, grotesk for the interface's own words, mono for the verbatim.
 */

/* ── The faces ─────────────────────────────────────────────────────────
 *
 * Served by the instance itself and subset to the Latin these pages set.
 * `swap` because a page of mathematics is worth reading in a fallback for
 * the tenth of a second the real face takes to arrive.
 */

@font-face {
    font-family: "Libertinus Serif";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/libertinus-serif-400.woff2") format("woff2");
}

@font-face {
    font-family: "Libertinus Serif";
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/libertinus-serif-400-italic.woff2") format("woff2");
}

@font-face {
    font-family: "Libertinus Serif";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/assets/fonts/libertinus-serif-700.woff2") format("woff2");
}

@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/archivo-400.woff2") format("woff2");
}

@font-face {
    font-family: "Archivo";
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/archivo-400-italic.woff2") format("woff2");
}

@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/assets/fonts/archivo-500.woff2") format("woff2");
}

@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/assets/fonts/archivo-600.woff2") format("woff2");
}

@font-face {
    font-family: "Archivo Narrow";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/archivo-narrow-400.woff2") format("woff2");
}

@font-face {
    font-family: "Iosevka";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/assets/fonts/iosevka-400.woff2") format("woff2");
}

:root {
    --paper: #edeee8;
    --paper-raise: #f6f7f3;
    --paper-sunk: #e2e4dc;
    --ink: #16191a;
    --ink-2: #474d4c;
    --ink-3: #636967;
    --rule: #c5c8c0;
    --rule-soft: #d7dad2;
    --ditto: #463a85;
    --verified: #1d5347;
    --refuted: #93221b;

    --serif: "Libertinus Serif", "Linux Libertine O", Georgia, serif;
    --grotesk: "Archivo", "Archivo Narrow", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --narrow: "Archivo Narrow", "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --mono: "Iosevka", "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

    --step-1: 12px;
    --step-2: 13px;
    --step-3: 15px;
    --step-4: 17px;
    --step-5: 21px;
    --step-6: 27px;
    --step-7: 34px;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;
    --space-8: 64px;
}

.proposal pre {
  white-space: pre-wrap;
  font: 0.875rem/1.55 var(--mono);
  border: 1px solid var(--rule);
  padding: 1.5rem;
  background: var(--paper-raise);
}

.findings {
  font-family: var(--mono);
  color: var(--ink-3);
  list-style: none;
  padding: 0;
}

/* The dark theme is selected, not inverted: the same green-biased neutral
 * run cold, with the earned colours re-stepped against the dark ground. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --paper: #141715;
        --paper-raise: #1c201d;
        --paper-sunk: #0f1210;
        --ink: #e4e6e0;
        --ink-2: #aeb3ac;
        --ink-3: #858b85;
        --rule: #343833;
        --rule-soft: #242824;
        --ditto: #a395ee;
        --verified: #5fae96;
        --refuted: #e0705f;
    }
}

:root[data-theme="dark"] {
    --paper: #141715;
    --paper-raise: #1c201d;
    --paper-sunk: #0f1210;
    --ink: #e4e6e0;
    --ink-2: #aeb3ac;
    --ink-3: #858b85;
    --rule: #343833;
    --rule-soft: #242824;
    --ditto: #a395ee;
    --verified: #5fae96;
    --refuted: #e0705f;
}

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

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--grotesk);
    font-size: var(--step-3);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
    font-family: var(--grotesk);
    font-weight: 600;
    letter-spacing: -0.01em;
    text-wrap: balance;
    margin: 0;
}

h1 {
    font-size: var(--step-6);
    line-height: 1.2;
}

h2 {
    font-size: var(--step-5);
    line-height: 1.25;
}

h3 {
    font-size: var(--step-4);
    line-height: 1.3;
}

p {
    margin: 0;
    max-width: 62ch;
}

a {
    color: var(--ditto);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

a:hover {
    text-decoration-thickness: 2px;
}

/* Focus is never removed and never a glow. */
:focus-visible {
    outline: 2px solid var(--ditto);
    outline-offset: 2px;
}

code,
.mono,
.identifier {
    font-family: var(--mono);
    font-size: var(--step-2);
}

.serif {
    font-family: var(--serif);
    font-size: var(--step-4);
    line-height: 1.62;
}

/* An eyebrow labels a block. It is never a heading and never a link. */
.label {
    font-family: var(--narrow);
    font-size: var(--step-1);
    line-height: 1.2;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin: 0;
}

.quiet {
    color: var(--ink-3);
}

.numeric {
    font-variant-numeric: tabular-nums;
}

/* ── The page ──────────────────────────────────────────────────────────── */

.masthead {
    border-bottom: 1px solid var(--rule);
    background: var(--paper-raise);
}

.masthead__inner,
.sheet,
.foot__inner {
    max-width: 68rem;
    margin: 0 auto;
    padding: 0 var(--space-5);
}

.masthead__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-5);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
}

.wordmark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--grotesk);
    font-size: var(--step-4);
    font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--ink);
    text-decoration: none;
}

.wordmark svg {
    display: block;
}

/* Navigation is words. The active destination takes a rule on the edge it
 * belongs to, never a filled shape. */
.nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-left: auto;
    font-size: var(--step-2);
}

.nav a {
    color: var(--ink-2);
    text-decoration: none;
    padding-bottom: var(--space-1);
    border-bottom: 2px solid transparent;
}

.nav a:hover {
    color: var(--ink);
}

.nav a[aria-current="page"] {
    color: var(--ink);
    border-bottom-color: var(--ditto);
}

.sheet {
    padding-top: var(--space-7);
    padding-bottom: var(--space-8);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.sheet--narrow {
    max-width: 34rem;
}

.foot {
    border-top: 1px solid var(--rule);
    color: var(--ink-3);
}

.foot__inner {
    padding-top: var(--space-4);
    padding-bottom: var(--space-4);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    font-family: var(--mono);
    font-size: var(--step-1);
}

/* ── Blocks ────────────────────────────────────────────────────────────── */

.block {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.block + .block {
    border-top: 1px solid var(--rule);
    padding-top: var(--space-5);
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.stack--tight {
    gap: var(--space-2);
}

.row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-3);
}

.row--spread {
    justify-content: space-between;
}

/* A list of things, hairline-separated. Not cards. */
.register {
    list-style: none;
    margin: 0;
    padding: 0;
}

.register li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-top: 1px solid var(--rule-soft);
}

.register li:last-child {
    border-bottom: 1px solid var(--rule-soft);
}

.register__name {
    font-weight: 500;
}

.register__aside {
    margin-left: auto;
    color: var(--ink-3);
    font-size: var(--step-2);
}

/* ── Forms ─────────────────────────────────────────────────────────────── */

form {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.field__hint {
    font-size: var(--step-2);
    color: var(--ink-3);
}

input[type="text"],
input[type="email"],
input[type="password"],
textarea,
select {
    font-family: inherit;
    font-size: var(--step-3);
    color: var(--ink);
    background: var(--paper-sunk);
    border: 1px solid var(--rule);
    padding: var(--space-2) var(--space-3);
    width: 100%;
}

input[name="code"],
input[name="slug"] {
    font-family: var(--mono);
}

textarea {
    min-height: 6rem;
    resize: vertical;
}

.button {
    font-family: var(--grotesk);
    font-size: var(--step-3);
    font-weight: 500;
    color: var(--ink);
    background: var(--paper-raise);
    border: 1px solid var(--ink);
    padding: var(--space-2) var(--space-4);
    cursor: pointer;
    text-decoration: none;
    display: inline-block;
    align-self: flex-start;
}

.button:hover {
    background: var(--paper-sunk);
}

.button--quiet {
    border-color: var(--rule);
    color: var(--ink-2);
}

.actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
}

.actions form {
    display: inline;
}

/* A problem with what was typed. No colour: red means a negation was
 * proved, and nothing here is a mathematical result. */
.problem {
    background: var(--paper-sunk);
    border-left: 2px solid var(--ink);
    padding: var(--space-3) var(--space-4);
    font-size: var(--step-3);
}

.done {
    background: var(--paper-sunk);
    border-left: 2px solid var(--rule);
    padding: var(--space-3) var(--space-4);
}

/* Something given out once, which has to be copied before it is gone. */
.secret {
    font-family: var(--mono);
    font-size: var(--step-2);
    background: var(--paper-sunk);
    border: 1px solid var(--rule);
    padding: var(--space-3);
    overflow-wrap: anywhere;
}

.empty {
    color: var(--ink-3);
    max-width: 62ch;
}

table {
    border-collapse: collapse;
    width: 100%;
    font-size: var(--step-2);
}

th {
    font-family: var(--narrow);
    font-size: var(--step-1);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-3);
    text-align: left;
    font-weight: 400;
    padding: 0 var(--space-4) var(--space-2) 0;
    border-bottom: 1px solid var(--rule);
}

td {
    padding: var(--space-2) var(--space-4) var(--space-2) 0;
    border-bottom: 1px solid var(--rule-soft);
    vertical-align: baseline;
}

td.numeric,
th.numeric {
    font-variant-numeric: tabular-nums;
}

.scroll {
    overflow-x: auto;
}

/* ── The front door ────────────────────────────────────────────────────── */

.doorway {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    padding-top: var(--space-8);
}

/* The instance's name is the largest type on the page because it is a fact,
 * not a slogan. Nothing in the product is larger than 34px. */
.doorway__name {
    font-size: var(--step-7);
    line-height: 1.1;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.doorway__operator {
    color: var(--ink-2);
}

@media (max-width: 40rem) {
    .masthead__inner {
        gap: var(--space-3);
    }

    .nav {
        margin-left: 0;
        width: 100%;
    }

    .doorway__name {
        font-size: var(--step-6);
    }
}

/* ── The apparatus ─────────────────────────────────────────────────────
 *
 * A measured column with functional margins: the document holds the
 * centre, the gutter on the left carries what the system knows about
 * each node, and the register on the right carries the blocks. Neither
 * margin disappears on a narrow screen — both carry information, so they
 * degrade in position, not in existence.
 */

.apparatus {
    display: grid;
    grid-template-columns: 11rem minmax(0, 1fr) 21rem;
    gap: var(--space-5);
    align-items: start;
}

.apparatus__gutter {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    font-family: var(--narrow);
    font-size: var(--step-1);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-3);
    text-align: right;
    padding-top: 2px;
}

.apparatus__gutter .identifier {
    font-family: var(--mono);
    font-size: var(--step-2);
    letter-spacing: 0;
    text-transform: none;
}

.apparatus__document {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    min-width: 0;
}

.apparatus__register {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    border-left: 1px solid var(--rule);
    padding-left: var(--space-4);
}

/* One node in the document. Weight on the left edge says who committed
 * to it: the heavier rule is a human declaration that the line rests on
 * this. */
.node {
    display: grid;
    grid-template-columns: 11rem minmax(0, 1fr);
    gap: var(--space-5);
    align-items: start;
}

.node__mark {
    font-family: var(--narrow);
    font-size: var(--step-1);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-3);
    text-align: right;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.node__mark .identifier {
    font-family: var(--mono);
    font-size: var(--step-2);
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-2);
}

.node__body {
    border-left: 1px solid var(--rule);
    padding-left: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
}

.node--central > .node__body {
    border-left-width: 1.6px;
    border-left-color: var(--ditto);
}

.node__name {
    font-family: var(--serif);
    font-size: var(--step-4);
    line-height: 1.3;
}

.node__uses {
    font-family: var(--mono);
    font-size: var(--step-2);
    color: var(--ink-3);
}

/* A black box: a declared absence. Hatched, never coloured — a gap is
 * not a failure and not an alarm. */
.box {
    display: grid;
    grid-template-columns: 11rem minmax(0, 1fr);
    gap: var(--space-5);
    align-items: start;
}

.box__band {
    min-height: 3rem;
    border: 1px solid var(--rule);
    padding: var(--space-3) var(--space-4);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--ink-3);
    font-size: var(--step-2);
    background-image: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 7px,
        var(--rule-soft) 7px,
        var(--rule-soft) 8px
    );
}

/* Filled by hand is ordinary content, so it carries no texture. */
.box--filled .box__band {
    background-image: none;
}

.box__count {
    font-variant-numeric: tabular-nums;
}

@media (max-width: 75rem) {
    .apparatus {
        grid-template-columns: 9rem minmax(0, 1fr);
    }

    .apparatus__register {
        grid-column: 1 / -1;
        border-left: 0;
        border-top: 1px solid var(--rule);
        padding-left: 0;
        padding-top: var(--space-5);
    }
}

@media (max-width: 56rem) {
    .apparatus,
    .node,
    .box {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-3);
    }

    .apparatus__gutter,
    .node__mark {
        text-align: left;
        flex-direction: row;
        flex-wrap: wrap;
        gap: var(--space-3);
    }
}

/* ── The anchored launcher ─────────────────────────────────────────────
 *
 * An agent action is offered where its effect will land, so this is a
 * popover beside the mathematics and not a screen of its own. At rest it
 * is one line of grey grotesk: something that starts work must never be
 * the loudest thing on a page of mathematics. It earns its rule on hover,
 * on focus and when it is open, and the only colour in it is that rule on
 * what is currently chosen.
 */

.launcher > summary {
    display: inline-block;
    font-family: var(--grotesk);
    font-size: var(--step-2);
    color: var(--ink-3);
    cursor: pointer;
    padding-left: var(--space-2);
    border-left: 2px solid transparent;
    list-style: none;
}

.launcher > summary::-webkit-details-marker {
    display: none;
}

.launcher > summary:hover,
.launcher > summary:focus-visible,
.launcher[open] > summary {
    color: var(--ink);
    border-left-color: var(--ditto);
}

.launcher__panel {
    position: relative;
    margin-top: var(--space-3);
    margin-left: var(--space-4);
    max-width: 32rem;
    border: 1px solid var(--rule);
    background: var(--paper-raise);
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* The leader back to the line that opened it. */
.launcher__panel::before {
    content: "";
    position: absolute;
    top: var(--space-4);
    left: calc(-1 * var(--space-4));
    width: var(--space-4);
    border-top: 1px solid var(--rule);
}

.launcher__machine {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.launcher__name {
    font-family: var(--narrow);
    font-size: var(--step-1);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-2);
}

.launcher__agent {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-family: var(--mono);
    font-size: var(--step-2);
    padding-left: var(--space-2);
    border-left: 2px solid transparent;
}

.launcher__agent:has(input:checked) {
    border-left-color: var(--ditto);
}

.launcher__agent input {
    accent-color: var(--ditto);
}

/* Shown, named and unavailable. An agent a machine does not have implies
 * nothing false, and its absence teaches the owner about their machine. */
.launcher__agent--out {
    color: var(--ink-3);
}

.box__ask {
    grid-column: 2;
}

/* A count is on a person's decision and never on the state of the
 * mathematics, so it is ink among grey rather than a colour of its own. */
.count {
    font-family: var(--mono);
    font-size: var(--step-2);
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

@media (max-width: 56rem) {
    .box__ask {
        grid-column: auto;
    }
}

/* ── The descent ───────────────────────────────────────────────────────
 *
 * A stemma codicum: the line's definitions, what it rests on, and the
 * boxes between them. The drawing is done on the canvas; the list below
 * it is what a reader with nothing running gets instead, so it is only
 * taken away once the drawing is actually there.
 */

.descent {
    margin: 0 0 var(--space-6);
    padding: var(--space-4) 0 var(--space-5);
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
    overflow-x: auto;
}

.descent figcaption {
    margin-bottom: var(--space-4);
}

.descent__canvas {
    display: block;
    max-width: none;
}

.descent__list {
    margin: var(--space-4) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--step-2);
    color: var(--ink-3);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
}

.descent--drawn .descent__list {
    display: none;
}

/* A set of choices where exactly one holds: the question is the legend,
 * and each answer is a whole line, so the words are the target and not
 * the eight pixels of the control. */

fieldset {
    border: 1px solid var(--rule);
    padding: var(--space-3) var(--space-4) var(--space-4);
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

legend {
    padding: 0 var(--space-2);
}

.choice {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    font-size: var(--step-3);
}

.choice input {
    accent-color: var(--ditto);
}

/* ── What changed ──────────────────────────────────────────────────────
 *
 * A proposal arrives whole and is read by what moved. Added and taken
 * out are told apart by the mark in the margin and by a hairline on the
 * edge, never by colour: green and red mean a machine proof and a
 * refutation, and nothing else in the product may borrow them.
 *
 * A statement the line rests on carries corner marks, because the guard
 * forbids touching it and the screen should say so where it is.
 */

.diff {
    font: var(--step-2) / 1.6 var(--mono);
    background: var(--paper-sunk);
    border: 1px solid var(--rule);
    padding: var(--space-3) 0;
    overflow-x: auto;
    white-space: pre;
}

.diff__row {
    display: grid;
    grid-template-columns: 3.5ch 3.5ch 2ch 1fr;
    gap: var(--space-2);
    padding: 0 var(--space-3);
    border-left: 2px solid transparent;
}

.diff__row--added {
    border-left-color: var(--ink);
    background: var(--paper-raise);
}

.diff__row--removed {
    border-left-color: var(--rule);
    color: var(--ink-3);
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

/* A registration frame around what the guard forbids touching: the
 * corners of the whole run, and the sides between them. */

.diff__row--held {
    box-shadow:
        inset 1px 0 0 -0.5px var(--ink-3),
        inset -1px 0 0 -0.5px var(--ink-3);
}

.diff__row--held-first {
    background-image:
        linear-gradient(var(--ink-3), var(--ink-3)),
        linear-gradient(var(--ink-3), var(--ink-3));
    background-size: 7px 1px, 7px 1px;
    background-position: 0 0, 100% 0;
    background-repeat: no-repeat;
}

.diff__row--held-last {
    background-image:
        linear-gradient(var(--ink-3), var(--ink-3)),
        linear-gradient(var(--ink-3), var(--ink-3));
    background-size: 7px 1px, 7px 1px;
    background-position: 0 100%, 100% 100%;
    background-repeat: no-repeat;
}

.diff__at {
    color: var(--ink-3);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.diff__mark {
    color: var(--ink-3);
}

.diff__text {
    white-space: pre-wrap;
    word-break: break-word;
}

