/* ---------------------------------------------------------------- paper & ink */
:root{
  --paper:#fdfcfa;
  --ink:#17140f;
  --ink-soft:#17140f99;
  --ink-faint:#17140f33;
  --ink-mid:#17140f80;
  --ink-ghost:#17140f14;
  --accent:#b3241c;
  --draw:620ms;
  /* The name and the study tab hang off one line. --tab-drop is the distance from
     the top of the header down to the middle of the name, less half the tab. */
  --top-y:clamp(1rem,3vh,2rem);
  --tab-drop:1.13rem;
}
/* Dark applies when the system asks for it AND light has not been forced,
   or when dark is chosen outright with `b`. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:#100e0b;
    --ink:#ece6db;
    --ink-soft:#ece6dba8;
    --ink-faint:#ece6db38;
    --ink-mid:#ece6db80;
    --ink-ghost:#ece6db14;
    --accent:#ef7367;
  }
}
:root[data-theme="dark"]{
  --paper:#100e0b;
  --ink:#ece6db;
  --ink-soft:#ece6dba8;
  --ink-faint:#ece6db38;
  --ink-mid:#ece6db80;
  --ink-ghost:#ece6db14;
  --accent:#ef7367;
}

*{box-sizing:border-box;margin:0;padding:0}
/* pan and scroll, but no pinch and no double-tap zoom */
html,body{touch-action:pan-x pan-y}
[hidden]{display:none !important}
html,body{height:100%}
body{
  background:var(--paper);
  color:var(--ink);
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow:hidden;
  cursor:default;
}

/* ---------------------------------------------------------------- stage */
#stage{
  height:100%;
  display:grid;
  place-items:center;
  padding:clamp(2rem,7vh,6rem) clamp(1.5rem,6vw,7rem);
  position:relative;
}
#verse-wrap{
  max-width:min(100%,1200px);
  width:100%;
  text-align:left;
  padding-right:3.5rem;          /* the lines stop short of the edge, and of the study panel */
  /* A clean page puts the verse in the middle of the screen. It travels by
     transform, so the measure never changes and not one line re-wraps on the way. */
  transform:translate(var(--clean-x,0px),var(--clean-y,0px));
  transition:transform 560ms cubic-bezier(.32,.72,0,1);
}

.verse{
  font-size:var(--size,clamp(1.7rem,3.5vw,3.1rem));
  line-height:1.42;
  letter-spacing:-0.011em;
  font-weight:400;
  hyphens:none;
  max-width:min(44ch,100%);
}
.verse .w{display:inline-block;white-space:nowrap}
.verse .c{
  display:inline-block;
  opacity:0;
}
.verse.draw .c{
  animation:ink var(--draw) cubic-bezier(.22,.68,.32,1) both;
  will-change:opacity,filter,transform;
}
/* Once the draw finishes we swap to a static class. The animation's fill-mode
   would otherwise pin opacity forever and outrank the read-position styles below,
   and dropping will-change releases the compositor layers. */
.verse.drawn .c{opacity:1}

@keyframes ink{
  0%  {opacity:0;   filter:blur(9px);   transform:translate3d(-.05em,.06em,0) scale(1.22)}
  50% {opacity:.92; filter:blur(1.4px); transform:translate3d(0,.012em,0)     scale(1.03)}
  100%{opacity:1;   filter:blur(0);     transform:none}
}

/* Reading can begin while the ink is still arriving. The animation owns opacity
   until it finishes, but never colour - so the word being read is lit even mid-draw,
   and the receding of the words behind takes over once the verse has landed. */
.verse .w.saying .c{color:var(--accent)}

/* read position - words behind you recede, the word you are on is lit.
   Scoped to .drawn and more specific than .drawn .c so they win the cascade. */
.verse.drawn .w.said .c{opacity:.24;transition:opacity .55s ease}
.verse.drawn .w.saying .c{
  opacity:1;color:var(--accent);
  transition:opacity .18s ease,color .18s ease;
}

.ref{
  margin-top:clamp(1.3rem,3vh,2.4rem);
  font-size:.76rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--ink-soft);
  opacity:0;
  transition:opacity .7s ease .25s;
}
.ref.in{opacity:1}
.ref .tr{margin-left:.9em;color:var(--ink-mid)}

/* ---------------------------------------------------------------- the gate */
.gate{
  position:fixed;inset:0;z-index:30;background:var(--paper);
  display:grid;place-items:center;text-align:center;overflow-y:auto;
  padding:clamp(2rem,7vh,6rem) clamp(1.5rem,6vw,7rem);
}
.gate-form{width:100%;max-width:20em;display:flex;flex-direction:column;align-items:center}
.gate-name{font-family:"Iowan Old Style",Palatino,Georgia,serif;
  font-size:clamp(1.7rem,3.4vw,2.4rem);color:var(--accent);letter-spacing:.02em}
.gate-note{margin-top:1.4em;font-size:.86rem;line-height:1.7;color:var(--ink-soft);
  font-family:"Iowan Old Style",Palatino,Georgia,serif}
