/* gassert.ch
   ==========================================================================
   GT Sectra in four cuts, and two colours: slate and a grey. The night is
   the day turned over, the same pair swapped, nothing added.

   Everything that is not the background is the ink, at full strength or at
   an opacity of it. There is exactly one exception, a pink, and it appears
   only under the pointer: nothing on a page at rest is any colour but the
   two. The only loud thing on a page at rest is the name.
   ---------------------------------------------------------------------- */

@font-face {
    font-family: "GT Sectra";
    src: url("/fonts/GT-Sectra-Book.woff2") format("woff2");
    font-weight: 350; font-style: normal; font-display: swap;
}
@font-face {
    font-family: "GT Sectra";
    src: url("/fonts/GT-Sectra-Book-Italic.woff2") format("woff2");
    font-weight: 350; font-style: italic; font-display: swap;
}
@font-face {
    font-family: "GT Sectra";
    src: url("/fonts/GT-Sectra-Bold.woff2") format("woff2");
    font-weight: 700; font-style: normal; font-display: swap;
}
/* The Display cut, drawn for large sizes. Declared with a fallback on
   purpose: if the file is missing the family does not resolve and headings
   fall back to the Text cut, flatter but still correct. */
@font-face {
    font-family: "GT Sectra Display";
    src: url("/fonts/GT-Sectra-Display-Medium.woff2") format("woff2");
    font-weight: 500; font-style: normal; font-display: swap;
}

/* Two stand-ins, so the page does not move when GT Sectra arrives.
   Until the webfont is there the text is set in whatever serif the device
   has, and those are not the same width: on a phone without Iowan or
   Palatino the fallback is a Times, 7 percent narrower, so the paragraph
   breaks into different lines and jumps the moment the real font lands.
   That jump was the whole of this page's layout shift, 0.252 of it.

   size-adjust scales the stand-in to GT Sectra's average advance width,
   measured over the letters English prose is actually made of, so the
   lines break in the same places. The ascent and descent overrides put the
   baseline where GT Sectra would put it. Two faces because the two camps
   differ: Apple ships Iowan and Palatino, which are already close, and
   everything else lands on a Times metric. Noto Serif is deliberately not
   listed: it is wider again, and a wrong correction is worse than none, so
   where no named face exists the stack falls through uncorrected.

   The numbers come from the font files; tools/font-fallback-metrics.py
   recomputes them if a cut is ever replaced. */
@font-face {
    font-family: "GT Sectra stand-in Apple";
    src: local("Iowan Old Style"), local("Palatino"), local("Palatino Linotype");
    size-adjust: 96.7%;
    ascent-override: 101.3%;
    descent-override: 26.9%;
    line-gap-override: 0%;
}
@font-face {
    font-family: "GT Sectra stand-in";
    src: local("Times New Roman"), local("Tinos"), local("Liberation Serif"),
         local("Nimbus Roman"), local("Thorndale AMT");
    size-adjust: 107.4%;
    ascent-override: 91.3%;
    descent-override: 24.2%;
    line-gap-override: 0%;
}

/* ---- Palette -----------------------------------------------------------
   Two colours, and the night is the day turned over. Not a darker variant
   of the same scheme: the identical pair, swapped. Slate carries the type
   by day and the page by night, and the grey does the opposite.

   Links, rules and list markers are the ink at a reduced opacity, which is
   what keeps the page quiet enough for the one loud thing on it to be the
   name. Measured: 9.3:1 in both directions, because inverting a pair cannot
   change the ratio between them.

   The pink is the one thing that is neither, and it is only ever a hover
   state, so the page has to be touched before it appears. It is not the
   same pink by day and by night, because the pair is inverted and a colour
   that holds against slate washes out against grey. Measured on the
   background it sits on: 4.6:1 by day, 7.7:1 by night. */
:root {
    --slate: #2B323B;
    --grey:  #D8DBDE;

    --bg:   var(--grey);
    --ink:  var(--slate);
    --pink: #B5176B;
    color-scheme: light;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg: var(--slate); --ink: var(--grey); --pink: #FFB3C7;
        color-scheme: dark;
    }
}
:root[data-theme="dark"] {
    --bg: var(--slate); --ink: var(--grey); --pink: #FFB3C7;
    color-scheme: dark;
}

:root {
    --measure: 34rem;
    --wide: 52rem;
    /* The body runs at 20px. This is the only other size on the page that is
       not a heading, and two places use it: the footer, and the note that
       appears under the pointer. Everything else is the body size. */
    --small: 1rem;
}

