🧪 Zero known production vulnerabilities + profile services
- Replaced the write-only SheetJS xlsx package with a small local OOXML writer.
  `npm audit --omit=dev` is now **0 vulnerabilities**.
- Personal profiles now show a **Lab services** strip linking to their
  Transport, coaching, design, building and other Lab profiles.
- Added tests for the Transport parser and XLSX writer (156 tests total).

---

🔍 Audit pass: counts, forms, dependencies
- Followers now query up to 500 follow lists instead of 100, so profile and
  sponsor counts are less likely to undercount.
- Clothing designers were missing from /stats and Supporters impact; they now
  have their own count and card (15 Lab crafts total).
- The floating Sasquatch bubble is hidden on /become forms, create/edit forms
  and /supporters so it can't cover inputs or the grantmaker form.
- protobufjs override moved to 7.6.5, clearing the moderate ONNX-path advisory.
  The only remaining production advisory is xlsx (write-only export, no fix
  published).

---

🛠 Cordn empty-response fix
- The coordinator client now accepts both structuredContent and JSON text
  responses, and treats an empty list response as an empty list. This fixes the
  “expected object, received undefined” error when a coordinator omits the
  structured field on an empty join-request/welcome/message result.

---

🚐 Transport / Driver profiles in The Lab
- New Transport craft for skaters who move people, gear or cargo:
  cars, taxis, vans, motorcycles, helicopters, planes and boats.
- Services: people, goods/cargo, skate gear, airport and venue transfers,
  tours and event logistics.
- Capabilities, capacity and coverage filters on /lab: cargo, bike/board rack,
  wheelchair access, pets, cross-border, night driving, covered, group size,
  local/regional/national/international.
- Capacity, cargo, coverage, availability, base area and accessibility fields.
- WoT badge, crew link, vouches, reviews and the normal report/hide flow.
- Explicitly self-attested: SkateSpots does not verify licences, insurance,
  vehicle roadworthiness or operator permits. A visible notice says so.
- Transport counts on /stats and Supporters impact.
- All Transport copy is in all 24 languages at 100%.

---

🗺 Cleaner map footer + follower stat fit
- The grey floating “Links” pill between Events and Crews is gone. The map
  footer is now a slim, always-visible strip above the bottom nav.
- Profile stats use 2/3/6 responsive columns; the Followers label and caveat
  no longer overflow or open an edge tooltip.
- The Bitcoin grantmaker section now states its ethos and privacy boundaries:
  no KYC of SkateSpots, no tracking/CRM, private NIP-17 DM, and only grants
  that keep the project open source, self-hosted and analytics-free.

---

🧾 Grantmaker transparency + stat fit
- The Followers stat no longer overflows its card: stats use 2/3/6 columns,
  and the relay-reported caveat is a proper footnote instead of an edge tooltip.
- The Bitcoin grantmaker section now spells out the ethos and the boundaries:
  no KYC of SkateSpots, no tracking/CRM, private NIP-17 DM, and only grants
  that keep the project open source, self-hosted and analytics-free.

---

💸 Sponsorship opt-in + Bitcoin grantmakers
- Profiles have an explicit “Open to sponsorships” switch and optional note;
  the badge and sponsor card only claim it after the skater opts in.
- The Supporters page now has a Bitcoin grantmaker inquiry form. It opens a
  private DM to the owner and stores nothing: not to KYC us — to KYC YOU.
  It is only for grantmakers that KYC/KYB their grantees.
- The Followers stat carries an info tooltip: relay-reported, not audited
  analytics.

---

👤 Sponsor-ready profiles
- Profiles now have Follow/Unfollow, Followers and Following counts, and an
  Events hosted section.
- New sponsor/collab card shows followers, events, spots and zaps received,
  with a prefilled collab DM and a direct link to the skater's Rider Card.
- Stats strip is a balanced six cells: Spots, Shops, Crews, Events, Gear and
  Followers.
- NIP-05 now shows a real verifying state instead of briefly looking unverified.
- Public stash images use the same resilient image fallback as the rest of the app.

---

🛹 Rolling logo, Cordn inbox, safer sends
- The app now opens on the orange SkateSpots wheel: it rolls in, keeps
  spinning and throws sparks. Reduced-motion users get the clean static mark.
- Android's launch screen is regenerated from the same source instead of the
  stock placeholder, so the first frame is on-brand too.
- Messages gains Private Rooms: Community plus every crew MLS room, with
  Open/Set up state and local unread dots.
- Cordn rooms now have per-room mute, in-room message search, Chat vs Private
  chat guidance and a last-checked coordinator status.
- Approving or removing a device asks for confirmation.
- Failed Cordn sends are kept in a device-local outbox, retried a few times
  when online, and can be retried or discarded later.
- The mobile wordmark no longer truncates in the logged-in header.

---

🔒 Community join hardening
- /cordn now opens the in-app Community room too; the raw Cordn link is
  copy-only from Advanced, so no browser short link lands in the stalled Cordn
  web client.
- Approving a device now asks for confirmation before adding it to the
  encrypted room.
- Corrected the second-device hint: use Link device for a direct handoff, or
  ask to join again with the new device.
- The community bot enforces an hourly approval brake (30/hour) on top of the
  250-member and 5-devices-per-account caps.
- Daily encrypted state backups now run via a user timer: 30 local snapshots
  plus restic when configured. ops-health reports the backup timer.

---

