132 Commits

Author SHA1 Message Date
kennethreitz 4a452a7564 Repeated end-word is a monorhyme (again / again)
A word repeated at line endings now colors as a rhyme family, since
that's a real monorhyme scheme. Guarded so it stays refrain (not
colored) when: the whole lines are identical duplicates, the word is a
hook used 4+ times, or it's a repeated phrase rather than a single
word. Mid-line repetition is still refrain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 12:47:57 -04:00
kennethreitz 11eda0ab52 Add "Contact the author" button in the header
Mailto link (styled as a button) to Kenneth in the top-right; brand +
tagline wrapped on the left, stacks cleanly on mobile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 12:28:42 -04:00
kennethreitz b3a5b5eaf7 Mobile polish: safe-area, no h-overflow, bigger tap targets
- viewport-fit=cover + env(safe-area-inset) padding so content clears
  the notch / home indicator
- overflow-x:hidden and -webkit-tap-highlight-color:transparent
- roomier buttons/tabs/toggles and touch-action:manipulation on mobile
- (editor layers already wrap via pre-wrap, so long bars never scroll
  sideways; 16px inputs already prevent iOS zoom-jump)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:58:28 -04:00
kennethreitz e332b4fae7 SEO pass + OG card
- Full meta set: canonical, Twitter summary_large_image card, og:image/
  site_name/locale, author, robots, JSON-LD WebApplication
