/* Research Workbench — site styles.

   Palette concept: oxidation. Verdigris and iron oxide are what copper and iron
   become as a record of elapsed time, which is the subject of the project. Paper
   is cool engineering stock rather than warm cream.

   Colour is systematic, not decorative. Five hues, each with ONE fixed meaning
   across the whole site — the way a geological map or a pH chart is colourful
   without being frivolous. Never introduce a hue for variety; if a new colour is
   needed, it needs a new meaning first.

     verdigris  local, available, works offline
     indigo     cloud, provenance, reconstruction
     ochre      degraded, caution, an approval gate
     iron       unavailable as a fault, risk, injected failure
     plum       human judgement, trust

   Slate carries "not available" rather than iron, because a capability absent by
   design is a fact, not an error, and should not read as alarm. */

:root {
    --paper: #f2f4f1;
    --paper-deep: #e6eae5;
    --panel: #1d2622;
    --panel-2: #232e29;
    --ink: #1b2421;
    --graphite: #49524e;
    --rule: #c4ccc5;
    --rule-soft: #d9ded8;
    /* The heavy rule that closes a table head and opens the footer: ink in the light theme,
       held back in the dark one, where a full-strength light bar is the loudest thing on the page. */
    --rule-heavy: var(--ink);

    /* Text-weight hues: contrast-checked against --paper. */
    --verdigris: #26594b;
    --verdigris-deep: #1b4438;
    --indigo: #223e73;
    --ochre: #8a5a10;
    --iron: #8a3b2a;
    --plum: #653563;
    --slate: #6c756f;

    /* Mark-weight hues: rules, bars, fills. Brighter, never used for small text. */
    --verdigris-mark: #2f6f5e;
    --indigo-mark: #2b4c8c;
    --ochre-mark: #b07a18;
    --iron-mark: #a8482f;
    --plum-mark: #83457f;

    /* On the dark panel. */
    --verdigris-lit: #7fc4a9;
    --indigo-lit: #93b4e8;
    --ochre-lit: #e5b65c;
    --iron-lit: #e39a7f;
    --plum-lit: #c79bc7;

    /* Text on a filled hue (a button, an avatar, a step number); a field to type into; the
       wash behind a caution. */
    --on-accent: #f2f4f1;
    --field: #fff;
    --caution-wash: #f8e9c9;

    --display: "Newsreader", "Iowan Old Style", Georgia, serif;
    --text: "Instrument Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
    --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

    --measure: 34rem;
    --frame: 70rem;

    color-scheme: light;
}

/* Dark: the same five hues, each keeping its meaning, lifted until they read against a dark
   paper. Every text-weight hue is at least 6:1 on --paper and 5:1 on --paper-deep. The panel
   goes darker than the page rather than lighter, so the one dark band still reads as the
   deepest thing on it, and its hard-coded light text and the -lit hues need nothing new.

   The same tokens appear twice: once for a visitor who chose dark, once for one who has not
   chosen and whose system is dark. CSS cannot share a block between a selector and a media
   query, so the two are kept identical by a test (SiteThemeTests) rather than by care.

   Bootstrap's own variables are pointed at the palette too, so the Wiki and Blog packages,
   which are built on them, change with the site rather than into Bootstrap's dark grey. Its
   background utilities read the -rgb forms, which have to be written out as numbers: they are
   --paper and --paper-deep again. */
:root[data-theme="dark"] {
    --paper: #121916;
    --paper-deep: #1a231f;
    --panel: #0b100e;
    --panel-2: #101713;
    --ink: #dce4df;
    --graphite: #a2aea8;
    --rule: #34413b;
    --rule-soft: #25302b;
    --rule-heavy: #56655e;
    --verdigris: #7fc4a9;
    --verdigris-deep: #a6dcc6;
    --indigo: #9ab8ea;
    --ochre: #e2b45e;
    --iron: #e89e84;
    --plum: #cfa2cf;
    --slate: #8f9993;
    --verdigris-mark: #4e9e86;
    --indigo-mark: #6286c9;
    --ochre-mark: #c8922f;
    --iron-mark: #cc6a4d;
    --plum-mark: #a86ba3;
    --on-accent: #0f1613;
    --field: #0e1412;
    --caution-wash: #3a2d12;
    --bs-body-bg: var(--paper);
    --bs-body-color: var(--ink);
    --bs-secondary-color: var(--graphite);
    --bs-secondary-bg: var(--paper-deep);
    --bs-tertiary-bg: var(--paper-deep);
    --bs-body-bg-rgb: 18, 25, 22;
    --bs-secondary-bg-rgb: 26, 35, 31;
    --bs-tertiary-bg-rgb: 26, 35, 31;
    --bs-border-color: var(--rule);
    --fli-card-bg: var(--paper-deep);
    color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
        --paper: #121916;
        --paper-deep: #1a231f;
        --panel: #0b100e;
        --panel-2: #101713;
        --ink: #dce4df;
        --graphite: #a2aea8;
        --rule: #34413b;
        --rule-soft: #25302b;
        --rule-heavy: #56655e;
        --verdigris: #7fc4a9;
        --verdigris-deep: #a6dcc6;
        --indigo: #9ab8ea;
        --ochre: #e2b45e;
        --iron: #e89e84;
        --plum: #cfa2cf;
        --slate: #8f9993;
        --verdigris-mark: #4e9e86;
        --indigo-mark: #6286c9;
        --ochre-mark: #c8922f;
        --iron-mark: #cc6a4d;
        --plum-mark: #a86ba3;
        --on-accent: #0f1613;
        --field: #0e1412;
        --caution-wash: #3a2d12;
        --bs-body-bg: var(--paper);
        --bs-body-color: var(--ink);
        --bs-secondary-color: var(--graphite);
        --bs-secondary-bg: var(--paper-deep);
        --bs-tertiary-bg: var(--paper-deep);
        --bs-body-bg-rgb: 18, 25, 22;
        --bs-secondary-bg-rgb: 26, 35, 31;
        --bs-tertiary-bg-rgb: 26, 35, 31;
        --bs-border-color: var(--rule);
        --fli-card-bg: var(--paper-deep);
        color-scheme: dark;
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--text);
    font-size: 1.0625rem;
    line-height: 1.6;
    font-feature-settings: "kern" 1;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
    font-family: var(--display);
    font-weight: 500;
    letter-spacing: -0.012em;
    margin: 0;
    text-wrap: balance;
}

p {
    margin: 0;
}

a {
    color: var(--verdigris);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

a:hover {
    color: var(--iron);
}

:focus-visible {
    outline: 2px solid var(--verdigris-mark);
    outline-offset: 3px;
}

.skip {
    position: absolute;
    left: -9999px;
}

.skip:focus {
    left: 1rem;
    top: 1rem;
    z-index: 10;
    background: var(--paper);
    padding: 0.5rem 0.85rem;
    border: 1px solid var(--ink);
}

/* ---------- frame ---------- */

.frame {
    max-width: var(--frame);
    margin-inline: auto;
    padding-inline: 1.5rem;
}

.band {
    padding-block: 4.5rem;
    border-top: 1px solid var(--rule-soft);
}

.band-open {
    padding-block: 3rem 4.5rem;
    border-top: 0;
}

/* One dark band gives the page rhythm and lets the hue system show at full
   strength. Deliberately only one. */
.band-dark {
    background: var(--panel);
    color: #dfe6e1;
    border-top: 0;
}

.band-dark h2 {
    color: #f0f4f1;
}

.band-dark .head-note {
    color: #9fb0a7;
}

.prose {
    max-width: var(--measure);
}

.prose p + p {
    margin-top: 1rem;
}

.stack-s {
    margin-top: 1rem;
}

.stack-l {
    margin-top: 3rem;
}

/* ---------- masthead ---------- */

.masthead {
    border-bottom: 1px solid var(--rule);
    background: linear-gradient(
        to right,
        var(--verdigris-mark) 0 20%,
        var(--indigo-mark) 20% 40%,
        var(--ochre-mark) 40% 60%,
        var(--iron-mark) 60% 80%,
        var(--plum-mark) 80% 100%
    ) top / 100% 3px no-repeat;
}

/* Centred, not baseline-aligned. The wordmark begins with a picture, and a picture has no
   baseline: the browser substitutes its bottom edge, which lifted the whole wordmark until
   the logo's foot sat on the navigation's text line. */
.masthead-inner {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 2rem;
    align-items: center;
    justify-content: space-between;
    padding-block: 1.35rem 1.1rem;
}

.wordmark {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-family: var(--display);
    font-size: 1.1875rem;
    font-weight: 500;
    color: var(--ink);
    text-decoration: none;
    letter-spacing: -0.01em;
}

.wordmark-mark {
    display: block;
    flex: none;
}

.wordmark:hover {
    color: var(--verdigris);
}

/* Items are centred on one line. The account link is taller than the rest, because of
   its picture; stretched to the top instead, its label sat below every other label. */
.masthead-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.5rem;
    font-size: 0.9375rem;
}

.masthead-nav a {
    color: var(--graphite);
    text-decoration: none;
}