/* ---- Page -------------------------------------------------------------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
    margin: 0;
    padding: 0 20px 5rem;
    background: var(--bg);
    color: var(--ink);
    font-family: "GT Sectra", "GT Sectra stand-in Apple",
                 "GT Sectra stand-in", "Iowan Old Style",
                 "Palatino Linotype", Palatino, Times, serif;
    font-weight: 350;
    font-size: 20px;
    line-height: 32px;
    transition: background-color 140ms ease, color 140ms ease;
}
main { max-width: var(--measure); margin: 0 auto; }

/* ---- The bar, holding only the switch ---------------------------------- */
.bar {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 22px 0 0;
    display: flex;
    justify-content: flex-end;
}

/* Lifted from darioamodei.com: a 40x20 pill with a 14px knob. Deliberately
   unlabelled, because a switch that says "Dark" is ambiguous about whether
   that is the state or the destination. */
.theme-toggle {
    position: relative;
    width: 40px; height: 20px;
    padding: 0; border: 0; cursor: pointer;
    border-radius: 999px;
    background: color-mix(in srgb, var(--ink) 28%, transparent);
    transition: background-color 140ms ease;
}
.theme-toggle::before {
    content: "";
    position: absolute; top: 3px; left: 2px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--ink);
    transition: left 140ms ease;
}
.theme-toggle[aria-pressed="true"]::before { left: 22px; }
.theme-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---- Type -------------------------------------------------------------- */
h1, h2 {
    font-family: "GT Sectra Display", "GT Sectra",
                 "GT Sectra stand-in Apple", "GT Sectra stand-in",
                 "Iowan Old Style", Palatino, Times, serif;
    font-weight: 500;
    color: inherit;
}
h1 {
    /* Aligned to the text, which is the only edge on the page it could be
       aligned to. It used to break out to a 52rem column and was sized to
       fill it; once the size came down it stopped filling that column, and
       its left edge stood 9rem clear of the prose, lined up with nothing
       you could see. The cap is the size at which the name still fits the
       column on one line: measured, 529px of a 544px measure. */
    margin: 7vh 0 2.2rem;
    font-size: min(max(2.9rem, 11vw), 5.4rem);
    line-height: 0.86;
    letter-spacing: -0.035em;
}
h2 {
    /* scroll-margin so a jump from the contents list does not put the
       heading flush against the top edge. */
    scroll-margin-top: 2.5rem;
    font-size: 1.6rem;
    line-height: 1.15;
    letter-spacing: -0.02em;
    margin: 3.4rem 0 0.9rem;
}
p { margin: 0 0 1.4rem; }
em { font-style: italic; }
strong { font-weight: 700; }

/* ---- Links ------------------------------------------------------------- */
a {
    color: inherit;
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
    text-decoration-color: color-mix(in srgb, var(--ink) 42%, transparent);
    transition: text-decoration-color 120ms ease, opacity 120ms ease;
}
a:hover {
    color: var(--pink);
    text-decoration-color: var(--pink);
}

/* ---- Lists ------------------------------------------------------------- */
ul { list-style: none; margin: 0 0 1.4rem; padding: 0; }
/* Scoped to ul on purpose. An ordered list means the number carries
   information, and the footnotes at the foot of an essay are one, so they
   keep their numerals and must not also sprout a bar. */
ul > li { margin: 0 0 0.5rem; padding-left: 1.1rem; position: relative; }
/* A short bar rather than a bullet, in the ink at half strength. */
ul > li::before {
    content: "";
    position: absolute; left: 0; top: 0.97em;
    width: 0.55rem; height: 2px;
    background: color-mix(in srgb, var(--ink) 50%, transparent);
}

/* ---- The one piece of ornament ----------------------------------------- */
hr, .rule {
    border: 0;
    height: 1px;
    margin: 3rem 0;
    background: color-mix(in srgb, var(--ink) 28%, transparent);
}

/* ---- Back to home, on subpages ----------------------------------------
   A link rather than chrome, because the template has no conditionals and
   the home page should not link to itself. Sits above the title, at the
   measure, and at the size of the text, since a smaller cut of the same
   thing would be one more size for no reason. */
.back { max-width: var(--measure); margin: 0 auto; }
.back a::before { content: "\2190\00a0"; }

/* ---- Quotations -------------------------------------------------------- */
blockquote {
    margin: 2rem 0;
    padding-left: 1.4rem;
    border-left: 2px solid color-mix(in srgb, var(--ink) 28%, transparent);
    /* The real Book Italic, not a slanted Book: the face is declared above at
       the same weight the body runs at, so the browser has one to pick. */
    font-style: italic;
}
blockquote p:last-child { margin-bottom: 0; }

/* ---- Footnotes ---------------------------------------------------------
   The same note in two places. The list at the foot of the page is the real
   one: it is in the document, its links work, and it survives printing, a
   text browser and a reader with no pointer. The copy inside the marker is
   built by build.py and is a convenience for a mouse, nothing more, which is
   why it carries aria-hidden and why its links are flattened to their own
   text. A thing that vanishes when the pointer leaves cannot be clicked.
   ---------------------------------------------------------------------- */
