// ============================================================ // BLIND QUILL — shared components // Stateless presentational pieces, exported to window. // ============================================================ const { useState, useEffect, useRef } = React; // ---------- Icons (stroke-only, 24x24) ---------- function Icon({ name, size = 18, stroke = 1.7, style }) { const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round", style, }; switch (name) { case "quill": return ( ); case "lock": return (); case "arrow-right": return (); case "arrow-left": return (); case "plus": return (); case "book": return (); case "link": return (); case "seal": return (); case "check": return (); case "scroll": return (); case "eye-off": return (); default: return null; } } // ---------- Wordmark ---------- function Wordmark({ onClick }) { return (
Blind Quill The Invisible Bindery
); } // ---------- Buttons ---------- function Btn({ kind = "ghost-paper", size, icon, iconRight, children, onClick, disabled, type }) { const cls = ["btn", `btn--${kind}`, size ? `btn--${size}` : ""].join(" "); return ( ); } // ---------- Badge + Ledger ---------- function StatusBadge({ status }) { const sealed = status === "sealed"; return ( {sealed ? "Sealed" : "Open"} ); } function Ledger({ count, max, sealed }) { const pct = Math.round((count / max) * 100); return ( {count} / {max} ); } // ---------- Veiled lines (blinded text) ---------- function Veil({ lines = 4, widths }) { const ws = widths || Array.from({ length: lines }, (_, i) => 70 + ((i * 37) % 28)); return (