/* The diary's design system. International Typographic Style: one family (ABC Areal), two weights, a 1.5 scale,
   a 12-column grid on desktop and 4 on a phone, everything flush left, ragged right. One paper per mode (Milk light,
   Ink dark) and one accent, picked by the reader from three (periwinkle, sage, rose), each with a dark-mode pair.
   The colours themselves live in src/shared/palette.ts; the page's <head> sets them before the first paint. */

/* ABC Areal, variable: weight 400-700, slant, and a dark-mode axis (DRKM), used in dark mode. */
@font-face { font-family: "Areal"; src: url("/assets/ABCArealVariable.woff2") format("woff2"); font-weight: 400 700; font-display: block; }

/* The accent. Changing it blends over 0.9s: app.ts sets each in-between colour itself, frame by frame, so everything
   mixed from it recomputes from the same value. (A CSS transition on a registered --mark left some links painted
   black mid-blend in Chromium.) */
@property --mark { syntax: "<color>"; inherits: true; initial-value: #6F86D9; }

:root {
  --paper: #FBFAF7; --ink: #252422; --mute: #6A6762; --line: #E7E5E0;
  /* The soft tint (40% accent on paper) is mixed right where it's used, not through a shared variable: text coloured
     through one went black mid-blend when the accent changed, then snapped. */
  --t1: 14px; --t2: 18px; --t3: 27px; --t4: 40px; --t5: 60px; --t6: 90px; --t7: 135px; --m: 48px; --gut: 24px; --cols: 12;
  /* The right gutter, where the accent dots, the pencil and the scroll rail sit, centred. On a desktop it's the page
     margin; on a phone the 20px margin is too tight for them, so the right side gets a wider gutter of its own. */
  --gr: var(--m);
}
@media (max-width: 700px) { :root { --t2: 17px; --t3: 22px; --t4: 30px; --t5: 40px; --t6: 46px; --t7: 72px; --m: 20px; --gut: 16px; --cols: 4; --gr: 44px; } }

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--paper); color: var(--ink); font-family: "Areal", "ABC Areal", Arial, "Helvetica Neue", Helvetica, sans-serif;
       font-size: var(--t2); line-height: 1.5; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%;
       scrollbar-width: none; color-scheme: light; }
html::-webkit-scrollbar { display: none; }
/* Dark mode: Areal's dark-mode axis, which tunes the letters for light text on a dark ground. */
html[data-theme="dark"] { color-scheme: dark; font-variation-settings: "DRKM" 1; }
/* Proportional figures on purpose: Areal's tabular "1" has a slab foot, and every date is left-aligned in its own cell. */
body { min-height: 100vh; }
a { color: inherit; text-decoration: none; transition: color .3s ease; -webkit-tap-highlight-color: transparent; }
ol, ul { list-style: none; }
h1, h2 { font-size: inherit; font-weight: inherit; }
input { font: inherit; color: inherit; background: transparent; border: 0; border-radius: 0; outline: 0; width: 100%; caret-color: var(--mark); }
:focus-visible { outline: 2px solid var(--mark); outline-offset: 4px; }
input:focus-visible, [contenteditable]:focus-visible { outline: 0; }
::selection { background: var(--line); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.g { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); column-gap: var(--gut); }
.page { padding: var(--m) var(--gr) calc(var(--m) * 3) var(--m); }
.err { min-height: 1.5em; margin-top: 12px; font-size: var(--t1); letter-spacing: 0; font-weight: 400; }
@keyframes shake { 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }
@keyframes blink { 50% { opacity: 0; } }
/* Words sized to their column (fit() in app.ts) stay hidden until they are, so they never flash at the wrong size. */
[data-fit]:not([data-fitted]), [data-cap]:not([data-fitted]) { visibility: hidden; }

/* An entry's text */
.prose { max-width: 34em; overflow-wrap: break-word; }
.prose > * + * { margin-top: 1em; }
.prose h2 { font-size: var(--t3); line-height: 1.2; font-weight: 700; letter-spacing: -.01em; margin-top: 1.4em; }
.prose h3 { font-weight: 700; margin-top: 1.4em; }
.prose strong { font-weight: 700; }
.prose a { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--mark) 40%, var(--paper)); text-underline-offset: .15em; text-decoration-thickness: 1px; }
.prose a:hover { color: var(--mark); }
.prose blockquote { font-size: var(--t3); line-height: 1.3; margin: 1.4em 0; }
.prose ul li, .prose ol li { position: relative; padding-left: 1.1em; }
.prose ul li + li, .prose ol li + li { margin-top: .2em; }
.prose ul li::before { content: "–"; position: absolute; left: 0; }
.prose ol { counter-reset: n; }
.prose ol li { counter-increment: n; }
.prose ol li::before { content: counter(n) "."; position: absolute; left: 0; }
.prose li > p + p { margin-top: .5em; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 2em 0; }
.prose img { display: block; max-width: 100%; height: auto; }
.prose figure { margin: 2em 0; }
.prose figcaption { margin-top: 8px; font-size: var(--t1); color: var(--mute); }
.prose del { text-decoration-color: var(--mute); }