.gate-input{
  width:100%;margin-top:1.5em;padding:.7em 0;
  background:none;border:none;border-bottom:1px solid var(--ink-ghost);
  font-family:"Iowan Old Style",Palatino,Georgia,serif;font-size:1.05rem;
  color:var(--ink);text-align:center;caret-color:var(--accent);outline:none;
  transition:border-color .3s ease;
}
.gate-input:focus{border-bottom-color:var(--ink-faint)}
.gate-input::placeholder{color:var(--ink-faint)}
.gate-go{
  margin-top:2.4em;padding:.7em 2.6em;cursor:pointer;
  background:none;border:1px solid var(--ink-ghost);border-radius:2px;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.7rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-soft);
  transition:border-color .3s ease,color .3s ease;
}
.gate-go:hover{border-color:var(--ink-faint);color:var(--ink)}
.gate-msg{min-height:1.4em;margin-top:1.6em;font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.7rem;letter-spacing:.06em;color:var(--accent);opacity:0;transition:opacity .3s ease}
.gate-msg.in{opacity:1}

/* ---------------------------------------------------------------- the opening */
/* Centred, unlike the reading itself, so the way in feels like its own place. */
.opening{
  position:fixed;inset:0;z-index:24;background:var(--paper);
  display:flex;text-align:center;overflow-y:auto;
  padding:clamp(2rem,7vh,6rem) clamp(1.5rem,6vw,7rem);
}
/* margin:auto centres it while still allowing a tall slide to scroll without
   the top being clipped, which place-items:center would do. */
/* margin:auto centres it while still allowing a tall slide to scroll without the
   top being clipped. The bottom padding biases it slightly above centre. */
#op-body{max-width:32em;width:100%;margin:auto;padding-bottom:clamp(1.5rem,7vh,4.5rem)}
.opening .c{display:inline-block;opacity:0}
.opening.draw .c{
  animation:ink var(--draw,640ms) cubic-bezier(.22,.68,.32,1) both;
  will-change:opacity,filter,transform;
}
.opening.drawn .c{opacity:1}
.opening .w{display:inline-block;white-space:nowrap}

.op-verse{font-size:clamp(1.5rem,3.1vw,2.35rem);line-height:1.5;letter-spacing:-.01em}
.op-lead{font-size:clamp(1.2rem,2.4vw,1.7rem);line-height:1.6;color:var(--ink-soft)}
.op-name{font-size:clamp(1.8rem,3.6vw,2.8rem);line-height:1.4;margin-top:.5em;color:var(--accent)}
.op-title{font-size:.74rem;letter-spacing:.24em;text-transform:uppercase;color:var(--ink-mid);margin-bottom:2.4em}

.op-ref,.op-line{opacity:0;transition:opacity .9s ease}
.op-ref.in,.op-line.in{opacity:1}
.op-ref{margin-top:clamp(1.4rem,3vh,2.2rem);font-size:.74rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent)}
.op-line{margin-top:clamp(1.6rem,3.5vh,2.6rem);font-size:.95rem;line-height:1.8;color:var(--ink-soft)}

/* A sentence, not a label - uppercase letterspacing makes this length unreadable. */
.op-need-lead{
  margin-top:3.2em;margin-bottom:1.8em;
  font-family:"Iowan Old Style",Palatino,Georgia,serif;
  font-size:.95rem;letter-spacing:0;text-transform:none;line-height:1.6;
  color:var(--ink-soft);
}
.op-need{
  list-style:none;padding:0;
  display:grid;grid-template-columns:repeat(2,auto);
  gap:.85em 2.8em;justify-items:start;
  width:fit-content;margin:0 auto;          /* rows stay aligned, block sits centred */
}
.op-need li{font-size:.94rem;color:var(--ink-soft);display:flex;align-items:baseline}
.op-need b{color:var(--accent);font-weight:400;letter-spacing:.12em;
  min-width:1.6em;flex:none;text-align:left}
@media (max-width:520px){ .op-need{grid-template-columns:auto;gap:.7em} }

.op-keys{list-style:none;display:grid;gap:1.05em;margin:0;padding:0}
.op-keys li{font-size:.98rem;line-height:1.5;color:var(--ink-soft)}
.op-keys b{color:var(--accent);font-weight:400;margin-right:.7em;letter-spacing:.12em}

.op-more{
  position:fixed;bottom:clamp(1.6rem,4vh,2.6rem);left:0;right:0;text-align:center;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-mid);
  opacity:0;transition:opacity 1s ease;pointer-events:none;
}
.op-more.in{opacity:1}

/* ---------------------------------------------------------------- top bar */
/* Standard reading shows only the name. Entering a topic turns it into a control
   naming what the verses are for, which opens the list of topics. */
.topbar{
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms;
  position:fixed;top:var(--top-y);left:clamp(1.1rem,5vw,6.2rem);
  z-index:23;display:flex;flex-direction:column;align-items:flex-start;  /* over the veil */
}
.topbar-btn{
  display:flex;flex-direction:column;align-items:flex-start;gap:.3em;
  background:none;border:none;margin:0;padding:.45em .7em .45em 0;cursor:pointer;
  color:var(--ink-faint);text-align:left;
  transition:color 320ms cubic-bezier(.32,.72,0,1);
}
.topbar-btn:hover,.topbar-btn:focus-visible{color:var(--ink-soft);outline:none}
.topbar-main{display:flex;align-items:center;gap:.55em}

/* The caption is always in the layout, just invisible while reading normally, so
   the word beneath it never shifts when a topic is chosen - only the word changes. */