.masthead-nav a:hover,
.masthead-nav a[aria-current="page"] {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--verdigris-mark);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

.masthead-nav .pending {
    color: #8b938e;
    cursor: default;
}

/* ---------- narrow-screen menu ---------- */

/* Below this width the signed-in navigation no longer fits on one line beside the
   wordmark, and wrapped into a second and third row it pushed every page down. It moves
   behind a Menu button instead. */
.nav-drawer {
    display: none;
}

@media (max-width: 64rem) {
    .masthead {
        position: relative;
    }

    .masthead-inner {
        flex-wrap: nowrap;
        gap: 1rem;
    }

    .masthead-inner > .masthead-nav {
        display: none;
    }

    .nav-drawer {
        display: block;
        flex: none;
    }

    .nav-drawer > summary {
        display: inline-flex;
        align-items: center;
        gap: 0.55rem;
        padding: 0.45rem 0.75rem;
        list-style: none;
        cursor: pointer;
        user-select: none;
        font-size: 0.9375rem;
        color: var(--ink);
        border: 1px solid var(--rule);
    }

    .nav-drawer > summary::-webkit-details-marker {
        display: none;
    }

    .nav-drawer > summary:focus-visible {
        outline: 2px solid var(--verdigris-mark);
        outline-offset: 2px;
    }

    .nav-drawer[open] > summary {
        background: var(--paper-deep);
    }

    /* Three bars that fold into a cross while the menu is open. */
    .nav-drawer-icon,
    .nav-drawer-icon::before,
    .nav-drawer-icon::after {
        display: block;
        width: 1.1rem;
        height: 2px;
        background: currentColor;
        transition: transform 0.15s ease, background-color 0.15s ease;
    }

    .nav-drawer-icon {
        position: relative;
    }

    .nav-drawer-icon::before,
    .nav-drawer-icon::after {
        content: "";
        position: absolute;
        left: 0;
    }

    .nav-drawer-icon::before {
        top: -6px;
    }

    .nav-drawer-icon::after {
        top: 6px;
    }

    .nav-drawer[open] .nav-drawer-icon {
        background: transparent;
    }

    .nav-drawer[open] .nav-drawer-icon::before {
        transform: translateY(6px) rotate(45deg);
    }

    .nav-drawer[open] .nav-drawer-icon::after {
        transform: translateY(-6px) rotate(-45deg);
    }

    /* The panel spans the whole masthead beneath it and sits over the page, rather than
       squeezing into the space beside the button. */
    .nav-drawer-panel {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 30;
        display: flex;
        flex-direction: column;
        padding: 0.25rem 1.5rem 1rem;
        background: var(--paper);
        border-bottom: 1px solid var(--rule);
        box-shadow: 0 8px 16px rgba(27, 36, 33, 0.08);
        font-size: 1rem;
    }

    /* Full-width rows with room for a thumb. */
    .nav-drawer-panel > a,
    .nav-drawer-panel > .menu,
    .nav-drawer-panel > .nav-form {
        display: block;
        padding-block: 0.75rem;
        border-bottom: 1px solid var(--rule-soft);
    }

    .nav-drawer-panel > :last-child {
        border-bottom: 0;
    }

    .nav-drawer-panel a {
        color: var(--graphite);
        text-decoration: none;
    }

    .nav-drawer-panel a:hover,
    .nav-drawer-panel a[aria-current="page"] {
        color: var(--ink);
        text-decoration: underline;
        text-decoration-color: var(--verdigris-mark);
        text-decoration-thickness: 2px;
        text-underline-offset: 0.35em;
    }

    .nav-drawer-panel > a.account-link {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .nav-drawer-panel .menu {
        display: block;
    }

    .nav-drawer-panel .menu > summary,
    .nav-drawer-panel .link-button {
        font-size: 1rem;
    }

    /* The admin menu opens in place inside the drawer, rather than as a floating panel. */
    .nav-drawer-panel .menu-panel {
        position: static;
        min-width: 0;
        margin-top: 0.5rem;
        padding: 0 0 0 0.25rem;
        border: 0;
        box-shadow: none;
    }
}

/* On the narrowest phones the word goes and the bars stay, so the wordmark keeps its line.
   The word stays in the accessibility tree as the button's name. */
@media (max-width: 24rem) {
    .nav-drawer-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

/* ---------- section marker ---------- */

/* A short coloured bar keys each section to its hue. Not a label — the colour is
   the information, and the type stays undecorated. */
.marker {
    display: block;
    width: 2.75rem;
    height: 3px;
    margin-bottom: 1.15rem;
    background: var(--slate);
}

.marker-local { background: var(--verdigris-mark); }
.marker-cloud { background: var(--indigo-mark); }
.marker-caution { background: var(--ochre-mark); }
.marker-risk { background: var(--iron-mark); }
.marker-trust { background: var(--plum-mark); }

/* ---------- hero ---------- */

.hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3.5rem;
    align-items: start;
}

.hero h1 {
    font-size: clamp(2.25rem, 5.2vw, 3.4rem);
    line-height: 1.08;
    max-width: 22ch;
}

.hero-lede {
    margin-top: 1.5rem;
    max-width: 40ch;
    font-size: 1.125rem;
    color: var(--graphite);
}

/* The free desktop workbench, under the opening paragraph: a mark in the colour of "on your computer". */
.hero-free {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin-top: 1.25rem;
    max-width: 44ch;
    font-size: 1rem;
}

.hero-free b {
    font-weight: 600;
}

.free-mark {
    flex: none;
    padding: 0.15rem 0.7rem;
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--paper);
    background: var(--verdigris);
    border-radius: 999px;
}

.standing {
    margin-top: 2rem;
    padding: 1rem 0 0 1.15rem;
    border-top: 1px solid var(--rule);
    border-left: 3px solid var(--ochre-mark);
    max-width: 42ch;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.standing b {
    color: var(--ochre);
    font-weight: 600;
}

/* ---------- trace specimen ---------- */

.specimen {
    background: var(--panel);
    color: #dfe6e1;
    padding: 1.5rem 1.5rem 1.6rem;
    font-family: var(--mono);
    font-size: 0.8125rem;
    line-height: 1.75;
    overflow-x: auto;
    border-top: 3px solid var(--indigo-mark);
}

.specimen-caption {
    margin-top: 0.85rem;
    font-family: var(--text);
    font-size: 0.875rem;
    color: var(--graphite);
    max-width: 44ch;
}

.spec-row {
    display: grid;
    grid-template-columns: 11.5rem minmax(0, 1fr);
    gap: 1rem;
    white-space: nowrap;
}

.spec-key {
    color: #7d938a;
}

.spec-val {
    color: #e8efe9;
}

/* Values carry the same hue meanings as the rest of the site. */
.v-local { color: var(--verdigris-lit); }
.v-prov { color: var(--indigo-lit); }
.v-caution { color: var(--ochre-lit); }
.v-risk { color: var(--iron-lit); }
.v-trust { color: var(--plum-lit); }

/* ---------- two products ---------- */

.pair {
    display: grid;
    grid-template-columns: 1.35fr 1fr;
    gap: 0;
    margin-top: 2.5rem;
}

.pair-primary {
    padding: 0 3rem 0 1.25rem;
    border-left: 3px solid var(--verdigris-mark);
}

.pair-secondary {
    padding-left: 1.25rem;
    border-left: 3px solid var(--indigo-mark);
}

.pair h3 {
    font-size: 1.4375rem;
    line-height: 1.2;
}

.pair-primary h3 { color: var(--verdigris); }
.pair-secondary h3 { color: var(--indigo); }

.pair p {
    margin-top: 0.85rem;
    color: var(--graphite);
    font-size: 0.9375rem;
}

.pair-primary p {
    font-size: 1rem;
}

.pair dl {
    margin: 1.5rem 0 0;
    display: grid;
    gap: 0.5rem 1rem;
    grid-template-columns: max-content minmax(0, 1fr);
    font-size: 0.875rem;
}

.pair dt {
    color: var(--slate);
}

.pair-primary dt { color: var(--verdigris); }
.pair-secondary dt { color: var(--indigo); }

.pair dd {
    margin: 0;
}

.bridge-note {
    margin-top: 2.5rem;
    padding: 1.15rem 1.35rem;
    background: var(--paper-deep);
    border-left: 3px solid var(--verdigris-mark);
    max-width: 56ch;
    font-size: 0.9375rem;
}

/* ---------- section heads ---------- */

.head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 2rem;
    align-items: baseline;
    justify-content: space-between;
}

.head h2 {
    font-size: clamp(1.625rem, 3vw, 2.125rem);
    line-height: 1.15;
}

.head-note {
    font-size: 0.875rem;
    color: var(--graphite);
    max-width: 30ch;
}

/* ---------- capability table ---------- */

.matrix-intro {
    margin-top: 1.25rem;
    max-width: var(--measure);
    color: var(--graphite);
}

.matrix-scroll {
    margin-top: 2rem;
    overflow-x: auto;
}

.matrix {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    min-width: 46rem;
}