/* ---------- Lock: one blinking cursor, centered vertically, on the left margin. A tap anywhere (or Enter) asks
   for the passkey; while the device asks you, the cursor holds still. ---------- */
.b-lock { min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; padding: 0 var(--m); cursor: pointer;
  -webkit-tap-highlight-color: transparent; }
.b-form { position: relative; width: 100%; }
.b-form .err { position: absolute; left: 0; top: 100%; max-width: 40em; }
.b-form .err.hint { color: var(--mute); }
.b-field { display: block; position: relative; width: 100%; height: 1em; padding: 0; border: 0; background: none; color: inherit;
  font: inherit; font-size: var(--t7); font-weight: 700; line-height: 1; cursor: inherit; }
.b-field:focus-visible { outline: 0; }
.b-field::before {
  content: ""; position: absolute; left: 0; top: .08em; width: .045em; height: .84em; background: var(--mark); animation: blink 1.1s steps(1) infinite; }
.is-busy .b-field::before { animation: none; }
.is-wrong .b-field { animation: shake .3s; }

/* ---------- Month: sized in em, so the same component scales between the year view and an entry ---------- */
.b-m { font-size: 14px; }
.b-mn { font-size: 1.2857em; font-weight: 700; line-height: 1.5; margin-bottom: .3em; }
.b-mn span, .b-yn, .b-n { display: inline-block; }
/* A month name's own box is cropped to its capitals, as on an entry, so the small name and the big one have the same
   shape and morph into each other in place (the line around it keeps its height). */
.b-mn span { line-height: .74; }
.b-yn, .y-yn { white-space: nowrap; } /* a year is four digit slots; it must never break between them */
.b-days { display: grid; grid-template-columns: repeat(7, 1fr); }
/* In the year view the numbers sit at the left of their columns, so seven equal columns left a band of white after
   the last one. The last column takes only its numbers' width and the other six share the rest: the columns stay
   evenly spaced, and a month ends where its last digits do. (The entry's calendar keeps equal columns: its cells have
   rules and the dark block, which already run to the edge.) */
.b-months .b-days { grid-template-columns: repeat(6, minmax(0, 1fr)) auto; }
.b-days > * { line-height: 1.9; }
.b-x { color: color-mix(in srgb, var(--mute) 42%, var(--paper)); }
.b-new:hover { color: var(--mark); }
.b-on { font-weight: 700; }
.b-on:hover { color: var(--mark); }
.b-today { color: var(--mark); }
.b-sel, .b-sel:hover { color: var(--paper); background: var(--ink); margin-left: -.3em; padding-left: .3em; margin-right: .2em; }
.b-n { line-height: 1; letter-spacing: -.03em; }

/* ---------- Year view: one year per screen; scrolling moves between years ---------- */
/* In a window too short for the whole year it scrolls first (see the wheel handler in app.ts). */
.b-index { position: relative; min-height: 100vh; overflow-x: clip; padding-bottom: var(--m); }
.b-top { align-items: end; }
.b-year { grid-column: 1 / span 6; font-size: min(var(--t7), 17vh); font-weight: 700; line-height: .74; letter-spacing: -.045em; color: color-mix(in srgb, var(--mark) 40%, var(--paper)); }
.b-year a:hover { color: var(--mark); }
/* Each digit of a year sits in a slot that clips (with a little room for the glyphs' overshoot), so it can roll
   like a tally counter. */
.b-dg { display: inline-block; vertical-align: top; height: .94em; padding: .1em .05em; margin: -.1em -.05em; overflow: hidden; }
.b-reel, .b-reel > span { display: block; }
.b-reel > span { height: 1em; }
.b-peek { grid-column: 7 / -1; font-size: var(--t3); line-height: 1.2; min-height: 1.2em; padding-bottom: .1em; }
.b-months { margin-top: 56px; row-gap: 40px; }
/* The months grow with the page's height, so three rows fill whatever is left under the year
   (14px at 900px tall; the 332px is the margins, the year, and the gaps between rows). */
