Skip to content

chore: reconcile production release into staging#815

Closed
wilhel1812 wants to merge 4 commits intostagingfrom
chore/reconcile-main-0.18.0-to-staging
Closed

chore: reconcile production release into staging#815
wilhel1812 wants to merge 4 commits intostagingfrom
chore/reconcile-main-0.18.0-to-staging

Conversation

@wilhel1812
Copy link
Copy Markdown
Owner

Summary

  • Merge the production release commit from origin/main back into staging before issue Add username to deeplinks #813 work.
  • Keep staging as the conflict-favored branch per drift reconciliation policy.

wilhel1812 and others added 4 commits April 25, 2026 00:03
* ui: align sidebar heading with Path terminology (#411) (#434)

* chore: reconcile main into staging (2026-04-06 refactor prep) (#437)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* release: v0.11.0 (#214)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding + simulation library
- First visit: WelcomeModal opens with onboarding collapsed + library visible
- Deep-link visits skip the welcome modal entirely
- Returning users with no simulation auto-open the Simulation Library
- ? button opens WelcomeModal with onboarding expanded
- Delete old OnboardingTutorialModal

* refactor(onboarding): compact welcome card, simple onboarding modal (#152) (#211)

- Welcome modal: compact card with 3 action buttons (not full-screen)
- Onboarding: restored as simple text modal (no library, no collapsible)
- OS detection: Cmd on Mac, Ctrl elsewhere via {{MODIFIER}} placeholder
- Simulation Library button in onboarding text via custom ReactMarkdown component
- Trimmed onboarding: removed basemap providers, workflow, roles, security note
- Added showNewSimulationRequest store state to trigger New Simulation from welcome

* refactor(onboarding): inline links for Simulation Library and Site Library (#152) (#212)

* feat(deeplink): live update browser URL to match current share link (#190) (#213)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* feat(deeplink): live update browser URL to match current share link (#190)

Add buildDeepLinkPathname helper for pathname-only computation.
Sync browser URL bar via history.replaceState when simulation or
site selection changes. Clears stale deeplink when no simulation
is active. Skips sync until initial deeplink resolution settles.

Includes drift reconcile (0863752: unblock blank simulation workflows).

* release: prepare v0.11.0 changelog and metadata

* fix(api): restore no-store headers for profile and public simulation

* chore: retrigger release checks

---------

Co-authored-by: Mats <heigre@protonmail.com>

* ci: add workflow to require milestone on completed issue close (#217)

* release: v0.12.0 (#280)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding + simulation library
- First visit: WelcomeModal opens with onboarding collapsed + library visible
- Deep-link visits skip the welcome modal entirely
- Returning users with no simulation auto-open the Simulation Library
- ? button opens WelcomeModal with onboarding expanded
- Delete old OnboardingTutorialModal

* refactor(onboarding): compact welcome card, simple onboarding modal (#152) (#211)

- Welcome modal: compact card with 3 action buttons (not full-screen)
- Onboarding: restored as simple text modal (no library, no collapsible)
- OS detection: Cmd on Mac, Ctrl elsewhere via {{MODIFIER}} placeholder
- Simulation Library button in onboarding text via custom ReactMarkdown component
- Trimmed onboarding: removed basemap providers, workflow, roles, security note
- Added showNewSimulationRequest store state to trigger New Simulation from welcome

* refactor(onboarding): inline links for Simulation Library and Site Library (#152) (#212)

* feat(deeplink): live update browser URL to match current share link (#190) (#213)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* feat(deeplink): live update browser URL to match current share link (#190)

Add buildDeepLinkPathname helper for pathname-only computation.
Sync browser URL bar via history.replaceState when simulation or
site selection changes. Clears stale deeplink when no simulation
is active. Skips sync until initial deeplink resolution settles.

Includes drift reconcile (0863752: unblock blank simulation workflows).

* chore: back-merge main into staging after v0.11.0 release (#215)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* release: v0.11.0 (#214)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding + simulation library
- First visit: WelcomeModal opens with onboarding collapsed + library visible
- Deep-link visits skip the welcome modal entirely
- Returning users with no simulation auto-open the Simulation Library
- ? button opens WelcomeModal with onboarding expanded
- Delete old OnboardingTutorialModal

* refactor(onboarding): compact welcome card, simple onboarding modal (#152) (#211)

- Welcome modal: compact card with 3 action buttons (not full-screen)
- Onboarding: restored as simple text modal (no library, no collapsible)
- OS detection: Cmd on Mac, Ctrl elsewhere via {{MODIFIER}} placeholder
- Simulation Library button in onboarding text via custom ReactMarkdown component
- Trimmed onboarding: removed basemap providers, workflow, roles, security note
- Added showNewSimulationRequest store state to trigger New Simulation from welcome

* refactor(onboarding): inline links for Simulation Library and Site Library (#152) (#212)

* feat(deeplink): live update browser URL to match current share link (#190) (#213)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* feat(deeplink): live update browser URL to match current share link (#190)

Add buildDeepLinkPathname helper for pathname-only computation.
Sync browser URL bar via history.replaceState when simulation or
site selection changes. Clears stale deeplink when no simulation
is active. Skips sync until initial deeplink resolution settles.

Includes drift reconcile (0863752: unblock blank simulation workflows).

* release: prepare v0.11.0 changelog and metadata

* fix(api): restore no-store headers for profile and public simulation

* chore: retrigger release checks

---------

Co-authored-by: Mats <heigre@protonmail.com>

---------

Co-authored-by: Mats <heigre@protonmail.com>

* chore: sync staging with main after v0.11.0 (#216)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* release: v0.11.0 (#214)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding + simulation library
- First visit: WelcomeModal opens with onboarding collapsed + library visible
- Deep-link visits skip the welcome modal entirely
- Returning users with no simulation auto-open the Simulation Library
- ? button opens WelcomeModal with onboarding expanded
- Delete old OnboardingTutorialModal

* refactor(onboarding): compact welcome card, simple onboarding modal (#152) (#211)

- Welcome modal: compact card with 3 action buttons (not full-screen)
- Onboarding: restored as simple text modal (no library, no collapsible)
- OS detection: Cmd on Mac, Ctrl elsewhere via {{MODIFIER}} placeholder
- Simulation Library button in onboarding text via custom ReactMarkdown component
- Trimmed onboarding: removed basemap providers, workflow, roles, security note
- Added showNewSimulationRequest store state to trigger New Simulation from welcome

* refactor(onboarding): inline links for Simulation Library and Site Library (#152) (#212)

* feat(deeplink): live update browser URL to match current share link (#190) (#213)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* feat(deeplink): live update browser URL to match current share link (#190)

Add buildDeepLinkPathname helper for pathname-only computation.
Sync browser URL bar via history.replaceState when simulation or
site selection changes. Clears stale deeplink when no simulation
is active. Skips sync until initial deeplink resolution settles.

Includes drift reconcile (0863752: unblock blank simulation workflows).

* release: prepare v0.11.0 changelog and metadata

* fix(api): restore no-store headers for profile and public simulation

* chore: retrigger release checks

---------

Co-authored-by: Mats <heigre@protonmail.com>

---------

Co-authored-by: Mats <heigre@protonmail.com>

* refactor: extract coverage state into separate Zustand store (#159) (#218)

Move coverageSamples, isSimulationRecomputing, simulationProgress,
simulationRunToken, and recomputeCoverage action out of appStore.ts
into a dedicated coverageStore.ts. Components subscribe to coverage
state via useCoverageStore, narrowing the re-render fan-out during
coverage recompute lifecycle.

* fix: update simulation snapshot after library entry edit (#91) (#219)

updateSiteLibraryEntry was missing the updateCurrentSimulationSnapshot()
call that every other mutation function makes. This caused gain, power,
cable loss, antenna height, and other fields edited via the resource
details popup to not reflect in the simulation preset snapshot until a
full page reload.

* fix: move map to background overlays and consolidate inspector (#88) (#224)

* feat: add mobile tabbed map overlays for viewing workflow (#171) (#225)

* fix: refine mobile full-screen map and profile panel behavior (#171) (#226)

* fix: enable mobile viewport-fit and keep environment frame (#171) (#227)

* fix: force true full-viewport mobile map sizing (#171) (#228)

* fix: stabilize iOS viewport sizing for full-screen mobile map (#171) (#229)

* fix: use layout viewport sizing for iOS full-bleed map (#171) (#230)

* feat: improve mobile panel toggles and map selection controls (#171) (#231)

* fix: polish mobile tabs and unify panel/header controls (#171) (#232)

* fix: normalize mobile panel sizing and centralize ui icons (#171) (#233)

* fix: make mobile panel and attribution layout robust (#171) (#234)

* fix: use unified mobile attribution clearance offsets (#171) (#235)

* fix: measure mobile overlay clearance for attribution and restore env badge (#171) (#237)

* fix: reset mobile map layout and top-anchor attribution (#171) (#238)

* fix: stabilize mobile full-bleed map and attribution top anchoring (#171) (#239)

* fix: show multi-select toggle only on mobile (#171) (#241)

* fix: use default carto normal style for provider fallback (#167) (#242)

* fix: default basemap preset to carto normal-themed on fresh load (#167) (#243)

* fix: set desktop sidebar and inspector width to 20vw max 400px (#240) (#244)

* fix: move env badge to sidebar title row and compact user chip (#240) (#245)

* fix: simplify sidebar header controls to icon-only row (#240) (#246)

* fix: make inspector a right sidebar and simplify header controls (#240) (#247)

* fix: move results panel into right inspector (#240) (#248)

* feat: unify UI iconography with Lucide controls (#249)

* fix: remove remaining icon chrome and unify expand/collapse cues (#251)

* fix: correct map icon states and tighten icon accessibility (#253)

* fix: use fullscreen fit icon and prevent pill shadow clipping (#254)

* fix: reorder map utility icons and use stack multi-select icon (#255)

* fix: center compact map utility pill on mobile (#257)

* chore: reconcile main into staging (#258)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* release: v0.11.0 (#214)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding + simulation library
- First visit: WelcomeModal opens with onboarding collapsed + library visible
- Deep-link visits skip the welcome modal entirely
- Returning users with no simulation auto-open the Simulation Library
- ? button opens WelcomeModal with onboarding expanded
- Delete old OnboardingTutorialModal

* refactor(onboarding): compact welcome card, simple onboarding modal (#152) (#211)

- Welcome modal: compact card with 3 action buttons (not full-screen)
- Onboarding: restored as simple text modal (no library, no collapsible)
- OS detection: Cmd on Mac, Ctrl elsewhere via {{MODIFIER}} placeholder
- Simulation Library button in onboarding text via custom ReactMarkdown component
- Trimmed onboarding: removed basemap providers, workflow, roles, security note
- Added showNewSimulationRequest store state to trigger New Simulation from welcome

* refactor(onboarding): inline links for Simulation Library and Site Library (#152) (#212)

* feat(deeplink): live update browser URL to match current share link (#190) (#213)

* fix: unblock blank simulation workflows (#179)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* feat(deeplink): live update browser URL to match current share link (#190)

Add buildDeepLinkPathname helper for pathname-only computation.
Sync browser URL bar via history.replaceState when simulation or
site selection changes. Clears stale deeplink when no simulation
is active. Skips sync until initial deeplink resolution settles.

Includes drift reconcile (0863752: unblock blank simulation workflows).

* release: prepare v0.11.0 changelog and metadata

* fix(api): restore no-store headers for profile and public simulation

* chore: retrigger release checks

---------

Co-authored-by: Mats <heigre@protonmail.com>

* ci: add workflow to require milestone on completed issue close (#217)

---------

Co-authored-by: Mats <heigre@protonmail.com>

* feat: add Easter holiday theme override framework (#256) (#259)

* fix: expand Easter theme window across Easter week (#256) (#260)

* refine map panel controls and sidebar glass treatment (#261)

Move map settings into the right Map expandable, keep the utility pill on-map, and adjust panel styling/behavior so controls fit better and profile expansion hides the right inspector.

* fix mobile viewport fill and tab panel offset (#262)

Align mobile tab-bar height with the glass tab container to prevent panel overlap, and use fixed inset map sizing with dvh/lvh fallback so iOS keeps the map full-bleed behind browser chrome.

* fix mobile panel gap and iOS map anchoring (#263)

Add a consistent gap between the mobile tab bar and panel stack, and switch the mobile map shell to top/left/right anchoring with large viewport height so the background map can extend behind iOS browser chrome.

* fix iOS mobile map full-bleed sizing (#264)

Revert mobile map shell to full-edge anchoring and add robust viewport-height fallbacks while keeping the panel gap spacing fix, so iOS can keep the map behind browser chrome without bottom panel overlap.

* fix iOS full-bleed map with webkit fallback (#265)

Apply a clean mobile viewport fallback stack with  for root/app/map shells and trigger map resize on visualViewport changes, while keeping the tab-to-panel spacing fix consistent.

* fix iOS map full-bleed inset sizing (#266)

Simplify the mobile map shell to fixed inset-only sizing and narrow WebKit fill-available fallback scope so the map is not constrained by intermediate mobile containers.

* Recover iOS full-bleed map behavior (#220) (#267)

* Revert "fix iOS map full-bleed inset sizing (#266)"

This reverts commit 5568a0c116f7fb1433e63c7386a9bb3f8b21c15b.

* fix iOS map resize clamping on safari chrome

Stop resizing the map on visualViewport changes so Safari URL bar transitions do not clamp map canvas height against the visible viewport while full-bleed container sizing remains in place.

* restore iOS partial-fix resize baseline (#268)

Re-enable visualViewport resize map refresh to match the 3eed567 behavior, but avoid scroll-driven resize churn so Safari toolbar motion is less likely to force repeated visible-viewport clamping.

* fix iOS map full-bleed canvas bounds (#269)

Restore the 3eed567 viewport listener baseline and pin the internal MapLibre map/canvas stack to the mobile map shell bounds so Safari toolbar transitions no longer leave a clipped map rectangle.

* add staging-only mobile viewport diagnostics (#270)

Temporarily disable the staging frame border and add a staging-only viewport metrics overlay (inner/visual/map/canvas heights) to remove visual ambiguity and diagnose iOS full-bleed map clipping.

* move staging viewport debug chip above mobile UI (#271)

Center the staging diagnostics chip with an extremely high z-index so it remains visible above the mobile tab bar and overlays during iOS viewport debugging.

* stabilize iOS map initial canvas sizing (#272)

Force an immediate + delayed post-mount map resize sequence to prevent stale initial canvas bounds on iOS, and improve staging diagnostics by reading map/container/canvas heights from MapLibre directly.

* repair iOS diagnostic probe and add maplibregl-wrapper override (#273)

Add onLoad callback to Map component to track when MapLibre is ready for diagnostics probe, and add CSS override for .maplibregl-wrapper to force full-bleed on mobile.

* fix iOS map background color and viewport transform (#274)

Add background-color to maplibregl-wrapper to cover default yellow tile background, and reset viewport transform to none on mobile to prevent rendering gaps.

* anchor mobile map to bottom and expand viewport diagnostics (#275)

Revert the temporary map background workaround, switch the mobile map shell to bottom-anchored sizing with lvh fallback, and add top/bottom debug metrics for panel/map/canvas to pinpoint vertical offset behavior on iOS.

* top-anchor iOS mobile map shell (#276)

Force top anchoring for the mobile map shell and remove map-panel from WebKit fill-available fallback scope so extra viewport height extends below the visible area instead of shifting map content upward.

* clean up mobile map sizing and remove diagnostics (#277)

Remove temporary viewport debug instrumentation and iOS-specific map sizing experiments, restore normal fullscreen map sizing on mobile, and keep only safe-area based UI offsets with viewport-fit=cover behavior.

* chore: sync unpushed staging fullscreen toggle fixes (#278)

* fix path profile fullscreen toggle to only toggle profile, not map

* fix: map and path profile fullscreen toggles work independently

* fix: decouple map and path profile fullscreen toggles

* fix: correct app shell CSS class for profile vs map expansion

* release: bump version to 0.12.0

* release: trigger CI for v0.12.0

---------

Co-authored-by: Mats <heigre@protonmail.com>

* Release v0.12.1 hotfix (#286)

* fix: share holiday theme state via Zustand & bump to v0.12.1

Lift holidayWindowState from useThemeVariant local useState into the
appStore so AppShell, MapView, and Sidebar share reactive state.
Fixes Revert Theme refresh requirement and adds yellow Easter option
to color theme dropdown.

* chore: re-trigger CI for release/v0.12.1

* chore: update workflows to set explicit commit status checks

* chore: finalize v0.12.1 version (#288)

* hotfix: reconcile production auth fix and v0.12.2 in main (#334)

* hotfix: restore production sign-in recovery from locked state (#24)

* chore: bump version to 0.12.2 for production hotfix release

* fix: align required status checks to PR head SHA (#335)

* fix: publish required statuses on PR head SHA

* fix: keep CI status publish working on push events

* release: 0.13.0 (#368)

* Deep link V2 + FastAPI calculation (#192)

* fix: align multi-site overlays with radial terrain loading

* fix: remove relay overlay bounding box artifact

* fix: update profile when selected sites change

* fix: clear map selection before add-site and default zero-select heatmap

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: prevent fallback link after deselect and gate profile to two sites

* fix: remove fallback profile link message and stale first-link fallback

* fix: preserve deselect state and sync profile cursor on direction flip

* fix: apply buffered overlay mask when no sites selected

* fix: use simulation-wide boundary for overlays and terrain loading

* fix: remove manual terrain controls and online elevation sync

* sidebar: text overhaul per issue #184

* sidebar: remove (saved) label and helper line

* sidebar: combine simulation name with heading

* heatmap: default to contours and allow selection when no sites selected

* heatmap: default to contours instead of smooth

* Implement shorter deeplinks (issue #144)

- New URL format: /<simulation>/<site>+<site2> or /<simulation>/<site1><><site2>
- Keep Unicode characters (æøå) in URLs
- Strip delimiter chars (+ < > /) from slugs
- Backward compatible with old ?dl=1 format

* Fix deeplinks: preserve case, remove query params, no encoding

- Keep original case in URLs (Blefjell not blefjell)
- Remove dl=2 and sim=xxx query params for clean URLs
- Build URL manually to prevent <> encoding to %3C%3E
- V2 format detected by path presence

* Fix: preserve <> in URLs, encode unicode chars

- Use encodeURIComponent but keep <> unencoded
- Unicode chars like ø encode to %C3%B8 (browsers auto-decode)
- <> stays as <> (not %3C%3E)

* Fix: actually decode %3C and %3E back to <>

* Fix: don't re-encode URL when copying share link

* Fix: don't encode URLs - preserve emojis and unicode as-is

* feat: add FastAPI calculation API with hardened Docker target

* chore: ignore Python cache artifacts

* feat: add configurable rate limiting to calculation API

* feat(api): proxy calculation endpoint through Pages

* Fix: use slugifyName for slug matching instead of toLowerCase

* Add debug logging for deep link processing

* Fix: decode URL-encoded slugs before matching

- Decode simulation slug with decodeURIComponent before slugifyName
- Decode site/link slugs before matching
- Remove debug logging

* Fix deep-link resolution for encoded path slugs

Decode URL-encoded path segments and use canonical slug matching so shared Simulation links resolve reliably after hydration for ASCII, Unicode, and emoji names.

* Use tilde delimiter in generated deep links

Switch link delimiter generation to tilde to avoid browser percent-encoding in the address bar, keep legacy angle-bracket parsing support, and normalize emoji variation selectors for cleaner URLs.

* feat(api): cut over calculate endpoint to app terrain logic

* docs: add deep-link format specification

---------

Co-authored-by: Mats <heigre@protonmail.com>

* fix(deeplink): only encode link paths when a link is explicitly selected (#193)

* fix(deeplink): apply multi-site selections deterministically (#194)

* fix: unblock blank simulation workflows (#179) (#195)

* fix: persist blank simulation load session state

* fix: allow blank simulations to continue in workspace

* fix: keep blank load session persistence main-compatible

* chore: bump release version to 0.10.3

* docs: add staging-first milestone workflow to AGENTS.md (#196)

* fix(deeplink): only encode link paths when a link is explicitly selected

* fix(deeplink): apply multi-site selections deterministically

* docs: add staging-first milestone workflow to AGENTS.md

* feat(api): proxy calculation endpoint through Pages (#197)

Co-authored-by: Mats <heigre@protonmail.com>

* Revert "feat(api): proxy calculation endpoint through Pages (#197)" (#198)

This reverts commit 0138c1bd1aaa8f6adc5fd26f2512540ea5593f8d.

* Restore native terrain API optimization line from pre-regression commits (#199)

* feat(api): add async terrain jobs endpoints and request guardrails

* feat(api): process terrain jobs asynchronously with status updates

* feat(api): compute terrain job results from sampled elevations

* feat(api): use Copernicus terrain tiles via proxy for terrain jobs

* fix(api): correct Copernicus tile naming and bucket paths

* fix: fallback to Open-Meteo if Copernicus tiles fail

* Revert "fix: fallback to Open-Meteo if Copernicus tiles fail"

This reverts commit c50820f429dc0558743277a79aa11450090a8ef5.

* refactor(api): share app propagation logic across calculate endpoints

* fix(api): resolve Copernicus tile paths from tileList directories

* docs(api): document Copernicus-backed terrain analysis path

* feat(api): cut over calculate endpoint to app terrain logic

* fix(api): stabilize terrain calculate and reduce tile decode load

* Enforce async jobs path for terrain calculate requests (#200)

Route terrain-mode requests from /api/v1/calculate to /api/v1/calculate/jobs and return queued 202 responses, keeping sync calculate for non-terrain mode while preventing CPU-heavy terrain sync execution.

* Route terrain sync calculate requests to async jobs (#201)

Enforce jobs-first terrain execution by delegating mode=terrain requests on /api/v1/calculate to the async jobs queue path and returning 202 queued responses, preventing CPU-heavy synchronous terrain runs.

* Fix deep-link sharing to prefer actual site selection (#202)

Clear stale selectedLinkId when selecting sites and only emit link-style share URLs when the selected sites exactly match the active link endpoints.

* Fix deep-link unicode matching for emoji and Korean names (#203)

Preserve Unicode and emoji semantics in slug/canonical key generation, avoid ASCII-only canonical collapse, and add emoji/Korean deep-link regression coverage.

* Normalize emoji variation selectors in deep-link keys (#204)

Treat FE0E/FE0F variants consistently in slug and canonical key generation so emoji deep links resolve to the correct Site regardless of URL serialization differences.

* Harden deep-link site matching for emoji variations (#205)

Normalize variation selectors in generated path segments and require full site slug resolution before applying selections so emoji/Korean deep links do not silently fall back to incorrect default selections.

* Harden deep-link matching order for emoji/unicode selections (#206)

Use exact-normalized matching before slug/canonical fallback for site/link deep-link selection and clear active selection when deep-link resolution is partial, preventing silent fallback to default first site/link.

* Add deep-link debug instrumentation for selection apply (#207)

Add temporary DeepLinkDebug console logs around payload parsing, slug matching, and post-apply selection state to trace why some deep links fall back to first-site selection on staging.

* Apply deep-link selections after init cycle settles (#208)

Prevent startup hydration from overwriting deep-link site/link selections by deferring deep-link application until the initializeCloudSync cycle has been observed and settled.

* chore(deeplink): remove temporary DeepLinkDebug instrumentation (#209)

* feat(onboarding): merge onboarding with simulation library into welcome modal (#152) (#210)

- Rewrite onboarding content: ctrl/cmd-click links, auto-overlay switching, simplified sharing
- Extract SimulationLibraryPanel reusable component from Sidebar
- Create WelcomeModal: merged onboarding +…
@wilhel1812
Copy link
Copy Markdown
Owner Author

Closing this reconcile PR because the observed main-only commit is the latest normal production squash release, which AGENTS.md treats as expected ancestry-only drift. Proceeding with #813 from origin/staging instead.

@wilhel1812 wilhel1812 closed this Apr 29, 2026
@wilhel1812 wilhel1812 deleted the chore/reconcile-main-0.18.0-to-staging branch April 29, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant