/* ============================================================================
   coda-buttons.css — THE CODA BUTTON.  OK-U5 · v0
   ----------------------------------------------------------------------------
   The one thing on a page a visitor PRESSES, designed as a press.

   The ladder the field already climbs — pulli, then the line, then the ink —
   is the whole grammar. A button is a rung on it:

     THE WORD   .kbtn         the quiet act. A word; the pen underlines it as
                              the hand arrives (drawn left to right, never
                              faded in), and takes the line away to the right.
     THE LINE   .kbtn.line    the open act. A pill whose rim is a row of
                              pulli; the hand JOINS them into the line; the
                              press pours the ink.
     THE INK    .kbtn.ink     the committed act — at most one per leaf. The
                              line already closed. The hand raises the bow one
                              level (a second ring, one step out) and the
                              press sets the nib down: the ring tightens and
                              the button gives one pixel.

   THE LIMIT (figured 2026-08-29). On a screen a woven LETTER holds only
   while its field's tile keeps ~2.4px — the Latin hand is 14 rows, so a
   name reads at ≥ 34px letter height (देवनागरी, 22 rows, at ≥ 53px); at
   20px it survives as a mark; at button height it is simply ink. So BUTTON
   WORDS ARE HERSHEY, always — data-coda on a .kbtn below the limit is
   refused by the hand (coda-buttons.js strips it; the label stays type).
   And no stroke on a screen goes under .4px (0.3 pt) — the pen's floor.

   THE WOVEN CODA. The coda a button carries is a FIGURE, not letters:
   data-weave (its own seed, or the label's) presses two mirrored bands of
   the weave — one continuous sikku line, cell ~9px, well above the limit —
   flanking the word, and the figure DRAWS ITSELF when the button first
   scrolls into view: the same pen that joins the rim's pulli. A designed
   figure from the mural press rides in on the seed.

     CHOSEN    .on / [aria-pressed="true"]  the line closed on a toggle.
     WORKING   [aria-busy="true"] / .working  the pen travels the rim until
                                            the work is done. Nothing spins;
                                            something is being drawn.
     DISABLED  :disabled                    the line not yet drawn — the dots
                                            stay dots and the ink thins.
     THE DROP  every press lands one ring from the nib's point, gone in half
               a second — the window's water. Skipped for visitors who ask
               for reduced motion.

   Two inks only — var(--ink) on var(--paper) — so one law stands on the
   white page and on the black market. No grey, no shadow, no border. The rim
   and the traveling pen are one injected SVG (coda-buttons.js); without the
   script the ladder still stands, the rim simply holds a plain drawn line.

   Load AFTER kala-ui.css (public leaves) or studio.css (benches).
============================================================================ */

/* ─── the rung every voice shares ────────────────────────────────────────── */
.kbtn, button.kbtn, a.kbtn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  font-family: var(--hand, inherit) !important;
  font-size: .7rem !important; font-weight: 400 !important; letter-spacing: .12em;
  text-transform: uppercase; font-style: normal; line-height: 1.1;
  color: var(--ink, #000) !important;
  background-color: transparent !important; background-image: none !important;
  border: 0 !important; border-radius: 999px !important;
  padding: .55rem .4rem !important; min-height: 0;
  box-shadow: none !important; opacity: 1;
  text-decoration: none !important;
  cursor: pointer; user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  outline: 1px solid transparent; outline-offset: 3px;
  transition: transform .12s ease, color .15s ease, background-color .15s ease,
              outline-color .18s ease, outline-offset .18s ease;
}
/* the nib touches the paper */
.kbtn:active { transform: translateY(1px); }
/* the finger's landing band — the pill is smaller than a fingertip */
.kbtn::after { content: ''; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 44px; border-radius: inherit; }

/* ─── THE WORD — the pen underlines it as the hand arrives ──────────────── */
.kbtn::before { content: ''; position: absolute; left: .4rem; right: .4rem;
  bottom: .3em; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left center;
  transition: transform .28s ease; }