.matrix caption {
    text-align: left;
    font-size: 0.875rem;
    color: var(--graphite);
    padding-bottom: 0.85rem;
}

.matrix th {
    font-weight: 600;
    text-align: left;
    vertical-align: bottom;
    padding: 0 0.85rem 0.6rem 0;
}

/* Each tier column is keyed by hue in its header rule, so a reader can tell at a
   glance which tier a cell belongs to without tracking back up the table. */
.matrix thead th {
    border-bottom: 3px solid var(--rule-heavy);
}

.matrix thead .t-offline { border-bottom-color: var(--verdigris-mark); color: var(--verdigris); }
.matrix thead .t-keys { border-bottom-color: var(--ochre-mark); color: var(--ochre); }
.matrix thead .t-cloud { border-bottom-color: var(--indigo-mark); color: var(--indigo); }

.matrix th span {
    display: block;
    font-weight: 400;
    color: var(--graphite);
    font-size: 0.8125rem;
}

.matrix td {
    padding: 0.55rem 0.85rem 0.55rem 0;
    border-bottom: 1px solid var(--rule-soft);
    vertical-align: top;
}

.matrix tbody th {
    padding: 0.55rem 0.85rem 0.55rem 0;
    border-bottom: 1px solid var(--rule-soft);
    font-weight: 400;
    vertical-align: top;
}

.matrix tbody tr:hover td,
.matrix tbody tr:hover th {
    background: var(--paper-deep);
}

.matrix .cap {
    width: 30%;
}

/* The rows that carry the argument. */
.matrix .cloud-only th.cap {
    font-weight: 600;
    color: var(--indigo);
    box-shadow: inset 3px 0 0 var(--indigo-mark);
    padding-left: 0.75rem;
}

.state {
    display: block;
}

.state-full { color: var(--verdigris); font-weight: 500; }
.state-degraded { color: var(--ochre); font-weight: 500; }
.state-none { color: var(--slate); }

.state small {
    display: block;
    color: var(--graphite);
    font-weight: 400;
    font-size: 0.8125rem;
    line-height: 1.45;
    max-width: 22ch;
}

/* Each cell's own tier name, for the narrow layout below. */
.tier-label {
    display: none;
}

/* On a narrow screen the table becomes one card per capability. Four columns cannot fit a
   phone, and a table scrolled sideways hides the very comparison it exists to make. The
   header row is hidden visually but kept for screen readers, and each cell shows its own
   tier name instead. */
@media (max-width: 50rem) {
    .matrix-scroll {
        overflow-x: visible;
    }

    .matrix,
    .matrix tbody {
        display: block;
        min-width: 0;
    }

    .matrix caption {
        display: block;
    }

    .matrix thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .matrix tbody tr {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 0.45rem 1rem;
        padding-block: 0.9rem;
        border-bottom: 1px solid var(--rule-soft);
    }

    .matrix tbody th.cap {
        grid-column: 1 / -1;
        width: auto;
        padding: 0;
        border: 0;
        font-weight: 600;
    }

    .matrix .cloud-only th.cap {
        padding-left: 0.75rem;
    }

    .matrix td {
        display: block;
        padding: 0;
        border: 0;
    }

    .matrix tbody tr:hover td,
    .matrix tbody tr:hover th {
        background: none;
    }

    .tier-label {
        display: block;
        margin-bottom: 0.1rem;
        font-size: 0.75rem;
        font-weight: 600;
    }

    .tier-label.t-offline { color: var(--verdigris); }
    .tier-label.t-keys { color: var(--ochre); }
    .tier-label.t-cloud { color: var(--indigo); }

    .state small {
        max-width: none;
    }
}

/* On a phone even three narrow columns squeeze the notes to a word a line, so each tier
   takes its own line, name beside state. */
@media (max-width: 30rem) {
    .matrix tbody tr {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.5rem;
    }

    .matrix td {
        display: grid;
        grid-template-columns: 8.5rem minmax(0, 1fr);
        gap: 0 0.75rem;
    }

    .tier-label {
        margin-bottom: 0;
        padding-top: 0.1rem;
    }
}

.tally {
    margin-top: 2rem;
    max-width: 54ch;
    font-size: 0.9375rem;
    padding: 0.15rem 0 0.15rem 1.15rem;
    border-left: 3px solid var(--verdigris-mark);
}

.tally b {
    color: var(--verdigris);
}

/* ---------- research questions ---------- */

.questions {
    margin: 2.5rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 1.75rem;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.questions li {
    padding-left: 1.15rem;
    border-left: 3px solid var(--slate);
}

.questions h3 {
    font-size: 1.0625rem;
    font-family: var(--text);
    font-weight: 600;
    letter-spacing: 0;
    color: #f0f4f1;
}

.questions p {
    margin-top: 0.6rem;
    font-size: 0.9375rem;
    color: #a8b8ae;
}

.q-prov { border-left-color: var(--indigo-mark); }
.q-prov h3 { color: var(--indigo-lit); }

.q-risk { border-left-color: var(--iron-mark); }
.q-risk h3 { color: var(--iron-lit); }

.q-caution { border-left-color: var(--ochre-mark); }
.q-caution h3 { color: var(--ochre-lit); }

.q-trust { border-left-color: var(--plum-mark); }
.q-trust h3 { color: var(--plum-lit); }

/* ---------- download ---------- */

.download-build {
    margin-top: 2rem;
    font-size: 1rem;
}

.download-build code,
.download-checksum code {
    font-family: var(--mono);
    font-size: 0.8125rem;
}

.download-warning {
    margin-top: 1rem;
    padding: 0.85rem 1rem 0.85rem 1.15rem;
    max-width: 70ch;
    font-size: 0.9375rem;
    color: var(--graphite);
    background: var(--paper-deep);
    border-left: 3px solid var(--ochre-mark);
}

.download-platforms {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
    gap: 2rem 2.5rem;
    margin-top: 2.5rem;
}

.download-platform {
    padding-left: 1.15rem;
    border-left: 3px solid var(--verdigris-mark);
}

.download-platform h2 {
    font-size: 1.4375rem;
}

.download-platform h3 {
    margin-top: 1.5rem;
    font-size: 1rem;
}

.download-needs {
    margin-top: 0.5rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.download-files {
    margin: 1.25rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 1rem;
}

.download-files li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.9rem;
}

.download-link.download-secondary {
    color: var(--verdigris);
    background: transparent;
    border-color: var(--rule);
}

.download-link.download-secondary:hover {
    color: var(--verdigris-deep);
    background: var(--paper-deep);
    border-color: var(--verdigris);
}

.download-meta {
    font-size: 0.875rem;
    color: var(--graphite);
}

.download-checksum {
    flex-basis: 100%;
    font-size: 0.8125rem;
    color: var(--graphite);
}

.download-checksum summary {
    cursor: pointer;
}

.download-checksum code {
    display: block;
    margin-top: 0.3rem;
    overflow-wrap: anywhere;
}

.download-steps {
    margin: 0.5rem 0 0;
    padding-left: 1.2rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.download-steps li + li {
    margin-top: 0.4rem;
}

.download-footnote {
    margin-top: 2.5rem;
    max-width: 70ch;
    font-size: 0.9375rem;
    color: var(--graphite);
}

/* Earlier versions: each folded into one line until opened, so the newest stays what the page is about. */
.download-earlier {
    margin-top: 3rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--rule);
    max-width: 70ch;
}

.download-earlier-note {
    font-size: 0.9375rem;
    color: var(--graphite);
}

.download-release {
    margin-top: 0.75rem;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--rule);
    border-radius: 6px;
}

.download-release > summary {
    cursor: pointer;
}

.download-release[open] > summary {
    margin-bottom: 0.25rem;
}

.download-summary {
    margin-top: 0.75rem;
    max-width: 70ch;
}

/* Under the version line, visible while the version is folded away, as a release's description is. */
.release-summary {
    display: block;
    margin: 0.3rem 0 0 1.1rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.download-changes {
    margin-top: 1.25rem;
    max-width: 70ch;
}

.download-changes h2 {
    font-size: 1.125rem;
}

.download-changes h3 {
    font-size: 1rem;
    margin-top: 0.75rem;
}

.download-changes ul {
    margin: 0.4rem 0 0;
    padding-left: 1.25rem;
}

.download-changes li + li {
    margin-top: 0.25rem;
}

/* The rest of What's new, behind a link-like line that says how many more there are. */
.download-more > summary {
    display: inline-block;
    margin-top: 0.5rem;
    color: var(--verdigris);
    text-decoration: underline;
    text-underline-offset: 0.15em;
    cursor: pointer;
    list-style: none;
}

.download-more > summary::-webkit-details-marker {
    display: none;
}

.download-more .more-open,
.download-more[open] .more-closed {
    display: none;
}

.download-more[open] .more-open {
    display: inline;
}

.download-more ul {
    margin-top: 0.25rem;
}

.download-release-files {
    gap: 0.6rem;
    margin-top: 0.75rem;
}

.download-release .download-footnote {
    margin-top: 0.75rem;
}

.download-extension {
    margin-top: 3rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--rule);
    max-width: 70ch;
}