.topbar-kicker{
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.6rem;letter-spacing:.17em;text-transform:lowercase;
  color:var(--ink-mid);
  opacity:0;transition:opacity 320ms cubic-bezier(.32,.72,0,1);
}
.topbar.in-mode .topbar-kicker{opacity:1}

/* the name, when nothing in particular is being carried */
.topbar-label{
  font-family:"Iowan Old Style",Palatino,Georgia,serif;
  font-size:.95rem;letter-spacing:.06em;color:var(--accent);
  opacity:.42;                              /* present, but well out of the way */
  transition:color 320ms ease,opacity 320ms ease,letter-spacing 320ms cubic-bezier(.32,.72,0,1);
}
.topbar-btn:hover .topbar-label,
.topbar-btn:focus-visible .topbar-label{opacity:.85}
.topbar.in-mode .topbar-label{opacity:1}    /* a topic should read plainly */
.topbar-label b{font-weight:400;color:var(--accent)}

/* In a topic the same slot simply carries the topic's name instead. */
.topbar.in-mode .topbar-label{letter-spacing:.04em}

.topbar-caret{display:flex;color:var(--ink-faint);transition:color 300ms ease,transform 360ms cubic-bezier(.32,.72,0,1)}
.topbar-btn:hover .topbar-caret{color:var(--ink-faint)}
.topbar.menu-open .topbar-caret{transform:rotate(180deg);color:var(--accent)}

.topbar-menu{
  margin-top:.5em;min-width:15em;padding:.5em 0;
  background:var(--paper);border:1px solid var(--ink-ghost);border-radius:4px;
  box-shadow:0 8px 30px rgba(0,0,0,.07);
  transform-origin:top center;
  animation:menuIn 300ms cubic-bezier(.32,.72,0,1) both;
}
@keyframes menuIn{from{opacity:0;transform:translateY(-.4em) scale(.98)}to{opacity:1;transform:none}}
.topbar-menu button{
  display:flex;align-items:baseline;gap:.9em;width:100%;
  background:none;border:none;margin:0;padding:.6em 1.2em;cursor:pointer;text-align:left;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;font-size:.82rem;
  color:var(--ink-soft);transition:color 200ms ease,background 200ms ease;
}
.topbar-menu button:hover{color:var(--ink);background:var(--ink-ghost)}
.topbar-menu button.on{color:var(--accent)}
.topbar-menu button kbd{
  font-family:inherit;font-size:.7rem;min-width:1.4em;text-align:center;
  color:var(--accent);flex:none;
}
.topbar-menu hr{border:none;border-top:1px solid var(--ink-ghost);margin:.5em 0}

/* ---------------------------------------------------------------- listening */
.listening{
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms;
  position:fixed;bottom:clamp(3.4rem,9vh,5.4rem);left:50%;transform:translateX(-50%);z-index:19;
  display:flex;align-items:center;gap:.6em;
  font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-mid);
}
.pip{width:7px;height:7px;border-radius:50%;background:var(--accent);animation:breathe 1.7s ease-in-out infinite}
@keyframes breathe{0%,100%{opacity:.25;transform:scale(.8)}50%{opacity:1;transform:scale(1.15)}}

/* ---------------------------------------------------------------- resources */
:root{--res-w:clamp(300px,32vw,420px)}

/* The tab rides with the panel, so it always sits on its edge. Transform only,
   critically damped, no overshoot - the panel is not thrown, it is opened. */
.res-tab{
  position:fixed;top:calc(var(--top-y) + var(--tab-drop));right:0;z-index:16;
  padding:.62em 1.15em;margin:0;cursor:pointer;
  background:var(--paper);border:1px solid var(--ink-ghost);border-right:none;
  border-radius:3px 0 0 3px;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-mid);
  transition:transform 460ms cubic-bezier(.32,.72,0,1),color 300ms ease,border-color 300ms ease,
             opacity 380ms cubic-bezier(.32,.72,0,1) 220ms;
}
.res-tab:hover,.res-tab:focus-visible{color:var(--ink);border-color:var(--ink-faint);outline:none}
.res-tab:active{color:var(--accent)}
body.res-open .res-tab{transform:translate3d(calc(-1 * var(--res-w)),0,0);color:var(--accent)}

.res{
  position:fixed;top:0;right:0;bottom:0;z-index:15;width:var(--res-w);
  background:var(--paper);border-left:1px solid var(--ink-ghost);
  overflow-y:auto;overscroll-behavior:contain;
  transform:translate3d(100%,0,0);visibility:hidden;
  transition:transform 460ms cubic-bezier(.32,.72,0,1),visibility 0s linear 460ms;
}
body.res-open .res{
  transform:none;visibility:visible;
  transition:transform 460ms cubic-bezier(.32,.72,0,1),visibility 0s;
}
.res-inner{padding:clamp(2.4rem,6vh,3.6rem) clamp(1.5rem,2.4vw,2.2rem)}

/* The reading gives way rather than being covered. The width change itself is not
   animated - re-wrapping text on every frame is what made this feel rough. The
   reading dips out, re-wraps while it is barely visible, and comes back:
   critically damped, no overshoot, and only opacity actually moves. */
#stage{transition:opacity 300ms cubic-bezier(.32,.72,0,1)}
#stage.reflowing{opacity:.12;transition:opacity 140ms cubic-bezier(.32,.72,0,1)}
body.res-open #stage{padding-right:calc(var(--res-w) + clamp(1.5rem,6vw,7rem))}