🧵 Community polish + host tooling
- The Advanced Cordn web link now warns that Cordn web may stall after sign-in;
  the in-app join remains the reliable path.
- Admins get a “Request handled” confirmation after clearing a join request.
- Added scripts/deploy-community-bot.sh: builds, backs up, uploads, restarts
  skatespots-community and refreshes the local 0600 state backup.
- ops-health now reports whether the community Cordn bot is active.

---

💬 Community joins that actually finish
- skate-spots.org/c now opens the in-app Community room instead of Cordn web,
  which currently stalls after NIP-42. /cordn remains the raw Cordn reference
  for Staircase/Cordn clients.
- Join requests now say the community bot or an admin approves them, with a
  Request again action and an admin banner when requests are waiting.
- Second-device users are told to use Link device; the bot cannot add a second
  MLS key for the same account.
- The community bot now retires handled and stale requests (fixing requests
  stuck on “Join request sent”), prefers the exact key package, logs pending
  queues, and stops automatic approval at 250 members or 5 devices per account.
- The room warns when the bot is missing, so admins know to review manually.

---

♿ Accessibility and clearer crew-chat aggregation
- The mobile map Local Chat button now has a screen-reader name and title.
- The first-run tip's close and “Find a crew” controls get a visible keyboard
  focus ring.
- The bell's message row is now “Messages & crew chats”, making it clear that
  crew-chat envelopes are part of that single encrypted unread count (still
  envelope-only, still no background decryption).

---

💬 Per-thread mute, event passes, and unmute
- 1:1 and group DM threads have a mute toggle in the thread header; muted
  threads stop showing unread dots on the inbox. Your choice is device-local.
- Card Mute actions can now be undone: muted accounts show “Unmute”.
- Event pages get an Event Pass shortcut when you’re the organiser or RSVP’d
  going/interested; it opens the card studio with that event preselected.
- The mobile header wordmark truncates at 200% text instead of colliding with
  search/profile controls.
- The frictionless first-run tip keeps one quiet “Find a crew” link.

---

🗓 Small clarity and recovery wins
- Event pages now show the viewer's timezone under the local start/end time, so
  a shared event can't silently mean another city's clock.
- The Gear Swap error state has a real Retry button instead of only an apology.

---

🛒 A smarter, safer Gear Swap
- Save the current search/filters under a name and restore them with one tap.
- Offer dialog gained quick note templates (discount, swap, pickup, shipping).
- A collapsed safety guide now sits above the marketplace: meet in public,
  inspect the gear, keep deals in chat, never share keys, and read escrow terms
  before shipping.
- Saved searches are device-local; no new server or tracking.

---

🧭 First run is one tap, not a to-do list
- Removed the Add Spot / Join Crew / Wallet / Community CTAs from the first-run
  tip. A new skater now sees one optional "Near Me" button and "Got it"; the map
  is already populated and nothing needs setting up.
- The fresh-signup checklist no longer fires a crew query, so it also costs less.

🛡 Inline safety actions
- Report already lives on cards; Mute now sits beside it on spot, event, tour and
  gear cards, using the same NIP-51 mute list as the rest of the app.
- Hidden content still explains itself to its author on the detail page.

---

🗺 The map remembers your view
- The map restores the last center/zoom on return, so you don't re-find your
  neighbourhood every time.
- The Events/Crews layer choices and the new global search already persist.
- The first-run checklist now includes the Community room alongside Add Spot,
  Crew and Wallet.

---

💬 DMs now reach the notification bell — without decrypting
- A Messages row appears when new NIP-17 gift-wrap envelopes are waiting. The
  count uses envelope IDs only, so Amber is never prompted; opening Messages
  acknowledges the envelope. Your own sent copies are tracked and excluded.
- 1:1 and group DM unread dots remain on the inbox and clear when the thread is
  opened. This is the first slice of the unified inbox; per-thread mute and
  crew-chat aggregation are next.

---

💬 Group DMs now show unread state
- NIP-17 group conversations get the same unread dot and red-tinted card as
  1:1 DMs; opening the group marks it read. One less blind spot in the inbox.
- No decrypt-on-background change: Amber users still refresh manually.

---

🔎 Global search, and the app remembers where you were
- New command palette: Cmd/Ctrl+K or the header search button. Search spots,
  crews, shops, events, gear, skaters and app pages from one place; recent
  searches are kept locally.
- Search only queries the datasets while the palette is open, so it does not add
  to cold-start relay load.
- Browser Back/Forward restores the scroll position for that history entry; query
  and tab changes on the same page do not jump you to the top.
- The opt-in Events and Crews map layers are remembered across visits.
- No new vendor, analytics, or server; all state is local.

---

🧠 Amber now tells you its prompt budget
- The Signers page shows an Amber-only card explaining exactly what prompts:
  high-value signed actions do, reads/background decrypts do not; group DMs cost
  one approval per recipient and Cordn may ask per coordinator request.
- It suggests a bunker or local key for long private/crew chats while keeping
  Amber for high-value signing.
- Service-worker update headers were tightened: no long browser cache for
  `push-sw.js`, and App Links assetlinks is served with a short cache.

---

📱 Android Back, deep links, and faster repeat web loads
- Hardware Back now closes the open menu/sheet first, then walks history, then
  minimises at the map instead of killing the app.
- `https://skate-spots.org` links can open the installed app (verified Android
  App Links), and `org.skatespots.app://` links are routed correctly through the
  HashRouter. Uses the official @capacitor/app plugin; no new vendor.
