Made With ❤️ From California + Florida
support@limondaytrips.com
Limon Day Trips - Header and Footer (Logo)
  • Home
  • Download
  • Invest
  • Press
iOS / AndroidDesktop Version
daytrips

#1 Day Trips App

  • Home
  • Download
  • Invest
  • Press

Explore Categories

  • Nature Day Trips
  • Sports Day Trips
  • Food & Drink Day Trips
  • Entertainment Day Trips
  • Cultural Sites Day Trips
  • Shopping Day Trips
Limon Day Trips - App Store (Logo)

🍋 Limon v13.23.1 Tankan · Block 38
drag
🟩 2026-10-13T22:30:00Z ⬆ 13.23.1 Tankan (pre-flight) ⛓ 13.23.1.5b033c87b5 2026-11-04T06:03:42+00:00

Diagnosis

Two beta-test agents audited 15 profiles × 15 steps of GhostLab screenshots for 13.23.0 and 13.23.1 (safe areas, clipping, overlaps, targets, copy, regressions). Every finding was reproduced on the live canvas or in WordPress 7.1.3 first; findings that were GhostLab's own drawing or the sandbox's missing network were set aside.

What changed in this block

  • (a) Canvas · the two demo comments leave the markup; renderComments inserts beside the input row wherever the fold put it.
  • (b) Canvas · after a publish the new card carries the recording (data-audio) and the player is repainted from it (LimonSetoka.repaint).
  • (c) Server · Limon_CPT::story_ts(): post_date_gmt, else post_date in the site's zone, else post_modified — for date, ago and ts; the device feed sorts on it.
  • (d) Canvas · .ctrl-btn.skip svg is 24 px; the skip pair, the photo ×, "See all" join the 44 pt hit-area list.
  • (e) Canvas · the stale-feed banner is kept in front of the first card.
  • (f) Canvas · while the player bar is up, the map's stops list sits above it (body.limon-bar-up, --limon-bar-h).
  • (g) Canvas · on the author's own device, a card that is one of their local stories is signed with their handle, not "traveler".
  • (h) Canvas · plurals on the AGI hint and the photo toast; NEXT ▶|; the Explore compass keeps its needle; Upload & Continue centred at 48 px; the fold's duplicate heading hidden; the feedback subject names the running version.
Founder boards
Map behavior 8 / 8
Reproduce and diagnose blank map on pinless posts
Block 32 traced it: Ki.paintMap → hydrateStops() resolves ~1s later and calls Ki.blueprint(), wiping the Leaflet already mounted. Second late writer: Ha.drawMap mounts a second Leaflet on the same host, fails, falls to Iyokan’s tile plane.
high
Implement coordinate fallback chain
Mu.centre() — pin → stop coordinates → geocoded stop → the day’s city → the listener’s location → placeholder. Block 32.
high
Add geocoding service for stop addresses
Block 29 removed a double-encoded Nominatim query that had broken every typed address since Block 26, and added a five-rung query ladder. Cached and rate-limited.
high
Guard against rendering an empty map
Block 30 base plate + Block 32 .lf-nocentre placeholder. Block 34 guards the last four hardcoded California setView() calls.
high
Fix tile loading/blanking regression
Block 30 tile-health ladder; Block 32 Mu.claimCanvas makes every older writer a no-op; Block 34 removes the Carto rung whose KEY REQUIRED tiles loaded successfully while ruining the map, and stops the loading plate lingering.
medium
Add loading and error states for map view
Block 34: a mango spinner while the centre resolves, and a Retry on tier 0 that clears Mu._you and the city cache and re-runs the chain.
medium
Handle unknown/warning stops gracefully
Block 34: the ⚠ row is now the control — tapping an unpinned stop opens the same editor the placeholder button aims at.
low
Add automated tests for fallback logic
build/test_murcott.js covers every rung (pin, stop coords, geocoded, city, user location, placeholder). Native parity is a handoff item, listed under open_native.
medium
Viewing a post 4 / 8
Review video brief and document requirements
Block 32 read the brief frame by frame — Spotify Now Playing. The three asks it carries are implemented; a founders’ initialled one-pager is still worth having before the header refactor.
high
Audit current daytrip post-viewing page
docs/BLOCK-32-MURCOTT.md and this ledger are the baseline.
high
Design Spotify-inspired audio-first post layout
OPEN — mockups. The behaviour landed first (pull, chrome retreat, canvas strip); the header hierarchy waits on the initialled spec, deliberately, so it is not designed twice.
high
Build persistent audio player component
play/pause, scrubber, ±15s, remaining — and Block 34 adds elapsed beside remaining and a playback-speed control cycling 0.75 / 1 / 1.25 / 1.5, persisted in limon_rate.
high
Refactor post metadata and header section
OPEN — blocked on vp3 by choice.
medium
Implement responsive and accessibility improvements
Block 34: Space toggles, J/L and ←/→ seek ±15s, Shift+←/→ change day, aria-live on the title when Up Next commits, and the transport keeps its focus ring and label while the chrome is retreated.
medium
QA and cross-device testing
OPEN — the island walk on the live embed is a human pass. The seven web suites are green.
medium
Stakeholder review and design sign-off
OPEN — founders.
low

Lineage

7.0.0 Yuzu8.0.0 Finger Lime9.0.0 Persian Lime10.0.0 Buddha Hand11.0.0 Calamansi12.0.0 Bergamot13.0.0 Makrut13.1.0 Kabosu13.2.0 Shikuwasa13.2.1 Shikuwasa · delivery patch13.3.0 Rangpur13.4.0 Tangelo13.4.1 Tangelo hardening13.5.0 Dekopon13.6.0 Pomelo13.7.0 Oroblanco13.8.0 Calamansi13.9.0 Ponkan13.10.0 Kishu13.11.0 Iyokan13.12.0 Hassaku13.12.1 Hassaku · hotfix13.13.0 Kiyomi13.14.0 Setoka13.15.0 Harumi13.16.0 Encore13.17.0 Murcott13.18.0 Ortanique13.19.0 Hyuganatsu13.20.0 Kanpei13.21.0 Amanatsu13.22.0 Haruka13.23.0 Tankan13.23.1 Tankan

Evolution ledger

⬛ v13.23.1 · Tankan Block 38 · 2026-10-13T20:00:00Z

