/* Self-hosted Crimson Pro — Latin subset only, weight 400 in two styles.
   font-display: block per DESIGN.md (sanctuary tone — quiet FOIT over
   jarring FOUT). Both files preloaded in index.html so first paint of
   the wordmark + Begin slowly action lands with the real face.
   Font files: SIL Open Font License. Source: Google Fonts v28. */
@font-face {
  font-family: "Crimson Pro";
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url("fonts/crimson-pro-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Crimson Pro";
  font-style: italic;
  font-weight: 400;
  font-display: block;
  src: url("fonts/crimson-pro-400-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --paper: #FAF6EC;
  --paper-deep: #F4EFDD;   /* breath-cycle low point — barely visible shift */
  --ink: #1A1A1A;
  --ink-faint: #B5B0A4;
  --ink-dim: rgba(26, 26, 26, 0.22);
  --ink-italic: #6E6A60;

  --measure: 32rem;
  --line-height: 1.85;

  --serif: "Crimson Pro", "Source Serif Pro", Garamond, Georgia, serif;

  --pace: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-feature-settings: "kern", "liga", "onum";
  -webkit-font-smoothing: antialiased;
  text-rendering: geometricPrecision;
}

/* The room breathes — three synchronized layers at the same 15s
   rhythm. 15s/cycle = 4 breaths/min, the entry point of traditional
   pranayama and a comfortable Daoist meditation pace. Coherent
   breathing (Brown & Gerbarg, 6 bpm) is the HRV-peak rate, but for
   "Linger" with Tao Te Ching the slower 4 bpm sits closer to the
   contemplative register the product is aiming at. Apple Watch
   Breathe defaults to 7 bpm; this is roughly half that — long, open
   inhales and exhales.
   The three layers:
   1) Page background pulses subtly (paper → paper-deep).
   2) A horizontal ink mark below the page-mark grows and shrinks
      with the same cycle, giving a visible breath reference.
   3) The caret breath (further down) shares the same 15s cycle.
   All three active only during the typing state, all at a constant
   rate — no rush detection, no rate changes based on typing speed. */
.breath-mark {
  position: fixed;
  top: 4rem;
  left: 50%;
  transform-origin: center;
  width: 20rem;
  aspect-ratio: 5.36 / 1; /* preserves the source image's aspect */
  background-image: url("breath-mark.png");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  background-color: transparent;
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

body[data-state="typing"] .breath-mark {
  animation: breath-mark 15000ms cubic-bezier(0.4, 0.0, 0.6, 1.0) infinite;
}

@keyframes breath-mark {
  0%, 100% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.45;
  }
  50% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 0.9;
  }
}

@media (max-width: 720px) {
  .breath-mark { top: 3rem; width: 13rem; }
}

@media (prefers-reduced-motion: reduce) {
  body[data-state="typing"] .breath-mark {
    animation: none;
    opacity: 0.6;
    transform: translateX(-50%) scaleX(0.7);
  }
}

body[data-state="typing"] {
  animation: paper-breath 15000ms cubic-bezier(0.4, 0.0, 0.6, 1.0) infinite;
}

@keyframes paper-breath {
  0%, 100% { background-color: var(--paper); }
  50%      { background-color: var(--paper-deep); }
}

/* 4-4-6 rhythm — opt-in via data-pace="deep" on body.
   Inhale 4s, hold 4s (kumbhaka), exhale 6s. Total 14s/cycle.
   Keyframe stops at 0% / 28.571% / 57.143% / 100% map to 0s / 4s / 8s / 14s.
   The longer exhale and brief hold pull the breath toward the
   parasympathetic register — closer to traditional pranayama relaxation
   patterns than the even sine of the default.
   Per-keyframe animation-timing-function lets each segment have its own
   ease (smooth into hold, no motion during hold, smooth out of hold). */
body[data-pace="deep"][data-state="typing"] .breath-mark {
  animation: breath-mark-deep 14000ms linear infinite;
}

@keyframes breath-mark-deep {
  0% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.45;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0);
  }
  28.571% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 0.9;
    animation-timing-function: linear;
  }
  57.143% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 0.9;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0);
  }
  100% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.45;
  }
}

