/* Quiet Stanza — one page, three twins.
   What the journal, the gift pad and the photo journal share: the frame around the stage
   (drag strip, scale grip, full-screen chrome and turn controls), the dog-eared corners, the
   page itself (paper, margins, ruling drawn to the writing), the written rows in the hand,
   the karaoke words, the writing ruler, and the procedural-ink canvas that every written mark
   is drawn on. Each twin's scoped stylesheet keeps only its own furniture: a cover, a band and
   gutter, a staple and stub, a photo face.
   Geometry is CSS millimetres; the page margins come from --page-margin-* / --page-foot, which
   the journal sets from its A5 tokens and the pad from its format. */

/* ── the frame ── */
.journal-root {
    position: relative;
    width: 100%;
}
.journal-root.is-framed .journal-stage,
.journal-root.is-framing .journal-stage {
    will-change: transform;
}
/* The writer has dragged / scaled: the stage's size is the script's, not the layout's. */
.journal-root.is-framed .journal-stage {
    max-width: none;
    height: auto;
}
.journal-root.is-framing {
    z-index: 7;
    user-select: none;
}
.journal-root.is-framing .book {
    transition: none !important;
}

/* Top strip + band: grab to move. Top-right grip: pull to scale. */
.journal-drag {
    position: absolute;
    top: 0;
    left: var(--paper-l, 0px);
    right: calc(var(--paper-r, 0px) + 28px);
    height: 18px;
    z-index: 7;
    cursor: grab;
    touch-action: none;
}
/* The closed cover's bookmark sits under this strip. Clicks belong to the ribbon. */
.journal-root.is-closed .journal-drag { pointer-events: none; }
.journal-root.is-framing .journal-drag { cursor: grabbing; }
.band[data-journal-drag] {
    cursor: grab;
    touch-action: none;
    z-index: 7;
}
.journal-root.is-framing .band[data-journal-drag] { cursor: grabbing; }

.journal-scale {
    position: absolute;
    top: 0;
    right: var(--paper-r, 0px);
    width: 28px;
    height: 28px;
    z-index: 8;
    cursor: nesw-resize;
    touch-action: none;
    outline: none;
}
/* Quiet paper corner fold — readable on hover/focus, calm at rest. */
.journal-scale::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 18px;
    height: 18px;
    opacity: 0.42;
    background:
        linear-gradient(
            to bottom left,
            color-mix(in srgb, var(--ink) 22%, transparent) 0%,
            color-mix(in srgb, var(--ink) 22%, transparent) 38%,
            transparent 39%
        );
    transition: opacity .2s ease;
}
.journal-scale:hover::before,
.journal-scale:focus-visible::before,
.journal-root.is-framing .journal-scale::before {
    opacity: 0.78;
}

.journal-stage {
    position: relative;
    width: 100%;
    margin: 0 auto;
    overflow: hidden;
}

.book {
    position: absolute;
    top: 0;
    left: 0;
    width: var(--journal-book-w);
    height: var(--journal-book-h);
    transform-origin: top left;
    transition: transform .35s cubic-bezier(.36,.1,.3,1);
}

/* ── full screen: the paper, the way out, and a quiet turn at each end ── */
.journal-fs-top {
    position: absolute;
    top: 12px;
    right: 16px;
    z-index: 8;
}
.journal-fs-leave {
    background: color-mix(in srgb, var(--paper) 88%, transparent) !important;
    backdrop-filter: blur(6px);
}
.journal-fs-status {
    margin: 12px 0 0;
    text-align: center;
    font-family: var(--serif);
    font-style: italic;
    font-size: 13px;
    color: color-mix(in srgb, var(--ink) 55%, transparent);
}
/* Always drawn in full screen, where the nav has gone: a page is turned with a control, not
   a hidden corner. Faint until the hand comes near; gone at the ends. The writing session
   keeps its own bar, so the twin's controls stay away while the pen is down. */