- The web app now has a small service worker shell: hashed assets cache-first,
  navigations network-first, old shell caches cleaned up. Push handlers are
  unchanged; API and model requests are never cached.
- `public/.well-known/assetlinks.json` pins the release certificate for App Links.

---

🛍 Zapstore now shows the current app
- Replaced the empty marketplace listing image with the current community room
  and refreshed the map/spot screenshots.
- Listing images are compressed; no app code changed. Version bumped only so the
  new Zapstore metadata/media can be published.

---

🔔 Amber gets fewer surprise prompts
- Cordn join-request bell notices are encrypted, so reading them costs a signer
  prompt on Amber. They now wait until you actually open the bell. Passive
  signers (nsec/bunker/extension) still preload them quietly, and the NIP-17 DM
  push path is unchanged.
- The capability check uses the safe signer probe, so an extension that has not
  injected yet cannot crash the bell.

🛍 Zapstore listing refreshed
- Added map, spot and marketplace screenshots; updated copy for crews, private
  chat, the Lab, translation, community and notifications; expanded supported
  NIPs and added a publisher-key guard.
- No behaviour change outside the listing.

---

🧹 Leaner repo, same features
- Removed 1,295 stale Gradle build files that were accidentally tracked under
  the NFC plugin; Gradle regenerates them locally and they were already ignored.
- Dropped the unused sticker-design source and recompressed the large logo,
  newsletter cover and Sasquatch guide images. No app image paths changed.
- The on-device translation worker runs ONNX Runtime single-threaded, so the
  unused threaded WASM variants were removed. The SIMD and non-SIMD fallbacks
  remain, so every browser/device path is unchanged.
- README rewritten to match the current app; the tracked tree is ~47 MB instead
  of ~66 MB. Git history is untouched (no rewritten hashes).

---

🖼 Load images and crews only where they matter
- Content images now default to lazy loading + async decode. Long spot, gear,
  event and crew lists no longer pull every off-screen photo up front.
- Crew notifications no longer fetch every crew: the bell asks only for crews
  that actually list you as a member. The full crew directory is loaded only
  when an admin has an incoming join request to resolve.
- These are local rendering/query changes — no CDN, no analytics, no new server.

---

🔔 The notification bell is off the critical path
- The whole notification center is now code-split and deferred until the app
  has painted (or until you tap the bell). The bell icon is still there
  immediately; its five data sources no longer compete with the map/profile
  queries on a cold start.
- The map and route chunks get the first network slots; the bell chunk and its
  feeds arrive after first paint. If you tap the bell before that, it loads and
  opens immediately.
- Still local-first: no analytics, no new vendor, no notification server. The
  existing push path is unchanged.

---

⚡ Faster cold starts, same ethos
- Profile lookups are batched: one relay round-trip per 100 authors instead of
  three per card. Avatars and names on the map, crews and lists stop stampeding
  the relays.
- The map only asks for layers that are actually on. Events and Crews are opt-in
  and no longer fetch until you toggle them; Shops, Gear and Tours follow the
  same rule.
- The local public cache now rehydrates crews, tours, the shop directory and
  newsletter issues on a cold start, so those screens render from disk before
  the relay answers.
- No analytics, no new vendor, no server-side shortcut: this is batching,
  gating and local-first caching. Next targets are the notification bell's
  cold-start query storm, map pagination, a no-vendor app-shell service worker,
  and a smaller translation model.

---

🧭 The map footer is back
- DIY, Newsletter, License and Privacy are always visible on the desktop map
  again, plus the OpenSats note. We removed the hide toggle that could bury the
  only footer on the map forever. Mobile keeps the compact Links chip.

🔔 Cordn private-chat join requests now push
- A background watcher checks the coordinator every minute and turns each new
  request into a NIP-17 DM (so the phone can wake with the app closed) and an
  encrypted notification-bell card.
- The bell shows "Private chat request" with Review and Dismiss; the in-app
  request dot still works. The watcher uses its own key — never an admin key.

🛡 Inline crew roles + private-chat controls
- The founder can promote/demote a member directly from the Private chat member
  row (it republishes the crew event with the updated admin tag).