GhostLab 1.1.1 walked the release's own canvas on 15 device profiles (posts, voice playback, photos in JPG/WebP/AVIF, share, map, back, profile, record + photo + publish, settings, delete account, airplane mode). Publishing never reached WordPress; a fake-microphone recording was WebM and was filed as a video; the player bar covered the publish button. Three beta-test agents reviewed iOS, Android and the media formats independently; their findings were reproduced first.

  • (a) Canvas · pre-flight layer: a document capture listener gives "Upload & Continue" to the Post Details gate alone (edit mode untouched).
  • (b) Canvas · the recorder asks for audio/mp4;codecs=mp4a.40.2, then audio/webm;codecs=opus, then audio/mp4, then audio/webm, then the default.
  • (c) Server · upload_media files a voice clip (declared audio/*, kind=audio or voice-*) in WebM as audio/webm; WebM uploads run under a numeric memory limit; AVIF joins the allow-list; voice clips filed as video before 13.23.1 are re-filed once (Limon_Media::heal_voice_clips).
  • (d) Canvas · the player bar hides on Record (as it does on the player); tapping the mic pauses the story first.
  • (e) Canvas · Open in Maps de-duplicated; Ortanique caches and serves only the feed, never a search or a profile answer.
  • (f) Canvas · offline on a fresh install the empty state says "You’re offline"; the stage label, footer, badge and drawer read 13.23.1.
⬛ v13.23.0 · Tankan Block 38 · 2026-10-13T12:00:00Z

The Launch Board's gp.account_deletion probe was green on the in-app path and noted "Play also needs a web link where users can request deletion". A read of limondaytrips.com found no such page — nor a privacy or terms link. The store apps cannot be submitted to Play production without the URL in the Data safety form, and WordPress is the natural home for it.

  • (a) includes/class-limon-account-deletion.php — a public page at /limon/delete-account/ (rewrite rule, flushed once per release), ?limon_delete_account=1 (always) and [limon_account_deletion]. Standalone markup: the app and developer names, the in-app steps, what is deleted, what may be kept, the answer time (30 days by default), a request form.
  • (b) The form posts to admin-post.php (limon_delete_account, logged-out and logged-in): nonce, hidden honeypot, five requests per connection per hour (salted IP hash, never the raw IP), email or phone validated, @handle and note sanitised.
  • (c) A request is stored as a private limon_deletion record (Tools › Limon deletion requests, read-only meta box) and emailed to the support address and the site admin, Reply-To the traveller when it is an email address. The page answers the same way whether or not an account exists.
  • (d) The web never deletes anything: accounts live behind api.limondaytrips.com; support completes the request there (users/delete-account, status 2).
  • (e) Every sentence is filterable (limon_deletion_texts, limon_deletion_contact) — the founders review the wording before the link goes into Play Console.
  • (f) Canvas: version strings (title, badge, tooltip — Codename: Tankan · Block 38) and a Tankan layer that makes the Settings drawer read v13.23.0.
⬛ v13.22.0 · Haruka Block 37 · 2026-10-12T21:30:00Z

GhostLab 1.1.0 ingested LIMON-REACT-NATIVE v13.22.0 Haruka and ran its Simulator on seven device shells (iPhone 18 Pro · iPhone SE · iPad (A16) compatibility window · Pixel 11 · Galaxy S26 · Pixel 11 Pro Fold · Pixel Tablet). The package's own facts say back reaches BackHandler (enableOnBackInvokedCallback=false) and BackHandler calls goBack() when canGoBack — so the Simulator walked the canvas: it never calls history.pushState, therefore canGoBack() is false on every screen and the press falls through to the OS. The fix belongs to the canvas, which ships from WordPress the moment the plugin updates — no store resubmission — and the offline snapshot refreshes in the same block.

  • (a) STORE APP ONLY. The layer arms when a shell is present (__LIMON_NATIVE__ or ReactNativeWebView) and after every earlier layer has wrapped switchView (+900 ms). A browser never sees a history entry from it; iOS keeps allowsBackForwardNavigationGestures off, so iPhone is unchanged.
  • (b) DETAIL SCREENS ARE ONE ENTRY. A story, its map, a collab or admin view pushes {limon, depth}; back pops it and switchView() returns to the screen recorded underneath.
  • (c) THE TABS SHARE ONE ENTRY ABOVE EXPLORE. Saved · Discover · Me · Record replace each other; back from any of them returns to Explore; tapping Explore unwinds every entry; back at Explore leaves the app (canGoBack false).
  • (d) SHEETS ARE ONE ENTRY. A visible [aria-modal="true"] sheet pushes an entry when it opens; back closes it with its own ✕ / Cancel, else its dim, else its overlay, and stays on the screen. A sheet closed by its own ✕ gives its entry back silently, so one press is always one step.
  • (e) Version strings: title, badge, tooltip (Codename: Haruka · Block 37).
  • (f) LimonPonkan.viewing is a resolver again (Calamansi → Oroblanco → me(), Ponkan's own order), installed as an accessor at parse time: a function written to it replaces the resolver, a handle written to it is routed to LimonCalamansi.viewing. test_amanatsu.js resolves the pointer instead of comparing it.
  • (g) The Settings drawer reads v13.22.0 (Amanatsu's painter is wrapped). test_amanatsu.js and test_kanpei.js pin their own layer's version instead of the moving ledger.
  • (h) fetch is wrapped once: a request whose X-WP-Nonce header is empty goes out without it (Headers, arrays and plain objects); a real nonce is untouched.
⬛ v13.21.0 · Amanatsu Block 36 · 2026-10-12T06:40:00Z

A GhostLab beta walk of the Kanpei canvas in native mode on five devices (iPhone SE · 15 Pro · 16 Pro Max · Pixel 8 · Galaxy S24 Ultra), read against the react-native-webview source and the GitLab production tree. The RN package had never been run as a store app, so its defects were structural rather than cosmetic: the wire could not reach the shell on iOS, nobody carried the legacy identity across, and the two account verbs a store reviewer tries first were cosmetic. The canvas defects (tab bar, Leaflet, targets, duplicate zoom, stale version) were all visible in the first screenshot of each screen.

  • (a) THE CANVAS SELF-BRIDGES. When __LIMON_NATIVE__.bridge is present and there is no parent frame, the Amanatsu layer calls LimonPomelo.onBridge once — what app-shell.php used to post into its iframe. The shell also injects the same call on limon:ready; both are idempotent.
  • (b) IDENTITY ADOPTION. __LIMON_NATIVE__.identity {legacy_id, handle, name, avatar, provider, signed_in} becomes limon_profile.username/handle/name and limon_user {name, onboarded, legacy_id, provider, source:legacy}; the face is taught to Hassaku's book (Ha.learn) so every surface shows it; applyProfile repaints Me. A limon:identity CustomEvent re-adopts. Native identity wins over whatever a demo persona left in localStorage.
  • (c) SETTINGS VERBS GO NATIVE. In the store app, Logout posts limon:signout and Delete Account (after the existing confirm) posts limon:delete-account {confirmed:true} and clears the same keys confirmDeleteAccount clears. The browser behaviour is untouched when there is no shell.
  • (d) #screen-record .tab-bar { margin-top:auto }.
  • (e) Mu.apply is wrapped: a map host with no size defers the centre until switchView('map') has made it visible and invalidateSize has run.
  • (f) 44pt hit-slop on: .header-btn · card actions · .card-manage · player Prev/Next/Like/Save/Share/Map/report · #lbClose · .ob-skip · .chips .chip · .new-btn · #editProfileBtn · .player-top buttons · .map-credit a · .tab-bar .tab (min-height 48). Visual design unchanged.
  • (g) .embed-phone .leaflet-control-zoom hidden; the canvas keeps its own pair.
  • (h) .ls-ver reads the sealed version when the drawer opens; the canvas tooltip reads Block 36.
⬛ v13.20.0 · Kanpei Block 35 · 2026-09-08T20:14:22Z

A keyless geocoder that was never reachable. /geocode required a Google key before it would try anything, including the keyless rung built for installs without one — so the map could resolve an address the itinerary editor could not.

  • (b) a typed address earns its pin with no Google key — the gate now admits the keyless rung, and the client cache is versioned so every miss recorded under the old gate is re-asked once
  • (b) a resolved coordinate is written back to the stop, so “no pin yet” clears when the pin lands
  • (b) Save itinerary is confirmed end to end, including the reopen
  • (a) the attribution leaves the map surface and lives under it — the licence is kept, the real estate is not
  • (c) the playback-speed control is withdrawn
  • (d) the progress bar is a real scrubber: taller target, buffered range, drag and keyboard, and a thumb that only appears when it is wanted
  • (e) a cycled day brings its photographs — the gallery cycler is restarted from the new day’s media
⬛ v13.19.0 · Hyuganatsu Block 34 · 2026-09-08T19:03:54Z

A tile source that answers with a watermark instead of an error defeats every health check that only asks whether bytes arrived. Carto now does exactly that, and the ladder trusted it.

  • Carto is off the ladder — "KEY REQUIRED" tiles load successfully, which is worse than failing
  • the loading plate clears on the first tile and on a hard ceiling, so it can never linger over a drawn map
  • the vendor badge is gone from the map; attribution stays, because that is a licence term
  • the route legend moves clear of the attribution row
  • every hardcoded California centre is guarded at its own call site — four of them
  • a stop with no coordinates is never handed to L.marker
  • a mango spinner while the centre resolves, and Retry on the placeholder
  • the ⚠ row is the control: tapping an unpinned stop opens the stop editor
  • playback speed — 0.75 / 1 / 1.25 / 1.5, persisted, one control, no second transport
  • elapsed beside remaining, as the retreat strip already promised
  • Space, J / L, ← / → seek; Shift+← / → change day; aria-live on the title for Up Next
  • the two founder boards ship inside the plugin — admin page, version modal and GET limon/v1/tasks, all projected from dna.json
⬛ v13.18.0 · Ortanique Block 33 · 2026-09-05T22:13:20Z

Sample days were markup, and markup outlives every prune. A canvas that ships content cannot be a view of the server’s content; it can only ever be a view of both.

  • no sample content in either package — the fifteen markup cards, the seed importer and its photographs are gone; a fresh install shows an empty state that invites the first day
  • the server is the only source of truth: every card is built from limon/v1, and a card the wire does not know is removed
  • stale-while-revalidate: the last successful feed is cached and served when the wire is down, so a traveller on a ferry sees real days, not samples
  • the outbox flushes the moment the network returns, and says how many days are waiting
  • uninstall keeps every story, every member record and every ledger; it removes caches and options only, and stamps a count of what it kept
  • PERSISTENCE.md — one page saying where every kind of data lives in both packages
⬛ v13.17.0 · Murcott Block 32 · 2026-09-05T21:42:24Z

The map went blank because two older layers kept writing to a canvas a newer one already owned — one of them a second late, after an asynchronous geocode. The player could not be pulled because nothing had ever listened for the pull.

  • (a) pull a day up into the next one, or down into the last, on mouse, trackpad and touch — the outgoing day moves with the finger, snaps, and the incoming one slides in; a rubber band at the ends of the series
  • (a) the chrome retreats: three seconds of listening without a touch and the transport fades to the title and a thin progress line, the way Spotify’s canvas mode does; any touch brings it back
  • (a) up next, when the series runs out, is a seeded shuffle — Fisher–Yates over a mulberry32 stream, a ring of the last twelve days so nothing repeats, and a light weight toward the categories the listener has liked
  • (b) Murcott claims the map canvas: every older writer — Kishu’s blueprint, Iyokan’s tile plane, Hassaku’s second Leaflet — is a no-op while a live map is mounted
  • (b) the centre chain: pin coordinates → stop coordinates → geocoded stop → the day’s city → the listener’s location → a placeholder that says so. Never a blank grid
  • (b) the sample posts leave: retired to the trash on upgrade, never a user’s post, restorable from one button; seeding is opt-in from now on
⬛ v13.16.0 · Encore Block 31 · 2026-08-31T21:49:08Z

The player face was never a JavaScript problem. `background:#333 !important` on .player-avatar resets background-image to none and outranks inline styles, so every correct paint since Block 26 was discarded by the stylesheet before it reached the screen.

  • (d) the player face paints at last — through a custom property an !important shorthand cannot reset, and an <img> that falls down the size ladder if a crop is missing
  • (a) a stop typed as text earns its pin again — the geocode step lost in the Block 30 takeover is back in the draw path
  • (a) the route follows real streets between stops, through a keyless OSRM rung with Google Directions when a key exists
  • (b) the board sheet stacks its fields and both New buttons open the same sheet
  • (c) the series line moves out from under the comments and stops pushing past the bottom of the screen
⬛ v13.15.0 · Harumi Block 30 · 2026-08-31T21:00:55Z

The map could be blank for three separate reasons and reported none of them: a rung whose stylesheet never got replaced, a tile source with no health check, and a stop whose failed lookup was cached before the lookup was fixed.

  • (a) MapLibre GL 4.7.1 ships inside the plugin beside Leaflet, driven by a keyless raster style — smoother panning and a genuinely dark map with no CSS filter
  • (a) a tile-health ladder: repeated errors or no tile at all move the canvas to the next source, and a base plate means it is never a blank rectangle
  • (a) each rung installs and removes its own stylesheet, so a failed rung cannot leave its CSS behind
  • (a) stops that failed to geocode before the Block 29 fix are asked again, once, under a geocoder revision
  • (a) the native map gains offline tile caching, retina tiles and fitToCoordinates — straight from the react-native-maps source
  • (b) comments fold away by default and expand on a tap, the way YouTube does it, so the media keeps the screen
  • (c) My Boards is a shelf: name, rename, reorder, empty and delete, with counts and covers
⬛ v13.14.0 · Setoka Block 29 · 2026-08-31T19:50:25Z

The ledger could not read itself. Three blocks of evolution_log entries were appended in an invented schema, so the modal that exists to tell the founders what changed reported that nothing had.

  • (a) the ledger tells the truth again — lineage back to display strings with every detail row preserved, evolution_log repaired to the canonical schema, and a compactor that runs every block so the drift cannot return
  • (b) the outer transport buttons walk the series you are actually in — Explore, Saved, a Discover category, Me, or another traveller’s profile
  • (c) a cycled day repaints whole: background, transcript, title, byline, face, location, counts and comments
  • (d) every address finds its pin — the double-encoded Nominatim query is fixed and a five-rung ladder follows it
  • (e) Update photos opens the same editor as Edit info, with the media strip in view
⬛ v13.13.0 · Kiyomi Block 28 · 2026-08-31T18:58:00Z

BORROW. The control, the sheet, the flag and the card styling are gone. Limon_Social stays because face_rev is load-bearing for every avatar in this block, the /borrow route stays reachable, and no row is deleted

  • (c)(h) #playerAvatar was empty — Iy.dressPlayer returns early when playerAuthor() resolves nothing, so the one element whose comment says "never allowed to be empty" was the one element…
  • (d)(i) Edit Profile opened nothing on the live canvas, and the modal it builds carries only name/handle/tagline/bio
  • (e)(f) the map drew no tiles and collapsed its zoom controls: leaflet.css was loaded from unpkg and never applied. Layout, not logic
  • (e)(f) a text-typed stop carries no coordinates, so the itinerary had nothing to pin
  • (a)(j) the second post-meta span showed a seeded number; nothing ever counted a view
  • (g) the card action row had share/like/comment but no save-to-board and no map
  • (k)(l)(m) the transcript was read-only and a replaced voice clip left the old follow-along running
  • BORROW. The control, the sheet, the flag and the card styling are gone. Limon_Social stays because face_rev is load-bearing for every avatar in this block, the /borrow route stays…
⬛ v13.12.0 · Hassaku Block 27 · 2026-08-31T04:24:00Z
  • (a) a profile picture never left the phone — 128px data-URL in localStorage, consulted before the wire
  • (b) #playPauseBtn was a silent dead button — loadTrack ran only when T.card was null AND O.current was set, and the rejection was swallowed by an empty .catch()
  • (c) the gallery was served at preview size — `m.thumb || m.url` preferred a 300px file for a full-bleed background, and an edited gallery repainted from cache
  • (d) the player’s one line of prose reported an absence
  • (e) .map-canvas had no open-source engine
  • (g) `ago` had been on the wire since Pomelo and rendered nowhere
  • limonConfig.ts VERSION/CODENAME drifted two blocks behind every other version surface
  • Pomelo and Calamansi both bind #playPauseBtn on the same node; stopPropagation cannot separate listeners on one node, so both have always run
  • author_avatar() served a 150px thumbnail into a 72px disc on a 3× screen
  • the suite’s $ / $$ helpers ignored their root argument, so $(sel, card) read the FIRST match in the document
  • showToast was stubbed in beforeParse and overwritten by the page during boot
  • the mock fetch read opts.json, which api() never passes — it serialises into body
  • the mock play() recorded a call on an element that was already playing; a real HTMLMediaElement resolves without restarting
  • devicePixelRatio 1 — the pixelation defect only exists above 1×
⬛ v13.12.1 · Hassaku Block 27 · 2026-08-31T06:37:00Z
  • (a) a profile picture never left the phone — 128px data-URL in localStorage, consulted before the wire
  • (b) #playPauseBtn was a silent dead button — loadTrack ran only when T.card was null AND O.current was set, and the rejection was swallowed by an empty .catch()
  • (c) the gallery was served at preview size — `m.thumb || m.url` preferred a 300px file for a full-bleed background, and an edited gallery repainted from cache
  • (d) the player’s one line of prose reported an absence
  • (e) .map-canvas had no open-source engine
  • (g) `ago` had been on the wire since Pomelo and rendered nowhere
  • limonConfig.ts VERSION/CODENAME drifted two blocks behind every other version surface
  • Pomelo and Calamansi both bind #playPauseBtn on the same node; stopPropagation cannot separate listeners on one node, so both have always run
  • author_avatar() served a 150px thumbnail into a 72px disc on a 3× screen
  • the suite’s $ / $$ helpers ignored their root argument, so $(sel, card) read the FIRST match in the document
  • showToast was stubbed in beforeParse and overwritten by the page during boot
  • the mock fetch read opts.json, which api() never passes — it serialises into body
  • the mock play() recorded a call on an element that was already playing; a real HTMLMediaElement resolves without restarting
  • devicePixelRatio 1 — the pixelation defect only exists above 1×
⬛ v13.11.0 · Iyokan Block 26 · 2026-08-25T23:10:00Z

Founders' field report from the live [limon_phone] surface — four defects, lettered (a)-(d), each with a single mechanical cause, plus five more the repairs uncovered. (a) was a stale pointer, not a broken router: C.viewing held me() and won the || chain in Ponkan's healed dressProfile. (b) was an un-healable closure: Ponkan fixed openEditInfo and could not reach updatePhotos. (c) was a ladder whose every rung required a credential nobody had pasted. (d) was a silent bail on an empty data-av. Underneath them: P.authHdrs called but never exported since Block 24, a snapshot two blocks stale, iOS a block behind Android, and a native map hardcoded to a provider that needs a key. Block 26 fixes the four that were reported and the five that were not.

  • (a) A TAPPED @USERNAME OPENS THAT TRAVELLER — not a broken router, a stale pointer. Oroblanco's O.openProfile sets only O.viewing; Ponkan's healed C.dressProfile resolves `c.viewing || O().viewing || me()` and C.viewing STILL HELD me(), written by Ponkan's Me-tab pointerdown guard. C.viewing wins the || chain, so every username tap after a single Me visit resolved to the signed-in user. Discover worked only because its .ss-row path runs C.openProfile, which sets C.viewing first — that asymmetry was the whole defect. Iyokan arms one authoritative pointer on pointerdown, before any click router can read it, writes it to every layer at once, and re-asserts it after the switch
  • (b) UPDATE PHOTOS OPENS THE WHOLE POST — Ponkan healed openEditInfo and never healed updatePhotos(), which is closure-local (`photoCtx = …; photoIn.click()`) and cannot be overridden at all. It is re-bound on the sheet Pomelo builds, in the capture phase. The editor grew the rest of the daytrip with it: title, place, category, caption, the voice clip (preview, re-record, remove) and the itinerary — because "update and continue" has to mean the post, not a gallery
  • (c) .map-canvas IS A MAP WITH NO CREDENTIAL — Limon_Maps::ready() requires a saved key and `js` is `$ready && js_enabled()`, so with nothing configured tiers 1, 2 and 3 were ALL false and the ladder fell straight to the Blueprint. Kishu's drawLive was correct code that could never run. Tier 0 is a real slippy map drawn in-house: Web Mercator, raster tiles, drag, pinch, wheel, double-tap, numbered mango pins, InfoWindows, the route polyline, fitBounds and a scale bar. Google's JS API still wins the instant a key exists
  • (d) THE PLAYER WEARS THE POSTER'S FACE — dressAvatar() bails silently on a missing handle and O.openStory writes data-av="" for any story whose author did not resolve; #playerAvatar has no .post-card ancestor to fall back to, so the circle stayed empty. playerAuthor now walks every source for a HANDLE rather than picking one story object. Separately, patchCard already stamped data-avatar from the wire and Pk.statsFor already carried rec.avatar — neither was ever consumed, so the real WordPress photo was on the wire and never reached the glass
  • (e) A STOP TYPED AS TEXT CAN BECOME A PIN — the only path to a coordinate was the billable Google Geocoding API, which is therefore opt-in and therefore off, so the map had nothing to draw even once it had a canvas. Limon_Geo grew a free rung underneath the paid one: server-side, single-flight, a contactable User-Agent, every answer cached (hits AND misses), endpoint configurable
  • (f) P.authHdrs IS EXPORTED — Ponkan's saveEdit has read `P().authHdrs` since Block 24 and silently fallen back to {}, because authHdrs is closure-local and was never assigned onto P. Every media-order save since then has posted with no author token. Exported byte-identical, alongside tokenFor, saveEditPatch, applyEditToCard and the category maps, so the call Ponkan already makes starts working
  • (g) THE OFFLINE SNAPSHOT TELLS THE TRUTH — limonSnapshot.ts still froze 13.8.0 'Calamansi' (532,996 B, sha f8912c52…), two blocks stale, so every offline cold launch rendered Calamansi while the listing said Kishu. Re-frozen at 13.11.0 Iyokan, 719,777 B, sha 0f7d14a1…, byte-identical to the plugin canvas
  • (h) THE TWO STORE RAILS ARE REALIGNED — iOS sat a whole block behind Android: MARKETING_VERSION 13.9.0 and CURRENT_PROJECT_VERSION 142 against versionCode 143 / versionName 13.10.0. Both rails now read 13.11.0, build 144. 143 is burned unsubmitted, exactly as 136 and 138 were
  • (i) THE NATIVE MAP GETS TIER 0 TOO — LimonMapScreen hardcoded PROVIDER_GOOGLE, which on Android needs a key in the manifest, so a keyless build showed the same grey nothing one rail over. PROVIDER_DEFAULT plus a UrlTile overlay, fed by the same Limon_Maps::tiles() config the WebView reads
⬛ v13.10.0 · Kishu Block 25 · 2026-08-25T06:20:00Z

Block 24 pointed the Map button at the real world and shipped the itinerary as three strings. That was enough to hand a place to Google's own app — which is exactly why "Open" worked from the first day and masked the hole — and it was not enough to draw a map of our own, because a marker needs a latitude and a longitude and there was nowhere to put them. The canvas therefore fell back to the Maps Embed API, a surface that structurally cannot plot an arbitrary set of pins: it renders one place, or one A→B route with waypoints, and exposes no marker array. So .map-canvas was a real element containing something that could never become a real map, and with no key configured every story on the platform showed the same three hard-coded Anaheim pins. Block 25 gives every stop a coordinate, gives the canvas the Maps JavaScript API to draw them with, and gives creators the '+' to fix any pin the photos failed to supply.

  • (a) .map-canvas RUNS THE MAPS JAVASCRIPT API — Ponkan's Maps Embed iframe could render one place or one A→B route and had no marker array at all, so a five-stop daytrip could never show five pins. Kishu draws a real google.maps.Map inside the element: one numbered mango pin per stop, an InfoWindow on each, a mango route polyline, fitBounds with bezel padding, the Brand Guide dark basemap, and clustering past 8 pins
  • (b) EVERY STOP IS A COORDINATE — stops were {name, detail, query}: three strings, enough to hand a place to somebody else's map (which is why Open always worked) and not enough to draw our own. They now carry lat · lng · place_id · address · source, appended to the wire, never renamed
  • (c) A PASTED GOOGLE MAPS LINK BECOMES A PIN, FREE — /@lat,lng · !3d!4d · ?q= · ?ll= · ?daddr= · ?destination= · place_id: · geo: and the maps.app.goo.gl shortener (followed server-side) are all read locally with no API call; the pin lands while the field still has focus
  • (d) THE '+' BESIDE ADD LOCATION — the founders' retroactive repair: add, reorder, relabel, remove and re-pin an itinerary on a post that is already published, from Edit info, from the publish gate, or from the map screen itself
  • (e) PHOTOS THAT KNOW WHERE THEY WERE TAKEN PIN THEMSELVES — the GPS IFD is read in the browser before upload (first 128KB, no library) and again server-side on sideload; the first located photo becomes the story's home coordinate, and a pin a human placed always outranks one a JPEG remembered
  • (f) A FOUR-TIER LADDER, NOT A CLIFF — Maps JavaScript API → Maps Embed API → Maps Static API (route drawn from our own PolyUtil `path=enc:`) → the Blueprint, now projected from THIS story's real coordinates through Web Mercator instead of showing Disneyland to every daytrip on the platform
  • (g) POLYUTIL AND SPHERICALUTIL PORTED from googlemaps/android-maps-utils into PHP and JS, so the plugin, the canvas and both store apps compute one encoded polyline and one trip distance from one set of points
  • (h) THE NATIVE MAP IS IN-APP — limon:map now carries the whole located itinerary, and LimonMapScreen renders it on react-native-maps with PROVIDER_GOOGLE: numbered markers, the route, fitToCoordinates, and Open in Google Maps as a deliberate action rather than the only one
  • (i) GEOCODING IS OPERATOR-GATED AND CACHED — the only billable path is opt-in, tried last, rate-limited per IP, and remembered (hits and misses alike) so a place is never billed twice and a typo is never retried in a loop
⬛ v13.9.0 · Ponkan Block 24 · August 24, 2026 · 23:05 UTC

Founders' field report from the live [limon_phone] surface — nine defects, lettered (a)–(i), almost all of them identity defects. dna.json's evolution_log had Blocks 22 and 23 appended to the tail in a second schema, so Limon_Version's $log[0] resolved to Block 21 and the public ledger printed Pomelo's diagnosis under a Calamansi pill. patchCard() and injectCard() wrote the author's name into .username but never onto data-user, so C.renderProfileFeed had nothing to match and Me read "No daytrips yet" over a feed full of the signer's own posts; injectCard additionally stamped the literal string "you" as an author name. #profileAvatar's file input was armed on every profile, not just the owner's. C.dressProfile repainted the picture and the grid but never the name, handle or bio, so a visited traveller's identity stayed printed across Me. The Calamansi mirror interceptor swallowed ••• on every cloned card, which is why Manage worked in Explore and nowhere else. Listens · Followers · Following · Stories were local guesses with no network behind them and no tap target. The Map button opened a hard-coded Anaheim blueprint unrelated to the story being read. Edit info opened a four-field text box while Update photos opened a bare file picker — between them there was no way to reorder, replace or remove what was already published.

  • (a) One ledger, two surfaces: dna.json's evolution_log is normalised to a single newest-first schema (Blocks 22 and 23 restored and promoted to the head), Limon_Version now selects by MAX(block) instead of array position and renders fixes maps as well as changes lists, and the new GET limon/v1/ledger serves dna.json to the canvas so [limon_app]'s badge and the [limon_version] popup repaint from the same bytes. The embedded #limon-changelog stays as the offline snapshot the store apps fall back to when WordPress is unreachable.
  • (b) A post now carries its author. patchCard() and buildCard() stamp data-user from the wire's new story.user handle slug, injectCard() stamps the signed-in handle instead of the literal "you", and renderProfileFeed matches on handle, on data-user, on the .username text and on device ownership — so every daytrip you have uploaded shows under Me, and under a traveller's own profile when you open it from Discover.
  • (c) Only your own face is editable. The avatar file input is armed exclusively while #screen-profile carries data-own="1"; on anyone else's profile the tap is swallowed in the capture phase, before Dekopon's picker can open, and the app says whose photo it is.
  • (d) Me is always you — the whole card, not just the picture. dressIdentity repaints name, handle, home, tagline, bio, stats, avatar and grid together from one identity record, and the Me tab resets the viewing pointer on pointerdown, so no part of a visited profile survives the trip back.
  • (e) Manage ••• travels with the post. Profile-grid cards are cloned as first-class twins rather than mirrors, the mirror interceptor stands down whenever the press landed on ••• · 📣 · ♡ · 💬 · 🔖, and openManage resolves a twin back to its source card in Explore so an edit or a delete lands on the real post and both copies follow.
  • (f) Real numbers. The new limon/v1 people ledger aggregates Listens (summed plays), Stories (published count), Followers and Following per handle across the whole network; the canvas reads it for your profile and for every traveller you open, and falls back to the live feed count offline instead of to a decorative constant.
  • (g) The four stats are doors. Tapping Followers or Following opens the roster — every profile in the network on that side of the edge, visible to everyone, exactly as a social network behaves; Stories lists that traveller's daytrips and Listens breaks the plays down per story. Follow and unfollow write one edge through POST limon/v1/follow and the reverse side is derived from it, so the two counts cannot disagree.
  • (h) The Map button opens the real world. Map and 📍 read the open story's own stops and render a live Google map — Maps Embed API in the browser once a key is saved in Limon › Settings, and the native Maps SDK path through the limon:map side-channel in the store apps — with one-tap Directions and an honest blueprint fallback, drawn from the same real stops, when no key is configured yet.
  • (i) Edit info reopens the whole post. Instead of a four-field box, ••• → Edit info loads the daytrip back into Tell your story: every photo and video in the strip ready to reorder, replace or remove, the voice clip attached, title · 📍 location · category · caption preloaded, and "Save changes →" writing the new gallery order through POST limon/v1/stories/{id} with the media array — the same editor that created the post now edits it, on WordPress and in both store apps.
⬛ v13.8.0 · Calamansi Block 23 · August 24, 2026 · 21:40 UTC

Recon of the live Oroblanco canvas against the founders' eight-defect field report. The transport bar was mounted inside #screen-explore, so switchView() carried it off screen the moment you browsed; Oroblanco's own switchView wrapper called stopTransport on leaving the player. Discover held three invented placeholder cards. The Me tab reopened whichever traveller you last looked at. paintAvatars guarded #profileAvatar with `if (photo || !style.backgroundImage)`, so one picture stuck to every profile with the handle's initials stacked over it. The blanket .header-btn binding sent the profile X to openSettings().

  • (a) transport bar moved from #screen-explore onto .iphone so switchView cannot take it away; Oroblanco's stopTransport-on-leave healed in the Calamansi switchView wrapper; ▶ plays in place instead of jumping to the player; navigator.mediaSession + limon:audio; native AppKilledPlaybackBehavior.ContinuePlayback and the Android media foreground service
  • (b) three hard-coded Discover placeholders removed; Discover mirrors the live Explore feed and re-mirrors on mutation
  • (c) the Me tab always resolves to the signed-in handle; #screen-profile carries data-own
  • (d) #profileAvatar repaint made unconditional and keyed to the handle — the `if (photo || !style.backgroundImage)` guard was the sticky-picture bug
  • (e) .av-i initials layer retired; deterministic procedural portraits generated per handle
  • (f) the blanket .header-btn → openSettings() binding now skips buttons carrying their own onclick; the X declares data-exit and force-closes the drawer
  • (g) Discover, Boards and every profile render the Explore .post-card skin
  • (h) other travellers' profiles leave Discover active; predictive search over a local index, widened by limon/v1 GET /stories?search=
⬛ v13.7.0 · Oroblanco Block 22 · August 24, 2026 · 19:20 UTC

Recon of the live Pomelo canvas against the founders' report. Comments were held in one flat session array, so every story appeared to share a single thread; the feed's .avatar holders were empty discs because the wire carried no author picture; and the follow relationship had nowhere to persist.

  • (a) Every story owns its own comment thread. v13.6.0 held one flat session array, so a comment posted on any daytrip appeared under all of them; the thread now persists per post in _limon_comments and rides the wire as story.comments.
  • (b) The feed shows real faces. story.avatar carries the author's picture — app avatar first, then the WordPress avatar — so the .avatar holders fill the moment WordPress hydrates instead of staying empty discs.
  • (c) Follow persists. profile.graph stores the relationship in limon_graph user meta, so Following survives a reload instead of resetting with the session.
⬛ v13.6.0 · Pomelo Block 21 · 2026-08-24T02:40:00Z

Recon of the live Dekopon canvas against the founders' eight production asks. The fifteen Explore posts were static HTML — nothing in wp-admin could edit or retire them, and uploads lived only in localStorage. openShare() targeted #share-sheet, an id that never existed, so Share was dead on every surface. cardStory() only matched data:/blob: thumbnails and Dekopon's finishPublish regex missed the browser-serialised url("blob:…"), so WordPress-hosted thumbs never reached a board tile and published media silently became []. The photo strip appended after three demo thumbs. Edit Profile had no tagline/bio and never persisted. Two more latent Dekopon circuits were found dead at runtime: the Post Details gate on #uploadStoryBtn was overwritten by the base layer's DOMContentLoaded rebind, and the Change-profile-photo wrap ran before openEditProfile existed. The header tip still read Shikuwasa; mobile-dna.json read Tangelo.

  • (a) Limon_Seed: the 15 demo Explore posts are seeded once as real limon_story posts (idempotent by _limon_seed, thumbs sideloaded into the Media Library, FileBird › Demo stories); Story Uploads edits them, Trash retires them, Settings can restore them; the canvas replaces each static card with its live twin on hydrate and drops trashed ones.
  • (a) Persistence: the record flow creates the story in limon/v1 (POST /stories → id · status · edit_token) and uploads every photo, video, and voice clip via POST /media in strip order; GET /stories?device= returns the requesting device’s own pending stories so an upload survives reload while it awaits moderation.
  • (b) Share fixed and rebuilt 1:1 with the store app — 📣 Share this post · 🔗 Copy link · Close; 📣 on every Explore card and in the player; native iOS/Android share handle via limon:share / limon:copy over ReactNativeWebView, Web Share API + clipboard in browsers; iframes now carry allow="web-share".
  • (c) My Boards shows only the user’s boards — the six placeholder boards evicted; 🔖 Saved Stories (Dekopon) + boards the user creates (persisted, deletable); hold 🔖 files a story into a named board; tiles fill from saved media including WordPress-hosted thumbnails (quoted url() + https now match).
  • (d) Tell your story: three empty slots fill left → right from the green block, extra media appends and the strip scrolls; hold and drag to reorder (#1 is the cover, numbered badges, × removes, a slot returns below three); videos preview inline with a 🎬 tag and feed the player cycler.
  • (e) Manage ••• on every post you own (feed + Me grid) → Update photos · Edit info (title · 📍 location · category · caption · Update/Cancel, 1:1 with the store app) · Delete; authors carry an edit token per story, wp-admin carries edit_post; GET|POST|DELETE /stories/{id} added to limon/v1.
  • (f) Limon_Media: every clip lives in the default WordPress Media Library, attached to its story and filed under FileBird › Limon Day Trips › Photos | Videos | Voice recordings | Profile photos | Demo stories (Folder::newOrGet + setFoldersForPosts, guarded — FileBird absent is a no-op); ordered gallery meta _limon_media_ids; Story Uploads carries the media strip (add · remove · drag-reorder, inline audio/video previews), a 🎞 inventory column, and the app-handle override.
  • (g) Edit Profile persists username · handle · tagline · profile description on the phone and mirrors them to WordPress user meta (limon_handle · limon_tagline · limon_bio) through GET|POST /profile when signed in; User Profiles gained the tagline field.
  • (h) [limon_version] — mango pill (⛓ vX.Y.Z · codename · live UTC clock) → draggable, resizable 22px public ledger read from dna.json: block, sealed stamp, build token, diagnosis, changes, lineage, and the collapsible evolution ledger. WordPress-only, zero dependencies, one shimmer.
  • Latent repairs: Post Details gate re-armed after the base rebind; Change-profile-photo row restored in Edit Profile; window.LIMON_CFG now set on bridge so account deletion relays; injectCard cards carry identity (data-local/data-client), engine category keys, and the styled .post-info/.location classes; version stamps and the header tip read 13.6.0 Pomelo everywhere.
  • Security: guest media uploads are token-bound to the device’s own story, MIME allow-listed, size-capped (Settings › Guest upload cap), and rate-limited; edit tokens are stored only as wp_hash and compared in constant time; private meta (gallery · token · device) is excluded from wp/v2; every new REST field is additive.
  • Floors: versionCode/build 139 · marketing 13.6.0 (138 burned unsubmitted, per discipline).
⬛ v13.5.0 · Dekopon Block 20 · 2026-08-19T19:30:00Z

Fine-tooth-comb pass on the stable Tangelo canvas. Recon proved EXIF-GPS, the share sheet, edit-profile, feed injection and ±15 skips already alive; the misses were the phone-header logo (old SVG), video intake, a background media cycler, an unwired play/pause + Like, the post-details location screen, Change-profile-photo, and the entire Save/Saved circuit.

  • Phone header carries the founders' true wordmark (2x data-URI, trimmed + LANCZOS, responsive height).
  • Layer-3 media engine: camera/photo/video intake, video-tagged thumbs, player background cycles media full-bleed at 4500 ms with 4000 ms cross-fade.
  • Transport + Like wired with live progress and persistence; Save circuit added (cards, player, Saved Stories board, working + New).
  • Location gate: Post Details screen with EXIF prefill and Next locked until location.
  • Change profile photo from Edit Profile or avatar tap, resized 128px, persisted.
  • Floors: versionCode/build 138 · marketing 13.5.0 (137 burned unsubmitted).
⬛ v13.4.1 · Tangelo Block 19 · 2026-08-12T04:00:00Z

The founders handed over the actual GitLab production ZIP for absorption. A full sha256 walk proved Tangelo = live tree + exactly the documented mutations (735/762 files byte-identical, 12 surgical edits, 15 additive files, one new dependency). One genuine crash surface remained: the canvas shell was imported eagerly by the navigator, so react-native-webview's JS evaluated at every cold launch even in LAUNCH_MODE:'screen'.

  • RN: shell registration made lazy — in 'screen' mode the default binary provably never evaluates a line of new-module JS.
  • RN: docs/PROVENANCE-AUDIT.md — the absorption certificate (method, full classification, dependency delta, crash-surface analysis).
  • WP: limon/v1/canvas answers Cache-Control: no-store — the heartbeat can never be served stale.
  • Floors: versionCode/build 137 · marketing 13.4.1 (136 burned unsubmitted, per discipline).
⬛ v13.4.0 · Tangelo Block 18 · 2026-08-12T00:00:00Z

The generator brief v2.0 left three gaps open after Rangpur: no iOS privacy manifest in the app bundle, no heartbeat for the native shell to detect a revived/refreshed canvas, and a theme-pass instruction written against an older repo state — recon proved the legacy orange tokens are dead code with zero consumers while Brand Guide tokens carry 76 live usages.

  • GET limon/v1/canvas — version + codename + live build token + ts; powers snapshot→live auto-heal in the RN shell.
  • body.embed-native standalone hiding rule — native mode survives any future embed-phone refactor.
  • Mobile ledger synced: RN 13.4.0 Tangelo, versionCode 136 (135 burned unsubmitted), PrivacyInfo.xcprivacy shipped app-side.
  • limon/v1 wire grown additively; nothing renamed, nothing removed.
⬛ v13.3.0 · Rangpur Block 17 · 2026-08-11T00:00:00Z

The live store apps (bare RN 0.78, Android versionCode 134 / iOS 0.14) and the WordPress canvas evolved on separate rails. The [limon_phone] ground truth had no bezel-free surface a real device could wear, and prior mobile checklists carried versionCode 30 — which Play would reject below the live 134.

  • ?embed=native — device-stage-only rendering with the drawn iPhone flattened to the real viewport; drawn status bar hidden (the OS provides the real one; the RN SafeAreaView owns insets).
  • app-shell.php ?native=1 passthrough — same fresh-per-request build token, so native clients inherit the D1 cure for free and a 13.2.1 site degrades gracefully to the standard shell.
  • window.__LIMON_NATIVE__ pre-script handshake + limon:ready over ReactNativeWebView.postMessage.
  • identity ledger RESOLVED — iOS bundle com.limondaytrips.limons read from the production Xcode project; Android com.limondaytrip confirmed; mobile version floor recorded (next versionCode 135 over live 134).
  • limon/v1 wire untouched; all mutations additive on the Makrut trunk.
⬛ v13.2.1 · Shikuwasa · delivery patch Block 16 · 2026-08-04T03:55:00Z

public/index.html shipped byte-identical to the preview. The content was correct; DELIVERY failed. Three defects, none of them visible to a content diff.

  • (D1) STALE-FOREVER URL fixed — the iframe src was the fixed string public/index.html?embed=app. index.html is a STATIC file inside the plugin folder, so WP Engine's edge cache and the visitor's browser both key on that URL. Updating the plugin rewrote the bytes on disk but never the URL, so every cache on the path kept serving the pre-update build indefinitely. Every iframe URL now carries a build token folding LIMON_VERSION with the file's own mtime and size, so it moves when either the release moves or the file is touched by hand.
  • (D2) DEAD LETTERBOX CSS fixed — v13.2.0 shipped body.embed-app rules that nothing ever applied; only embed-phone was set. Three letterbox guards were dead code in the exact [limon_app] context reported as broken. The layer now applies embed-app, autoheight, and is-embedded.
  • (D3) MARKETING NO LONGER TRAPPED — .limon-app-embed was pinned to 100dvh, and the parent bridge applied limon:height only to .limon-phone-frame. The FIGMA rail, founders band, and platform band therefore sat below the fold inside a nested scrollbar. height="auto" now grows the frame to its own document so the OUTER page scrolls as one continuous surface, exactly like the preview.
  • Height reporting hardened for lazy images — a ResizeObserver on <body> plus per-image load listeners, coalesced through requestAnimationFrame and de-duplicated at 2px, so a growing frame never thrashes.
  • Purge orchestrator added — WP Engine, WP Rocket, W3 Total Cache, LiteSpeed, SG Optimizer, WP Fastest Cache, Cachify, and the object cache. Every call guarded; a missing host plugin is a no-op, never a fatal.
  • Self-healing drift detection — an FTP/SFTP upload fires no upgrader hook, so the token re-mints silently while the PARENT page may still be cached carrying the old token in its iframe src. The drift is detected and page caches flush once, on shutdown, off the critical path.
  • Frontend Health panel added to the Dashboard — the live iframe URL, build token, on-disk fingerprint of index.html, asset resolution check, detected cache layers, and a one-click purge. The v13.2.0 failure was invisible from wp-admin; this class of failure is now visible before a visitor ever meets it.
⬛ v13.2.0 · Shikuwasa Block 15 · 2026-08-04T02:15:00Z

Sealed before the diagnosis field entered the ledger schema in Block 16 — the change list below is this block's complete record.

  • (a) TRANSPARENT LOGO SURGERY — the master RGBA PNG is now the single source. Six opaque JPEG rasters (mislabelled image/webp, rendering as a white plate on charcoal) evicted from the header, footer, login sheet, and both responsive variants. Forged limon-logo-wide.webp (96px wordmark), limon-logo-square.webp (192px transparent app icon), limon-favicon.png. Alpha preserved end to end; the square variant no longer sits on a border-radius plate.
  • (b) FIGMA MARKETING RESTORED — the 12 real MVP frames ship as files in public/assets/screenshots/ rather than megabytes of inline base64. index.html is a 312 KB shell referencing 596 KB of cacheable WebP instead of the 1.9 MB inline payload v13.0.0 carried.
  • (c) NATIVE SETTINGS DRAWER — the shipped React Native menu, 1:1: Logout (with the 'guest · early access' identity ledger), Change username, Change profile photo, Invite friends, Help, Invest, Send us feedback, Replay welcome tour, destructive Delete Account, version stamp. Pocket Lemon sheet, a real verb behind every row, native share sheet with clipboard fallback.
  • (d) HEADER LETTERBOX KILLED — three vectors: an explicit zero box on html/body, a margin-collapse guard so the sticky bar cannot inherit leading margin, and a JS letterbox reaper in the parent bridge that walks the real ancestor chain and zeroes top padding wherever the app is the first rendered thing. :has() covers modern browsers; the reaper covers every theme.
  • (e) 22px DRAGGABLE MODAL PLATFORM — every editing surface is a draggable, resizable, 22px-bordered modal. Onboarding renders real FIGMA frames with drag-to-reorder, add, edit, enable/disable, delete, and full-size preview. Add New Story opens a modal carrying every field including media-library pickers for the featured photo and the voice recording. User Profiles split into the APP profile (handle, bio, home city, onboarding goal, tier, avatar, notifications, verified) and the WORDPRESS profile (display name, email, website, role, WP bio) — cross-linked, each able to jump to the other.
  • (f) FIGMA SLIDER ON THE HOMEPAGE — a real rail with pointer drag, touch swipe, arrow buttons, keyboard navigation, and page dots. Marketing surface only, hard-excluded from ?embed=phone, honouring the v10 architectural separation.
  • Founders band and platform band restored alongside the rail.
  • Seven nonce-guarded AJAX routes added under manage_options: save_onboarding, save_story, delete_story, get_story, save_appprofile, save_wpprofile, get_user.
  • Role-change safety: an operator can never change their own role, and the last administrator can never be demoted.
  • Account deletion wired end to end — required by both the Apple Review Guidelines and the Google Play Developer Policy for any app that creates accounts.
⬛ v13.1.0 · Kabosu Block 14 · 2026-08-03T21:30:00Z

Sealed before the diagnosis field entered the ledger schema in Block 16 — the change list below is this block's complete record.

  • Six Explore categories restored incl. Shopping — equidistant flex columns, two-line labels, zero truncation; data-cat engine values preserved
  • Settings unified to ONE surface: the production panel sliding from the right
  • [limon_phone] shortcode — the isolated interactive device (?embed=phone)
  • [limon_app] full-bleed contract — 100vw x 100dvh, Impreza/WPBakery letterboxing neutralized
  • 22px admin platform shipped: Dashboard, Onboarding, Story Uploads, User Profiles, Documentation, Settings
  • limon/v1 grew /media and hardened /report with the auto-pending threshold
  • Player +/-15s skips; report/block loop contained in-device
Founded by Lili & Ramon Montes Developed by Bitghost.com · ghost@bitghost.com

THE place for your travel stories. Audio-first day trips shared in your own voice.

support@limondaytrips.com
Bitghost Ai