.download-extension .download-footnote {
    margin-top: 1rem;
}

.download-next {
    margin-top: 2.5rem;
    max-width: 70ch;
    font-size: 0.9375rem;
}

/* ---------- get started ---------- */

/* Four steps, numbered because they are done in that order: an account first, since everything
   after it opens with one. Each ends in the one thing to press. */
.start-steps {
    counter-reset: start;
    margin: 2.25rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 1.25rem;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.start-step {
    counter-increment: start;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1.1rem 1.2rem 1.25rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-top: 3px solid var(--verdigris-mark);
}

.start-step:nth-child(3) { border-top-color: var(--ochre-mark); }
.start-step:nth-child(4) { border-top-color: var(--indigo-mark); }

.start-step h3 {
    font-size: 1.1875rem;
    line-height: 1.25;
}

.start-step h3::before {
    content: counter(start) ".";
    margin-right: 0.45rem;
    color: var(--slate);
    font-variant-numeric: tabular-nums;
}

.start-step p {
    margin: 0;
    flex: 1;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.start-step .button {
    align-self: flex-start;
}

.start-forum {
    margin-top: 1.75rem;
    max-width: 70ch;
    font-size: 0.9375rem;
    color: var(--graphite);
}

/* ---------- what already works ---------- */

/* The groups as cards, three to a row where there is room, each topped with its legend colour. */
.working-groups {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
    gap: 1.25rem;
    margin-top: 2.25rem;
}

.working-group {
    padding: 1.1rem 1.2rem 1.2rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-top: 3px solid var(--verdigris-mark);
}

.working-group.tone-cloud { border-top-color: var(--indigo-mark); }

/* The cloud is the newest part and the one a visitor asks about: it takes a row of its own, its list
   in two columns where there is room. */
.working-group.tone-cloud {
    grid-column: 1 / -1;
}

.working-group.tone-cloud .working-list {
    columns: 2 20rem;
    column-gap: 2.5rem;
}
.working-group.tone-caution { border-top-color: var(--ochre-mark); }
.working-group.tone-risk { border-top-color: var(--iron-mark); }
.working-group.tone-trust { border-top-color: var(--plum-mark); }

.working-group h3 {
    font-size: 1.1875rem;
    line-height: 1.25;
}

.working-group-note {
    margin: 0.35rem 0 0;
    font-size: 0.875rem;
    color: var(--slate);
}

/* Inside a card the list needs no rule of its own, and no columns unless the card asks: the card is both. */
.working-group .working-list {
    margin-top: 0.85rem;
    padding-left: 0;
    border-left: 0;
    columns: auto;
}

.working-group .working-list li {
    font-size: 0.90625rem;
}

.working-group.tone-cloud .working-list li::before { background: var(--indigo-mark); }
.working-group.tone-caution .working-list li::before { background: var(--ochre-mark); }
.working-group.tone-risk .working-list li::before { background: var(--iron-mark); }
.working-group.tone-trust .working-list li::before { background: var(--plum-mark); }

.working-list {
    margin: 2.25rem 0 0;
    padding: 0 0 0 1.15rem;
    border-left: 3px solid var(--verdigris-mark);
    list-style: none;
    columns: 2 22rem;
    column-gap: 2.5rem;
}

.working-list li {
    break-inside: avoid;
    padding: 0.3rem 0 0.3rem 1.1rem;
    position: relative;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.working-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.85rem;
    width: 0.45rem;
    height: 0.45rem;
    background: var(--verdigris-mark);
}

/* Columns in proportion to each picture's width over its height, so the two stand equally tall. */
.screenshots {
    display: grid;
    grid-template-columns: minmax(0, 1.2575fr) minmax(0, 0.8177fr);
    gap: 1.5rem;
    align-items: start;
    margin-top: 2.5rem;
}

.screenshot {
    margin: 0;
}

.screenshot a {
    display: block;
}

.screenshot img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--rule);
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.06);
}

.screenshot figcaption {
    margin-top: 0.7rem;
    max-width: 52ch;
    font-size: 0.875rem;
    color: var(--graphite);
}

@media (max-width: 50rem) {
    .screenshots {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The rest of the pictures, two to a row, each captioned with what it shows. */
.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
    gap: 2rem 1.75rem;
    align-items: start;
    margin-top: 2.5rem;
}

.gallery .screenshot h4 {
    margin: 0 0 0.6rem;
    font-size: 1.0625rem;
}

.gallery-group {
    margin-top: 2.75rem;
    padding-left: 0.85rem;
    border-left: 3px solid var(--verdigris-mark);
    font-size: 1.25rem;
}

.gallery-group.gallery-cloud {
    border-left-color: var(--indigo-mark);
}

.gallery-group.gallery-planning {
    border-left-color: var(--ochre-mark);
}

.gallery-group + .gallery {
    margin-top: 1.25rem;
}

/* ---------- audience ---------- */

.audience {
    margin: 2.5rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 1.75rem 2.5rem;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.audience li {
    padding-left: 1.15rem;
    border-left: 3px solid var(--slate);
}

.audience h3 {
    font-size: 1.125rem;
    line-height: 1.25;
}

.audience p {
    margin-top: 0.6rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.a-prov { border-left-color: var(--indigo-mark); }
.a-prov h3 { color: var(--indigo); }

.a-trust { border-left-color: var(--plum-mark); }
.a-trust h3 { color: var(--plum); }

.a-caution { border-left-color: var(--ochre-mark); }
.a-caution h3 { color: var(--ochre); }

.a-risk { border-left-color: var(--iron-mark); }
.a-risk h3 { color: var(--iron); }

/* ---------- origin note ---------- */

.origin {
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid #3a463f;
    max-width: 56ch;
    font-size: 0.9375rem;
    color: #a8b8ae;
}

/* ---------- key ---------- */

.key {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    margin-top: 1.5rem;
    padding: 0;
    list-style: none;
    font-size: 0.8125rem;
    color: var(--graphite);
}

.key li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.key i {
    width: 0.75rem;
    height: 0.75rem;
    flex: none;
}

.k-local { background: var(--verdigris-mark); }
.k-cloud { background: var(--indigo-mark); }
.k-caution { background: var(--ochre-mark); }
.k-risk { background: var(--iron-mark); }
.k-trust { background: var(--plum-mark); }

/* ---------- footer ---------- */

.foot {
    border-top: 3px solid var(--rule-heavy);
    padding-block: 2.5rem 3.5rem;
    font-size: 0.875rem;
    color: var(--graphite);
}

.foot-inner {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 3rem;
    justify-content: space-between;
}

.foot-inner .link-button {
    font-size: inherit;
}

/* Where to find the author: links, but in the footer's own quiet colour. */
.foot-inner .author-link,
.foot-home,
.foot-policies a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.foot-inner .author-link:hover,
.foot-home:hover,
.foot-policies a:hover {
    color: var(--ink);
}

/* ---------- analytics consent ---------- */

.consent-banner {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 40;
    padding-block: 1rem;
    background: var(--paper);
    border-top: 3px solid var(--rule-heavy);
    box-shadow: 0 -6px 16px rgba(27, 36, 33, 0.08);
    font-size: 0.9375rem;
}

.consent-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 2rem;
}

.consent-inner p {
    margin: 0;
    max-width: var(--measure);
}

.consent-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* Refusing carries the same weight as agreeing: an outlined button the same size, not the
   underlined link the secondary style is elsewhere. */
.consent-actions .button-secondary {
    padding-inline: 1.25rem;
    color: var(--verdigris);
    text-decoration: none;
    border-color: var(--verdigris);
}

.consent-actions .button-secondary:hover {
    color: var(--verdigris-deep);
    background: var(--paper-deep);
    border-color: var(--verdigris-deep);
}

/* ---------- error ui (framework) ---------- */

#blazor-error-ui {
    background: var(--caution-wash);
    color: var(--ink);
    bottom: 0;
    display: none;
    left: 0;
    padding: 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    border-top: 3px solid var(--ochre-mark);
    font-size: 0.875rem;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 1rem;
    top: 0.6rem;
}

/* ---------- narrow ---------- */

@media (max-width: 60rem) {
    .hero {
        grid-template-columns: minmax(0, 1fr);
        gap: 2.5rem;
    }

    .pair {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }

    .pair-primary {
        padding: 0 0 0 1.25rem;
    }
}

@media (max-width: 40rem) {
    .band {
        padding-block: 3rem;
    }

    .band-open {
        padding-block: 2rem 3rem;
    }

    .spec-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
        white-space: normal;
    }

    .spec-row + .spec-row {
        margin-top: 0.6rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}

/* ---------- forms and account pages ---------- */

/* Bootstrap is loaded for the Wiki and Blog packages, which are built against it.
   Everything below is therefore SCOPED to the site's own pages: unscoped overrides of
   .btn or .form-control would repaint the packages' interfaces too, which is what turned
   their outline icon buttons into solid green rectangles.

   Inside .account-page the Identity templates' Bootstrap class names are re-pointed at
   the site's design; outside it, Bootstrap is left to do its job. */

.account-page {
    max-width: 42rem;
}

.account-page h1 {
    font-family: var(--display);
    font-size: clamp(1.875rem, 4vw, 2.5rem);
    line-height: 1.1;
}

.account-page h2 {
    font-family: var(--display);
    font-size: 1.375rem;
    margin-top: 2rem;
}

.account-page h3 {
    font-size: 1.0625rem;
    font-family: var(--text);
    font-weight: 600;
    letter-spacing: 0;
}

.account-page hr {
    border: 0;
    border-top: 1px solid var(--rule);
    margin: 2rem 0;
    opacity: 1;
}

.account-page > p,
.account-page section > p {
    margin-bottom: 1rem;
    max-width: var(--measure);
}

/* The templates use a 12-column grid only to centre a narrow form. The account page is
   already narrow, so the grid collapses to one column. */
.account-page .row {
    display: block;
}

.account-page [class*="col-md-"],
.account-page [class*="col-lg-"],
.account-page [class*="col-xl-"] {
    width: 100%;
    max-width: none;
    flex: none;
}

/* form-floating puts the label AFTER the input in the markup. Reversing the flex
   direction gives a conventional label-above-input field without reproducing the
   floating behaviour, which does not suit this design. */
.account-page .form-floating {
    display: flex;
    flex-direction: column-reverse;
    margin-bottom: 1.15rem;
}

.account-page .form-floating > label,
.account-page .form-label {
    position: static;
    padding: 0;
    height: auto;
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    margin-bottom: 0.35rem;
    color: var(--ink);
    transform: none;
    pointer-events: auto;
}

/* Bootstrap's form-floating reserves space inside the control for a label that floats
   into it. The label is stacked above the input here, so all of that geometry has to go
   or the field is 3.5rem tall with its text pushed to the bottom. */
.account-page .form-floating > .form-control {
    height: auto;
    min-height: 0;
    line-height: inherit;
    padding: 0.6rem 0.75rem;
}

.account-page .form-floating > label {
    position: static;
    z-index: auto;
    height: auto;
    padding: 0;
    border: 0;
    overflow: visible;
    transform: none;
    opacity: 1;
    pointer-events: auto;
}

/* The pale bar behind the floating label. It exists to mask the input's border where the
   label sits over it, and with the label outside the control it is just a stripe. */
.account-page .form-floating > label::after {
    display: none;
}

/* Bootstrap animates the label on focus and when the field has content. Both would move a
   label that is no longer floating. */
.account-page .form-floating > .form-control:focus ~ label,
.account-page .form-floating > .form-control:not(:placeholder-shown) ~ label,
.account-page .form-floating > .form-control-plaintext ~ label {
    transform: none;
    opacity: 1;
    color: var(--ink);
}

.account-page .form-control,
.field .input {
    width: 100%;
    padding: 0.6rem 0.75rem;
    font: inherit;
    font-size: 0.9375rem;
    color: var(--ink);
    background: var(--field);
    border: 1px solid var(--rule);
    border-radius: 0;
    box-shadow: none;
}

.account-page .form-control:focus,
.field .input:focus {
    outline: 2px solid var(--verdigris-mark);
    outline-offset: 1px;
    border-color: var(--verdigris-mark);
    box-shadow: none;
}

.account-page .form-control.invalid,
.field .input.invalid {
    border-color: var(--iron-mark);
}

.field {
    margin-bottom: 1.15rem;
    max-width: 26rem;
}

.field label {
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    margin-bottom: 0.35rem;
}

.account-page .checkbox label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.9375rem;
    font-weight: 400;
}

