/* Valkyrie Typeface OT A */
@font-face {
    font-family: "Valkyrie OT A";
    src: url("../assets/fonts/valkyrie_ot_a_regular.woff2");
    font-weight: 400;
    font-style: normal;
    font-display: block;
}

@font-face {
    font-family: "Valkyrie OT A";
    src: url("../assets/fonts/valkyrie_ot_a_italic.woff2");
    font-weight: 400;
    font-style: italic;
    font-display: block;
}

/* Foundations */

:root {
    /* Body type grows earlier than the heading/spacing interval (64–104rem).
       Around a 1512px laptop: body ~22px, running titles ~19px, 33em measure.
       Labels never size the body. Beyond 96rem the outer frame stops widening.
       rem limits preserve reader enlargement; typography does not animate on resize. */
    --reading-growth: clamp(0rem, calc(2.5vw - 1.6rem), 1rem);
    --reading-font-size: clamp(1.125rem, calc(1rem + 0.42vw), 1.5rem);
    --reading-line-height: 1.5;
    --reading-heading-size: calc(1rem + var(--reading-growth) * 0.25);
    --reading-rule-weight: round(nearest, calc(var(--reading-heading-size) * 0.075), 1px);
    --reading-page-gutter: 1.5rem;
    --reading-outer-width: 96rem;
    --reading-outer-inset: max(0px, calc((100% - var(--reading-outer-width)) / 2));
    --reading-header-gap: var(--reading-page-gutter);
    --reading-header-padding: var(--reading-page-gutter);
    --reading-measure: 33;
    --reading-width: calc(var(--reading-font-size) * var(--reading-measure));
    /* “Design is…” occupies 6.05em in Valkyrie's small caps. Match the reading
       measure through font size, without stretching glyphs or a resize script.
       Remeasure this advance if the cover wording or typeface changes. */
    --title-font-size: calc(min(var(--reading-width), calc(100vw - var(--reading-page-gutter) * 2)) / 6.05);
    /* Valkyrie's capital height is 663/1000 em. Header padding measures from
       the visible capitals; the line-box excess is removed on each edge below.
       JS records the actual height when a long title wraps. */
    --reading-header-min-height: calc(var(--reading-heading-size) * 0.663 + var(--reading-header-padding) * 2);
    --reading-header-height: var(--reading-header-min-height);
    --reading-gap: var(--reading-growth);
    --reading-anchor-offset: calc(var(--reading-header-height) + var(--reading-gap));
    --reading-snap-inset: 3rem;
    /* Colours */
    --paper-color: #d8cfb8;
    --ink-color: #141414;
    --muted-opacity: 64%;
    --fade-duration: 120ms;
    --fade-in-duration: 180ms;
    --fade-easing: ease;
    --title-fade-duration: 650ms;
    --title-fade-easing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --header-handoff-easing: cubic-bezier(0.645, 0.045, 0.355, 1);
    --contents-open-duration: 320ms;
    --contents-open-easing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --motion-easing: cubic-bezier(0.22, 1, 0.36, 1);
    /* Selection moves sideways first, then gathers into the shared rise. */
    --contents-fold-easing: cubic-bezier(0.645, 0.045, 0.355, 1);
}

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

html {
    background: var(--ink-color);
}

html:has(.keys-page) {
    background: var(--paper-color);
}

/* Hide native scrollbars, keep scroll and keyboard input */
* {
    scrollbar-width: none;
    -webkit-tap-highlight-color: transparent;
}

*::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
}

html:has(.writing-page) {
    background: var(--ink-color);
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
}

.writing-page {
    background: var(--ink-color);
    color: var(--paper-color);
}

.writing-page main {
    background: var(--ink-color)
}

html.is-positioning-reading:has(.writing-page) {
    scroll-snap-type: none;
    scroll-behavior: auto;
    overflow-anchor: none;
}

/* Preserve layout for poisitioning, reveal chapter and header together */
html.is-opening-reading body {
    visibility: hidden;
}

/* A failed enhancement returns to the document's normal reading flow. */
html.reading-fallback {
    scroll-snap-type: none;
    scroll-behavior: auto;
}

.reading-fallback .title-fade-in {
    animation: none;
}

html.is-opening-reading[data-opening-theme="paper"] {
    background: var(--paper-color);
}

@media (prefers-reduced-motion: reduce) {
    html:has(.writing-page) {
        scroll-snap-type: none;
        scroll-behavior: auto;
    }
}