.res-ref{font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent);margin-bottom:2.4em}
.res-group{font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-mid);margin:2.4em 0 1em}
.res-group:first-child{margin-top:0}
.res-item{
  display:block;text-decoration:none;padding:.85em 0;
  border-bottom:1px solid var(--ink-ghost);
}
.res-item:last-child{border-bottom:none}
.res-name{font-family:"Iowan Old Style",Palatino,Georgia,serif;font-size:1.05rem;
  color:var(--ink);transition:color 250ms ease}
.res-item:hover .res-name{color:var(--accent)}
.res-name .arrow{margin-left:.5em;color:var(--ink-ghost);font-size:.85em;
  transition:transform 250ms cubic-bezier(.32,.72,0,1),color 250ms ease;display:inline-block}
.res-item:hover .arrow{transform:translateX(.25em);color:var(--accent)}
.res-name{display:block}
.res-tradition{display:block;font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-mid);
  margin-top:.5em}
.res-note{display:block;font-size:.82rem;color:var(--ink-soft);margin-top:.35em;line-height:1.5}
.res-video{display:block;padding:.85em 0;border-bottom:1px solid var(--ink-ghost)}
.res-play{
  position:relative;display:block;width:100%;aspect-ratio:16/9;margin:0 0 .8em;padding:0;
  border:1px solid var(--ink-ghost);border-radius:3px;overflow:hidden;cursor:pointer;
  background:var(--ink-ghost);
}
.res-play img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 500ms cubic-bezier(.32,.72,0,1),opacity 300ms ease;opacity:.9}
.res-play:hover img{transform:scale(1.03);opacity:1}
.res-play-mark{
  position:absolute;inset:0;display:grid;place-items:center;
  font-size:1.5rem;color:#fff;text-shadow:0 1px 12px rgba(0,0,0,.6);
  transition:transform 400ms cubic-bezier(.32,.72,0,1);
}
.res-play:hover .res-play-mark{transform:scale(1.12)}
.res-video iframe{width:100%;aspect-ratio:16/9;border:1px solid var(--ink-ghost);
  border-radius:3px;margin-bottom:.8em;display:block}
.res-video .res-note a{color:var(--ink-faint);text-decoration:underline;
  text-underline-offset:2px;transition:color 250ms ease}
.res-video .res-note a:hover{color:var(--accent)}

.res-credit{margin-top:3.4em;padding-top:1.6em;border-top:1px solid var(--ink-ghost);
  font-size:.72rem;line-height:1.7;color:var(--ink-mid)}

@media (prefers-reduced-motion: reduce){
  .res,.res-tab,#stage{transition:none}
}
@media (max-width:680px), (max-height:560px) and (pointer:coarse){
  :root{--res-w:100vw}
  body.res-open #stage{padding-right:clamp(1.5rem,6vw,7rem)}
}

/* ---------------------------------------------------------------- rail */
.rail{position:fixed;left:0;right:0;bottom:0;height:1px;background:var(--ink-ghost);z-index:19;
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms}
#rail-fill{height:100%;width:0;background:var(--ink-faint);transition:width .6s cubic-bezier(.22,.68,.32,1)}

/* ---------------------------------------------------------------- hint */
.hint{
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms;
  position:fixed;bottom:clamp(1.1rem,3vh,2rem);left:50%;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;white-space:nowrap;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.68rem;letter-spacing:.04em;color:var(--ink-mid);
}
.hint-row{display:flex;align-items:center}

/* The third state. The row rises because the legend takes room beneath it, and
   the whole footer stays pinned to the bottom - nothing jumps. */
.hint-legend{
  display:grid;grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows 440ms cubic-bezier(.32,.72,0,1),opacity 300ms ease;
}
.hint-legend > span{overflow:hidden;padding-top:0;transition:padding-top 440ms cubic-bezier(.32,.72,0,1)}
.hint.legend .hint-legend{grid-template-rows:1fr;opacity:1}
.hint.legend .hint-legend > span{padding-top:1.1em}
/* .hint b has the same specificity and is declared later, so it would win and
   grey these out. Scope them to the footer to keep the letters lit. */
.hint .hint-legend b{font-weight:600;color:var(--accent);margin-right:.4em}
.hint .hint-legend i{font-style:normal;color:var(--ink-ghost);margin:0 .7em}
.hint .hint-legend{color:var(--ink-faint)}
.hint-items .act{cursor:pointer;transition:color 250ms ease}
.hint-items .act:hover,.hint-items .act:focus-visible{color:var(--ink);outline:none}
.hint-items .act:active{color:var(--accent)}
.hint b{font-weight:600;color:var(--ink-soft);transition:color .25s ease}
.hint .on,.hint .on b{color:var(--accent)}
.hint .msg{color:var(--accent)}

/* The triangle the hints fold back into. Deliberately larger than the hint text
   beside it, so it reads as a control rather than another label. */
.hint-toggle{
  flex:none;display:flex;align-items:center;justify-content:center;
  background:none;border:none;margin:0;padding:.55em .7em;cursor:pointer;
  color:var(--ink-faint);
  transition:color 400ms cubic-bezier(.32,.72,0,1);
}
.hint-toggle:hover,.hint-toggle:focus-visible{color:var(--ink);outline:none}
.hint-toggle:active{color:var(--accent)}          /* feedback on press, not release */
.hint.closed .hint-toggle{color:var(--ink-soft)}
.hint-toggle svg{
  fill:currentColor;
  transform:rotate(180deg);                       /* open: points back at itself */
  transition:transform 420ms cubic-bezier(.32,.72,0,1);
}
.hint.closed .hint-toggle svg{transform:rotate(0deg)}
.hint.legend .hint-toggle svg{transform:rotate(90deg)}
.hint.legend .hint-toggle{color:var(--accent)}

/* Items fold back toward the triangle, nearest first. Only transform and opacity
   are animated - the width easing is what used to force layout on every frame,
   which is what made this feel abrupt. Critically damped: no overshoot, since
   nothing here carries momentum from a gesture. */
.hint-items{
  display:flex;align-items:center;gap:1.6em;overflow:hidden;
  max-width:80em;padding-left:.9em;
  transition:max-width 460ms cubic-bezier(.32,.72,0,1),
             padding-left 460ms cubic-bezier(.32,.72,0,1);
}
.hint.closed .hint-items{max-width:0;padding-left:0}
.hint-items span{
  will-change:transform,opacity;
  transition:transform 440ms cubic-bezier(.32,.72,0,1),
             opacity 300ms cubic-bezier(.32,.72,0,1);
  transition-delay:calc(var(--i) * 38ms);
}
.hint.closed .hint-items span{
  transform:translate3d(-.7em,0,0);               /* a fold, not a shrink */
  opacity:0;
  transition-delay:calc(var(--i) * 26ms);
}

/* ---------------------------------------------------------------- a clean page

   Just the verse and its reference. Everything else stops being visible without
   stopping taking up room, so not one word moves on the way in or out. */
body.clean .topbar,
body.clean .res-tab,
body.clean .rail,
body.clean .listening,
body.clean .hint,
body.clean .mnav{
  opacity:0;pointer-events:none;
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 0ms;
}
/* Sits exactly where the key hints sit, so the one replaces the other in place. */
.clean-out{
  position:fixed;bottom:clamp(1.1rem,3vh,2rem);left:50%;transform:translateX(-50%);
  z-index:17;background:none;border:none;margin:0;padding:.6em 1.1em;cursor:pointer;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.68rem;letter-spacing:.04em;color:var(--ink-mid);white-space:nowrap;
  opacity:0;pointer-events:none;
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 0ms,color 250ms ease;
}
.clean-out b{font-weight:600;color:var(--ink-soft)}
.clean-out:hover,.clean-out:focus-visible{color:var(--ink-soft);outline:none}
.clean-out:active{color:var(--accent)}
/* Faded down to almost nothing, since it is the only thing on the page besides
   the verse. Coming near it brings it back up. */
body.clean .clean-out{opacity:.55;pointer-events:auto;
  transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms,color 250ms ease}
body.clean .clean-out:hover,
body.clean .clean-out:focus-visible,
body.clean .clean-out:active{opacity:1;transition:opacity 180ms ease 0ms}

/* ---------------------------------------------------------------- touch controls
   Everything below is off unless the screen is small. The desktop reading is
   driven entirely by the keyboard and must not gain a single pixel of chrome. */
.mnav{display:none}
.msheet{display:none}
.res-close{display:none}

/* The study tab and the touch bar both sit above the veil, so they would land on
   top of an open overlay. Get them out of the way while one is up. */
body.overlay-open .res-tab,
body.overlay-open .mnav{opacity:0;pointer-events:none;transition:opacity 180ms ease}

/* The topics at the foot of "how to navigate" were a plain list eating half the
   screen. They are targets now - pressing one goes there - laid out two across. */
.howto-lead{
  margin:2.6em 0 1.2em;
  font-family:"Iowan Old Style",Palatino,Georgia,serif;
  font-size:.95rem;line-height:1.6;color:var(--ink-soft);
}
.howto-topics{
  display:grid;grid-template-columns:repeat(2,1fr);gap:.6rem;
}
.howto-topics button{
  display:block;width:100%;text-align:left;cursor:pointer;
  padding:.85em 1em;margin:0;
  background:none;border:1px solid var(--ink-ghost);border-radius:4px;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
  font-size:.92rem;color:var(--ink);
  -webkit-tap-highlight-color:transparent;
  transition:border-color 220ms ease,color 220ms ease,background 220ms ease;
}
.howto-topics button:hover,.howto-topics button:focus-visible{
  border-color:var(--ink-faint);color:var(--accent);outline:none;
}
.howto-topics button:active{background:var(--ink-ghost);color:var(--accent)}

/* ---------------------------------------------------------------- overlay */
.veil{
  position:fixed;inset:0;background:var(--paper);
  display:grid;place-items:center;padding:clamp(2rem,7vh,5rem) clamp(1.5rem,6vw,7rem);
  z-index:22;animation:veil .28s ease both;overflow-y:auto;overflow-x:hidden;
}
@keyframes veil{from{opacity:0}to{opacity:1}}
.panel{width:100%;max-width:44em;min-width:0;overflow-wrap:anywhere;
  font-family:ui-sans-serif,-apple-system,system-ui,sans-serif}
.panel h2{
  font-family:inherit;font-size:.74rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-mid);margin-bottom:2em;
}
.panel .esc{
  position:fixed;top:clamp(1.2rem,3.5vh,2.4rem);right:clamp(1.5rem,6vw,7rem);
  background:none;border:none;padding:.4em .5em;margin:0;cursor:pointer;
  font-family:inherit;font-size:.68rem;letter-spacing:.1em;color:var(--ink-faint);
  transition:color 250ms ease;
}
.panel .esc:hover,.panel .esc:focus-visible{color:var(--ink);outline:none}

/* keys grid */
.keys{display:grid;grid-template-columns:repeat(auto-fill,minmax(15em,1fr));gap:.85em 2.5em}
.keys div{display:flex;align-items:baseline;gap:.9em;font-size:.86rem;color:var(--ink-soft)}
.keys kbd{
  font-family:inherit;font-size:.7rem;font-weight:600;min-width:2.1em;text-align:center;
  padding:.32em .5em;border:1px solid var(--ink-ghost);border-radius:5px;color:var(--ink);
  background:var(--ink-ghost);flex:none;
}
.keys .grp{grid-column:1/-1;margin-top:1.4em;font-size:.68rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-mid)}
.keys .grp:first-child{margin-top:0}
.about{margin-top:3.4em;padding-top:1.6em;border-top:1px solid var(--ink-ghost);
  font-size:.76rem;color:var(--ink-mid)}
.linkish{
  background:none;border:none;padding:0;margin:0;cursor:pointer;
  font-family:inherit;font-size:.86rem;color:var(--accent);
  text-decoration:underline;text-underline-offset:3px;
  transition:opacity .25s ease;
}
.linkish:hover,.linkish:focus-visible{opacity:.7;outline:none}

/* thought composer */
textarea{
  width:100%;min-height:9em;background:none;border:none;outline:none;resize:none;
  font-family:"Iowan Old Style",Palatino,Georgia,serif;font-size:1.35rem;line-height:1.6;
  color:var(--ink);caret-color:var(--accent);
}
textarea::placeholder{color:var(--ink-faint)}
.composer-ref{font-size:.74rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink-mid);margin-bottom:1.6em}
.composer-ref .just{margin-left:1.2em;color:var(--accent);letter-spacing:.1em;text-transform:none}
.composer-ref .count{float:right;color:var(--ink-mid);letter-spacing:.12em}
.composer-ref .tr{margin-left:.9em;color:var(--ink-faint)}
.composer-verse{font-family:"Iowan Old Style",Palatino,Georgia,serif;font-size:1rem;overflow-wrap:anywhere;
  line-height:1.6;color:var(--ink-soft);margin-bottom:2.2em;max-width:34em}
.composer-hint{margin-top:1.6em;font-size:.7rem;color:var(--ink-mid);letter-spacing:.04em}

/* journal */
.entry{padding:1.5em 0;border-bottom:1px solid var(--ink-ghost)}
.entry:last-child{border:none}
.entry .er{font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mid);
  overflow-wrap:anywhere}
.entry .et{font-family:"Iowan Old Style",Palatino,Georgia,serif;font-size:1.02rem;
  line-height:1.62;color:var(--ink);margin-top:.7em;
  white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word}
.entry .ed{font-size:.7rem;color:var(--ink-mid);margin-top:.6em}
.empty{color:var(--ink-soft);font-size:.9rem;line-height:1.7}
.stat{display:flex;gap:3em;margin-bottom:2.6em}
.stat div b{display:block;font-family:"Iowan Old Style",Palatino,Georgia,serif;
  font-size:2.2rem;font-weight:400;color:var(--ink)}
.stat div span{font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mid)}

@media (prefers-reduced-motion: reduce){
  .verse.draw .c{animation:fade .4s ease both}
  @keyframes fade{from{opacity:0}to{opacity:1}}
  .pip{animation:none;opacity:.7}
  /* no travel, no stagger - just a gentle cross-fade */
  .hint-items span{transition:opacity 200ms ease;transition-delay:0ms}
  .hint.closed .hint-items span{transform:none;transition-delay:0ms}
  .hint-toggle svg{transition:none}
  .opening .c,.hint-items{transition-duration:1ms}
}
@media (max-width:640px){
  .hint-items{gap:1.1em}
  .hint{font-size:.62rem}
  /* the legend is far too long for a phone in one line */
  .hint .hint-legend{white-space:normal;max-width:88vw;text-align:center;line-height:2}
  .hint .hint-legend i{margin:0 .45em}
  .topbar{max-width:92vw}
  .topbar-label{white-space:normal;text-align:center}
  .verse{max-width:100%}
}


/* ================================================================== mobile
   A phone has no keyboard, so every action that was a keystroke gets a target.
   Scoped entirely to small screens: nothing here reaches the desktop layout. */