body[data-pace="deep"][data-state="typing"] {
  animation: paper-breath-deep 14000ms linear infinite;
}

@keyframes paper-breath-deep {
  0%      { background-color: var(--paper);      animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0); }
  28.571% { background-color: var(--paper-deep); animation-timing-function: linear; }
  57.143% { background-color: var(--paper-deep); animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0); }
  100%    { background-color: var(--paper); }
}

body {
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr;
  padding: 2rem clamp(1.5rem, 6vw, 6rem) 4rem;
  gap: 3rem;
}

/* Page mark — restrained wordmark + locator */
.page-mark {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
}
.wordmark {
  font-style: italic;
  color: var(--ink);
  text-decoration: none;
  transition: color 320ms var(--pace);
}
.wordmark:hover { color: var(--ink-italic); }
.wordmark:focus-visible {
  outline: none;
  text-decoration: underline dashed 1px;
  text-underline-offset: 0.22em;
}
.locator {
  font-size: 0.75rem;
  color: var(--ink-italic);
  letter-spacing: 0.04em;
}

/* Reading desk — single continuous surface, no cards */
.desk {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 4rem;
  justify-items: center;
  align-content: start;
  padding-top: clamp(1rem, 6vh, 4rem);
}

.chapter {
  position: relative;
  width: min(var(--measure), 100%);
  font-size: clamp(1.0625rem, 1vw + 0.875rem, 1.25rem);
  line-height: var(--line-height);
}

/* Arrival as a preview of the typing state — chapter at full reading
   size with every char in the dim color the typing-untyped chars use.
   The visual continuity tells the visitor "this is the text you're
   about to bring to life, line by line" without saying it. When they
   click Begin slowly, nothing resizes; the active line just brightens
   into ink. Earlier we tried to compress arrival to keep Begin slowly
   above the fold, which solved discoverability at the cost of the
   preview metaphor — this version solves it through the dim-vs-bright
   contrast instead (the dim chapter is obviously passive, the bright
   Begin slowly is obviously the action).

   The chapter still scrolls if it exceeds the viewport on shorter
   screens; the threshold sticks to the bottom of the visible area so
   the action stays reachable regardless. */
body[data-state="arrival"] .char {
  color: var(--ink-dim);
}

body[data-state="arrival"] .threshold {
  position: sticky;
  bottom: 1.5rem;
  margin-top: auto;
  background: linear-gradient(to bottom, transparent, var(--paper) 30%, var(--paper));
  padding-top: 1.5rem;
  z-index: 5;
}

.ink {
  position: relative;
  white-space: pre-wrap;
  word-break: keep-all;
  /* No overflow-wrap: break-word. With per-char spans the browser would
     otherwise break a word like "unchanging" at any char, and the wrap
     point would jitter every keystroke as the cursor changes which span
     it attaches to. Keep whole words together; overflow only if the
     word is genuinely too long for the column (none in Tao Te Ching). */
  overflow-wrap: normal;
}

.line {
  display: block;
  transition: opacity 700ms var(--pace), color 700ms var(--pace);
}

.char {
  display: inline;
  color: var(--ink);
  transition: color 380ms var(--pace);
  position: relative; /* anchor for ::after cursor */
}

/* During typing, untyped chars dim back so the user feels the
   ink-reveal one character at a time. Outside typing state, the
   chapter reads as a fully present page. */
body[data-state="typing"] .char {
  color: var(--ink-dim);
}
body[data-state="typing"] .char.struck {
  color: var(--ink);
}
body[data-state="completion"] .char {
  color: var(--ink);
}
/* Cursor pseudo-element is absolutely positioned so it contributes
   zero width to the line. The .cursor class lives on the next char to
   be typed; with left near 0 the caret sits at that char's leading edge,
   which visually is right after the last typed char — the standard
   text-editor caret position.
   Caret breath cycle matches the paper-breath (15s) so cursor and
   room exhale together. */