body {
    font-family: "Valkyrie OT A", Georgia, serif;
    font-kerning: normal;
    margin: 0;
    color: var(--ink-color);
}

/* Highlight colour */
::selection {
    background-color: color-mix(in srgb, var(--ink-color) 25%, transparent);
}

:is(.title-section, .inverted, .reading-header-inverted, .reading-contents.is-inverted)::selection,
:is(.title-section, .inverted, .reading-header-inverted, .reading-contents.is-inverted) *::selection {
    background-color: color-mix(in srgb, var(--paper-color) 25%, transparent);
}

/* Typography */

.title-fade-in {
    animation: title-fade-in var(--title-fade-duration) var(--title-fade-easing) both;
}

/* Start the entrance once fonts and the restored reading position are ready. */
:is(.is-opening-reading, .is-positioning-reading) .title-fade-in {
    animation-play-state: paused;
}

@keyframes title-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .title-fade-in {
        animation: none;
    }
}

.title {
    font-size: var(--title-font-size);
    font-weight: 400;
    font-style: normal;
    line-height: 1.1;
    text-align: center;
    font-variant-caps: small-caps;
    /* Use real small caps when available; otherwise retain the written case. */
    font-synthesis: none;
}

.text {
    font-size: var(--reading-font-size);
    font-weight: 400;
    font-style: normal;
    line-height: var(--reading-line-height);
    text-wrap: pretty;
}

.text-small-caps {
    font-variant-caps: small-caps;
    font-synthesis: none;
}