@media (max-width:680px), (max-height:560px) and (pointer:coarse){

  /* the keyboard hints are meaningless without a keyboard */
  .hint{display:none}
  /* On the line the control bar's labels sit on, so the word does not move when
     the bar goes and this takes its place. */
  .clean-out{bottom:calc(.85rem + env(safe-area-inset-bottom,0));font-size:.66rem;padding:.7em 1.2em}

  /* the reading itself, tightened */
  #stage{
    padding:calc(4.2rem + env(safe-area-inset-top,0)) 1.25rem 5.9rem calc(1.25rem + env(safe-area-inset-left,0));
    touch-action:pan-y;
    display:flex;overflow-y:auto;-webkit-overflow-scrolling:touch;
  }
  /* margin:auto centres it and still lets a long verse scroll. The bottom padding
     carries it above centre; the right keeps the lines off the edge, which reads
     as deliberate rather than as text that ran out of room. */
  /* auto top and bottom centres it vertically; left 0 keeps the text against the
     left edge instead of drifting to the middle once the screen is wide. */
  #verse-wrap{margin:auto auto auto 0;padding-bottom:17vh;padding-right:2.6rem;max-width:34rem}
  .verse{line-height:1.34;max-width:100%}
  .ref{margin-top:1.5rem;font-size:.66rem;letter-spacing:.14em}
  .ref .tr{margin-left:.7em}

  :root{--top-y:calc(1.15rem + env(safe-area-inset-top,0))}
  .topbar{
    left:calc(1.35rem + env(safe-area-inset-left,0));
    max-width:70vw;
  }
  .topbar-label{font-size:.9rem}
  .topbar-kicker{font-size:.56rem;letter-spacing:.14em}
  .topbar-menu{min-width:13em}

  /* the study tab has to clear the panel and stay reachable */
  .res-tab{right:0;padding:.55em .85em;font-size:.6rem}
  /* The chip is about 20px tall - well under the 44pt a thumb needs, which is why
     the tap missed as often as it landed. The hit area grows; the chip does not. */
  .res-tab::after{content:"";position:absolute;inset:-13px -10px -13px -16px}
  body.res-open .res-tab{transform:translate3d(0,-150%,0);opacity:0;pointer-events:none}

  /* both of these sat underneath the control bar, which is opaque */
  .rail{bottom:calc(3.4rem + env(safe-area-inset-bottom,0))}
  .listening{bottom:calc(4.5rem + env(safe-area-inset-bottom,0))}

  .mnav{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:18;
    transition:opacity 380ms cubic-bezier(.32,.72,0,1) 220ms;
    padding-left:calc(.5rem + env(safe-area-inset-left,0));padding-right:.5rem;
    align-items:stretch;
    padding-bottom:env(safe-area-inset-bottom,0);
    background:var(--paper);border-top:1px solid var(--ink-ghost);
  }
  .mnav-b{
    flex:1 1 0;min-width:0;min-height:3.4rem;
    display:flex;align-items:center;justify-content:center;
    background:none;border:none;margin:0;padding:.5em .2em;cursor:pointer;
    font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
    font-size:.63rem;letter-spacing:.1em;text-transform:uppercase;
    color:var(--ink-mid);-webkit-tap-highlight-color:transparent;
    transition:color 200ms ease,background 200ms ease;
  }
  .mnav-b:active{background:var(--ink-ghost);color:var(--ink)}
  .mnav-b.on{color:var(--accent)}
  .mnav-b[data-act="prev"] span,.mnav-next span{font-size:1.5rem;line-height:1}
  .mnav-b[data-act="prev"],.mnav-next{flex:0 0 3.1rem;color:var(--ink-mid)}
  .mnav-next{color:var(--accent)}

  /* the sheet behind "more" */
  .msheet{
    display:block;position:fixed;inset:0;z-index:19;
    background:rgba(0,0,0,.22);
    animation:msheetIn 260ms cubic-bezier(.32,.72,0,1) both;
  }
  @keyframes msheetIn{from{opacity:0}to{opacity:1}}
  .msheet-panel{
    position:absolute;left:env(safe-area-inset-left,0);right:0;bottom:0;
    background:var(--paper);border-top:1px solid var(--ink-ghost);
    border-radius:12px 12px 0 0;
    padding:.6rem 0 calc(.6rem + env(safe-area-inset-bottom,0));
    animation:msheetUp 320ms cubic-bezier(.32,.72,0,1) both;
  }
  @keyframes msheetUp{from{transform:translateY(100%)}to{transform:none}}
  .msheet-panel::before{
    content:"";display:block;width:2.2rem;height:3px;border-radius:2px;
    background:var(--ink-ghost);margin:.35rem auto .9rem;
  }
  .msheet-row{
    display:flex;align-items:center;justify-content:space-between;gap:1em;
    width:100%;background:none;border:none;cursor:pointer;
    padding:.95rem 1.5rem;text-align:left;
    font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;font-size:.92rem;
    color:var(--ink);-webkit-tap-highlight-color:transparent;
  }
  .msheet-row:active{background:var(--ink-ghost)}
  .msheet-row i{font-style:normal;font-size:.76rem;color:var(--ink-mid)}

  /* the study panel takes the whole screen - there is no room beside it */
  :root{--res-w:100vw}
  body.res-open #stage{padding-right:1.35rem}
  .res{border-left:none;z-index:20}          /* over the control bar: the whole page */
  body.res-open .mnav{opacity:0;pointer-events:none;transition:opacity 200ms ease}
  .res-inner{padding:1.2rem 1.35rem calc(2rem + env(safe-area-inset-bottom,0))}
  .res-close{
    display:flex;align-items:center;gap:.5em;
    position:sticky;top:0;z-index:2;width:100%;
    background:var(--paper);border:none;margin:0 0 1.2rem;padding:.7rem 0;
    cursor:pointer;font-family:ui-sans-serif,-apple-system,system-ui,sans-serif;
    font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent);
  }

  /* overlays and the opening need room for thumbs, not a desktop's margins */
  /* The header stays through an overlay - it is how you change topic from here -
     so the overlay starts below it rather than under it. */
  .veil{
    place-items:stretch;
    padding:calc(5.1rem + env(safe-area-inset-top,0)) 1.35rem calc(4.6rem + env(safe-area-inset-bottom,0));
  }
  /* the note saves on its own; there is no need to say so every time */
  .panel[data-kind="thought"] .composer-hint{display:none}
  /* the writing space is the point of this screen, so give it what is left */
  .panel[data-kind="thought"]{display:flex;flex-direction:column;padding-bottom:0}
  .panel[data-kind="thought"] h2{margin-bottom:1.1em}
  .panel[data-kind="thought"] .composer-ref{margin-bottom:.9em}
  .panel[data-kind="thought"] .composer-verse{margin-bottom:1.1em;max-width:none}
  .panel[data-kind="thought"] textarea{
    flex:1 1 auto;min-height:38vh;
    padding-top:.2em;border-top:1px solid var(--ink-ghost);
  }
  .panel[data-kind="thought"] .composer-hint{margin-top:1em}
  .panel .esc{
    top:auto;bottom:calc(1.1rem + env(safe-area-inset-bottom,0));right:1.15rem;
    padding:.75em 1.4em;border:1px solid var(--ink-ghost);border-radius:3px;
    background:var(--paper);
    font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent);
  }
  .panel{padding-bottom:4.5rem}             /* room for it, clear of the writing */
  .opening{padding:calc(3.4rem + env(safe-area-inset-top,0)) 1.35rem 4rem}
  .op-verse{font-size:clamp(1.3rem,5.4vw,1.7rem)}
  .op-name{font-size:clamp(1.5rem,6.4vw,2rem)}
  .op-line,.op-need-lead{font-size:.88rem}
  .gate{padding:calc(3rem + env(safe-area-inset-top,0)) 1.6rem 3rem calc(1.6rem + env(safe-area-inset-left,0))}
  textarea{font-size:1.15rem}
  .composer-verse{font-size:.92rem}
}

