/* ledger-rule.css — the Ledger Rule, ported from LedgerRuleView.swift.
   Shippable as-is. The scroll binding is ledger-rule.js.

   A fixed ruler of short horizontal marks down the right-hand edge of
   the viewport. The marks never move. Position is carried by WIDTH: the
   marks lying inside the current scroll window grow outward, and shrink
   back to the ruler as the window passes them. There is no thumb and no
   track line — the lit run is the thumb.

   Every length here is a token so the rule can be retuned without
   touching the JS, which reads the pitch, the inset and the band floor
   back off these custom properties at build time. */

:root {
  --rule-gutter:   18px;   /* the rule's column, flush to the edge it sits on */
  /* How much of that gutter is taken out of the INLINE axis. The
     vertical rule reserves it on the right; the horizontal one reserves
     nothing there, and full-bleed elements measuring against 100vw need
     to know which. */
  --rule-gutter-inline: var(--rule-gutter);
  --rule-mark-h:   1.5px;  /* never past 2px — see the note below */
  --rule-mark-off: 3px;
  --rule-mark-on:  5.5px;
  --rule-pitch:    14px;   /* centre to centre, fixed */
  --rule-inset:    10px;   /* the first mark's y, and the tail margin */
  --rule-band-min: 28px;   /* floor on the lit band */

  --rule-grow:     0.18s;  /* per-mark width transition */
  --rule-fade-in:  0.12s;
  --rule-fade-out: 0.35s;

  /* The off mark is the page's ink at 22%, not a grey. The on mark is
     the flat accent at full strength — no gradient, no glow, no shadow.
     Both are overridable; a host with its own accent should point
     --rule-on at it rather than edit this file. */
  --rule-off: rgba(236, 234, 224, 0.22);
  --rule-on:  #FF5A1F;
}

@media (prefers-color-scheme: light) {
  :root {
    --rule-off: rgba(22, 23, 27, 0.22);
    --rule-on:  #D6480F;
  }
}

/* THE GUTTER IS RESERVED WITH PADDING, NEVER A MARGIN.
   A margin on the scrolling element becomes scrollable overflow; padding
   does not. The native bar goes at the same time — the rule replaces it,
   it does not sit beside it. */
html {
  padding-right: var(--rule-gutter-inline);
  scrollbar-width: none;
}
html::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* HORIZONTAL: the rule runs across the TOP instead of down the right.
   Same rule, transposed — the marks become short vertical ticks, growth
   runs downward out of the top edge instead of leftward out of the right
   one, and the pitch runs along x. Everything in §2-§5 holds with the
   axes swapped; nothing about the band arithmetic changes, because the
   band was always a fraction of the ruler's own length. */
html[data-ledger-rule="horizontal"] {
  --rule-gutter-inline: 0px;
  padding-top: var(--rule-gutter);
}

/* ...EXCEPT WHERE THERE WAS NEVER A BAR TAKING SPACE.
   The reservation exists to give back what hiding the native scrollbar
   took away. On a touch-primary device the native indicator is an
   overlay and takes no layout width, so reserving here does not give
   anything back — it ADDS 18px to one side of every section and
   unbalances padding that was set symmetrically. The rule still draws;
   it just overlays, and at 5.5px against a screen edge it clears any
   content that has a phone's ordinary side padding. */
@media (hover: none) and (pointer: coarse) {
  html { padding-right: 0; --rule-gutter-inline: 0px; }
  html[data-ledger-rule="horizontal"] { padding-top: 0; }
}

.ledger-rule {
  position: fixed;
  top: 0;
  right: 0;
  width: var(--rule-gutter);
  height: 100vh;
  height: 100dvh;
  z-index: 2147483000;

  /* INDICATOR, NOT A CONTROL. Nothing is draggable and nothing is
     clickable, so the 18px of ink needs no 44px hit target — and must
     not eat clicks meant for the page underneath. */
  pointer-events: none;

  opacity: 0;
  transition: opacity var(--rule-fade-out) linear;
}

/* Quick in, slower out — the same asymmetry a native scroll indicator
   uses, so it does not snatch itself away the instant you stop. */
.ledger-rule.is-awake {
  opacity: 1;
  transition-duration: var(--rule-fade-in);
}

/* Nothing to indicate: the JS sets this when the document is no taller
   than the viewport. Render nothing at all, not a full-height lit band. */
.ledger-rule[hidden] { display: none !important; }

/* MARKS ARE RIGHT-ALIGNED, NOT CENTRED IN THE GUTTER.
   A lit mark grows leftward out of the edge and the whole run keeps one
   straight right margin. Centred, the growth expands around its own
   centre and reads as a pulse rather than as an edge being pulled out
   of the screen.

   NEVER THICKEN A MARK PAST 2px. The whole signal is the width step; a
   taller mark turns the ruler into a texture and the step stops
   reading. */
.ledger-rule > i {
  position: absolute;
  right: 0;
  display: block;
  height: var(--rule-mark-h);
  width: var(--rule-mark-off);
  background: var(--rule-off);
  border-radius: 0;          /* square marks — no rounded ends */
  transition:
    width var(--rule-grow) linear,
    background-color var(--rule-grow) linear;
}

.ledger-rule > i.is-on {
  width: var(--rule-mark-on);
  background: var(--rule-on);
}

/* ── horizontal variant ──────────────────────────────────────────
   The rule lies along the top edge. Marks are TOP-aligned, which is the
   transpose of right-aligned: a lit mark grows downward out of the edge
   and the whole run keeps one straight top margin. */
.ledger-rule--x {
  top: 0;
  left: 0;
  right: auto;
  width: 100vw;
  width: 100dvw;
  height: var(--rule-gutter);
}

.ledger-rule--x > i {
  right: auto;
  top: 0;
  width: var(--rule-mark-h);
  height: var(--rule-mark-off);
  transition:
    height var(--rule-grow) linear,
    background-color var(--rule-grow) linear;
}

.ledger-rule--x > i.is-on {
  width: var(--rule-mark-h);
  height: var(--rule-mark-on);
}

/* Reduced motion drops the growth and the fade. Marks in the band render
   at full width immediately, marks outside at off width — and the rule
   stays permanently visible, since the fade was the only thing hiding
   it. */
@media (prefers-reduced-motion: reduce) {
  .ledger-rule            { opacity: 1; transition: none; }
  .ledger-rule.is-awake   { transition: none; }
  .ledger-rule > i        { transition: none; }
}