.b-months .b-m { grid-column: span 3; font-size: var(--mf, clamp(14px, calc((100vh - 332px) * 14 / 576), 22px)); }
.b-months.six .b-m { grid-column: span 2; } /* six by two, in a window too short for four by three */
/* (In a window too short for that, fit() in app.ts sets --mf smaller, so the whole year always fits: the year view
   never scrolls on a desktop, and scrolling only ever changes the year.) */

/* ---------- Entry: the month owns the left half and never moves; only the article scrolls ---------- */
.b-entry { align-items: start; padding-bottom: 0; }
.b-side { grid-column: 1 / span 6; position: sticky; top: var(--m); height: calc(100vh - var(--m) * 2); display: flex; flex-direction: column; }
/* Text starts one page margin from the calendar, so it has the same space on both sides. */
.b-art { grid-column: 7 / -1; padding: 2px 0 calc(var(--m) * 3) calc(var(--m) - var(--gut)); }
.b-art .prose { max-width: none; }
.b-h { font-size: var(--t4); line-height: 1.1; font-weight: 700; letter-spacing: -.01em; margin-bottom: 32px; }
.b-h:empty { margin-bottom: 0; }

/* The entry's month, read top to bottom: month name, days, year. Weeks you wrote more in grow taller (row
   weights are set inline); longer entries get bigger numbers. */
.b-big { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; --wk-min: 92px; --wk-empty: 46px; }
.b-big .b-days { flex: 1; min-height: 0; grid-auto-rows: minmax(0, 1fr); position: relative; z-index: 1; container-type: inline-size; }
/* Numbers never outgrow their cell (a seventh of the calendar's width), however narrow the window. */
.b-big .b-days > * { font-size: min(var(--t3), 7cqw); line-height: 1; padding: 10px 8px 0; border-top: 1px solid var(--line); overflow: hidden; }
.b-big .b-days > :nth-child(-n + 7) { border-top: 0; }
.b-big .b-on { font-size: min(calc(var(--t3) + var(--s) * 45px), 10.5cqw); }
.b-big .b-sel { margin: 0; padding-left: 8px; }
.b-tt { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-top: 10px;
        font-size: 12px; font-weight: 400; line-height: 1.3; letter-spacing: 0; color: var(--mute); }
.b-sel .b-tt { color: inherit; }
/* Titles never show half cut: two lines if they fit, else one with an ellipsis, else none. */
.b-tt.one { -webkit-line-clamp: 1; }
.b-tt.off { display: none; }
/* Picking another day in the same month slides the dark block there. */
.b-slide { position: absolute; z-index: 0; background: var(--ink); pointer-events: none; }
.b-big .b-sel.b-arriving { background: none; }

/* The month name and the year, each set as wide as the column; a short month name stops at 29% of the width.
   Line height is cropped to the capitals, so the gaps to the calendar are exactly 20px. */
.b-big .b-mn { margin: 0 0 20px; font-size: var(--t6); line-height: .74; letter-spacing: -.045em; white-space: nowrap; color: color-mix(in srgb, var(--mark) 40%, var(--paper)); }
.b-big .b-mn a { display: inline-block; }
.b-big .b-mn a:hover, .b-word:hover { color: var(--mark); }
.b-big .b-mn span, .b-word > span { padding-right: .045em; }
.b-word { align-self: flex-start; margin-top: 20px; font-weight: 700; line-height: .74; letter-spacing: -.045em; color: color-mix(in srgb, var(--mark) 40%, var(--paper)); }

/* ---------- All years: each year as a mosaic of its days, oldest at the top ---------- */
.b-years { min-height: 100vh; display: flex; flex-direction: column; padding-bottom: var(--m); }
.y-foot { margin-top: auto; }
.y-head { padding-bottom: 24px; }
.b-peek.y-peek { grid-column: 5 / -1; }
.y-row { align-items: end; }
.y-row + .y-row { margin-top: 48px; }
.y-year { grid-column: 1 / span 4; font-weight: 700; line-height: .716; letter-spacing: -.045em; color: color-mix(in srgb, var(--mark) 40%, var(--paper)); }
.y-yn { display: inline-block; position: relative; top: .024em; padding-right: .045em; }
.y-year:hover { color: var(--mark); }
.y-grid { grid-column: 5 / -1; display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, auto);
          grid-template-columns: repeat(var(--weeks, 53), minmax(0, 1fr)); gap: 3px; }