/* a phone in landscape is short, not roomy */
/* A phone on its side is wide and short. Left to itself the measure stretches the
   full width and the chrome eats the height, so pull both in. */
@media (max-height:560px) and (pointer:coarse){
  /* the header is ~60px tall here, so the reading has to start below it */
  #stage{padding:calc(4.1rem + env(safe-area-inset-top,0)) 1.6rem 4.2rem calc(1.6rem + env(safe-area-inset-left,0))}
  .rail{bottom:calc(2.7rem + env(safe-area-inset-bottom,0))}
  .listening{bottom:calc(3.6rem + env(safe-area-inset-bottom,0))}
  .gate{padding:1.6rem 1.6rem 1.6rem calc(1.6rem + env(safe-area-inset-left,0))}
  #verse-wrap{margin:auto auto auto 0;max-width:30rem;padding-bottom:8vh;padding-right:2rem}
  .verse{line-height:1.28}
  .ref{margin-top:.9rem}
  :root{--top-y:calc(.6rem + env(safe-area-inset-top,0));--tab-drop:1.23rem}
  .topbar{left:calc(1.6rem + env(safe-area-inset-left,0))}
  .res-tab{padding:.42em .75em}
  .mnav-b{min-height:2.7rem;font-size:.6rem}
  .clean-out{bottom:calc(.55rem + env(safe-area-inset-bottom,0))}  /* a shorter bar sits lower */
  .mnav-b[data-act="prev"],.mnav-next{flex:0 0 3.4rem}
  .veil{padding:calc(4.4rem + env(safe-area-inset-top,0)) 1.6rem calc(3.6rem + env(safe-area-inset-bottom,0)) calc(1.6rem + env(safe-area-inset-left,0))}

  /* On its side there is width to spare, so study opens BESIDE the reading rather
     than over it - the same arrangement as a desktop, and the reading stays in
     view while you read about it. */
  :root{--res-w:min(48vw,392px)}
  .res{border-left:1px solid var(--ink-ghost);z-index:15}
  .res-inner{padding:1.1rem 1.2rem calc(1.6rem + env(safe-area-inset-bottom,0))}
  .res-close{display:none}                      /* the tab is still on screen here */
  body.res-open .res-tab{
    transform:translate3d(calc(-1 * var(--res-w)),0,0);
    opacity:1;pointer-events:auto;
  }
  body.res-open .mnav{opacity:1;pointer-events:auto;right:var(--res-w)}
  body.res-open .rail{right:var(--res-w)}
  /* One gutter, not two: the column's own right margin is what opened a band of
     dead paper between the last word and the panel. */
  body.res-open #stage{padding-right:calc(var(--res-w) + 1.5rem)}
  body.res-open #verse-wrap{padding-right:0;max-width:none}
  .panel[data-kind="thought"] textarea{min-height:20vh}
  .opening{padding:2.2rem 1.25rem 2.6rem}
  #op-body{max-width:30rem}
  .op-verse{font-size:clamp(1.1rem,3.4vw,1.5rem)}
  .msheet-row{padding:.7rem 1.5rem}
}