.kbtn:hover::before, .kbtn:focus-visible::before { transform: scaleX(1); }
/* the loud rungs, the chosen and the still have no underline to draw */
.kbtn.line::before, .kbtn.ink::before, .kbtn.on::before,
.kbtn[aria-pressed="true"]::before, .kbtn:disabled::before { content: none; }
/* a working WORD writes its line, lets it go to the right, writes it again */
.kbtn[aria-busy="true"]::before, .kbtn.working::before {
  animation: kbtn-write 1.3s ease-in-out infinite;
}
@keyframes kbtn-write {
  0%   { transform: scaleX(0); transform-origin: left center; }
  45%  { transform: scaleX(1); transform-origin: left center; }
  55%  { transform: scaleX(1); transform-origin: right center; }
  100% { transform: scaleX(0); transform-origin: right center; }
}

/* ─── THE LINE — a rim of pulli; the hand joins them; the press pours ───── */
.kbtn.line, .kbtn.ink { padding: .6rem 1.35rem !important; }
.kbtn.line svg.kring, .kbtn.ink svg.kring {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; overflow: visible;
}
.kbtn.line svg.kring rect {
  fill: var(--ink, #000); fill-opacity: 0;
  stroke: var(--ink, #000); stroke-width: 1.3;
  stroke-linecap: round;
  /* pathLength=100: a pulli every 2.6 hundredths of the rim */
  stroke-dasharray: 0 2.6;
  transition: stroke-dasharray .32s ease, fill-opacity .15s ease, stroke-opacity .15s ease;
}
/* the dots join into the line */
.kbtn.line:hover svg.kring rect,
.kbtn.line:focus-visible svg.kring rect { stroke-dasharray: 2.6 0; }
.kbtn.line:focus-visible { outline-color: transparent; }
/* the press pours the ink */
.kbtn.line:active { color: var(--paper, #fff) !important; }
.kbtn.line:active svg.kring rect { fill-opacity: 1; stroke-dasharray: 2.6 0; }
/* without the hand (no script) the rim is simply the drawn line */
.kbtn.line:not(:has(svg.kring)) { box-shadow: inset 0 0 0 1px var(--ink, #000) !important; }

/* ─── THE INK — the line already closed; the hand raises the bow ────────── */
.kbtn.ink {
  background-color: var(--ink, #000) !important;
  color: var(--paper, #fff) !important;
}
.kbtn.ink:hover  { outline-color: var(--ink, #000); }
.kbtn.ink:active { outline-color: var(--ink, #000); outline-offset: 1px; }
.kbtn.ink svg.kring rect {
  fill: none; stroke: var(--paper, #fff); stroke-width: 1.3;
  stroke-linecap: round; stroke-dasharray: 24 76; stroke-opacity: 0;
}
/* attention is the same raised bow */
.kbtn:focus-visible { outline-color: var(--ink, #000); }

/* ─── CHOSEN — the line closed on a toggle ──────────────────────────────── */
.kbtn.on, .kbtn[aria-pressed="true"] {
  background-color: var(--ink, #000) !important;
  color: var(--paper, #fff) !important;
}
.kbtn.line.on svg.kring rect,
.kbtn.line[aria-pressed="true"] svg.kring rect { fill-opacity: 1; stroke-dasharray: 2.6 0; }

/* ─── WORKING — the pen travels the rim until the work is done ──────────── */
.kbtn[aria-busy="true"], .kbtn.working { pointer-events: none; cursor: progress; }
.kbtn.line[aria-busy="true"] svg.kring rect, .kbtn.line.working svg.kring rect,
.kbtn.ink[aria-busy="true"]  svg.kring rect, .kbtn.ink.working  svg.kring rect {
  stroke-dasharray: 24 76; stroke-opacity: 1; fill-opacity: 0;
  animation: kbtn-travel 1.15s linear infinite;
}
.kbtn.ink[aria-busy="true"], .kbtn.ink.working { outline-color: transparent; }
@keyframes kbtn-travel { to { stroke-dashoffset: -100; } }

/* ─── DISABLED — the line not yet drawn ─────────────────────────────────── */
.kbtn:disabled, .kbtn[aria-disabled="true"] {
  opacity: .35 !important; cursor: default; pointer-events: none; transform: none;
}

/* ─── the three sizes ───────────────────────────────────────────────────── */
.kbtn.sm { font-size: .62rem !important; padding: .38rem .35rem !important; }
.kbtn.sm.line, .kbtn.sm.ink { padding: .38rem 1rem !important; }
.kbtn.lg { font-size: .8rem !important; letter-spacing: .14em; padding: .8rem .5rem !important; }
.kbtn.lg.line, .kbtn.lg.ink { padding: .8rem 1.9rem !important; }

/* ─── THE LIMIT — button words are Hershey ───────────────────────────────
   A woven name needs its tile ≥ ~2.4px: 14 rows → ≥ 34px letter height on
   screen. No button is that tall; coda-buttons.js strips data-coda from any
   .kbtn under the limit so the label falls back to the hand's type. These
   rules only dress the rare hero-scale act that clears it. */
.kbtn[data-coda] { --coda-h: 36px; }
.kbtn svg.coda-word { display: block; width: auto; height: auto; max-width: none; }
/* the woven NAME's text stays for readers and machines, not for the eye
   (restated here so the sheet stands on leaves without kala-ui.css) */
.kbtn .coda-text { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }

/* ─── THE WOVEN CODA — the button's figure, drawn on arrival ─────────────
   Two mirrored bands of one continuous line flank the word (injected by
   coda-buttons.js from data-weave's seed, or the label's). Until the button
   scrolls into view the line is not yet drawn; then the pen travels it —
   dasharray/offset are set per-path inline, only the release lives here.
   Stroke ≈ .8px on screen: above the .4px (0.3 pt) floor, always. */
.kbtn .kweave { display: block; line-height: 0; color: inherit; pointer-events: none; }
.kbtn .kweave svg { display: block; height: 1.5em; width: auto; }
.kbtn .kweave.right svg { transform: scaleX(-1); }
.kbtn .kweave path { transition-property: stroke-dashoffset;
  transition-timing-function: cubic-bezier(.25, .5, .3, 1); }
.kbtn.kdrawn .kweave path { stroke-dashoffset: 0 !important; }
@media (prefers-reduced-motion: reduce) {
  .kbtn .kweave path { transition: none !important; stroke-dashoffset: 0 !important; }
}

/* ─── THE DROP — the press lands as one ring of the window's water ──────── */
.kbtn .kclip { position: absolute; inset: 0; border-radius: inherit;
  overflow: hidden; pointer-events: none; }
.kbtn .kdrop { position: absolute; width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border-radius: 999px !important;
  border: 1.5px solid currentColor !important; border-color: currentColor !important;
  background: transparent; opacity: .9; transform: scale(.2);
  animation: kbtn-drop .5s ease-out forwards; }
@keyframes kbtn-drop { to { transform: scale(var(--kd, 18)); opacity: 0; } }

/* ─── stillness, honoured ───────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .kbtn, .kbtn::before, .kbtn svg.kring rect { transition: none !important; animation: none !important; }
  .kbtn .kdrop { display: none; }
  /* working holds the drawn line instead of traveling it */
  .kbtn.line[aria-busy="true"] svg.kring rect, .kbtn.line.working svg.kring rect,
  .kbtn.ink[aria-busy="true"]  svg.kring rect, .kbtn.ink.working  svg.kring rect {
    stroke-dasharray: 2.6 0; stroke-opacity: 1;
  }
  .kbtn[aria-busy="true"]::before, .kbtn.working::before { transform: scaleX(1); }
}