.y-sq { display: block; aspect-ratio: 1; background: var(--line); }
.y-sq.y-f { background: none; }
.y-sq.l1 { background: color-mix(in srgb, var(--mark) 35%, var(--paper)); }
.y-sq.l2 { background: color-mix(in srgb, var(--mark) 58%, var(--paper)); }
.y-sq.l3 { background: color-mix(in srgb, var(--mark) 80%, var(--paper)); }
.y-sq.l4 { background: var(--mark); }
a.y-sq { transition: background-color .3s ease; }
a.y-sq:hover { background: var(--ink); }
/* While a new accent blends in, hover easing is off, so links follow the accent exactly instead of trailing it. */
.blending a, .blending a.y-sq { transition: none; }

/* ---------- Top right: the three accents, stacked; and, for the owner, Edit ---------- */
.pals { position: fixed; top: 16px; right: calc(var(--gr) / 2 - 7px); z-index: 20; width: 14px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.pals .dot { width: 10px; height: 10px; padding: 0; border: 0; border-radius: 50%; background: var(--pm); cursor: pointer;
             box-shadow: 0 0 0 2px var(--paper), 0 0 0 2px transparent; transition: box-shadow .35s ease; }
.pals .dot[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--pm); }
/* Edit mode: a pencil under the dots, grey when off, the accent (and filled) when on. */
.mode { display: block; width: 14px; height: 14px; margin-top: 4px; padding: 0; border: 0; background: none; cursor: pointer;
        color: var(--mute); transition: color .3s ease; }
.mode svg { display: block; width: 14px; height: 14px; overflow: visible; }
.mode path { fill: transparent; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; transition: fill .3s ease; }
.mode:hover, .mode[aria-pressed="true"] { color: var(--mark); }
.mode + .mode { margin-top: 0; } /* the pencil and the plus sit together, a dot's gap apart */
.mode[aria-pressed="true"] path { fill: currentColor; }
/* Light or dark: a circle, half filled; in the accent while dark mode is on. */
.mode circle { fill: transparent; stroke: currentColor; stroke-width: 1.5; }
.mode.theme .half { fill: currentColor; stroke: none; }
.mode[hidden], .screen-lock .pals { display: none; }

/* ---------- Scroll rail, as on ajiang.xyz, in black ---------- */
/* A hairline at the right, vertically centred; its marker (a fifth of it) travels down it as the page scrolls
   (app.ts). It stands in for the scrollbar, so it shows only where the page scrolls. On a phone it appears while
   scrolling and fades a second after. It hangs on the same centre line as the dots and pencil above it: the middle of
   the right gutter. */
.rail { position: fixed; top: 50%; right: calc(var(--gr) / 2 - .5px); z-index: 15; width: 1px; height: 22vh; transform: translateY(-50%);
        overflow: hidden; background: var(--line); pointer-events: none; transition: opacity .7s cubic-bezier(.16, 1, .3, 1); }
.rail i { position: absolute; top: 0; left: 0; width: 1px; height: 20%; background: var(--ink); will-change: transform; }
.rail[data-still] { opacity: 0; }

/* ---------- Writing (edit mode, the owner's passkey only) ---------- */
.b-h[contenteditable] { outline: 0; caret-color: var(--mark); margin-bottom: 32px; }
.b-h[contenteditable]:empty::before { content: attr(data-placeholder); color: var(--line); }
.b-ed { outline: 0; min-height: 50vh; caret-color: var(--mark); }
.b-ed p.is-editor-empty:first-child::before { content: attr(data-placeholder); color: var(--line); float: left; height: 0; pointer-events: none; }
.b-ed img { cursor: default; }
.b-ed img.ProseMirror-selectednode { outline: 2px solid var(--mark); outline-offset: 2px; }
/* Formatting bar: fixed to the bottom of the screen, over the text column only (it starts where the text does),
   on the paper, in the accent. On a phone it spans the width and rides just above the keyboard. */
.ed-bar { position: fixed; bottom: 0; left: calc(50vw + var(--m) - var(--gut) / 2); right: var(--gr); z-index: 30;
          display: flex; align-items: center; gap: 2px; padding: 8px 0 calc(8px + env(safe-area-inset-bottom));
          background: var(--paper); border-top: 1px solid var(--line); color: var(--ink); font-size: 16px; line-height: 1; }
.ed-bar button { min-width: 36px; height: 36px; padding: 0 6px; border: 0; background: none; color: inherit; font: inherit; cursor: pointer;
                 transition: color .3s ease; }