.account-page .checkbox input[type="checkbox"],
.account-page .form-check-input[type="checkbox"] {
    flex: none;
    width: 1rem;
    height: 1rem;
    min-height: 0;
    margin: 0;
    padding: 0;
    accent-color: var(--verdigris-mark);
}

/* The templates put form-label on the wrapping label, which would otherwise make it a
   block and break the row. */
.account-page .checkbox .form-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0;
    font-weight: 400;
}

/* Buttons: the site's own, plus the Identity templates' Bootstrap names. */
.button,
.account-page .btn {
    display: inline-block;
    padding: 0.6rem 1.25rem;
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--on-accent);
    background: var(--verdigris);
    border: 1px solid var(--verdigris);
    border-radius: 0;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
}

.button:hover,
.account-page .btn:hover {
    background: var(--verdigris-deep);
    border-color: var(--verdigris-deep);
    color: var(--on-accent);
}

.account-page .btn-lg { padding: 0.7rem 1.5rem; font-size: 0.9375rem; }

.account-page .btn-danger {
    background: var(--iron);
    border-color: var(--iron);
}

.account-page .btn-danger:hover {
    background: var(--iron-mark);
    border-color: var(--iron-mark);
}

/* The quieter action: same shape as the primary button, without the fill. */
.account-page .btn-secondary {
    color: var(--verdigris);
    background: transparent;
    border-color: var(--rule);
}

.account-page .btn-secondary:hover {
    color: var(--verdigris-deep);
    background: var(--paper-deep);
    border-color: var(--verdigris);
}

.button-secondary,
.account-page .btn-link {
    color: var(--verdigris);
    background: transparent;
    border-color: transparent;
    text-decoration: underline;
    text-underline-offset: 0.2em;
    padding-inline: 0;
}

.button-secondary:hover,
.account-page .btn-link:hover {
    color: var(--iron);
    background: transparent;
    border-color: transparent;
}

/* Validation and status. */
.account-page .text-danger,
.field-error,
.validation-message {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.8125rem;
    color: var(--iron);
}

.account-page .alert {
    padding: 0.85rem 1.15rem;
    margin-bottom: 1.5rem;
    font-size: 0.9375rem;
    border: 0;
    border-left: 3px solid var(--slate);
    border-radius: 0;
    background: var(--paper-deep);
    color: var(--ink);
}

.account-page .alert-danger { border-left-color: var(--iron-mark); }
.account-page .alert-warning { border-left-color: var(--ochre-mark); }
.account-page .alert-success { border-left-color: var(--verdigris-mark); }
.account-page .alert-info { border-left-color: var(--indigo-mark); }

/* The Manage area's navigation. */
.account-page .nav {
    gap: 0.25rem 1.5rem;
    border-bottom: 1px solid var(--rule);
    padding-bottom: 0.75rem;
    margin-bottom: 2rem;
}

.account-page .nav-link {
    padding: 0.25rem 0;
    font-size: 0.9375rem;
    color: var(--graphite);
    text-decoration: none;
}

.account-page .nav-link:hover,
.account-page .nav-link.active {
    color: var(--ink);
    background: transparent;
    text-decoration: underline;
    text-decoration-color: var(--verdigris-mark);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

.account-page .table {
    font-size: 0.9375rem;
}

/* Bootstrap 3 glyphicons, referenced by a couple of the Identity templates. The icon
   font does not exist here and they were decorative, so they are hidden. */
.account-page .glyphicon { display: none; }

.nav-form {
    display: inline;
}

/* The light/dark switch, at the end of the navigation. js/theme.js does the switching; without
   the script there is nothing to switch, so until it has marked the page the button is not
   shown. It says where a click goes: a moon and "Dark mode" on a light page, a sun and "Light
   mode" on a dark one. In the full-width navigation the icon alone says it; the drawer has room
   for the words as well. */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

:root:not([data-theme]) .theme-toggle {
    display: none;
}

.theme-toggle-icon::before {
    content: "\263E";
    font-size: 1.05rem;
    line-height: 1;
}

.theme-toggle[data-dark="true"] .theme-toggle-icon::before {
    content: "\2600";
}

.masthead-nav .theme-toggle-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.link-button {
    padding: 0;
    font: inherit;
    font-size: 0.9375rem;
    color: var(--graphite);
    background: none;
    border: 0;
    cursor: pointer;
}

.link-button:hover {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--verdigris-mark);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

/* ---------- package pages ---------- */

/* Wiki and Blog pages come from packages and bring no page frame, so their content would
   otherwise run edge to edge — which reads as a different site rather than a different
   section.

   The frame goes on <main> rather than on the package's own elements. Their admin screens
   are Bootstrap utility classes all the way down, with no stable container to hang a width
   on, and naming inner elements would mean revisiting this every time a package is
   updated. The host decides which routes get the class; see PackagePages.

   It cannot be the default for every page: the site's own sections use full-bleed
   backgrounds and rules that must reach the viewport edge. */
main.boxed {
    display: block;
    max-width: var(--frame);
    margin-inline: auto;
    padding-inline: 1.5rem;
    padding-block: 2.5rem;
}

/* The wiki is an app shell: .wiki-layout is 100vh tall with its sidebar and article
   scrolling independently. That is worth keeping — a long page of documentation with a
   table of contents that scrolls away is worse — but 100vh inside a framed page runs under
   the footer. Bounded to leave room for the masthead above and the footer below, so the
   package's own scrolling still works and the page ends where the page ends. */
main.boxed .wiki-layout {
    height: calc(100vh - 16rem);
    min-height: 30rem;
    border: 1px solid var(--rule-soft);
}

.wiki-article h1,
.wiki-article h2,
.wiki-article h3 {
    font-family: var(--display);
}

/* The Wiki's Books page (/docs/admin/books) puts each book's name and address beside its
   Default and Published badges, in a column marked "min-width-0" - a class Bootstrap does
   not have. Without it the column cannot shrink below its text, so the badges were pushed
   past the card's edge and cut off. The name and address wrap instead, so both are read whole. */
.wiki-book-card .min-width-0 {
    min-width: 0;
}

.wiki-book-card .min-width-0 h6 {
    white-space: normal;
}

.wiki-book-card .min-width-0 code {
    display: block;
    overflow-wrap: anywhere;
}

.wiki-book-card .card-body > .d-flex > .flex-column {
    flex-shrink: 0;
}

/* ---------- blog and docs ---------- */

.blog-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 17rem;
    gap: 3rem;
    align-items: start;
    margin-top: 2rem;
}

