diff --git a/.gitignore b/.gitignore
index 335434320..71f7c5f2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,3 +63,4 @@ sms_sponsorship/webapp/build
sms_sponsorship/webapp/.idea
/sbc_compassion/FPDF/.idea/
/sbc_compassion/FPDF/stderr.txt
+*.DS_Store
diff --git a/my_compassion/__manifest__.py b/my_compassion/__manifest__.py
index 5a976c5a5..a31861c90 100644
--- a/my_compassion/__manifest__.py
+++ b/my_compassion/__manifest__.py
@@ -59,6 +59,7 @@
"views/correspondence_view.xml",
"views/correspondence_prewritten_letter.xml",
"views/my2_header_menu.xml",
+ "views/my2_bottom_nav.xml",
"data/signup_email_confirmation.xml",
"data/communication_config.xml",
"data/dynamic_stylesheets.xml",
diff --git a/my_compassion/templates/pages/my2_child_letters.xml b/my_compassion/templates/pages/my2_child_letters.xml
index ae5bf4158..c38b454c5 100644
--- a/my_compassion/templates/pages/my2_child_letters.xml
+++ b/my_compassion/templates/pages/my2_child_letters.xml
@@ -338,6 +338,15 @@
+
+
+
+
diff --git a/my_compassion/views/my2_bottom_nav.xml b/my_compassion/views/my2_bottom_nav.xml
new file mode 100644
index 000000000..590146c1b
--- /dev/null
+++ b/my_compassion/views/my2_bottom_nav.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/theme_compassion_2025/data/pictograms.xml b/theme_compassion_2025/data/pictograms.xml
index b5d2ce243..a8cbe7e5e 100644
--- a/theme_compassion_2025/data/pictograms.xml
+++ b/theme_compassion_2025/data/pictograms.xml
@@ -81,6 +81,10 @@
Food
+
+ GiftBasket
+
+
GiftDonationGeneral
@@ -145,6 +149,10 @@
Neighbourhood
+
+ Profile
+
+
+
+ Writing
+
+
diff --git a/theme_compassion_2025/static/src/img/pictograms/GiftBasket.svg b/theme_compassion_2025/static/src/img/pictograms/GiftBasket.svg
new file mode 100644
index 000000000..1a0614ac5
--- /dev/null
+++ b/theme_compassion_2025/static/src/img/pictograms/GiftBasket.svg
@@ -0,0 +1,23 @@
+
+
+
diff --git a/theme_compassion_2025/static/src/img/pictograms/Profile.svg b/theme_compassion_2025/static/src/img/pictograms/Profile.svg
new file mode 100644
index 000000000..da0188c6e
--- /dev/null
+++ b/theme_compassion_2025/static/src/img/pictograms/Profile.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/theme_compassion_2025/static/src/img/pictograms/Writing.svg b/theme_compassion_2025/static/src/img/pictograms/Writing.svg
new file mode 100644
index 000000000..26e8f5819
--- /dev/null
+++ b/theme_compassion_2025/static/src/img/pictograms/Writing.svg
@@ -0,0 +1,7 @@
+
+
+
diff --git a/theme_compassion_2025/static/src/scss/layout/_header.scss b/theme_compassion_2025/static/src/scss/layout/_header.scss
index 8f416753e..050138338 100644
--- a/theme_compassion_2025/static/src/scss/layout/_header.scss
+++ b/theme_compassion_2025/static/src/scss/layout/_header.scss
@@ -30,3 +30,156 @@
}
}
}
+
+/* App-Style Bottom Navigation for /my2/ Portal */
+@include media-breakpoint-down(sm) {
+ .my2-bottom-nav {
+ position: fixed !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ width: 100% !important;
+
+ z-index: $zindex-fixed + 100;
+ /* Remove padding-bottom from the nav itself so the cutout aligns perfectly */
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08) !important;
+ background-color: #ffffff;
+
+ /* Ensure flex layout for the tabs ignores the absolute indicator */
+ display: flex;
+ justify-content: space-between;
+
+ .nav-tab {
+ position: relative;
+ z-index: 1;
+ /* Width adapts to --tab-count set on the nav (4 for non-sponsors, 6 for sponsors) */
+ width: calc(100% / var(--tab-count, 6));
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 40px;
+ text-align: center;
+ padding-bottom: env(safe-area-inset-bottom);
+
+ i, .vignette-icon {
+ position: relative;
+ font-size: 1.75rem;
+ margin-top: -20px;
+ transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), color 0.2s;
+ }
+
+ span {
+ position: absolute;
+ bottom: env(safe-area-inset-bottom);
+ left: 50%;
+ transform: translateX(-50%);
+ font-size: 0.6rem;
+ font-weight: 600;
+ white-space: nowrap;
+ opacity: 0;
+ transition: opacity 0.3s ease-in-out;
+ }
+
+ sup {
+ background-color: var(--core-blue);
+ position: absolute;
+ top: -10px;
+ right: -8px;
+ font-size: 0.6rem;
+ }
+
+ /* --- ACTIVE STATE --- */
+ &.active {
+ i, .vignette-icon {
+ /* Jump up into the floating bubble and turn white */
+ transform: translateY(-20px) scale(1.1);
+ color: #ffffff !important;
+ margin-top: 0;
+ }
+
+ span {
+ opacity: 1;
+ }
+
+ sup {
+ top: -20px;
+ right: -12px;
+ background-color: var(--low-yellow);
+ }
+ }
+ }
+
+ /* --- THE CUTOUT ILLUSION --- */
+ .indicator-wrapper {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: calc(100% / var(--tab-count, 6));
+ height: 100%;
+ z-index: 0;
+ transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ pointer-events: none;
+
+ .indicator {
+ position: absolute;
+ width: 60px;
+ height: 60px;
+ top: -22px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--core-blue);
+ border-radius: 50%;
+ border: 6px solid var(--pure-white);
+ }
+ }
+
+ /* --- THE SHIFTING LOGIC --- */
+ /* Moves the indicator wrapper by 100% of its own width for each slot */
+ .nav-tab:nth-child(1).active ~ .indicator-wrapper {
+ transform: translateX(0);
+ }
+
+ .nav-tab:nth-child(2).active ~ .indicator-wrapper {
+ transform: translateX(100%);
+ }
+
+ .nav-tab:nth-child(3).active ~ .indicator-wrapper {
+ transform: translateX(200%);
+ }
+
+ .nav-tab:nth-child(4).active ~ .indicator-wrapper {
+ transform: translateX(300%);
+ }
+
+ .nav-tab:nth-child(5).active ~ .indicator-wrapper {
+ transform: translateX(400%);
+ }
+
+ .nav-tab:nth-child(6).active ~ .indicator-wrapper {
+ transform: translateX(500%);
+ }
+ }
+
+ /* Floating round "write a letter" shortcut button on the per-child letters page */
+ #write_button {
+ position: fixed;
+ right: 1rem;
+ bottom: calc(5rem + env(safe-area-inset-bottom) + 0.75rem);
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ background: var(--core-blue);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
+ z-index: $zindex-fixed + 101;
+
+ .vignette-icon {
+ font-size: 1.6rem;
+ color: var(--pure-white);
+ }
+ }
+
+ /* Prevents content from hiding behind the bar */
+ #bottom_nav_spacer {
+ height: calc(5rem + env(safe-area-inset-bottom));
+ }
+}