.journal-fs-turn {
    position: absolute;
    z-index: 9;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 48px;
    min-height: 48px;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
    border-radius: 999px;
    background: color-mix(in srgb, var(--paper) 72%, transparent);
    color: var(--ink);
    font-family: var(--serif);
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    opacity: 0.45;
    backdrop-filter: blur(4px);
    transition: opacity .2s ease;
}
.journal-fs-turn:hover,
.journal-fs-turn:focus-visible,
.journal-root:hover .journal-fs-turn { opacity: 0.9; }
.journal-fs-turn:focus-visible { outline: 2px solid var(--laurel); outline-offset: 2px; }
.journal-fs-turn.is-off { visibility: hidden; }
.journal-fs-turn.is-x { top: 50%; transform: translateY(-50%); }
.journal-fs-turn.is-x.journal-fs-back { left: 6px; }
.journal-fs-turn.is-x.journal-fs-next { right: 6px; }
.journal-fs-turn.is-y { left: 50%; transform: translateX(-50%); font-size: 18px; }
.journal-fs-turn.is-y.journal-fs-next { top: 6px; }
.journal-fs-turn.is-y.journal-fs-back { bottom: 6px; }
@media (pointer: coarse) {
    .journal-fs-turn { opacity: 0.6; }
}
.journal-live .journal-fs-turn { display: none; }

/* ── a closer look, full screen ──
   The paper is the journal's to zoom (journal.js): the browser's own pinch, double-tap zoom
   and text selection stay out of it. Only here — the rest of the app zooms as usual. */
.journal-wrap.is-fullscreen:not(.journal-live) {
    touch-action: none;
}
.journal-wrap.is-fullscreen:not(.journal-live) .journal-stage {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}
.journal-wrap.is-fullscreen:not(.journal-live) .journal-stage.is-zoomed { cursor: grab; }
.journal-wrap.is-fullscreen:not(.journal-live) .journal-stage.is-zoomed:active { cursor: grabbing; }
/* In, out and fit, small in the corner below the paper; out and fit wake once zoomed. */
.journal-fs-zoom {
    position: absolute;
    right: 6px;
    bottom: 6px;
    z-index: 9;
    display: flex;
    border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
    border-radius: 999px;
    background: color-mix(in srgb, var(--paper) 72%, transparent);
    backdrop-filter: blur(4px);
    opacity: 0.45;
    transition: opacity .2s ease;
}
.journal-fs-zoom:hover,
.journal-fs-zoom:focus-within,
.journal-root:hover .journal-fs-zoom { opacity: 0.9; }
.journal-fs-zoom button {
    min-width: 40px;
    min-height: 40px;
    padding: 0 8px;
    border: 0;
    background: none;
    color: var(--ink);
    font-family: var(--serif);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}
.journal-fs-zoom [data-qs-zoom="fit"] { font-size: 13px; font-style: italic; }
.journal-fs-zoom button:focus-visible { outline: 2px solid var(--laurel); outline-offset: -2px; border-radius: 999px; }
.journal-stage:not(.is-zoomed) ~ .journal-fs-zoom :is([data-qs-zoom="out"], [data-qs-zoom="fit"]) {
    opacity: 0.35;
    cursor: default;
}
@media (pointer: coarse) {
    .journal-fs-zoom { opacity: 0.6; }
}
.journal-live .journal-fs-zoom { display: none; }

/* ── corner hot-zones with a dog-ear fold ──
   A quiet paper curl at rest; hover deepens the fold without a UI “pop”. The fit script
   sets --paper-l / --paper-r / --paper-b to where the paper's own corners are on the stage. */
.corner {
    position: absolute;
    bottom: var(--paper-b, 0px);
    width: 88px;
    height: 68px;
    cursor: pointer;
    z-index: 6;
    outline: none;
    /* The tall journey hit strip must not steal taps from the favourite heart in the margin:
       only the outer edge and the dog-ear take the pointer. */
    pointer-events: none;
}
.corner-left { left: var(--paper-l, 0px); }
.corner-right { right: var(--paper-r, 0px); }
.corner.is-off { visibility: hidden; }
/* Narrow outer edge — past the heart in the margin — plus the folded dog-ear. */
.corner:not(.is-off)::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 16px;
    pointer-events: auto;
}
.corner-right:not(.is-off)::before { right: 0; }
.corner-left:not(.is-off)::before { left: 0; }