- Private chat now has reactions, delete-for-everyone and read receipts. These
  ride as encrypted MLS control messages; the coordinator still sees ciphertext
  only. Delete is a tombstone, not a relay hard-delete. Automatic read receipts
  are silent-signer only (Amber users aren't prompted behind their back).

📊 Translation matrix runner (and a real finding)
- Added `npm run translation:matrix` to drive the actual built worker in a
  browser. First runs: en↔es ~54s, en↔ca ~21s; the Basque model downloads did
  not finish in 25 minutes. The 617 MB M2M100 is too slow for low-end phones —
  this needs a smaller model or native ONNX, not another checkbox. All-language
  APK/low-end verification is still open.

---

📰 The weekly newsletter builds itself (almost)
- The newsletter now assembles a complete weekly draft: four shipped highlights,
  three rotating South Park-style roasts, current tech headlines, and a fresh
  cover built from the same Drop #006 foundation.
- Admins get a "Weekly draft ready" banner. The composer loads every field,
  previews the Markdown safely, and publishes. Subscribers still get issues in
  the notification bell's News tab, and the archive no longer duplicates a
  backfilled live issue.
- A weekly timer generates the draft every Monday at 08:00. The first one is
  ready now. Auto-publish is opt-in after review (NEWSLETTER_AUTOPUBLISH=1), so
  the roast gets a second pair of eyes before it goes out under the founder key.
- The generator runs locally with the admin signer; no subscriber list or key
  leaves the box. Covers are uploaded to our own Blossom.

---

🧑‍🤝‍🧑 Private chat: devices + members
- Link a new phone or device with a QR code. An existing member scans it, and
  the new device joins without another founder approval round trip.
- Remove a member/device from the member list. Founders also get an Edit Crew
  link for admin roles.
- Copy or reply to any private-chat message.
- The Private chat tab keeps its unread and join-request dots.

🔐 Dependency hardening
- Patched the critical protobufjs advisory used by the on-device translation
  runtime and updated sharp. Only the write-only xlsx advisory remains.

---

💬 Private chat badges + remembered joins
- The Private chat tab now shows a dot when new messages arrive while you’re
  reading Events or Chat; opening the tab clears it.
- Founders/admins get a red dot when someone is waiting to join.
- A pending join request survives a reload; the auto-check resumes when you
  come back.
- Background checks run only for silent nsec/bunker signers. Amber and browser
  extension users are never prompted behind their back.

---

🔐 Sign up from anywhere, without losing the flow
- The sign-in/sign-up dialog now lives above the app, not inside cards, sheets
  or menus. Creating an account from Spot Chat, Settings, alerts or a profile
  card no longer closes the profile/backup steps when you log in.
- The language search clears when the menu closes, and the compact sign-in
  icons have proper screen-reader labels.

🔗 Safer trip links
- Links in AI-generated trip itineraries are sanitized before they render.

---

🔐 Sign-in from the menu, fixed
- Logging in or creating an account from the burger menu no longer opens behind
  the menu; the menu closes first and the auth dialog is always on top.
- Welcome → sign up/log in and Log In ↔ Create Account now keep exactly one
  dialog open.
- The desktop welcome prompt no longer pops over an in-progress sign-in.
- Choosing a language in the menu returns you to the menu.

---

💬 SkateSpots Community room
- New Community chat for questions and feedback — end-to-end encrypted.
- A community bot approves new devices automatically; admins can still approve.
- Find it in the menu or About, share the link/QR, or open it from Cordn.
- Menus: the language picker now has its own view, crew tabs fit long labels,
  and touch targets are roomier.

---

📱 Invite QR fixed on Android
- Invite QR codes now use the public skate-spots.org link instead of the app's
  local address, so another phone can scan them. The link opens the crew's
  Private chat tab.

---

🔐 Basque translation, repaired
- Basque ↔ English now gives real translations and stops cleanly instead of
  repeating a word. No new download of the large model is needed.

💬 Private crew chat polish
- After "Ask to join", the app checks for the invite automatically, so you can
  leave the page open.
- Three plain steps explain how to start or join; Cordn, group links and key
  packages now live under Advanced.
- Connection trouble shows a plain message and Retry; a new device can be set
  up again without losing access.
- See who's in the chat with avatars and founder/member roles, plus
  Sending… / Sent / Failed — Retry on messages.
- Invite links open the Private chat tab and have a QR code; the promo banner is
  dismissible.

---

🌍 Hindi, Català, Euskara and Galego
- The app is now fully available in Hindi (हिन्दी), Catalan, Basque and
  Galician — pick them from the language menu.
- The picker now shows the real regional flags: England, Catalonia, the Basque
  Country and Galicia, plus Português (Brasil) and Português (Portugal).
- Long translations no longer clip the menus: wider language menu, aligned
  flags, one-column language grid on phones, and a wider "More" menu.
- Devanagari, CJK and Thai labels are no longer letter-spaced, and the settings
  language grid now shows flags instead of file paths.

🗺 One world, no repeated continents
- Zooming out stops where the single world covers the map — no grey bands and
  no duplicated continents.
- You can still drag horizontally across the Pacific to Hawaii and the Pacific
  islands; the map wraps at the date line, and vertical panning stops at the
  poles.

---

🗺 The map is authoritative again
- Spots and shops on the map now come only from the SkateSpots community relay,
  so everyone sees the same pins — and it fixes the empty map some of you hit.
- A missing spot was restored to the community relay.

📲 Pass SkateSpots on
- On Android, the About page now has a "Share SkateSpots" card: show a QR, use
  the share sheet, or write the install link to an NFC tag.

🔑 A clearer way in
- Sign-in now leads with three plain choices — browser extension, signer app, or
  sign in with your phone — plus a quiet secret-key option.
- On desktop the welcome sign-in appears once per session for logged-out
  visitors (dismissible).

🛡 Security & stability
- Updated core libraries (router, validation, Nostr client) and cleared the
  known app-facing vulnerabilities; the dependency scanner now runs in the
  scheduled job too.

---

🔑 A clearer way in
- Sign-in now leads with three clear choices — browser extension, signer app
  (bunker/Amber), or scan a code to sign in with your phone — plus a quiet
  "Secret Key" option.
- On desktop, a welcome sign-in card appears once for logged-out visitors (you
  can dismiss it).

🛡 Dependency security
- Updated Vite, Vitest, unhead and yaml and pinned TypeScript; the OSV scan now
  reports far fewer known issues (remaining ones are upstream major versions or
  have no fix).

📄 License
- The Zapstore listing now shows the real licence: AGPL-3.0-only (was "custom").

---

🔧 Amber signing fix
- Fixed messages (and other long encrypted data) occasionally failing to open
  when signed with Amber — the signer can compress large results and the app now
  reads them correctly every time.
- Clearer wording if Amber doesn't respond (it no longer suggests Amber isn't
  installed).