.char.cursor::after {
  content: "";
  position: absolute;
  left: -0.05em;
  top: 0.13em;
  width: 1.5px;
  height: 1em;
  background: var(--ink);
  pointer-events: none;
  animation: breathe 15000ms cubic-bezier(0.4, 0.0, 0.6, 1.0) infinite;
}

@keyframes breathe {
  0%, 100% { opacity: 0.3; }
  50%      { opacity: 1.0; }
}

body[data-pace="deep"] .char.cursor::after {
  animation: breathe-deep 14000ms linear infinite;
}

@keyframes breathe-deep {
  0%      { opacity: 0.3; animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0); }
  28.571% { opacity: 1.0; animation-timing-function: linear; }
  57.143% { opacity: 1.0; animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0); }
  100%    { opacity: 0.3; }
}

/* Active typing — non-current lines fade back */
body[data-state="typing"] .line:not(.line-active) {
  opacity: 0.25;
}

body[data-state="typing"] .threshold,
body[data-state="completion"] .threshold {
  display: none;
}

/* Threshold — single quiet invitation, no button-y button */
.threshold {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  width: min(var(--measure), 100%);
  margin-top: 2rem;
  padding-left: 0.05em;
}

/* Begin slowly is THE primary action on the arrival page. Earlier
   iterations kept it small to match the contemplative tone, but
   first-time testers couldn't find what to click — the action
   blended into the surrounding "this is just reading material"
   visual register. Restraint is good; invisibility is a bug.
   Bigger size + a heavier two-line underline makes it read as an
   intentional action without crossing into SaaS-button territory. */
.begin {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0.1em 0 0.18em;
  font: inherit;
  font-style: italic;
  font-size: 1.625rem;
  line-height: 1.2;
  color: var(--ink);
  cursor: pointer;
  border-bottom: 2px solid var(--ink);
  letter-spacing: 0.005em;
  transition: color 320ms var(--pace), border-color 320ms var(--pace), transform 320ms var(--pace);
}
.begin:hover { transform: translateY(-1px); }
.begin:focus-visible {
  outline: none;
  border-bottom-style: dashed;
}

.rhythm-note {
  margin: 0.35rem 0 0;
  font-style: italic;
  font-size: 0.875rem;
  color: var(--ink-italic);
  letter-spacing: 0.02em;
}

/* Preset rows — *secondary* controls, clearly demoted from the primary
   "Begin slowly" action above. Labelled and separated by extra whitespace
   so a first-time visitor reads them as "optional preferences" rather
   than "another thing I might need to click before starting." Two rows
   share the same styling, distinguished only by their label content. */
.preset-row {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  font-style: italic;
  font-size: 0.75rem;
  color: var(--ink-faint);
}

.breath-presets { margin: 1rem 0 0; }
.pace-presets   { margin: 0.35rem 0 0; }

.breath-presets::before { content: "Breath mark:"; }
.pace-presets::before   { content: "Rhythm:"; }

.preset-row::before {
  font-style: italic;
  color: var(--ink-faint);
  margin-right: 0.3em;
}

.preset-row .preset {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline dashed 1px;
  text-underline-offset: 0.2em;
  transition: color 320ms var(--pace);
}
.preset-row .preset:hover { color: var(--ink-italic); }
.preset-row .preset:focus-visible {
  outline: none;
  text-decoration-style: solid;
}
.preset-row .preset[aria-current="true"] {
  color: var(--ink);
  text-decoration: none;
}
.preset-row .dot {
  color: var(--ink-faint);
  font-style: normal;
}

/* Settle phrase — appears after Begin slowly, one phrase per
   10-second breath cycle, three cycles total (~30s). Positioned
   just under the breath mark so the user sees mark + phrase as
   a single guidance moment. Fixed so it stays in place as the
   user starts typing and reads down the chapter.
   Soft fade transitions; never blocks. */
.settle-phrase {
  position: fixed;
  top: 6rem;
  left: 0;
  right: 0;
  margin: 0 auto;
  text-align: center;
  font-style: italic;
  font-size: 0.9375rem;
  color: var(--ink-italic);
  letter-spacing: 0.01em;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity 2400ms cubic-bezier(0.4, 0.0, 0.6, 1.0);
}