.text-muted,
.text a {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

.text a {
    /* Removing underline */
    text-decoration: none;
}

.text a:is(:hover, :focus, :active) {
    color: inherit;
    outline: none;
}

:is(.title-section, .inverted, .reading-header-inverted, .reading-contents.is-inverted) {
    --muted-opacity: 57%;
}

/* Creating title splash */

.title-section {
    position: relative;
    min-height: 100dvh;
    display: grid;
    place-items: center;
}

.title-section .title {
    margin: 0;
    white-space: nowrap;
    transform:translateY(-0.2em);
}

.writing-page .title-section {
    padding: 1.5rem var(--reading-page-gutter);
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

.cover-contents {
    position: absolute;
    /* Half the header's unequal line-box trims: (0.4415 - 0.3955) / 2.
       Match its optical centre while retaining the 44px interaction target. */
    top: calc((var(--reading-header-min-height) - 2.75rem) / 2 - var(--reading-heading-size) * 0.023);
    right: calc(var(--reading-outer-inset) + var(--reading-page-gutter));
    display: none;
    align-items: center;
    justify-content: flex-end;
    width: 2.75rem;
    min-width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--paper-color);
    font-family: inherit;
    font-size: var(--reading-heading-size);
    cursor: pointer;
    /* Stay a hover target while Contents temporarily disables the book below. */
    pointer-events: auto;
}

.has-reading-header .cover-contents:not([hidden]) {
    display: flex;
}

.cover-contents[hidden] {
    display: none;
}

/* The mark uses the same filled CSS rectangles as the reading rule.
   Its upper bar shares the header's centreline; all lengths stay in CSS. */
.cover-contents > span {
    width: 100%;
    text-align: right;
}

.cover-symbol {
    position: relative;
    width: 100%;
    height: 1.5em;
}

.cover-mark {
    --cover-line-length: 1.5em;
    --cover-short-line-length: 0.9em;
    --cover-line-gap: 0.5em;
    display: block;
    position: absolute;
    top: 0;
    right: 0;
    width: var(--cover-line-length);
    height: 1.5em;
}

.cover-mark > span {
    display: block;
    position: absolute;
    top: calc(50% - var(--reading-rule-weight) / 2);
    right: 0;
    width: 100%;
    height: var(--reading-rule-weight);
    background: currentColor;
}

.cover-mark > span:last-child {
    width: var(--cover-short-line-length);
    /* Keep both bars on the same pixel phase as the heading size changes. */
    margin-top: round(nearest, var(--cover-line-gap), 1px);
}

.cover-contents:is(:hover, :focus-visible) {
    color: color-mix(in srgb, var(--paper-color) var(--muted-opacity), transparent);
    outline: none;
}

/* Running title above centered reading column */

.reading-header {
    position: fixed;
    z-index: 10;
    inset: 0 0 auto;
    min-height: var(--reading-header-min-height);
    /* At line-height 1.5, Valkyrie's ascent/descent (978/269 per 1000 em)
       leave 0.4415em above capitals and 0.3955em below the baseline.
       Remove each separately so the visible top and bottom margins match. */
    padding-block: calc(var(--reading-header-padding) - var(--reading-heading-size) * 0.4415)
        calc(var(--reading-header-padding) - var(--reading-heading-size) * 0.3955);
    padding-inline: calc(var(--reading-outer-inset) + var(--reading-page-gutter));
    display: flex;
    align-items: center;
    gap: var(--reading-header-gap);
    color: var(--ink-color);
    background: var(--paper-color);
    pointer-events: none;
}

.reading-header[hidden] {
    display: none;
}

.reading-header-inverted {
    color: var(--paper-color);
    background: var(--ink-color);
    clip-path: inset(50%);
}

.reading-header.is-dark-underlay {
    background: var(--ink-color);
}

.reading-rule {
    flex: 1 1 0;
    min-width: 0;
    height: var(--reading-rule-weight);
    background: currentColor;
}

.reading-heading {
    flex: 0 0 auto;
    margin: 0;
    white-space: nowrap;
    font-size: var(--reading-heading-size);
    font-weight: 400;
    line-height: 1.5;
    font-variant-caps: small-caps;
    font-synthesis: none;
}

.reading-heading p {
    margin: 0;
}

.reading-home,
.reading-top {
    color: inherit;
    text-decoration: none;
    pointer-events: auto;
}

.reading-home:is(:hover, :active),
.reading-top:is(:hover, :active),
.reading-header:has(.reading-home:is(:hover, :active)) + .reading-header-inverted .reading-home,
.reading-header:has(+ .reading-header-inverted .reading-home:is(:hover, :active)) .reading-home {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

.reading-home:focus,
.reading-top:focus,
.section-title:focus,
.reading-contents > a:focus {
    outline: none;
}

.reading-home:focus-visible,
.reading-top:focus-visible,
.reading-header:has(.reading-home:focus-visible) + .reading-header-inverted .reading-home {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

.section-title {
    text-align: right;
    font-family:inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    appearance: none;
}

.section-title:not(:disabled) {
    pointer-events: auto;
}

button.section-title:not(:disabled) {
    cursor: pointer;
}

button.section-title:hover,
button.section-title[aria-expanded="true"],
button.section-title:active,
button.section-title:focus-visible,
.reading-header:has(.section-title:focus-visible) + .reading-header-inverted .section-title {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

.section-title > span {
    display: block;
}

/* Keep the home link visible; long titles wrap before type becomes too small. */
.reading-header .section-title {
    flex-shrink: 1;
    min-width: 0;
    margin-left: auto;
    white-space: normal;
    text-wrap: balance;
    overflow-wrap: anywhere;
}

.reading-label-measure {
    position: fixed;
    top: 0;
    left: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Without JS, use a conservative compact layout. With enhancement, the rule
   yields according to the longest title's measured fit, consistently per page. */
@media (max-width: 36rem) {
    html:not(.has-reading-layout) .reading-header > .reading-rule {
        display: none;
    }
}

.has-reading-layout.is-compact-header .reading-header > .reading-rule {
    display: none;
}

/* Contents */

.has-reading-header .reading-frame {
    position: fixed;
    inset: 0;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior: contain;
    background: var(--ink-color);
}

.has-reading-header .reading-surface {
    position: relative;
    min-height: 100dvh;
}

/* Pin within the horizontal surface, not the viewport. The book's inner
   vertical scroller can bounce independently; sideways frame motion is shared. */
.has-reading-header .writing-page .reading-surface {
    contain: layout;
}

.writing-page .reading-frame[data-view="reading"] {
    background-image: linear-gradient(to bottom,
        var(--ink-color) 0 var(--paper-start, 100dvh),
        var(--paper-color) var(--paper-start, 100dvh) var(--paper-end, 100dvh),
        var(--ink-color) var(--paper-end, 100dvh));
}

.has-reading-header .reading-frame main {
    position: absolute;
    height: 100dvh;
    inset: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: auto contain;
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
    outline: none;
}

:is(.is-positioning-reading, .is-restoring-scroll) .reading-frame main {
    scroll-snap-type: none;
    scroll-behavior: auto;
    overflow-anchor: none;
}

.keys-page .reading-frame,
.reading-frame:not([data-view="reading"]):not(.is-inverted) {
    background: var(--paper-color);
}

.keys-page .reading-frame main {
    scroll-snap-type: none;
    background: var(--paper-color);
}

.reading-frame:not([data-view="reading"]) {
    overflow: auto;
    overscroll-behavior: contain;
}

.reading-frame:not([data-view="reading"]) main {
    overflow: hidden;
    pointer-events: none;
}

/* Hover Contents leaves the book visible. Keep it user-scrollable so native
   Find can reveal a match even when its browser UI never sends us a shortcut.
   Once any close begins, release the book while the list finishes its fold. */
.reading-frame:not([data-view="reading"])[data-contents-activation="hover"] main,
.reading-frame[data-view="closing"] main {
    overflow-y: auto;
}

.reading-frame[data-view="closing"] main {
    pointer-events: auto;
}

.reading-frame .reading-header {
    position: absolute;
    top: 0;
}

/* The book header travels with the cover, then sticks. Its zero-height anchor
   overlays the chapter's existing top inset without adding another header gap.
   Both colour layers share this anchor, including while Contents owns the title. */
.reading-header-anchor {
    display: none;
}

.has-reading-header .reading-text:focus {
    outline: none;
}

.has-reading-header .reading-header-anchor {
    display: block;
    position: sticky;
    top: 0;
    height: 0;
    z-index: 10;
}

/* After the cover is safely behind the reader, detach the same anchor from
   the inner vertical scroller. Its sticky and fixed positions coincide here. */
.has-reading-header.has-pinned-reading-header .reading-header-anchor {
    position: fixed;
    inset-inline: 0;
}

/* At tight widths, the document's own headings replace the running header.
   The cover retains its Contents control; chapter headings are plain text. */
.is-inline-headings .reading-header-anchor {
    /* Retain its measurements for the fit decision; hidden controls cannot
       receive focus, and the zero-height anchor reserves no document space. */
    visibility: hidden;
}

.is-inline-headings .cover-contents {
    max-width: calc(100% - var(--reading-page-gutter) * 2);
}

.is-inline-headings .cover-contents > .reading-heading {
    white-space: normal;
    text-wrap: balance;
    overflow-wrap: anywhere;
}

.is-inline-headings {
    --reading-anchor-offset: var(--reading-page-gutter);
}

.is-inline-headings .text-small-caps {
    overflow-wrap: anywhere;
}

.reading-frame:has(.reading-contents:not([hidden])) .section-title {
    visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .has-reading-header .reading-frame main {
        scroll-snap-type: none;
        scroll-behavior: auto;
    }
}

.reading-contents {
    position: relative;
    z-index: 20;
    inset: auto;
    margin-left: auto;
    margin-right: var(--reading-outer-inset);
    width: calc(var(--contents-width) + var(--contents-inset) * 2);
    max-width: 100%;
    min-height: 100dvh;
    padding: var(--contents-top-padding) var(--contents-inset);
    background: transparent;
    color: var(--ink-color);
    text-align: left;
    font-size: var(--reading-heading-size);
    font-variant-caps: small-caps;
    font-synthesis: none;
}

.reading-contents[hidden] {
    display: none;
}

/* A departing list must not capture a new gesture or interrupt its own fold. */
.reading-frame[data-view="closing"] .reading-contents {
    pointer-events: none;
}

.reading-contents.is-inverted {
    color: var(--paper-color);
}

.reading-contents > a {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    min-height: round(nearest, max(2em, 36px), 1px);
    line-height: 1.5;
    color: inherit;
    text-decoration: none;
    white-space: normal;
    overflow-wrap: anywhere;
}

.reading-contents.is-touch > a {
    min-height: round(nearest, max(2em, 44px), 1px);
}

.reading-contents > a[aria-current] {
    justify-content: flex-end;
}

.reading-contents > a > span {
    display: block;
}

.reading-contents.is-heading-handoff > a[aria-current] > span {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

.reading-contents > a:focus-visible > span,
.reading-contents > a.is-closing-highlight > span {
    color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
}

@media (hover: hover) and (pointer: fine) {
    .reading-contents > a:hover > span {
        color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
    }
}

/* During a moving-list handoff, measured pointer ownership supersedes stale
   native :hover. Keyboard focus and the departing highlight remain independent. */
@media (hover: hover) and (pointer: fine) {
    .reading-contents.is-pointer-tracked > a:not(.is-pointer-hover):not(:focus-visible):not(.is-closing-highlight) > span {
        color: inherit;
    }

    .reading-contents.is-pointer-tracked > a.is-pointer-hover > span {
        color: color-mix(in srgb, currentColor var(--muted-opacity), transparent);
    }
}

/* Chapter layout */

.body-section {
    display: grid;
    width: min(var(--reading-width), calc(100% - var(--reading-page-gutter) * 2));
    margin-inline: auto;
    padding-block: var(--reading-anchor-offset);
}

.keys,
.gratitudes {
    gap: var(--reading-font-size);
}

.chapter {
    display: grid;
    gap: 1rem;
    align-items: start;
}

.keys > .chapter,
.gratitudes > .chapter {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
}

.chapter > .text {
    margin: 0;
}

.chapter-copy {
    min-width: 0;
}

.chapter-copy p {
    margin: 0;
}

.chapter-copy p + p {
    /* Epigraphs share body size and one paragraph's separation. Keep the
       quotation's own voice; no extra display size or forced line endings. */
    margin-top: 1em;
}

/* Credits start on new lines but read continuously, including in print. */
.gratitude-entries p + p {
    margin-top: 0;
}

/* Visually hidden, available for assistive technology */
.visually-hidden,
.has-reading-header .content .chapter > h2 {
    color: var(--paper-color);
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.inverted .visually-hidden {
    color: var(--ink-color)
}

.is-inline-headings .writing-page [data-section-title] > h2 {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    color: inherit;
    font-size: var(--reading-heading-size);
    font-weight: 400;
    line-height: 1.5;
    font-variant-caps: small-caps;
    font-synthesis: none;
    text-align: right;
}

.is-inline-headings .writing-section {
    align-content: center;
    gap: 1rem;
}

.is-inline-headings .writing-page .writing-section > h2 {
    width: 100%;
    max-width: var(--reading-width);
}

.writing-page .content {
    gap: 0;
    padding-block: 0;
    width: 100%;
    padding-inline: max(var(--reading-page-gutter), calc((100% - var(--reading-width)) / 2));
    background: var(--paper-color);
    color: var(--ink-color);
}

.writing-page .content > .chapter,
.writing-page .writing-section,
.writing-page .gratitudes {
    position: relative;
    min-height: calc(100dvh + var(--reading-snap-inset) * 2);
    padding-block: calc(var(--reading-anchor-offset) + var(--reading-snap-inset));
    scroll-margin-top: calc(-1 * var(--reading-snap-inset));
}

/* Longer writing stops at both edges */
.writing-page [data-section-title]::before,
.writing-page [data-section-title]::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    pointer-events: none;
}

.writing-page [data-section-title]::before {
    inset-block: var(--reading-snap-inset);
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

.writing-page [data-section-title]::after {
    bottom: var(--reading-snap-inset);
    height: 1px;
    scroll-snap-align: end;
    scroll-snap-stop: always;
}

/* End the final reading area and its end snap at the same page edge. Keep
   short sections on their single centered stop and preserve visible padding. */
.writing-page .reading-text > [data-section-title]:last-child:not(.fits-viewport)::before {
    bottom: 0;
}

.writing-page .reading-text > [data-section-title]:last-child::after {
    bottom: 0;
    height: 0;
}

/* If fits, only one spot */
.writing-page [data-section-title].fits-viewport::before {
    top: 50%;
    bottom: auto;
    height: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
}

.writing-page [data-section-title].fits-viewport::after {
    content: none;
}

.writing-page .content > .chapter,
.writing-page .gratitudes {
    align-content: center;
}

.gratitudes .chapter {
    scroll-margin-top: var(--reading-anchor-offset);
}

.writing-page .gratitudes.inverted {
    width: 100%;
    padding-inline: max(var(--reading-page-gutter), calc((100% - var(--reading-width)) / 2));
}

#care .chapter-copy {
    text-align: center;
}

/* Boundaries of design Q&A */

/* Preserve the introductory pause as spacing, on screen and in the print copy. */
.chapter-copy .boundaries-intro + p {
    margin-top: 1lh;
}

#boundaries .question,
#boundaries .answer {
    display: block;
}

#boundaries .question {
    text-align: left;
}

#boundaries .answer {
    text-align: right;
}

/* Zero-width inline boxes hang the actual glyph outside the line measure.
   Keep quotes in the text flow for copying; font and print sizes need no offset. */
.hanging-open,
.hanging-close {
    display: inline-flex;
    width: 0;
    white-space: nowrap;
}

.hanging-open {
    justify-content: flex-end;
}

#boundaries .door {
    text-align: center;
}

/* Additional writing section */

.writing-section {
    min-height: 100dvh;
    display: grid;
    place-items: center;
    padding: 2rem;
    text-align: center;
}

.writing-section > .text {
    max-width: var(--reading-width);
}

.writing-section p {
    margin: 0;
    text-wrap: balance
}

.writing-section p + p {
    margin-top: 1em;
}