.blog-main {
    min-width: 0;
}

.blog-side {
    font-size: 0.9375rem;
}

.blog-side > * + * {
    margin-top: 2rem;
}

.blog-side h2,
.blog-side h3 {
    font-family: var(--text);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0;
    padding-bottom: 0.5rem;
    margin-bottom: 0.75rem;
    border-bottom: 2px solid var(--indigo-mark);
}

.blog-side ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.blog-side li + li {
    margin-top: 0.4rem;
}

.blog-side a {
    color: var(--graphite);
    text-decoration: none;
}

.blog-side a:hover {
    color: var(--indigo);
    text-decoration: underline;
}

@media (max-width: 60rem) {
    .blog-layout {
        grid-template-columns: minmax(0, 1fr);
        gap: 2.5rem;
    }
}

/* ---------- admin menu ---------- */

/* Built on <details>, so it needs no JavaScript. The marker is removed and replaced with
   a caret that flips when open, since the default disclosure triangle sits oddly in a
   horizontal nav. */
.menu {
    position: relative;
    display: inline-block;
}

.menu > summary {
    list-style: none;
    cursor: pointer;
    font-size: 0.9375rem;
    color: var(--graphite);
    user-select: none;
}

.menu > summary::-webkit-details-marker {
    display: none;
}

.menu > summary::after {
    content: "";
    display: inline-block;
    margin-left: 0.4rem;
    border: 0.3em solid transparent;
    border-top-color: currentColor;
    transform: translateY(0.15em);
}

.menu[open] > summary::after {
    transform: translateY(-0.15em) rotate(180deg);
}

.menu > summary:hover,
.menu[open] > summary {
    color: var(--ink);
}

.menu > summary:focus-visible {
    outline: 2px solid var(--verdigris-mark);
    outline-offset: 3px;
}

.menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 0.6rem);
    z-index: 20;
    min-width: 13rem;
    padding: 0.4rem 0;
    background: var(--paper);
    border: 1px solid var(--rule);
    box-shadow: 0 2px 0 var(--rule-soft);
}

.menu-item {
    display: block;
    padding: 0.45rem 1rem 0.45rem 0.85rem;
    font-size: 0.9375rem;
    color: var(--graphite);
    text-decoration: none;
    border-left: 3px solid transparent;
}

.menu-item:hover,
.menu-item:focus-visible {
    background: var(--paper-deep);
    color: var(--ink);
}

/* The Project menu sits at the start of the masthead, so its panel opens to the right of it
   rather than hanging off the left edge. Its summary reads as current, like a single link. */
.menu-start > .menu-panel {
    left: 0;
    right: auto;
}

.menu.menu-current > summary {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--verdigris-mark);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

.menu-item[aria-current="page"],
.menu-item.active {
    color: var(--ink);
    border-left-color: var(--verdigris-mark);
}
.menu-local { border-left-color: var(--verdigris-mark); }
.menu-cloud { border-left-color: var(--indigo-mark); }
.menu-caution { border-left-color: var(--ochre-mark); }
.menu-risk { border-left-color: var(--iron-mark); }
.menu-trust { border-left-color: var(--plum-mark); }

/* The Project menu is a map of the site rather than a short list: three labelled columns side by
   side, so every page is one glance and one click away. On a phone they stack.

   Too wide to hang from its own summary, which sits towards the right of the masthead: it would
   run off the page. So it is placed against the masthead's own right edge instead, under the
   whole navigation, and never wider than the window. */
.menu-wide {
    position: static;
}

.menu-wide > .menu-panel {
    left: auto;
    right: 0;
    top: calc(100% - 0.4rem);
    max-width: calc(100vw - 2rem);
}

.menu-columns {
    display: grid;
    grid-template-columns: repeat(3, minmax(12rem, 1fr));
    gap: 0.25rem 1.5rem;
    min-width: min(46rem, calc(100vw - 2rem));
    padding: 0.9rem 0.6rem 0.8rem;
}

.menu-heading {
    margin: 0 0 0.35rem;
    padding: 0 1rem 0.35rem 0.85rem;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--graphite);
    border-bottom: 1px solid var(--rule-soft);
}

@media (max-width: 52rem) {
    .menu-columns {
        grid-template-columns: 1fr;
        min-width: 16rem;
    }

    .menu-group + .menu-group {
        margin-top: 0.6rem;
    }
}

@media (max-width: 40rem) {
    /* On a narrow screen an absolutely positioned panel can sit off-screen, so it
       becomes part of the flow instead. */
    .menu-panel {
        position: static;
        border: 0;
        box-shadow: none;
        min-width: 0;
        padding-left: 0.5rem;
    }
}

/* Diagnostic detail keeps the line breaks it was written with, and wraps rather than
   stretching the page when a message is one long line — an SSL error listing every name
   on a certificate is exactly that. */
.account-page .detail {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.875rem;
}

/* ---------- account settings ---------- */

/* The settings area needs two columns, so it widens past the narrow measure the rest of
   the account pages use for forms. */
.account-page:has(.manage) {
    max-width: var(--frame);
}

.manage {
    display: grid;
    grid-template-columns: 14rem minmax(0, 1fr);
    gap: 3rem;
    align-items: start;
    margin-top: 2rem;
}

.manage-body {
    min-width: 0;
    max-width: 32rem;
}

/* The panel heading. It repeats the selected item in the navigation beside it, which is
   what makes it easy to under-set: it needs to read as the start of a section rather than
   as a label sitting on the first field. The display face and a hairline beneath give it
   somewhere to end, so the first field label is not the next thing the eye meets. */
.manage-body > h2,
.manage-body > h3 {
    margin: 0 0 1.5rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--rule-soft);
    font-family: var(--display);
    font-size: 1.5rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* Where a page explains itself, the note carries the rule instead and the heading closes
   up against it — two rules a line apart would read as a mistake. */
.manage-body > h2:has(+ .manage-note),
.manage-body > h3:has(+ .manage-note) {
    margin-bottom: 0.4rem;
    padding-bottom: 0;
    border-bottom: 0;
}

.manage-note {
    margin: 0 0 1.6rem;
    padding-bottom: 1.2rem;
    border-bottom: 1px solid var(--rule-soft);
    color: var(--graphite);
    font-size: 0.9375rem;
    max-width: var(--measure);
}

/* Save sits below a rule rather than filling the column. A button as wide as the form is
   the same weight as the form, and there is only one thing to press. */
.manage-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin-top: 1.6rem;
    padding-top: 1.3rem;
    border-top: 1px solid var(--rule-soft);
}

.account-page .manage-actions .btn {
    min-width: 9rem;
}

/* A request's two answers side by side in its row, the one that grants first. */
/* The Contact us page: a field for software only, out of sight and out of the tab order, so a person never
   fills it in (SendContactMessage drops what does). */
.contact-trap {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* The form stands clear of the words above it, and the note on what is kept clear of the button below it. */
.contact-form {
    margin-top: 2rem;
}

.contact-form .contact-note {
    margin: 1.5rem 0;
}

/* The administrators' inbox: one card per message, those waiting marked, those dealt with quieter. */
.contact-messages {
    list-style: none;
    padding: 0;
    margin: 1.5rem 0 0;
    display: grid;
    gap: 1rem;
}

.contact-message {
    border: 1px solid var(--rule-soft);
    border-left: 4px solid var(--ochre-mark);
    padding: 1rem 1.25rem;
}

.contact-message.handled {
    border-left-color: var(--rule-soft);
    opacity: 0.75;
}

.contact-message-head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    align-items: baseline;
}

.contact-message-body {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    margin: 0.75rem 0;
}