.settle-phrase[data-active="1"] {
  opacity: 0.7;
}

@media (max-width: 720px) {
  .settle-phrase {
    top: 4.5rem;
    font-size: 0.875rem;
  }
}

/* Stronger breath-mark preset. Same image, wider span, deeper
   opacity arc. The mix-blend-mode multiply means the underlying
   paper-breath color shift still reaches the ink. */
body[data-breath="strong"] .breath-mark {
  width: 26rem;
  animation-name: breath-mark-strong;
}

@keyframes breath-mark-strong {
  0%, 100% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.65;
  }
  50% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 1.0;
  }
}

/* Strong + deep combo: keep the stronger amplitude but switch to the
   4-4-6 timing. Specificity (0,4,1) wins against both the plain strong
   selector (0,2,1) and the plain deep selector (0,3,1). */
body[data-pace="deep"][data-breath="strong"][data-state="typing"] .breath-mark {
  animation-name: breath-mark-strong-deep;
}

@keyframes breath-mark-strong-deep {
  0% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.65;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0);
  }
  28.571% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 1.0;
    animation-timing-function: linear;
  }
  57.143% {
    transform: translateX(-50%) scaleX(1.0);
    opacity: 1.0;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.6, 1.0);
  }
  100% {
    transform: translateX(-50%) scaleX(0.55);
    opacity: 0.65;
  }
}

@media (max-width: 720px) {
  body[data-breath="strong"] .breath-mark { width: 16rem; }
}

/* The hidden attribute must always win against display rules. */
[hidden] { display: none !important; }

/* Afterword — completion is a quiet ending, never a celebration */
.afterword {
  width: min(var(--measure), 100%);
  display: none;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
  margin-top: 4rem;
  opacity: 0;
}

body[data-state="completion"] .afterword {
  display: flex;
  animation: settle 1600ms var(--pace) forwards;
}

.dwell-line {
  margin: 0;
  font-style: italic;
  font-size: 0.875rem;
  color: var(--ink-italic);
  letter-spacing: 0.02em;
}

.dwell-time {
  margin: 0;
  font-size: 0.75rem;
  color: var(--ink-faint);
  letter-spacing: 0.05em;
  font-feature-settings: "tnum";
}

.afterword-actions {
  display: flex;
  gap: 0.5em;
  flex-wrap: wrap;
  align-items: baseline;
  margin-top: 0.5rem;
}

.afterword-actions button {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-style: italic;
  color: var(--ink);
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: border-color 320ms var(--pace), color 320ms var(--pace);
}
.afterword-actions button:hover { border-bottom-color: var(--ink); }
.afterword-actions button:focus-visible { outline: none; border-bottom: 1px dashed var(--ink); }

.dot {
  color: var(--ink-faint);
  font-style: italic;
}

@keyframes settle {
  from { opacity: 0; transform: translateY(0.35em); }
  to { opacity: 1; transform: translateY(0); }
}

/* Capture: invisible textarea catches keystrokes */
#capture {
  position: fixed;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  border: 0;
  outline: none;
  resize: none;
  top: 0;
  left: 0;
  caret-color: transparent;
}

/* IME hint — shown only if Hangul/composition input is detected, then
   auto-hides. Lives outside the contemplative reading area on purpose. */
.ime-hint {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  max-width: 36ch;
  padding: 0.7rem 1rem;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.8125rem;
  font-style: italic;
  line-height: 1.45;
  border-radius: 2px;
  z-index: 10;
  animation: settle 600ms var(--pace) forwards;
}
.ime-hint p { margin: 0; }