.ed-bar button:first-child { margin-left: -6px; }
.ed-bar button:hover, .ed-bar button[aria-pressed="true"] { color: var(--mark); }
.ed-bar .i { font-style: italic; } .ed-bar .b { font-weight: 700; }
.b-status { margin-left: auto; font-size: var(--t1); color: var(--mute); }

@media (max-width: 700px) {
  .b-m { font-size: 17px; }
  .b-days > * { line-height: 2.7; }
  .b-year { grid-column: 1 / -1; }
  .b-peek { display: none; }
  /* On a phone the year view scrolls through its months; a sideways swipe changes the year. */
  .b-index { height: auto; overflow: visible; overflow-x: clip; padding-bottom: calc(var(--m) * 3); }
  .b-months { display: flex; flex-direction: column; gap: 48px; margin-top: 40px; }
  .b-months .b-m { font-size: 17px; } /* all twelve, January first, as on a desktop */
  /* Entry: the calendar stays put and the article slides up over it, like a sheet of paper. */
  .b-entry { display: block; }
  /* The month name, days and year together take 63% of the screen; the days fill what the two words leave. */
  .b-side { position: sticky; top: var(--m); height: 63vh; height: 63svh; }
  .b-big .b-mn { margin-bottom: 16px; }
  .b-word { margin-top: 16px; }
  .b-big { --wk-min: 48px; --wk-empty: 32px; }
  .b-big .b-days > * { font-size: min(var(--t2), 6cqw); padding: 8px 6px 0; }
  .b-big .b-on { font-size: min(calc(var(--t2) + var(--s) * 20px), 10cqw); }
  .b-tt { display: none; }
  .b-art { position: relative; z-index: 2; background: var(--paper); padding: 40px 0 calc(var(--m) * 6); border-top: 1px solid transparent; }
  @supports (animation-timeline: scroll()) {
    /* An edge appears only once the sheet starts to cover the calendar. */
    .b-art { animation: sheet-edge linear both; animation-timeline: scroll(); animation-range: 0 40px; }
  }
  @keyframes sheet-edge { to { border-top-color: var(--line); } }
  .b-ed { min-height: 40vh; }
  /* The dots and pencil, smaller on a phone, centred in its wider right gutter, with bigger invisible tap areas. */
  .pals { top: 14px; right: calc(var(--gr) / 2 - 6px); width: 12px; gap: 10px; }
  .pals .dot { width: 8px; height: 8px; position: relative; }
  .mode { width: 12px; height: 12px; position: relative; }
  .mode svg { width: 12px; height: 12px; }
  .pals .dot::before, .mode::before { content: ""; position: absolute; inset: -6px -10px; }
  .rail { height: 14vh; opacity: 0; }
  .rail[data-awake]:not([data-still]) { opacity: 1; transition-duration: .2s; }
  .ed-bar { left: 0; right: 0; padding-left: var(--m); padding-right: var(--m); will-change: transform; }
  .ed-bar button { min-width: 40px; height: 40px; font-size: 17px; }
  /* All years: each year's number above its mosaic. */
  .y-head { display: none; }
  .y-row { display: block; }
  .y-row + .y-row { margin-top: 32px; }
  .y-year { display: block; font-size: var(--t5); line-height: .74; margin-bottom: 12px; }
  .y-yn { top: 0; }
  .y-grid { gap: 1px; }
}

/* ---------- Transitions: matching names glide between screens; everything else fades ---------- */
::view-transition-group(*) { animation-duration: .6s; animation-timing-function: cubic-bezier(.2, .8, .1, 1); }
/* The pages cross-fade quickly and in step (the two always add up to one opaque page), so the old screen doesn't
   linger under the new one. */
::view-transition-old(root) { animation: vt-out .3s ease-out both; }
::view-transition-new(root) { animation: vt-in .3s ease-out both; }
/* Words and days change size a lot; swap old for new quickly so the enlarged small text never shows (as a blurry
   ghost). Days land with a slight overshoot, one after another from the first (delays are set in app.ts). */
::view-transition-old(month), ::view-transition-old(year) { animation-duration: .2s; }
::view-transition-new(month), ::view-transition-new(year) { animation-duration: .35s; }
::view-transition-group(*.day) { animation-duration: .65s; animation-timing-function: cubic-bezier(.34, 1.3, .5, 1); }
::view-transition-old(*.day) { animation-duration: .18s; animation-delay: 0s; }
::view-transition-new(*.day) { animation-duration: .3s; animation-delay: 0s; }
@keyframes vt-in { from { opacity: 0; } }
@keyframes vt-out { to { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  a { transition: none; }
  *, ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