.request-decision {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.request-decision form {
    margin: 0;
}

/* The Identity templates make every settings submit button full width and large. That is
   a sign-in page's treatment — one action, nothing else on screen — and it is wrong on a
   settings panel that already has a navigation column beside it. Corrected here rather
   than in each page, so a template page added later inherits the correction. */
.manage-body .btn.w-100 {
    width: auto;
    min-width: 9rem;
    margin-top: 0.5rem;
}

/* A note belongs to the field above it, so the field closes up and the pair keeps the
   spacing one field would have had. */
.account-page .form-floating:has(+ .field-note) {
    margin-bottom: 0.3rem;
}

.account-page .form-floating + .field-note {
    margin-bottom: 1.15rem;
}

/* A field that cannot be edited should not look like one that can. White with a dark
   border is the invitation; this withdraws it. */
.account-page .form-control:disabled,
.account-page .form-control[readonly] {
    background: var(--paper-deep);
    border-color: var(--rule-soft);
    color: var(--graphite);
    cursor: default;
}

/* Something in effect — an address verified, a subscription active — stated in words. */
.account-page .status-ok {
    color: var(--verdigris);
    font-weight: 600;
}

/* A second section on a settings page starts well clear of the first. */
.manage-body > h3 ~ h3 {
    margin-top: 2.75rem;
}

/* ---------- registration ---------- */

/* Grouped, so a longer sign-up reads as four short questions. Bootstrap's reboot floats
   the legend and sets it at heading size; neither suits a form this narrow. */
.account-page .form-section {
    min-width: 0;
    margin: 0 0 1.75rem;
    padding: 0;
    border: 0;
}

.account-page .form-section > legend {
    float: none;
    width: 100%;
    margin: 0 0 1rem;
    padding: 0 0 0.5rem;
    border-bottom: 1px solid var(--rule-soft);
    font-family: var(--display);
    font-size: 1.25rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--ink);
}

/* .field caps its width for a lone input. In this form the column is already the measure,
   and a pair of names needs the full width to split. */
.register-form .field {
    max-width: none;
}

/* First and last name are one answer in two parts, so they share a row — until the screen
   is too narrow for two usable inputs. */
.field-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 1rem;
}

@media (max-width: 36rem) {
    .field-pair {
        grid-template-columns: minmax(0, 1fr);
    }
}

.optional {
    font-weight: 400;
    color: var(--graphite);
}

/* Consent wording runs to two lines, so the box sits against the first line rather than
   floating beside the middle of the sentence. */
.account-page .checkbox.consent label {
    align-items: flex-start;
    line-height: 1.5;
}

.account-page .checkbox.consent input[type="checkbox"] {
    margin-top: 0.25rem;
}

/* ---------- admin grids ---------- */

/* QuickGrid draws its sort arrows and pager icons in scoped CSS that this site does not
   load, so its markup is styled here, with text glyphs in place of masked icons. The class
   names are QuickGrid's own and stable across releases. */
.grid-scroll {
    overflow-x: auto;
    margin-top: 1rem;
}

.admin-grid {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9375rem;
}

.admin-grid th,
.admin-grid td {
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--rule-soft);
    text-align: left;
    vertical-align: top;
}

.admin-grid thead th {
    border-bottom-color: var(--rule);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--graphite);
    white-space: nowrap;
}

.admin-grid tbody tr:hover {
    background: var(--paper-deep);
}

/* With pagination on, QuickGrid pads every page to its full size with filler rows, so the
   table keeps its height from page to page. A short list then trails a column of blank
   lines, which reads as missing data rather than as a steady layout.

   The filler rows are not empty elements — each holds one empty cell per column, whose
   borders drew the lines — so they are recognised as rows with no cell that has content.
   UsersAndRolesPageTests checks that this still describes QuickGrid's markup. */
.admin-grid tbody tr:not(:has(> td:not(:empty))) {
    display: none;
}

.admin-grid .col-justify-end {
    text-align: right;
}

.admin-grid .col-header-content {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.admin-grid .col-justify-end .col-header-content {
    justify-content: flex-end;
}

.admin-grid .col-title {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0;
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    cursor: pointer;
}

.admin-grid .col-title:hover {
    color: var(--ink);
}

.admin-grid .col-title:focus-visible {
    outline: 2px solid var(--verdigris-mark);
    outline-offset: 2px;
}

.admin-grid .col-sort-asc .sort-indicator::after {
    content: "▲";
    font-size: 0.625rem;
}

.admin-grid .col-sort-desc .sort-indicator::after {
    content: "▼";
    font-size: 0.625rem;
}

.admin-grid small,
.grid-note {
    color: var(--graphite);
    font-size: 0.8125rem;
}

.admin-grid small {
    display: block;
}

.grid-tag {
    display: inline-block;
    margin: 0.25rem 0.35rem 0 0;
    padding: 0 0.4rem;
    font-size: 0.75rem;
    font-weight: 500;
    border: 1px solid var(--rule);
    color: var(--graphite);
}

.grid-tag-caution {
    border-color: var(--ochre-mark);
    color: var(--ochre);
}

.grid-tag-risk {
    border-color: var(--iron-mark);
    color: var(--iron);
}

.grid-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.5rem 1.5rem;
    margin-top: 1rem;
}

.grid-toolbar .field {
    flex: 1 1 18rem;
    margin-bottom: 0;
}

.grid-filter {
    margin: 0 0 0.6rem;
    font-size: 0.9375rem;
}

.grid-pager .paginator {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1.5rem;
    margin-top: 1rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.grid-pager .paginator nav {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.grid-pager .paginator button {
    min-width: 2.25rem;
    padding: 0.3rem 0.5rem;
    font: inherit;
    color: var(--verdigris);
    background: transparent;
    border: 1px solid var(--rule);
    cursor: pointer;
}

.grid-pager .paginator button:hover:not(:disabled) {
    background: var(--paper-deep);
    border-color: var(--verdigris);
}

.grid-pager .paginator button:disabled {
    color: var(--rule);
    cursor: default;
}

.grid-pager .paginator .go-first::before { content: "«"; }
.grid-pager .paginator .go-previous::before { content: "‹"; }
.grid-pager .paginator .go-next::before { content: "›"; }
.grid-pager .paginator .go-last::before { content: "»"; }

.grid-pager .summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.25rem;
}

.pager-size {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-weight: 400;
}

.pager-size .input {
    padding: 0.25rem 0.5rem;
    font: inherit;
    color: var(--ink);
    background: var(--field);
    border: 1px solid var(--rule);
    border-radius: 0;
}

.pager-size .input:focus {
    outline: 2px solid var(--verdigris-mark);
    outline-offset: 1px;
    border-color: var(--verdigris-mark);
}

/* An action inside a note is a link in the sentence, not a button beside it, so it drops
   the button's box and takes the note's type. */
.account-page .field-note .btn-link {
    padding: 0;
    font-size: inherit;
    vertical-align: baseline;
}

/* The navigation is a vertical list here, not the horizontal bar the account pages use
   elsewhere, so it overrides that rather than inheriting it. */
.manage-nav .nav {
    display: block;
    border-bottom: 0;
    padding-bottom: 0;
    margin-bottom: 0;
}

.manage-nav .nav-item + .nav-item {
    margin-top: 0.15rem;
}

.manage-nav .nav-link {
    display: block;
    padding: 0.5rem 0.75rem;
    border-left: 3px solid var(--rule);
    color: var(--graphite);
    text-decoration: none;
}

.manage-nav .nav-link:hover {
    background: var(--paper-deep);
    color: var(--ink);
    text-decoration: none;
}

.manage-nav .nav-link.active {
    border-left-color: var(--verdigris-mark);
    background: var(--paper-deep);
    color: var(--ink);
    font-weight: 600;
    text-decoration: none;
}

@media (max-width: 55rem) {
    .manage {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }
}

/* FocusOnNavigate moves focus to the page heading after navigation, which is right for
   screen-reader users but drew a box around the title for everyone else. Headings given
   focus programmatically carry tabindex="-1"; a genuine keyboard focus ring is unaffected
   because interactive elements are not focused this way. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
}

/* ---------- profile picture ---------- */

/* A round frame is the one place on this site that borrows a convention wholesale: an
   avatar that is not a circle reads as a logo. The fallback carries the account's initial
   on the section hue rather than a grey silhouette, so a signed-in masthead looks
   inhabited even before anyone uploads anything. */
.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    background: var(--paper-deep);
    border: 1px solid var(--rule);
    vertical-align: middle;
}

.avatar-initial {
    background: var(--verdigris);
    border-color: var(--verdigris-deep);
    color: var(--paper);
    font-family: var(--text);
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0;
}

.masthead-nav a.account-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* The underline hover treatment belongs to the word, not the picture. */
.masthead-nav a.account-link:hover,
.masthead-nav a.account-link[aria-current="page"] {
    text-decoration: none;
}

.masthead-nav a.account-link:hover span,
.masthead-nav a.account-link[aria-current="page"] span {
    text-decoration: underline;
    text-decoration-color: var(--verdigris-mark);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

.profile-image {
    display: flex;
    align-items: flex-start;
    gap: 2rem;
    flex-wrap: wrap;
    margin-top: 1.5rem;
}

.profile-image-preview .avatar {
    width: 128px;
    height: 128px;
    font-size: 3rem;
}

.profile-image-actions {
    flex: 1 1 18rem;
    min-width: 0;
}

.profile-image-actions .form-label {
    display: block;
    margin-bottom: 0.4rem;
    font-weight: 500;
    color: var(--ink);
}

.profile-image-actions .btn {
    margin-top: 1rem;
}

/* What the field will accept, stated where the choice is made rather than after it is
   refused. */
.field-note {
    margin: 0.6rem 0 0;
    font-size: 0.875rem;
    color: var(--graphite);
    max-width: var(--measure);
}

.profile-image-remove {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--rule-soft);
}