- Semantic <h1>/<p> for the wordmark and tagline (was divs)
- /robots.txt and /sitemap.xml routes (before the static mount)
- og.png (1200x630): wordmark + a color-coded verse so the share card
  shows what the tool does

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:56:44 -04:00
kennethreitz 2bb36f0c03 Add self-hosted Umami analytics
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:51:58 -04:00
kennethreitz cd88f17455 Rewrite README for current feature set
Updates the visual-language and engine descriptions to match what
shipped (color=family, brightness=strength, near-miss radar, hover,
PNG export, taste-tuned precision, paren/annotation handling), drops
removed features (stanza reordering, dictionary definitions), adds
license + live URL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:50:29 -04:00
kennethreitz 33ea42dc6e Add ISC license
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:38:12 -04:00
kennethreitz 9360d37187 ( lines are lyrics, not ignored annotations
Only # and [ lines are skipped now; full-line parentheticals are real
lyrics (MF DOOM's whole style) and get analyzed, sid'd, and rhymed.
Inline-paren ad-lib handling (rhyme internally, never claim the end
slot) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 08:22:02 -04:00
kennethreitz 4c99908d79 Phrases don't dangle on an open-vowel stopword tail
"smell like a" was matching "myself why" (EH-AY) because mosaic triples
were never weak-flagged — a trailing article "a" (bare open vowel)
dangles and isn't part of the rhyme. Triples now skip an open-syllable
stopword tail, while closed ones ("mean to it" -> theme music) stay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 18:06:35 -04:00
kennethreitz 23cc6434f7 Consonance only on the ending, not a buried stress
meticulous (me-TIC-ulous, IH-K under -ulous) was consonance-rhyming
quick. Consonance now fires only when the stressed vowel is within one
syllable of the word end — people/sleep still rhymes, meticulous/quick
doesn't. Gated the projection side too, so a long-rime group stops
advertising a misleading stressed-syllable consonance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 17:42:13 -04:00
kennethreitz 5f22e28721 Export PNG matches the editor: tints, strength, underlines, opens, near-miss
The export now mirrors render() — per-token fills scaled by strength,
rhyming words tinted in their family color, sub-word tail underlines,
gray unanswered endings, near-miss dotted marks, plus the existing
alliteration/rhythm/header styling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 17:39:33 -04:00
kennethreitz b1d411c8e7 No hover focus or inspector when rhyme is off
setEmphasis clears when the rhyme toggle is off, so hovering doesn't
light a family or show the inspector with the rhyme layer disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 13:48:54 -04:00
kennethreitz 952ce86de7 Tint rhyming words in their family color over the blocks
Rhyming words now take a quiet tint of their family hue (28-60% toward
the color by strength, mixed with ink for legibility) on top of the
soft block fill — both channels at once: the block groups, the tinted
glyphs carry the color. The sub-word underline still marks the exact
rhyme. Subtle enough to read through.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 04:33:43 -04:00
kennethreitz db91b61eb1 Hover-to-brighten focus, caret as the resting state
Hovering a rhyming word brightens its family's chips (CSS class
toggles, no re-render, smooth .2s transition); moving onto plain text
or off the editor falls back to the caret's family. Additive only —
nothing dims. Unified the caret spotlight and hover onto one
activeFam path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 04:21:23 -04:00
kennethreitz 96ab2e5e99 Hover-to-illuminate; drop the constellation overlay
Hovering a word now brightens its whole rhyme family (dark ink on lit
chips) plus the margin bracket — same as the caret spotlight, but
following the mouse so you can sweep a verse. The weave/constellation
overlay was tried (threads, taper, forks, dots) and cut: every step
revealed it was more than the page wanted. Hover-illuminate is the
clean version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 04:07:49 -04:00
kennethreitz 87a6fa5ec5 Constellation weave: glowing threads through the spotlit family
Click a rhyme and a soft thread of light weaves under the text through
every member of its family — a spine following the line-ending rhymes
with internal rhymes forking off, drawn-in on click, nodes sized by
each word's strength, anchored to the rhyming tail. Renders beneath
the glyphs (z-index 0) with a gentle gaussian glow so it reads as
light from underneath, not a stroke on top.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:52:11 -04:00
kennethreitz a973f35e20 Per-word brightness: anchors glow, slant attachments whisper
Strength is now per token, not per family — a word that only slant-
matches its family (placement riding creation/elation's -ation core)
caps at 0.6 while the perfect anchors stay at 1.0. The gradient now
lives within a single color, showing each word's own grip on the rhyme.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:26:43 -04:00
kennethreitz 1ea434e9a7 Brightness as a continuous rhyme-strength gradient
The fill (and tail underline) now scale through a per-group strength
from the founding key: perfect 1.0, multisyllabic .82, consonant-
backed .7, vowel slant .6, consonance .55, weak ending .5. So the
page reads rhyme quality as a smooth brightness ramp, not just
perfect-vs-slant — the feature, deepened.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:23:48 -04:00
kennethreitz fa3fd24163 Soften sub-word highlight: full fill, faint tail underline
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:17:08 -04:00
kennethreitz e134f33ec7 Near-miss radar (#3): dead endings one phoneme from a rhyme
A line ending that rhymes with nothing but sits one phoneme from
another ending in the stanza (hand/bond — one vowel apart) gets a
dotted gold underline: a tiny edit would lock it. Restricted to
genuinely-open endings, so it never duplicates the slant/consonance
detection (which already catches same-vowel near-rhymes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:16:08 -04:00
kennethreitz 1035af67b2 Fix rhyme_char_start test expectation (ight starts at 3) 2026-06-08 03:12:44 -04:00
kennethreitz 42d48b2c42 Sub-word rhyme highlighting: dim word fill + bright tail underline
Whole rhyming word fills dimly; a bright underline marks just the
rhyming part (tonight -> under 'ight'), so the precise interlock shows
without the fill looking ragged when the phoneme->letter guess is a
letter off. Removed 'scheme' from the toolbar readout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:12:20 -04:00
kennethreitz b4df695f57 Family inspector + strength-as-saturation
#4: caret in a colored word names its family in the readout —
"rhymes ay t — night, light, flight". The colors stop being a mystery.
#5: slant rhymes render at 62% of a perfect rhyme's fill, so the page
shows match strength, not just match presence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:07:40 -04:00
kennethreitz 0bd3dab542 Scope rhyme matching to within a stanza
Each blank-line-separated stanza is its own rhyme scheme. The perfect-
rhyme pass is now keyed per stanza, and the multi/coda fusion steps
won't union families across stanza boundaries (slant/multi/consonance
buckets were already stanza-keyed). light/night in verse 1 no longer
links to bright/sight in verse 2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 03:00:53 -04:00
kennethreitz 676a596a66 Weak endings need a full vowel; trailing sibilant is transparent
middle / unavoidable shared only a schwa+L tail — the weak-ending rule
firing on a reduced vowel. Weak endings now require a full final vowel
(infancy/see on IY stays). Surfaced that swimmers' plural -s blocked
its coda from nesting with finisher; a trailing sibilant is inflection,
so it's stripped from the coda tag — Wayne's chain stays whole, garbage
(JH) still stays out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 02:58:03 -04:00
kennethreitz b76430caaf Bold # header lines
Lines starting with # render bold and a touch brighter (a title, not
just a dim note); ( and [ annotation lines stay dim. Export matches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:11:24 -04:00
kennethreitz c86f87f707 Caret spotlight: brighten the family + margin brackets
Clicking into a colored word brightens its whole rhyme family (dark
ink on lit chips) and draws a soft rounded bracket in the left gutter
spanning the family's lines — rhyme and alliteration each get their
own bracket, gated to their toggle. No dimming of the rest; additive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:08:34 -04:00
kennethreitz c77d24fb83 Weak V-x attach needs coda nesting too
garbage/javascript were joining dollar/scholar's AA-x group via the
attach path, which lacked the coda-class guard the bucket path has.
Now a bare V-x key attaches only when the token's coda nests with the
group's — same rule both paths. syrup/burden was the same looseness
(ER-schwa, mismatched coda) and now correctly splits; the real
stir-up/were-up perfect phrase matches stay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:35:31 -04:00
kennethreitz e6b86a8a88 16-color palette with least-used assignment
The Python diss put pink on five different families: 18 families, 12
colors, and the assignment kept grabbing low indices so one hue piled
up. Now 16 colors (added cyan, amber, lavender, emerald) and each
family takes the globally least-used non-adjacent color, so hues
spread evenly — no color repeats more than twice on a dense page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:31:52 -04:00
kennethreitz 411681d0a0 Vowel families must be local
Slant/multi attachment, multi buckets, and unequal-length containment
fusion now require members within ~6-8 lines. "All Me" was chaining
Baby/Mercedes/loan/being/Daddy into one teal family across 110 lines;
vowel assonance is local evidence, not global. Perfect rhymes and
equal-key fusion stay global (a real rhyme carries any distance).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:56:56 -04:00
kennethreitz fec0485b68 Dark ink on the spotlit chips
At 85% fill the off-white text washed out; the focused family's
glyphs flip to dark (like the primary button) with a touch of weight.
Possible because the highlight layer owns glyph color.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:48:41 -04:00
kennethreitz 202ec1542d Spotlight brighter still (2.8x, cap 85%)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:46:24 -04:00
kennethreitz f320c0d9f4 Spotlight brightens the caret's family instead of dimming the rest
The full color field stays put; the family under the caret glows
~1.8x (capped at 60%). Additive, not subtractive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:44:05 -04:00
kennethreitz 77316330ea Weak V-x families stop gluing: coda-nested buckets, gated fusion
The spotlight exposed forever/question/extra/sequential as one EH-x
family. Three fixes:
- phrases obey refrain muting (the «Forever ever» carpet)
- bare V-x buckets subdivide by nesting final-coda classes, so
  placement (NT) keeps creation (N) but forever (.) releases
  sequential (L); phrases ride the main cluster
- single-vowel suffix fusion requires member coda sets to nest

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:40:34 -04:00
kennethreitz bd542e0b2e Spotlight: the family under the caret, automatically
Click into any colored word and every other family dims to a whisper
(22% of normal); the caret's rhyme thread stays lit across the whole
draft. Caret anywhere else restores the full field. No toggle — it
follows where you are. Smallest covering token wins (word over
phrase), recomputed after each analysis since gids shift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:31:19 -04:00
kennethreitz 329c114b3e Spend the palette better: dedupe hues, adjacency-aware assignment
r9/r10/r11 were a pale pink, a second teal, and a second orange — now
rose, indigo, and chartreuse. Color assignment stops being gid % 12:
each family picks the first hue not worn by families on its own or
neighboring lines, so similar colors never sit next to each other.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:15:58 -04:00
kennethreitz ec269dc6f9 Brighter internal fills; pin overlay heights to the textarea
Internals 19% (phrases 14%), ends stay 34%, export matches. On long
documents the overlay layers get a tail spacer equalizing their
scroll height with the editor's, so deep scroll positions can't clamp
and slide the colors off the visible text.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:54:25 -04:00
kennethreitz 3252d70c57 Remove the counts layer
The caret-line readout already gives syllables on demand; a number on
every line was furniture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:40:25 -04:00
kennethreitz fa539bbb68 Remove Save TXT
Share covers it (Notes, Files, anywhere), and drag-drop import remains
the way back in. Toolbar: Copy · Save PNG · Share + toggles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:39:09 -04:00
kennethreitz 7ff10af066 Share button via the Web Share API
Apple offers no content-accepting Notes URL scheme; the native share
sheet is the real path — Notes, Messages, Mail, one tap. Button only
appears where navigator.share exists (Safari, iOS, Android).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:37:21 -04:00
kennethreitz 5c87d827e6 Split the word entry into Explore and Wordplay lenses
Two sub-tabs under the lookup input: Explore (associations, describes,
synonyms — the meaning side) and Wordplay (rhymes, near, multis — the
sound side). Readout and history shared; switching repaints from the
cached entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:32:02 -04:00
kennethreitz 0bbbd46826 Associations section, above describes
What the word summons (Datamuse rel_trg): rain -> showers, monsoon,
shine, hail. The theme-building lens, first in the entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:27:45 -04:00
kennethreitz b204c8d9b9 Multis lookup and per-line syllable counts
- Multis: dictionary search by vowel skeleton — single words and
  two-word combos matching the target's run from its stressed anchor
  (charisma -> little/women/business; vacation plans -> information
  back). Perfect rhymes excluded; phrases supported as targets; new
  "multis" row in the rhymes section. Indexes warm at boot.
- Counts toggle: syllables per line in dim digits at the editor's
  right edge, wrap-safe and live; carried into the PNG export.
- Suffix fusion: multi families whose vowel keys are end-aligned
  containments merge (back pocket / rap profit / off it / still in
  office = one Em chain), with trailing schwas stripped before
  comparison; the longest end token now owns the scheme slot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:23:29 -04:00
kennethreitz f59e059f0d Actually wrap annotation lines in the dim span
The grey wrap targeted a renderer shape that no longer exists and
silently no-opped; it now applies at the real line-append point, and
the editor selection rule is un-nested for parser safety.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:04:14 -04:00
kennethreitz e9ebd318cd End-dominated vowel fusion; annotation lines render dimmer
- Same-vowel perfect families fuse when both live at line ends:
  blood/mud + thugs/drugs (+does/love/enough) read as Kanye's one AH
  chain; mid-line families keep their codas distinct
- Annotation lines (#, [, ( starts) render in a dim ink — the
  highlight layer now owns the glyph color (textarea text is
  transparent over it), in the editor and the PNG export

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:02:16 -04:00
kennethreitz 5e7845f0bb Parentheticals rhyme internally but never claim the line ending
(justify greed) now lights up with need/breed as internal rhyme; the
ending slot stays with the last word outside parens, so (yeah) tails
still can't set the scheme. The old all-or-nothing exclusion is gone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:57:49 -04:00
kennethreitz ff7a6b5790 Google search-page dumps extract to just the lyrics
Third extractor: the knowledge panel's standalone "Lyrics" header
through the Source:/Songwriters: footer — everything after (result
snippets, videos, People-also-search-for) drops. Requires both
markers, so a poem with a "Lyrics" line passes through whole.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:56:17 -04:00
kennethreitz 56ebb2046b Normalize Unicode line separators on paste
Google's lyrics box ships U+2028/U+2029 between lines, which a
textarea collapses — verses arrived as one giant line. All line-
separator flavors (CR, CRLF, LS, PS, NEL, VT, FF) normalize to \n,
and the Lyrics/Songwriters/Musixmatch furniture strips with the rest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:54:03 -04:00
kennethreitz d268755aa1 AZLyrics-style page dumps extract to just the lyrics
Second extractor alongside the Genius one: quoted-title headers up
top plus a Thanks-to/Writer(s)/licensed-by footer mark the envelope;
both header and footer evidence are required, so quoted lines in your
own writing never trigger it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:52:33 -04:00
kennethreitz 5e50664458 Sidebar sections always expanded; paste preserves undo
The more… expanders are gone — describes, rhymes, and synonyms render
in full and the entry just scrolls. Smart paste inserts through the
undo-aware path so Cmd+Z cleanly un-pastes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:51:10 -04:00