/* ─────────────────────────────────────────────────────────────────────
   MOBILE MODE — a different ritual, not a stacked desktop.
   Decision D6=A: line-by-line, no full-chapter split, generous pause,
   current phrase large and centered above where the keyboard sits.
   ───────────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  :root {
    --measure: 100%;
    --line-height: 1.55;
  }

  body {
    padding: 1.25rem 1.25rem 2rem;
    gap: 1.5rem;
    min-height: 100svh;
  }

  .page-mark {
    font-size: 0.75rem;
  }
  .locator { font-size: 0.6875rem; }

  /* Reading desk becomes a focused stage. The active line floats in the
     upper portion of the viewport, well clear of the keyboard. */
  .desk {
    gap: 1.5rem;
    padding-top: 0;
    min-height: 60svh;
    justify-content: flex-start;
  }

  .chapter {
    font-size: 1.5rem;       /* current line is large */
    line-height: 1.5;
    gap: 0;
    width: 100%;
  }

  /* The threshold (Begin slowly) stays quiet, but rises up so it's
     reachable above any virtual keyboard preview. */
  .threshold {
    margin-top: 0.5rem;
  }
  .begin {
    font-size: 1.125rem;
  }

  /* During typing, ALL lines collapse to zero size except the active
     one. This is the core mobile decision: one phrase at a time. */
  body[data-state="typing"] .line {
    display: none;
    font-size: 1.625rem;
    line-height: 1.55;
    letter-spacing: 0.01em;
  }
  body[data-state="typing"] .line.line-active {
    display: block;
    opacity: 1;
    animation: line-breath 700ms var(--pace) both;
  }

  /* Char dimming still applies during typing, but the line is the unit
     of attention here, not the chapter. */
  body[data-state="typing"] .char { color: var(--ink-dim); }
  body[data-state="typing"] .char.struck { color: var(--ink); }

  /* Inter-line pause: when the active line is being swapped out, fade
     it down briefly. JS sets data-pacing="resting" during the pause. */
  body[data-state="typing"][data-pacing="resting"] .line.line-active {
    opacity: 0.18;
    transition: opacity 1200ms var(--pace);
  }

  /* Completion in mobile: full chapter re-emerges at readable size,
     same quiet ending as desktop. */
  body[data-state="completion"] .line {
    display: block;
    font-size: 1.0625rem;
    line-height: 1.7;
  }
  body[data-state="completion"] .chapter { font-size: 1.0625rem; }

  .afterword { margin-top: 2rem; gap: 1rem; }
  .afterword-actions {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.65rem;
  }
  .afterword-actions .dot { display: none; }
}

@keyframes line-breath {
  from { opacity: 0; transform: translateY(0.4em); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Reduced motion respect */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
   ABOUT PAGE — static prose. Same paper tone, slightly wider reading
   measure than the chapter, no typing ritual. Reachable via the
   wordmark link in the page header or via direct URL (/about).
   ───────────────────────────────────────────────────────────────────── */
body[data-page="about"] {
  grid-template-rows: auto 1fr;
  gap: 2rem;
  padding-bottom: 5rem;
}

.about {
  width: min(42rem, 100%);
  margin: 0 auto;
  padding-top: clamp(1rem, 4vh, 3rem);
  font-size: clamp(1rem, 0.8vw + 0.85rem, 1.0625rem);
  line-height: var(--line-height);
}

.about h1 {
  margin: 0 0 1.25rem;
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.5rem, 2vw + 1rem, 2.125rem);
  letter-spacing: -0.01em;
}

.about h2 {
  margin: 2.75rem 0 0.75rem;
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.125rem, 0.8vw + 1rem, 1.3125rem);
  color: var(--ink);
  letter-spacing: 0.01em;
}

.about .lede {
  margin: 0 0 1.5rem;
  font-style: italic;
  font-size: clamp(1.0625rem, 0.8vw + 0.9rem, 1.1875rem);
  color: var(--ink-italic);
}

.about p {
  margin: 0 0 1.1rem;
}

.about em { font-style: italic; }

.about a {
  color: var(--ink);
  text-decoration: underline dashed 1px;
  text-underline-offset: 0.2em;
  transition: color 320ms var(--pace);
}
.about a:hover { color: var(--ink-italic); }
.about a:focus-visible {
  outline: none;
  text-decoration-style: solid;
}

.about .back {
  margin-top: 3rem;
  font-style: italic;
  color: var(--ink-italic);
}

@media (max-width: 720px) {
  body[data-page="about"] {
    padding: 1.25rem 1.25rem 3rem;
  }
  .about { padding-top: 0.5rem; }
}
