diff options
| author | Adam Soltys <[email protected]> | 2026-09-18 23:12:19 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-18 23:12:19 -0700 |
| commit | e07023af899f6682e088aee9ff3329b16b8f467d (patch) | |
| tree | 7b3f6926d476ebb3c41ad2f325a1029bf58d82aa /src/style.css | |
| parent | 703ee6e1281e72ec00f65768d7de7a015c242abb (diff) | |
| download | coinosv3-e07023af899f6682e088aee9ff3329b16b8f467d.tar.gz coinosv3-e07023af899f6682e088aee9ff3329b16b8f467d.zip | |
Zaps: the sound, the sender, and one action bar for every post.
Tap feedback: a bolt strike, the amount popping off the button, the post
trembling, and the zap.mp3 clip. The clip is 62KB of base64 and messages.js
is boot code, so it is its own chunk, fetched once a zappable post is on
screen and played inside the tap once loaded; the standalone build inlines
it. Ark zap receipts are signed by the wallet key, which has no profile: they
now carry the login identity as the sender (NIP-57's P tag), readers prefer
it, and our own older receipts read as us. The action bar is the same six
slots on every post: the zap button and the who-reacted chevron are always
there (inert until they have something to do), so the first zap no longer
reflows the row, and you can zap your own posts and messages. Community
rows centre their unread dot off the edge. Also in here: reactions with
custom emoji, reply-composer focus under the tapped post, profile fetch
retry, and Lightning zap failures that say so.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'src/style.css')
| -rw-r--r-- | src/style.css | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/style.css b/src/style.css index 3fd3de2..3629dfc 100644 --- a/src/style.css +++ b/src/style.css @@ -499,6 +499,43 @@ hr.divider { margin: 16px 0; } .zap-tally { display: inline-flex; align-items: center; gap: 2px; font-size: 11px; font-weight: 650; color: #e6a800; white-space: nowrap; flex-shrink: 0; } .zap-tally.chat-react { font-size: 12px; padding: 1px 7px 1px 5px; } .zap-tally.clickable { cursor: pointer; } +/* A tap-local lightning strike, followed by a floating amount and embers. */ +.zap-fx { position: fixed; inset: 0; z-index: 10000; pointer-events: none; overflow: hidden; contain: strict; } +.zap-fx-impact { position: absolute; left: var(--zap-x); top: var(--zap-y); width: 0; height: 0; color: #ffc83d; } +.zap-fx-bolt { position: absolute; width: 82px; height: 180px; left: -41px; bottom: 0; fill: #fff5c2; filter: drop-shadow(0 0 5px #fff3a1) drop-shadow(0 0 13px #ff9d00); transform-origin: 50% 100%; animation: zap-strike 430ms ease-out both; } +.zap-fx-flash, .zap-fx-ring { position: absolute; left: -28px; top: -28px; width: 56px; height: 56px; border-radius: 50%; animation: zap-impact 550ms 60ms ease-out both; } +.zap-fx-flash { background: radial-gradient(circle, #fffce0, #ffca45 25%, #ff980066 50%, transparent 70%); } +.zap-fx-ring { border: 2px solid #ffd76a; box-shadow: 0 0 12px #ffad32, inset 0 0 10px #ffad3266; animation-name: zap-ring; } +.zap-fx-amount { position: absolute; left: var(--zap-label-x); top: -60px; display: flex; align-items: baseline; gap: 6px; white-space: nowrap; color: #fff2ad; text-shadow: 0 2px 2px #713500, 0 0 9px #ff9c00, 0 0 22px #ff9500aa; animation: zap-amount 1450ms cubic-bezier(.16, 1, .3, 1) both; } +.zap-fx-amount strong { font-size: clamp(34px, 9vw, 48px); font-weight: 900; line-height: 1; letter-spacing: -.045em; } +.zap-fx-amount span { font-size: 13px; font-weight: 800; letter-spacing: .04em; } +.zap-fx-spark { position: absolute; width: 10px; height: 3px; left: -5px; top: -2px; border-radius: 3px; background: #ffe997; box-shadow: 0 0 6px #ffaf20; animation: zap-spark 720ms var(--delay) ease-out both; } +.zap-fx-spark.ember { left: calc(var(--zap-label-x) - 2px); top: -80px; width: 3px; height: 3px; background: #fff4c2; animation-duration: 750ms; } +@keyframes zap-strike { + 0% { opacity: 0; transform: scaleY(.15); } + 16%, 38% { opacity: 1; transform: scaleY(1); } + 65% { opacity: .8; } + 100% { opacity: 0; transform: scaleY(1.04); } +} +@keyframes zap-impact { 0% { opacity: 1; transform: scale(.2); } 100% { opacity: 0; transform: scale(2.4); } } +@keyframes zap-ring { 0% { opacity: .9; transform: scale(.25); } 100% { opacity: 0; transform: scale(2); } } +@keyframes zap-amount { + 0% { opacity: 0; transform: translate(-50%, 35px) scale(.35) rotate(-9deg); } + 16% { opacity: 1; transform: translate(-50%, -8px) scale(1.2) rotate(-5deg); } + 30% { opacity: 1; transform: translate(-50%, -4px) scale(1) rotate(-3deg); } + 58% { opacity: 1; filter: blur(0); } + 100% { opacity: 0; transform: translate(-50%, -65px) scale(1.08) rotate(2deg); filter: blur(3px); } +} +@keyframes zap-spark { + 0% { opacity: 0; transform: translate(0, 0) rotate(var(--angle)) scale(.4); } + 12% { opacity: 1; } + 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--angle)) scale(.1); } +} +@media (prefers-reduced-motion: reduce) { + .zap-fx-bolt, .zap-fx-flash, .zap-fx-ring, .zap-fx-spark { display: none; } + .zap-fx-amount { animation: zap-amount-reduced 1200ms ease-out both; } + @keyframes zap-amount-reduced { 0%, 65% { opacity: 1; transform: translateX(-50%); } 100% { opacity: 0; transform: translateX(-50%); } } +} /* A zap in flight: the chip lands the moment you tap and breathes until the payment settles — the bolt carries the pulse, the number stays readable. */ .zap-tally.flying { animation: zap-breathe 1.15s ease-in-out infinite; } @@ -529,6 +566,7 @@ hr.divider { margin: 16px 0; } .chat-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .thread-when { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; } .thread-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red); flex-shrink: 0; } +.chat-thread-row > .thread-dot { margin-right: 8px; } .chat-thread-row.unread .chat-name { font-weight: 700; } .chat-thread-row.unread .chat-preview { color: var(--ink); } .chat-invite { padding: 10px 12px; border-bottom: 1px solid var(--line); background: var(--surface2); flex: 0 0 auto; max-height: 40vh; overflow-y: auto; } @@ -574,6 +612,8 @@ hr.divider { margin: 16px 0; } .note-act-emoji { font-size: 17px; line-height: 1; } .note-act-n { font-size: 12px; font-weight: 600; color: var(--muted); } .note-who-toggle.on { color: var(--muted); } +.note-who-toggle[aria-disabled] { opacity: .3; cursor: default; } +.note-who-toggle[aria-disabled]:hover { background: none; color: var(--faint); } .note-who-chev { display: flex; transition: transform .2s; } .note-who-chev.open { transform: rotate(180deg); } /* who reacted, boosted and zapped: opened by the chevron on the bar */ |