.dogear {
    position: absolute;
    bottom: 0;
    width: 30px;
    height: 30px;
    pointer-events: auto;
}
/* Soft shade where the corner lifts off the page. */
.dogear::before {
    content: "";
    position: absolute;
    inset: 0;
    opacity: 0.28;
    transition: opacity .22s ease;
}
.corner-right .dogear::before {
    right: 0;
    background: linear-gradient(to top left, rgba(90, 70, 30, 0.18) 50%, transparent 50%);
}
.corner-left .dogear::before {
    left: 0;
    background: linear-gradient(to top right, rgba(90, 70, 30, 0.18) 50%, transparent 50%);
}
/* The folded flap — sheet-edge paper with a hairline crease. */
.dogear::after {
    content: "";
    position: absolute;
    inset: 0;
    opacity: 0.72;
    transition: opacity .22s ease;
}
.corner-right .dogear { right: 0; }
.corner-right .dogear::after {
    background:
        linear-gradient(to top left, #E6DCC4 0%, #E0D6BA 45%, #C9BD9E 46.5%, #C9BD9E 48%, transparent 49%);
}
.corner-left .dogear { left: 0; }
.corner-left .dogear::after {
    background:
        linear-gradient(to top right, #E6DCC4 0%, #E0D6BA 45%, #C9BD9E 46.5%, #C9BD9E 48%, transparent 49%);
}
.corner:hover .dogear::before,
.corner:focus-visible .dogear::before { opacity: 0.42; }
.corner:hover .dogear::after,
.corner:focus-visible .dogear::after { opacity: 1; }

/* ── a page ──
   A true leaf: cream + fiber + ruling. The journal's margins are its A5 tokens; the pad's
   leaf sets --page-margin-* from its format and has no page-number band.
   .page-face carries Face.Style (Blazor); .page keeps the ink host's snap vars so a turn's
   re-render cannot wipe --baseline-nudge and shove the writing. */
.book .page-face {
    position: absolute;
    inset: 0;
}
/* The face's paper is the page's: the paper class on .page sets the house pitch, ruling and
   margin rule on .page itself, which would outrank what .page-face hands down (a journal's
   7 mm lines drawn at 5 mm, under writing set at 7). So .page takes them from the face, and the
   house values only where the face has none. */
.page-face {
    --face-pitch: var(--paper-pitch);
    --face-ruling: var(--ruling);
    --face-margin-x: var(--paper-margin-x);
}
.page-face > .page:is(.paper-dots, .paper-lines, .paper-grid, .paper-margin, .paper-guide) {
    --paper-pitch: var(--face-pitch, 5mm);
    --ruling: var(--face-ruling, rgba(120, 105, 75, 0.28));
}
.page-face > .page.paper-guide { --paper-pitch: var(--face-pitch, 8mm); }
.page-face > .page.paper-margin { --paper-margin-x: var(--face-margin-x, 18mm); }
.book .page {
    --page-margin-x: var(--journal-margin-x);
    --page-margin-top: var(--journal-margin-top);
    --page-margin-bottom: var(--journal-margin-bottom);
    --page-foot: var(--journal-pagenum-band);
    position: absolute;
    inset: 0;
    background-color: var(--sheet);
    border: 1px solid var(--sheet-edge);
    border-radius: 1mm;
    padding:
        var(--page-margin-top)
        var(--page-margin-x)
        calc(var(--page-margin-bottom) + var(--page-foot));
    overflow: hidden;
    color: var(--journal-ink);
    /* The paper is drawn to the writing, not the writing to the paper: --baseline-nudge is
       where the first written baseline falls inside its pitch (qsInkHost measures it), and
       the ruling's origin moves so a rule, a dot row or a grid line lies under every
       baseline. Rules are drawn at the end of their tile, dots at its centre, grid lines at
       its start. Columns start on the text's own left edge. */
    background-position: 0 0, 0 calc(var(--page-margin-top) + var(--baseline-nudge, 0px) - var(--paper-pitch));
}
.book .page.paper-grid {
    background-position:
        0 0,
        var(--page-margin-x) calc(var(--page-margin-top) + var(--baseline-nudge, 0px)),
        var(--page-margin-x) calc(var(--page-margin-top) + var(--baseline-nudge, 0px));
}
.book .page.paper-dots {
    background-position:
        0 0,
        calc(var(--page-margin-x) - var(--paper-pitch) / 2) calc(var(--page-margin-top) + var(--baseline-nudge, 0px) - var(--paper-pitch) / 2);
}
.book .page.paper-margin {
    background-position: 0 0, 0 calc(var(--page-margin-top) + var(--baseline-nudge, 0px) - var(--paper-pitch)), 0 0;
}
/* Quiet paper grain — multiply so the cream sheet and dots still read. */
.book .page::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    opacity: 0.28;
    mix-blend-mode: multiply;
    background-image:
        radial-gradient(ellipse 70% 50% at 18% 12%, rgba(160, 140, 100, 0.07), transparent 62%),
        radial-gradient(ellipse 55% 40% at 88% 78%, rgba(140, 120, 85, 0.06), transparent 60%),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.45'/%3E%3C/svg%3E");
    background-size: auto, auto, 180px 180px;
}
/* A page still to be written is faint: its writing fades, never the paper, which stays solid
   over whatever lies under the book (the writing pad's leather showed through it). */
.page-pending > * { opacity: 0.55; }
/* while the reader is inking it, the page is fully present and the lines carry the fade */
.page-pending.page-reading > * { opacity: 1; }
.page-pending > .j-today-marker,
.page-pending > .j-today-slot,
.page-pending > .j-today-sticky { opacity: 1; }

/* Browse hint: where today's sitting continues and the first blank leaf at the back. */
.j-today-marker {
    position: relative;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.45em;
    width: 100%;
    /* One whole row, so the writing under it stays on the paper's rules. */
    height: var(--pitch);
    margin: 0;
    padding: 0;
    border: none;
    background: none;
    font-family: var(--hand, inherit);
    font-size: calc(var(--sz, 3.2mm) * 0.72 * var(--page-fit, 1));
    line-height: var(--pitch);
    color: color-mix(in srgb, var(--journal-ink, #2b2a24) 55%, #8a6b12);
    animation: j-today-marker-breathe 2.8s ease-in-out infinite;
}
/* The mark heading today's pencilled pick and the sticky that hangs from it: one row, where
   the pick begins, so the sticky goes with it down the page instead of sitting at a fixed
   place over whatever is written there. */
.j-today-slot {
    position: relative;
    z-index: 5;
    height: var(--pitch);
}
/* Today's pick, pencilled and not yet written: a square yellow sticky beside its first verse
   lines (the header's four rows under the mark), written in Pilot Iroshizuku Kon-peki by the
   ink host (its own small page) and stuck on at a slant. */
.j-today-sticky {
    position: absolute;
    top: calc(var(--pitch) * 5);
    right: 9%;
    z-index: 6;
    width: 6.2em;
    height: 6.2em;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-sizing: border-box;
    overflow: hidden;
    font-family: var(--hand);
    font-size: calc(var(--sz) * 1.35);
    line-height: 1.1;
    text-align: center;
    color: #1386D3;
    /* the yellow the ink host's postIt paper is, so the ink's paper is the note's own */
    background: linear-gradient(to bottom, rgba(0, 0, 0, .06), transparent 18%) #F9E271;
    box-shadow: 1px 3px 6px rgba(60, 45, 10, .28), 0 0 0 0.5px rgba(120, 100, 20, .25);
    transform: rotate(7deg);
    pointer-events: none;
}
.j-today-sticky.is-square { transform: none; }
/* Its inked page is the note's face, not a leaf of the book: none of a book page's paper. It
   fills the note, so the ink's own paper (postIt) is the note's surface, edge to edge. */
.j-today-sticky > .page.j-sticky-page {
    position: relative !important;
    inset: auto !important;
    z-index: auto !important;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    padding: 0.5em !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    background: none !important;
    overflow: visible !important;
    color: #1386D3;
}
.j-today-sticky .j-sticky-page .j-title {
    display: block;
    margin: 0;
    height: auto;
    font-size: inherit;
    line-height: 1.15;
    text-align: center;
    white-space: nowrap;
}

/* Both marks keep to whole rows: a fraction of a pitch above or below one moved every line
   written after it off the rules. */
.j-today-marker--continue,
.j-today-marker--blank { margin: 0; }
.j-today-marker-wing {
    opacity: 0.72;
    letter-spacing: -0.08em;
    color: #c9a012;
    text-shadow: 0 0 12px color-mix(in srgb, var(--pen-marker) 35%, transparent);
}
.j-today-marker-label {
    padding: 0.22em 0.65em 0.28em;
    border-radius: 999px;
    white-space: nowrap;
    background: linear-gradient(
        105deg,
        color-mix(in srgb, var(--pen-marker) 22%, transparent),
        color-mix(in srgb, var(--pen-marker) 8%, transparent) 55%,
        transparent
    );
    border: 1px dashed color-mix(in srgb, #c9a012 55%, transparent);
    box-shadow:
        0 0 0 1px color-mix(in srgb, #fff 40%, transparent) inset,
        0 1px 8px color-mix(in srgb, #8a6b12 12%, transparent);
}
/* Inside the label, the choice of piece: poem, quote or haiku, each one tap to the desk. */
.j-today-marker-label {
    display: inline-flex;
    align-items: center;
    gap: 0.15em;
}
.j-today-marker-text { margin-right: 0.35em; }
.j-today-marker-kind {
    display: inline-flex;
    align-items: center;
    gap: 0.3em;
    margin: 0;
    padding: 0.05em 0.5em;
    border: none;
    border-left: 1px dashed color-mix(in srgb, #c9a012 45%, transparent);
    background: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
}
.j-today-marker-kind .fa { font-size: 0.8em; opacity: 0.75; }
.j-today-marker-kind:hover,
.j-today-marker-kind:focus-visible {
    outline: none;
    color: color-mix(in srgb, var(--journal-ink, #2b2a24) 80%, #8a6b12);
    background: color-mix(in srgb, #f2c230 22%, transparent);
    border-radius: 999px;
}
.j-today-marker-kind:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, #f2c230 45%, transparent); }
/* The kind already pencilled in (today's pick): lit with the highlighter, and inked darker. */
.j-today-marker-kind.is-current {
    color: color-mix(in srgb, var(--journal-ink, #2b2a24) 92%, #8a6b12);
    background: color-mix(in srgb, #f2c230 48%, transparent);
    border-radius: 999px;
    font-weight: 600;
}
.j-today-marker-kind.is-current .fa { opacity: 1; }
@keyframes j-today-marker-breathe {
    0%, 100% { opacity: 0.82; }
    50% { opacity: 1; }
}
.j-today-marker:hover,
.j-today-marker:focus-within {
    opacity: 1;
    outline: none;
    animation: none;
}
.j-today-marker:focus-within .j-today-marker-label {
    border-color: color-mix(in srgb, #c9a012 85%, var(--journal-ink, #2b2a24));
    box-shadow:
        0 0 0 2px color-mix(in srgb, var(--pen-marker) 45%, transparent),
        0 1px 10px color-mix(in srgb, #8a6b12 18%, transparent);
}

/* A page two sittings share (WM-28): each entry is a .j-entry — no box of its own, so the page
   keeps one column of rows — carrying its own pen and its own canvas. Today's entry is faint
   until it is inked, as a page of its own would be; the gap above it is one blank row. */
.j-entry { display: contents; }
.j-entry-gap { height: var(--pitch); }
.j-entry.entry-pending > canvas.j-ink { opacity: 0.55; }
.j-entry.entry-pending.entry-reading > canvas.j-ink { opacity: 1; }

/* ── the ink ──
   ProceduralInk draws every written mark on the canvas; the text under it stays for layout,
   the karaoke spans and assistive tech, and goes transparent once the page has ink. The
   writing-setup sample is a .page too and shares these. */
canvas.j-ink {
    position: absolute;
    top: calc(-1 * var(--ink-bleed));
    left: calc(-1 * var(--ink-bleed));
    right: calc(-1 * var(--ink-bleed));
    bottom: calc(-1 * var(--ink-bleed));
    width: calc(100% + 2 * var(--ink-bleed));
    height: calc(100% + 2 * var(--ink-bleed));
    z-index: 1;
    pointer-events: none;
}
.page.has-ink .j-date,
.page.has-ink .j-title,
.page.has-ink .j-author,
.page.has-ink .j-line,
.page.has-ink .j-pagenum,
.page.has-ink .j-index-title,
.page.has-ink .j-index-entry {
    color: transparent;
    position: relative;
    z-index: 2;
}
/* …but the page number keeps its place at the foot: relative positioning dropped it into the
   flow straight after the last line, half-way down a short page. */
.page.has-ink .j-pagenum { position: absolute; }
/* No wax on an inked page: the pen writes the spoken word a letter at a time, and the wet
   ink drying behind it is the reading cursor. Nothing to animate under the canvas. */
.page.has-ink .j-word,
.page.has-ink .j-word.lit { color: transparent; transition: none; }

/* ── the written rows ──
   Every row — the date, the title, the author, the breath after it, each verse line — is one
   writing pitch tall, so the ruling never drifts from the writing. --page-fit shrinks the
   letters a step when the browser's own wrapping needs more rows than the page holds. */
.j-date { text-align: right; font-family: var(--hand); font-size: calc(var(--sz) * 0.78 * var(--page-fit, 1)); line-height: var(--pitch); opacity: .62; }
/* A raised ordinal ("15th"), smaller and lifted without opening up the row; the ink writes it there too. */
.j-sup { font-size: .58em; line-height: 0; vertical-align: baseline; position: relative; top: -.62em; margin-left: .03em; }
.j-title { text-align: center; font-family: var(--hand); font-size: calc(var(--sz) * 1.22 * var(--page-fit, 1)); line-height: var(--pitch); margin: 0; }
.j-author { text-align: center; font-family: var(--hand); font-size: calc(var(--sz) * 0.78 * var(--page-fit, 1)); line-height: var(--pitch); opacity: .62; margin: 0 0 var(--pitch); }
.j-line { font-family: var(--hand); font-size: calc(var(--sz) * var(--page-fit, 1)); line-height: var(--pitch); white-space: pre-wrap; overflow-wrap: anywhere; }
/* the weight the ink is drawn in, so the text under it is the same font and the same width */
.j-date, .j-title, .j-author, .j-line, .j-pagenum, .j-index-title, .j-index-entry { font-weight: var(--ink-weight, 400); }

/* ── the reading cursor ──
   While the reader speaks, today's page inks as it goes: what has been said is written,
   what is coming waits faintly, and the word being spoken is lit. */
.j-line-inked { opacity: 1; }
.j-line-ahead { opacity: .3; }
.j-line-reading { opacity: 1; }
/* Spoken words keep wax briefly, then decay into ink; .lit snaps on quickly. */
.j-word {
    color: var(--ink);
    transition: opacity .28s ease, color 1.1s ease;
}
.j-word-inked { opacity: 1; }
.j-word-ahead { opacity: .3; }
.j-word.lit {
    color: var(--wax);
    transition: opacity .28s ease, color .1s ease;
}

/* Transparent plastic writing ruler — desktop MakeWritingRuler. The strip stays fully present;
   only the handwritten line inside may be pencil-faint (j-line-ahead). */
.j-ruler {
    position: relative;
    z-index: 2;
    background: color-mix(in srgb, var(--rule-line) 33%, transparent);
    /* edges drawn inside the strip, not as borders: the ruler must not add height, or every
       line below it would shift as it moves */
    box-shadow:
        inset 0 1px 0 color-mix(in srgb, var(--rule-line) 69%, transparent),
        inset 0 -1.5px 0 color-mix(in srgb, var(--rule-line) 69%, transparent);
    margin: 0 -6px;
    padding: 0 6px;
}
.j-ruler .j-line-ahead { opacity: .55; }
/* The author's breath row stays outside the strip. */
.j-ruler .j-author { margin-bottom: 0; }
.j-ruler:has(.j-author) { margin-bottom: var(--pitch); }

/* the page number, written at the foot */
.j-pagenum {
    position: absolute;
    z-index: 2;
    bottom: var(--page-margin-bottom);
    left: 0; right: 0;
    height: var(--page-foot);
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    font-family: var(--hand);
    font-size: calc(var(--sz) * 0.7);
    opacity: .5;
}

/* the index, written too: one entry a writing pitch (same as verse rows), so each baseline
   sits on a rule, a dot row or a grid line. A long entry carries on under itself (a hanging
   indent) rather than run off the right edge — each wrapped row still one pitch. */
.j-index-title {
    text-align: center;
    font-family: var(--hand);
    font-size: calc(var(--sz) * 1.25 * var(--page-fit, 1));
    line-height: var(--pitch);
    margin: 0 0 var(--pitch);
}
.j-index-entry {
    display: block;
    font-family: var(--hand);
    font-size: calc(var(--sz) * 0.9 * var(--page-fit, 1));
    line-height: var(--pitch);
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    padding-left: 1.2em;
    text-indent: -1.2em;
    overflow-wrap: anywhere;
    margin: 0;
}
.j-index-entry:hover,
.j-index-entry:focus-visible {
    text-decoration: underline;
    text-decoration-color: var(--wax);
    text-underline-offset: 0.18em;
    outline: none;
}
.j-index-entry.pending { opacity: .5; }

/* ── the writing session ──
   While a session runs the twin fills its page slot: the stage takes the slot's shape
   rather than the book's, and the page's own controls wait until the pen is up; turning is
   the pen's business here. Written as .ws.ws-running .ws-twin.journal-wrap so it
   carries the weight it had in WritingFocus's scoped sheet: it still outranks the
   full-screen sizes (book.css, desk.css) and the twins' own scoped stage rules. */
.ws.ws-running .ws-twin.journal-wrap .journal-root { height: 100%; display: flex; flex-direction: column; min-height: 0; }
.ws.ws-running .ws-twin.journal-wrap .journal-stage,
.ws.ws-running .ws-twin.journal-wrap .journal-root[data-fit="page"] .journal-stage {
    flex: 1 1 auto;
    max-width: none;
    width: 100%;
    height: auto;
    min-height: 0;
    aspect-ratio: auto;
    margin: 0;
    overflow: hidden;
}
.ws.ws-running .ws-twin.journal-wrap .journal-nav,
.ws.ws-running .ws-twin.journal-wrap .cj-toolbar { display: none; }

@media (prefers-reduced-motion: reduce) {
    .book { transition: none; }
    .journal-scale::before,
    .journal-fs-turn,
    .journal-fs-zoom,
    .dogear::before,
    .dogear::after { transition: none; }
    .j-today-marker { animation: none; }
}

/* A small yellow triangle whose apex is where the pen first touches the paper for the line in
   hand — the left of its first letter, on its first row's baseline (--pen-x/--pen-y, set by
   qs-ink-host). The ruler is there only while the pen is down, so it shows wherever the writer
   writes: the journal or the pad, one page or two, full screen or not, the cue or Paper view.
   It is drawn in the page's own layout px, so it scales and zooms with the paper; until the
   host has measured the line (data-pen) it isn't drawn at all. */
.j-ruler[data-pen]::after {
    content: "";
    position: absolute;
    left: calc(var(--pen-x, 0px) - 7px);
    top: var(--pen-y, 100%);
    width: 0; height: 0;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-bottom: 12px solid var(--pen-marker);
    filter: drop-shadow(0 1px 1px rgba(43, 42, 36, .35));
    pointer-events: none;
    z-index: 3;
}

/* ── an index card's face (CardPack, the card setup preview) ──
   The title is written on the title rule with the date at the end of the same row, and the
   byline on the row under it: no breath between header and verse. The title rule is printed
   in the marking colour's title ink, under the first row's baseline (--row-baseline, which
   qsInkHost measures; a blank card takes the usual place for it). Above it the card is clear. */
.page.card-face {
    /* The markings sit a touch under the measured baseline, so the writing rests on its rule
       as a hand does, rather than the rule running through the foot of each letter. */
    --card-sit: calc(var(--pitch) * 0.07);
    --row-baseline-at: calc(var(--row-baseline, calc(var(--pitch) * 0.72)) + var(--card-sit));
    isolation: isolate;
}
/* On a card the markings are measured from the title line — the first row's baseline, where
   the title rule is printed — and step down from it a pitch at a time: a rule ends each tile,
   a dot sits in the middle of its tile. Above the title line the card is clear (.card-title-band). */
.book .page.card-face {
    background-position: 0 0, 0 calc(var(--page-margin-top) + var(--row-baseline-at) - var(--paper-pitch));
}
.book .page.card-face.paper-dots {
    background-position:
        0 0,
        calc(var(--page-margin-x) - var(--paper-pitch) / 2) calc(var(--page-margin-top) + var(--row-baseline-at) - var(--paper-pitch) / 2);
}
/* on a card the margins are the card's own, and there is no page-number band */
.book .page.card-face {
    --page-margin-x: var(--card-margin-x);
    --page-margin-top: var(--card-margin-top);
    --page-margin-bottom: var(--card-margin-bottom);
    --page-foot: 0mm;
    border: none;
    border-radius: var(--card-radius);
}
.page.card-face > .j-date,
.page.card-face > .j-ruler:has(> .j-date) {
    position: absolute;
    top: var(--page-margin-top);
    right: var(--page-margin-x);
    margin: 0;
    z-index: 2;
}
.page.card-face > .j-ruler > .j-date { position: static; }
/* the title at the hand's own size, so its baseline lies on the title line exactly as each
   verse row's lies on its rule */
.card-face .j-title {
    text-align: left;
    font-size: calc(var(--sz) * var(--page-fit, 1));
    padding-right: calc(var(--sz) * 6);
}
.card-face .j-author {
    text-align: left;
    margin: 0;
}
.card-face .j-ruler:has(.j-author) { margin-bottom: 0; }
/* Under rules 4 the byline is written at the right, under the date, and an empty row is
   left before the verse (SittingLayout.CardBreath). */
.card-face .j-author-breath { text-align: right; margin-bottom: var(--pitch); }
.card-face .j-ruler > .j-author-breath { margin-bottom: 0; }
.card-face .j-ruler:has(> .j-author-breath) { margin-bottom: var(--pitch); }
.card-face .card-title-band {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: calc(var(--page-margin-top) + var(--row-baseline-at) - 1.5px);
    background: var(--sheet);
    border-radius: inherit;
    z-index: -1;
}
.card-face .card-head-rule {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(var(--page-margin-top) + var(--row-baseline-at) - 1px);
    height: 1.5px;
    background: var(--card-head-rule, var(--ruling));
    z-index: -1;
}
/* The blank card on top of a pack, seen on the Journals pad: write on it. */
.card-face .card-write-here {
    position: absolute;
    left: 50%;
    bottom: 3mm;
    transform: translateX(-50%);
    z-index: 4;
    width: auto;
    margin: 0;
    opacity: 1;
}