/* ---------- guide ---------- */

.guide-lede {
    font-size: 1.125rem;
    color: var(--ink);
}

/* What exists and what does not, said before anything is described as working. */
.guide-status {
    margin-top: 2rem;
    padding: 1rem 1.15rem;
    max-width: 52rem;
    border-left: 3px solid var(--ochre-mark);
    background: var(--paper-deep);
    font-size: 0.9375rem;
}

.guide-status b {
    font-weight: 600;
}

.tag {
    display: inline-block;
    padding: 0.05rem 0.45rem;
    border: 1px solid currentColor;
    border-radius: 999px;
    font-family: var(--mono);
    font-size: 0.75rem;
    line-height: 1.4;
    white-space: nowrap;
    vertical-align: 0.1em;
}

.tag-built { color: var(--verdigris); }
.tag-progress { color: var(--indigo); }
.tag-planned { color: var(--ochre); }

.timeline {
    margin: 2.5rem 0 0;
    padding: 0;
    list-style: none;
    counter-reset: step;
    max-width: 48rem;
}

.timeline li {
    position: relative;
    margin-left: 1rem;
    padding: 0 0 1.75rem 2.5rem;
    border-left: 1px solid var(--rule);
    counter-increment: step;
}

.timeline li:last-child {
    padding-bottom: 0;
    border-left-color: transparent;
}

.timeline li::before {
    content: counter(step);
    position: absolute;
    top: -0.2rem;
    left: -1rem;
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--plum-mark);
    color: var(--on-accent);
    font-family: var(--mono);
    font-size: 0.875rem;
}

.timeline h3 {
    font-size: 1.125rem;
    line-height: 1.3;
    color: var(--plum);
}

.timeline p {
    margin-top: 0.5rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.template-guide {
    margin: 2.5rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 2rem 2.5rem;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
}

.template-guide-item {
    padding-left: 1.15rem;
    border-left: 3px solid var(--slate);
}

.template-guide-item h3 {
    font-size: 1.1875rem;
    line-height: 1.25;
}

.template-guide-item > p {
    margin-top: 0.6rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.template-guide-folders {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0.85rem 0 0;
    padding: 0;
    list-style: none;
}

.template-guide-folders li {
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--rule);
    border-radius: 4px;
    background: var(--field);
    font-family: var(--mono);
    font-size: 0.75rem;
    color: var(--ink);
}

.template-guide-folders li:has(> a) {
    padding: 0;
}

.template-guide-folders a {
    display: block;
    padding: 0.15rem 0.5rem;
    border-radius: 3px;
    color: inherit;
    text-decoration: none;
}

.template-guide-folders a:hover,
.template-guide-folders a:focus-visible {
    background: var(--paper-deep);
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.template-guide-item .template-guide-note {
    font-size: 0.875rem;
    color: var(--ink);
}

.template-guide-none {
    font-style: italic;
}

.template-guide-more {
    margin-top: 2rem;
    font-size: 0.9375rem;
    color: var(--graphite);
}

/* The folders guide: an index of every folder, then one entry per folder, grouped by the stage of the work. */
.folder-guide-index {
    display: grid;
    gap: 1.25rem 2.5rem;
    grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
    margin-top: 2.5rem;
}

.folder-guide-index-title {
    font-size: 0.9375rem;
    font-weight: 600;
}

.folder-guide-index-title a {
    color: var(--ink);
}

.folder-guide-index .template-guide-folders {
    margin-top: 0.5rem;
}

.folder-guide {
    display: grid;
    gap: 2.5rem 3rem;
    grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
    margin-top: 2.5rem;
}

.folder-guide-item {
    padding-left: 1.15rem;
    border-left: 3px solid var(--rule);
    scroll-margin-top: 5rem;
}

.folder-guide-item:target {
    border-left-color: var(--verdigris-mark);
}

.folder-guide-item h3 {
    font-size: 1.1875rem;
    line-height: 1.25;
}

.folder-guide-flag {
    display: inline-block;
    margin-top: 0.5rem;
    padding: 0.05rem 0.5rem;
    border: 1px solid currentColor;
    border-radius: 999px;
    font-family: var(--mono);
    font-size: 0.75rem;
    color: var(--plum);
}

.folder-guide-purpose {
    margin-top: 0.6rem;
    color: var(--ink);
}

.folder-guide-details {
    margin: 0.75rem 0 0;
}

.folder-guide-details dt {
    margin-top: 0.85rem;
    font-family: var(--mono);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--graphite);
}

.folder-guide-details dd {
    margin: 0.25rem 0 0;
    font-size: 0.9375rem;
    color: var(--graphite);
}

.folder-guide-templates {
    margin-top: 1rem;
    font-size: 0.875rem;
    color: var(--graphite);
}

.folder-guide-templates ul {
    display: inline;
    margin: 0;
    padding: 0;
    list-style: none;
}

.folder-guide-templates li {
    display: inline;
}

.folder-guide-templates li:not(:last-child)::after {
    content: ",";
}

.decide {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    max-width: 48rem;
    margin: 2rem 0 0;
    border-top: 1px solid var(--rule-soft);
}

.decide dt,
.decide dd {
    margin: 0;
    padding: 0.65rem 0;
    border-bottom: 1px solid var(--rule-soft);
}

.decide dt {
    padding-right: 1.5rem;
    color: var(--graphite);
}

.decide dd {
    font-weight: 600;
    text-align: right;
    color: var(--verdigris);
}

/* The same ruled rows the other way round: a short field on the left, and what it is for, in a
   sentence or two, wrapping beside it. */
.decide-fields {
    grid-template-columns: max-content minmax(0, 1fr);
}

.decide-fields dd {
    font-weight: 400;
    text-align: left;
    color: var(--ink);
}

@media (max-width: 40rem) {
    .decide {
        grid-template-columns: 1fr;
    }

    .decide dt {
        padding-bottom: 0;
        border-bottom: 0;
    }

    .decide dd {
        padding-top: 0.2rem;
        text-align: left;
    }

    .timeline li {
        padding-left: 2rem;
    }
}

/* The forum package, in the site's palette. The package derives its greys from the text
   colour, so only the hues are set here, each with the meaning it already has on this site:
   verdigris for links and what is done, ochre for anything waiting at an approval gate,
   iron for faults (bug reports), indigo for questions, plum for human judgement (planned). */
.psc-forum {
    --pf-accent: var(--verdigris);
    --pf-accent-text: var(--paper);
    --pf-success: var(--verdigris);
    --pf-warning: var(--ochre);
    --pf-danger: var(--iron);
    --pf-info: var(--indigo);
    --pf-purple: var(--plum);
}

/* Coming next: planned work, drawn in the cloud hue's rule and never with the "works" styling, so a
   planned feature cannot be mistaken for one that can be tried. */
.coming-list {
    list-style: none;
    margin: 1.5rem 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: 1rem;
}

.coming-item {
    padding: 1rem 1.1rem;
    border: 1px dashed var(--rule);
    border-left: 3px solid var(--indigo-mark);
    background: var(--paper);
}

.coming-item h3 {
    margin: 0;
    font-size: 1.05rem;
}

.coming-item p {
    margin: 0.35rem 0 0;
    color: var(--graphite);
    font-size: 0.95rem;
}

.coming-item .coming-when {
    margin-top: 0.15rem;
    color: var(--indigo);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}
/* The Markdown editor the Wiki and Blog use, in the site's tokens. Its stylesheet paints the
   writing surface white and its text black outright, which in the dark theme left a white slab
   in a dark page. In the light theme these are the same colours near enough; the forum styles
   its own editor more specifically, so it keeps its look. */
.EasyMDEContainer .CodeMirror {
    color: var(--ink);
    background: var(--field);
    border-color: var(--rule);
}

.EasyMDEContainer .CodeMirror-cursor {
    border-left-color: var(--ink);
}

.EasyMDEContainer .CodeMirror-selected,
.EasyMDEContainer .CodeMirror-focused .CodeMirror-selected {
    background: color-mix(in srgb, var(--verdigris-mark) 28%, transparent);
}

.editor-toolbar {
    border-color: var(--rule);
}

.editor-toolbar.fullscreen {
    background: var(--paper);
}

.editor-toolbar button {
    color: var(--ink);
}

.editor-toolbar button.active,
.editor-toolbar button:hover {
    background: var(--paper-deep);
    border-color: var(--rule);
}

.editor-toolbar i.separator {
    border-left-color: var(--rule);
    border-right-color: transparent;
}

.editor-statusbar {
    color: var(--graphite);
}

.editor-preview,
.editor-preview-side {
    color: var(--ink);
    background: var(--paper-deep);
    border-color: var(--rule);
}

.editor-preview pre {
    background: var(--paper);
}