---

💬 Crew chat, simplified and faster
- The crew Chat always uses standard end-to-end encryption now — no more silent
  transport switching. (Coordinator/MLS chat lives in the crew's Private chat.)
- Messages you send appear instantly; the app no longer re-decrypts your whole
  inbox as you move around, and it remembers decrypted messages on your device,
  so reopening the app is quick. Far fewer signer prompts.

🔐 Private crew chat
- Admins can now Invite members straight from the private chat.

🌍 Languages
- All 20 languages are complete again (recent screens were falling back to
  English).

---

💬 Crew chat fixes
- Messages you send now appear straight away (they could seem to vanish before).
- Moving between Messages and a crew no longer re-decrypts your whole inbox, so
  the Amber app stops flashing and things feel faster. You're asked to approve
  each tap once per message, not over and over.

---

🩹 Crew chat sends with Amber
- Sending to a crew no longer fails with "Amber didn't respond". The approvals
  now come one at a time instead of all at once, so each one lands. (A 2-person
  crew still needs a few approvals — that's the encrypted-message cost.) For
  fewer taps, the crew's Private chat needs about one approval per message.

---

🧹 Fewer signer pop-ups
- Navigating around no longer re-decrypts your messages over and over, so the
  Amber app stops flashing as you move between screens. New messages are pulled
  in with a Refresh button on Messages.

💬 Crews in Messages
- Your crews now show up in the Messages tab, with a one-tap link straight into
  each crew's private chat.

🧭 Clearer crew chat
- The crew's "Encrypted chat" card no longer contradicts itself: it shows Chat
  (always on) and Private chat (MLS) side by side with their real state, and
  takes you straight to the private chat.
- Joining now confirms ("Request sent…"), and admins are told how to add members.

---

🧹 Fewer onboarding pop-ups
- The "get started" card on the map now shows only for genuinely new accounts —
  it no longer appears for returning skaters.
- "Save your login" no longer comes back every session once you've saved your
  key during signup, and the browser's save-password prompt is less likely to
  appear.

---

🆕 Private crew chat, end to end (MLS)
- Crews now get a real encrypted group chat: RFC 9420 MLS through our own
  self-hosted coordinator. Open a crew → "Private chat". Founders create it and
  approve join requests; members tap "Ask to join". Roughly a second to join.
- Send photos, copy the group link to open the same chat in Cordn or Staircase,
  and your messages stay between members. The coordinator routes ciphertext and
  metadata only — it never sees what you write.

🔒 Our infrastructure, not someone else's
- The community relay and photo/media storage now run on our own servers, so
  your spots, crews and photos no longer depend on a third party. Same data,
  faster and more independent.

🛒 Marketplace: close the deal in-app
- Accept an offer and pay right there (NWC / WebLN / Cashu), with the invoice
  amount verified so you can't be overcharged.
- Escrow now uses the mint the seller advertises, and confirmation is safer.

🛡 Trust you can steer
- Mute an account and it disappears everywhere (NIP-51 list).
- "Alerts" flags accounts you follow that trusted people reported.
- Choose your trust provider in Settings → Trust, and every badge says who
  decided.

🗺 Map & weather
- Search now suggests spots and places as you type.
- Spots show a 6-day forecast with a colour legend, sunrise/sunset, and a
  manual refresh.

🧵 New in The Lab
- Clothing Designer joins the craft roles.

🛠 Fixes & polish
- Long menus scroll properly, and the language picker is searchable.
- Spot cards are tappable across the whole card again.
- Deleted spots no longer flash back from cache after a refresh.
- Lighter on first load (CJK fonts download only if you pick that language).

---

🌍 Ten new languages
- Simplified Chinese, Traditional Chinese, Ukrainian, Turkish, Vietnamese,
  Indonesian, Swedish, Czech, Romanian and Greek are now selectable — full
  coverage, not partial. (And North/South Korean stay separate, as before.)
- Locales lazy-load, so picking a language only downloads that language.

💸 A proper support page
- New /donate — three honest rails: ⚡ Lightning, 🕵️ private on-chain (silent
  payments) and ⛓ Angor. Each with a clear purpose, so you pick what fits you.
- The Supporters wall now thanks backers with amounts, tiers and on-chain proof.

🛹 Fixes
- Top Shops shows real skateshops again (the community relay is shared, so other
  apps' shops no longer leak in).
- The Monday newsletter reminder no longer covers the map on phones.
- New comments appear immediately, and event tickets verify properly at the door.

🔧 Under the hood
- A full bug + UI/UX audit pass: safer payments, stricter verification, fewer
  mobile layout rough edges.

---

📍 The map, cleaner
- Fixed the search bar sitting on top of the map's zoom buttons.
- The "Offline — showing saved spots" banner now appears only when your device
  is actually offline (not just when one relay is slow), and you can dismiss it.
- The "you are here" dot shows your own profile picture.

✅ Spots are verified by real skaters
- Community confidence now counts what other skaters actually do here: photos,
  status reports, comments, reactions, zaps, saves, links from crews and Lab
  pros. Cheap signals count for less, a zap or a crew link counts for a lot.
- The spot page explains itself ("2 photos · 1 crew · 3 comments") and nudges
  you to help confirm a new spot.

🪪 More than one handle
- Crews, shops and your profile can each carry up to 5 NIP-05 handles, each with
  a live verified check.

🔐 Private things stay private
- Stash backups can now be password-protected (with a strength meter) — the
  exported file is no longer plain text.
- Marketplace payments verify the invoice amount; private messages verify the
  sender's signature.

✨ Smaller fixes
- Crew form tidied into groups (Advanced tucked away), with a "Check" button for
  a custom chat coordinator and "Sasquatch · Pro" naming.
- Stash and the marketplace listing form now fit narrow phone screens — the
  header, item rows and condition buttons no longer overlap.
- The Lab's "Offer" menu is now a tidy, scrollable list (small colour chips
  instead of a wall of coloured buttons), with "Get Rider Card" pinned at the
  bottom.
- Marketplace reputation no longer shows a stuck "Loading…".

---

v1.5.10

🧭 Directions, rebuilt for a phone
- Search a new destination right in the app: skate spots, skate shops and
  Bitcoin merchants (no Google/Apple Maps handoff).
- The map is much bigger and the vehicle picker moved below it.
- Following is smoother — it re-centres only when you actually move, so GPS
  jitter no longer twitches the map.

🪙 Mints, with the info that matters
- Tap a mint for community rating, reliability, uptime, location and a liveness
  audit — plus copy/open/terms. Ratings come from the community MintRadar data.

🤝 Haggling: counter-offers + barter
- Offers are now a real back-and-forth: accept, decline, withdraw, or counter
  with a new amount — either side, any number of rounds.
- Swapping instead of buying? Offer an item ("my 8.25 deck") instead of, or
  alongside, sats. Barter counts for reputation exactly like a sale.
- New Trades tab in the notification bell, plus notifications for every step:
  new offer, counter, accepted, declined, and confirm-a-trade requests.

✨ Smaller fixes
- Crews: one tidy type control (no more horizontally-scrolling chips).
- Spot sheet: single close button.
- Map controls float over the map so the map fills the screen.

---
v1.5.9

🗣️ Navigation you can actually follow
- Directions now talks: a prompt at 150 m and again at 40 m before each turn,
  plus "You've arrived". It's your phone's own voice — offline, no account,
  nothing sent anywhere.
- The screen stays awake while you're following, so guidance doesn't die
  mid-route.
- The map gets bigger when you hit Start, and the step list steps aside. Mute
  anytime with the speaker button.

🗺️ A bigger map on the home screen
- The map controls now float over the map instead of taking a bar above it, so
  the map fills the screen — especially on a phone.

---
v1.5.8

🛰️ Pick your own group-chat coordinator
- New Settings -> Coordinator: point SkateSpots at a Cordn coordinator you choose,
  see whether it's up, copy or scan its link, and share it on your profile so
  people can add it in one tap.

📱 Run one — even on a phone
- A coordinator can live on an old phone, a Raspberry Pi, or any small box you
  leave on. We hand you the doorway (the Cordn app, or a one-line Docker
  command), and your crew can route its encrypted chat through it. Crew founders
  get a "Use my coordinator" button.

👤 Edit Profile got a face
- See how you actually look — banner, avatar, handle, bio and badges — before you
  save, plus a short "finish your profile" list instead of guesswork.

🔎 Coordinators are discoverable
- If someone runs their own coordinator, their profile now shows it with an Add
  button instead of a bare link.

---
v1.5.7

⏰ Event reminders
- RSVP "going" or "interested" to an event and your phone nudges you an hour
  before it starts — even when SkateSpots is closed. It's an alarm the device
  holds, not a server, so nothing leaves your phone.
- Turn it on in Settings -> Notifications (Android app).

---
v1.5.6

🛹 The map is quicker off the mark
- Pins no longer rebuild themselves several times while the map loads, and they
  stream in instead of freezing the screen in a busy city. Same map, less
  waiting.

🔔 Notifications (opt-in)
- Turn them on in Settings -> Notifications and your phone can buzz for DMs,
  crew invites and join requests, zaps, replies and mentions, and new newsletter
  drops.
- Privacy first: nothing new is sent anywhere, and direct-message alerts never
  unlock your messages — so an Amber user is never asked to approve one just to
  be told a message arrived.
- Honest limits: alerts come from the device while the app is running. A fully
  closed app can't be reached without a push server, which SkateSpots doesn't
  run — we'd rather say that than pretend otherwise.

🏷️ Badges on your profile
- A free name@skate-spots.org handle now shows the SkateSpots badge, and you can
  list your own badges (Cordn, Cashu, NWC, Amber, BTCMap…) as clickable chips.

📍 "Closest spot to me"
- Ask the Sasquatch where to skate and it can sort by what's nearest — worked
  out on your device, without sending your location anywhere.

⚡ Keep the map free
- The Supporters page now has a one-tap way to chip in (zap publicly, or pay
  quietly), if you want to.

---
v1.5.5

🗺️ The map works offline now
- The basemap you've already looked at is cached on your device, so the map still
  draws when the signal drops at the park — no more blank grid.

🖼️ A dead image host no longer leaves a blank spot
- Photos upload to two hosts, and if one goes down the app quietly loads the copy
  from the other. Same for avatars and gear pics.

💬 Past conversations actually show up now
- Messages reads your real DM inbox relays, so older threads appear instead of
  the "No messages yet" screen. And if something genuinely can't be decrypted,
  the app says so rather than pretending your inbox is empty.

✅ Free `name@skate-spots.org`
- Pick a handle when you sign up — free, optional, changeable any time — and it
  shows a verified badge on your profile.

---

v1.5.4

🧹 Keeping the map real
- Every new spot now needs at least one photo — the cheapest defence against
  test entries and off-topic pins ("test of secret island airport").
- Spots only say "Community verified" when another skater has contributed (a
  photo or a status report). Until then they are labelled "Unverified" instead
  of looking endorsed.
- The weather score is now labelled "Conditions · weather only". It was never a
  verdict on whether a place is a real spot.
- One-tap "Not a skate spot" for off-topic pins (test entries, airports, malls,
  private land), plus an admin review queue that surfaces them for a human.
- The queue also weighs mapper trust, whether any skater has reported on the
  spot, and whether anyone has added a community photo — and a review can now
  **Confirm** a spot as well as hide it (a staff-vouched spot gets a badge).
- Moderation is **reversible**: Hide and Confirm can both be undone, returning the
  spot to neutral without hiding or vouching for it.
- **Reports now reach a human**: the review queue surfaces reported spots at the
  very top, above the automated signals — so "not a skate spot" actually lands.
- **Adding a spot warns you if one already exists** within 60 m, and links you
  straight to it instead of letting you create a duplicate.
- **If a moderator hides or vouches for your spot, you're told** — right there on
  the spot page (your own spots stay visible to you either way).
- **A photo is now strongly recommended, not required.** No picture on hand right
  now? Publish anyway — the spot just stays marked Unverified until one lands.
- **Empty map? It now says so and offers to fix it**: "No spots mapped yet — be
  the first to map your park", with a one-tap Add spot.
- The admin review queue now covers **shops, events, tours, gear, crews and Lab
  profiles** too, not just spots — and has a **report inbox** (every report, with
  the reported item resolved, not just whatever's already flagged) plus **bulk
  undo** for clearing old verdicts.

🛍 App Shop — a new section (empty on purpose, with free printables)
- Free to print, no sats needed: a 55 × 86 mm "DO YOU EVEN SKATE BRO?" sticker
  and an A3 poster, both print-ready vector files with a working QR.
- Merch is coming, and it'll be paid in sats: Lightning or Cashu, your choice.
  No cards, no accounts, no processor skimming the drop.
- To be clear: we hold no stock and nothing is for sale yet. No pre-orders, no
  countdown timers, no fake scarcity — the teasers are labelled "not for sale
  yet" and there are no prices anywhere.

✉️ Direct messages actually arrive now
- Your DM inbox relays were being forgotten every time the app loaded, so
  messages were sent to your normal relays instead of the ones the other person
  actually reads — which is why DMs looked like they never arrived. Your DM
  relays, local relays and relay blocklist now persist properly.
- Sending and loading DMs no longer stall or break because of one dead or
  login-only relay in your list; they now run in parallel.

🧭 Directions look and feel like a navigation screen
- A much bigger map, with a metric scale bar, and the plan at a glance:
  distance, time, arrival, step count and the average speed the route assumes.
- The map stays put while the details scroll, and Start/Stop is pinned at the
  bottom where your thumb already is.

📰 Newsletter reader
- Issue intros render as proper italics instead of showing literal underscores.

---

v1.5.3

🧭 Real navigation, not just a route preview
- Travel modes finally give genuinely different answers: walking 13 min, biking
  5, driving 2 on the same trip. Before, every mode showed the same number.
- Route steps — the actual turns and street names. Tap a step to jump to it on
  the map, and use "Whole route" to zoom back out.
- Tap Start and it follows you: your dot moves, the current step highlights, and
  it shows the next turn plus how far is left. (Still no voice guidance.)
- Arrival time ("arrive ~08:10 PM"), and it remembers the mode you picked last.
- Going somewhere first? "From → Choose on map" sets your start point instead of
  routing from where you're standing.
- Lose signal mid-route and it keeps showing your last route, clearly marked as
  saved, instead of going blank.
- Skating gets its own honest estimate ("~6 min cruise on a board") next to the
  walking time, and moto is labelled as using driving roads.

🔔 Amber stays out of the way
- Amber now only opens for real signed actions: log in / sign up, messages, your
  Stash, marketplace trades, invites, publishing. Browsing and moving between
  sections no longer trigger a signer prompt — the app's encrypted cross-device
  data stays local-only on Amber instead of decrypting on every screen.

---

v1.5.2

🛒 Marketplace, levelled up
- Every listing lives in one hub now: Browse, Selling (your own listings with
  one-tap Mark sold), your Trades, and Reputation.
- Rate a trade 1–10 skateboard decks when you confirm it. Ratings show on both
  profiles with an honest average — and every confirmation is with a real
  person, so two accounts can't pump each other's rep.

🧭 Directions actually work now
- Fixed the route map never drawing (you'd get an empty dialog and "no route").
  Routes now show your position, the spot, and the line between them.
- Opens instantly from your last known location; "Near Me" sorts by distance.

📱 Nav fixes
- The desktop "More" menu no longer vanishes when you pin Marketplace.
- Marketplace is now in the phone menu (☰) — pin it to the bottom bar too.

🪙 Mints loads in the app again
- The mints list was showing a JSON error on phones; it's fixed.

📰 Newsletter
- Fixed a bug that pegged your CPU on the newsletter page.
- Issues and subscriptions now publish to the community relay so everyone sees
  the drops.

✨ Smoother everywhere
- Amber only pops for things that need a signature — no more prompts just for
  reading your notifications.
- Logo no longer crowds the nav.

---

v1.5.1

🦧 Sasquatch — the AI guide, levelled up
- Ask real questions and get answers streamed as they're written.
- Sasquatch Pro unlocks AI answers plus personal actions (drafting posts &
  listings, your Stash/Crews in chat). Pay with Lightning — from 7 days.
- Free, always: trick & term lookups, and finding spots, events, crews, shops,
  tours and gear straight from the relays.
- Your Pro balance shows right in the guide.

🚇 Directions that stay in the app
- Route to any spot by public transport, bike, moto or car — drawn on our own
  map, no bouncing out to Google or Apple Maps. Pick a mode, see the line.

🧑🎨 New in The Lab: Barbers & Hairstylists
- Cuts, fades, beard trims and colour — shop chair or mobile. Find a fresh trim
  on the scene.

✨ Smoother everywhere
- The app shell no longer rebuilds on every screen, so the Sasquatch chat and
  your scroll position survive navigation.
- Directions opens instantly now (it draws from your last known location first).
- The signer only pops for things that need it — log in, messages, your Stash,
  the marketplace and publishing. No more prompts just from moving between tabs.
- Mints is now in the phone nav; tidier tab labels.

---

v1.4.5

🔄 Cross-device sync
- Your read state (notifications, messages, crew chat, newsletter) and app
  preferences now sync across devices via encrypted NIP-78 app data.

🔒 Security hardening
- Amber signatures are verified, and trust scores verify event signatures
  before they're used.
- Cashu wallet seed is stored in the native Keychain/Keystore with a mandatory
  first-time backup.
- The agent (CVM) server only serves signature-verified events.

🗺️ Map & spots
- Crisp map pins with spot-type and shelter glyphs, plus smoother loading.
- New "Shelter" (weather protection) field.
- Better spot dedupe across geohash/city and name variants.
- Faster cold-start: query persistence, optimistic geolocation, skeleton pins.

📅 Tours & events
- Tour countdown badges, session times on scheduled local tours, and calendar
  export. Polished Create Tour flow.

🐿️ Sasquatch
- Faster answers via a local fast-path, honest spot counts, deduped results,
  and no more empty/typo dead-ends.

🎨 Polish & accessibility
- Lighter onboarding, shared empty states, improved contrast, a skip-to-content
  link, and live-region announcements.
- Relay list UI polish with live connection indicators.
- Mobile fix: detail-page grids no longer overflow horizontally on narrow screens.

---

v1.3.3

📡 NEW — Local Relay (Citrine) · Android
Run a private Nostr relay right on your phone with the free Citrine app, then
flip it on in Settings → Relays. When it's connected you get:
- Instant reads — the map, spots, crews and messages load from your device
- Works offline — browse (and queue posts) at a spot with no signal
- On-device backup — a durable local copy of your own events
It's opt-in, Android-only, and your Stash and messages stay end-to-end
encrypted exactly as before — the local relay only speeds things up.

🛹 Reliability & polish across the app
- Events/Tours: month calendar view with a list⇄calendar toggle
- Notifications: RSVP/update alerts now open the event, not the sender
- Map: fixed trusted-first sorting and stash card borders
- Crews: fixed roster edits clobbering each other on rapid changes
- Lab/Market/Stash: always show the newest revision of a profile
- Wallet: clear warning (with the exact sats at risk) before removing a mint
- Spot claims: cleaner ownership history
- Newsletter: recurring issue titles no longer overwrite older issues
- Messages: group chats no longer leak into your 1:1 conversations

---

v1.2.14

🔒 Security hardening (payments & trust signals)
- Auto-pay now verifies every Lightning invoice's amount before paying (zaps,
  crew zaps, listing fee). A server can no longer return an inflated invoice to
  overcharge your wallet.
- Pro access is granted only by a verifiable, provider-issued zap receipt (plus
  platform owners). Self-signed receipts no longer grant Pro.
- "Verified payment" badges on featured listings now require a provider-issued
  zap receipt — self-published receipts can't fake verification.
- Crew funding goals tally only real invoice-backed zaps, so totals can't be
  inflated with fake zap receipts.

Plus the delete diagnostics from 1.2.13 to pinpoint the signing/publish step.

---

v1.2.10

🛠️ Fixes a startup crash (black screen) introduced in the previous build and
keeps the Amber signing fix: signing now opens Amber the same reliable way
login does, so delete / accept invite / zap complete instead of hanging.

After updating, log OUT and log back IN once.

---

v1.2.8

🛠️ Amber finally pops up — signing works (the real fix)
The big one. On some Android setups (notably GrapheneOS), tapping delete,
accepting a crew invite, sending a zap, or editing your profile would spin
forever and Amber never appeared.

Root cause: the app's browser layer was silently dropping the request that
opens Amber, so the approval screen never launched. We added a native hand-off
so signing requests now open Amber directly — exactly like login already does.

Now every signing/encryption action launches Amber, you approve, and the
action completes. If Amber genuinely doesn't respond you get a clear message
in seconds instead of an endless spinner.

IMPORTANT: after updating, log OUT and log back IN once. Then delete, accept
invite, zap, and profile edits will just work.

🔔 Notification bell "Mark read" actually clears the badge
Marking notifications read now clears the count for crew items too, while
your pending invites and requests stay visible in the Crews tab until you
act on them.

🧹 Housekeeping
Behind-the-scenes reliability fixes across the signing and notification flows.