/* Sized here rather than on the link inside, because the browser has already
   shrunk the sup once and a second reduction on the link compounded into
   something nobody could read. */
sup {
    position: relative;
    line-height: 0;
    font-size: 0.75em;
}
.footnote-ref {
    font-size: inherit;
    padding: 0 0.12em;
    text-decoration: none;
}
.footnote-ref:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

.footnote { margin-top: 4.5rem; }
/* A short rule, not a full one: this is a seam in the page, not a new page. */
.footnote hr { width: 5rem; margin: 0 0 1.8rem; }
/* Child selectors throughout: a note may contain a list of its own, and that
   list has to keep the bars and the spacing every other list on the site
   gets, not the hanging number and the gaps that belong to the notes.

   The list gives up its own markers, because build.py has put a number at the
   head of each note that is also the link back to the sentence that raised
   it. Two numbers on one line would be one too many. */
.footnote > ol { list-style: none; margin: 0; padding-left: 0; }
.footnote > ol > li {
    position: relative;
    margin-bottom: 1.3rem;
    padding-left: 2.3rem;
    scroll-margin-top: 3rem;
}
.fn-back {
    position: absolute;
    left: 0;
    top: 0;
    text-decoration: none;
    color: color-mix(in srgb, var(--ink) 68%, transparent);
}
.fn-back:hover { color: var(--pink); }
.footnote ul { margin: 0.5rem 0 0.8rem; }
.footnote p { margin: 0 0 0.5rem; }
.footnote p:last-child { margin-bottom: 0; }
/* Arriving from a marker: tint the note that was asked for. The box-shadow
   spreads the same tint past the text box without moving anything. */
.footnote > ol > li:target {
    background: color-mix(in srgb, var(--ink) 9%, transparent);
    box-shadow: 0 0 0 0.45rem color-mix(in srgb, var(--ink) 9%, transparent);
}
.footnote > ol > li:target::marker { color: var(--ink); }

/* The copy in the marker. Hidden outright unless the visitor has a fine
   pointer and a window wide enough to hold 20rem of note beside the measure,
   because it is centred on the marker and would otherwise hang off the edge
   of a narrow page. Everyone else taps the number and reads the note below. */
.fn-note { display: none; }
@media (hover: hover) and (pointer: fine) and (min-width: 56rem) {
    .fn-note {
        display: block;
        position: absolute;
        top: 1.15rem;
        left: 50%;
        transform: translateX(-50%);
        width: 20rem;
        padding: 0.9rem 1.1rem 0.95rem;
        /* Two colours still: the page colour, lifted off the page by a rule
           and a shadow rather than by a third tone. */
        background: var(--bg);
        border: 1px solid color-mix(in srgb, var(--ink) 34%, transparent);
        box-shadow: 0 3px 12px color-mix(in srgb, var(--slate) 20%, transparent);
        font-size: var(--small);
        line-height: 1.5;
        letter-spacing: 0;
        text-align: left;
        vertical-align: baseline;
        z-index: 10;
        opacity: 0;
        pointer-events: none;
        transition: opacity 120ms ease;
    }
    .fn-note .fn-n {
        float: left;
        margin-right: 0.4em;
        font-size: 0.75em;
        vertical-align: super;
        color: color-mix(in srgb, var(--ink) 55%, transparent);
    }
    .fn-note .fn-p { display: block; }
    .fn-note .fn-p + .fn-p { margin-top: 0.5rem; }
    sup:hover > .fn-note,
    .footnote-ref:focus-visible + .fn-note { opacity: 1; }
}

/* ---- The error page -----------------------------------------------------
   Centred in the window instead of starting at the top, where four lines of
   text read as a page that happens to be nearly empty rather than as an
   answer to a request that failed. The footer keeps its own margin, so the
   middle is the middle of what is left between the bar and the footer. */
body.error { min-height: 100vh; display: flex; flex-direction: column; }
/* A flex item with an auto margin on the cross axis does not stretch, and
   the bar, the column and the footer all centre themselves with one. Without
   this they would each shrink to their own content and line up on the middle
   of the window instead of on the measure. */
body.error > * { width: 100%; }
body.error main {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
body.error h1 { margin-top: 0; }

/* ---- Footer ------------------------------------------------------------ */
.foot {
    max-width: var(--measure);
    margin: 5rem auto 0;
    padding-top: 1.4rem;
    border-top: 1px solid color-mix(in srgb, var(--ink) 28%, transparent);
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem 1.6rem;
    font-size: var(--small);
}

/* ---- Phones ------------------------------------------------------------ */
@media (max-width: 600px) {
    body { font-size: 19px; line-height: 30px; }
    h1 { margin-top: 5vh; }
    h2 { font-size: 1.4rem; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before { transition: none !important; }
}
