diff --git a/src/components/Box/Box.module.scss b/src/components/Box/Box.module.scss
index 60aaf94..1dc7f6d 100644
--- a/src/components/Box/Box.module.scss
+++ b/src/components/Box/Box.module.scss
@@ -4,7 +4,8 @@
env() is 0 on devices without a safe area, so desktop layout is
unchanged. Pairs with `viewport-fit=cover` in SeoGenerator. */
bottom: max(15px, env(safe-area-inset-bottom));
- right: 15px;
+ left: 50%;
+ transform: translateX(-50%);
width: 100%;
max-width: 480px;
padding: 20px;
@@ -154,10 +155,8 @@
@media (max-width: 500px) {
.content {
- right: unset;
- margin: 0 15px;
+ width: calc(100% - 30px);
max-width: unset;
- width: unset;
bottom: max(15px, env(safe-area-inset-bottom));
}
}
diff --git a/src/components/Headline/Headline.module.scss b/src/components/Headline/Headline.module.scss
index a2bc14b..3ba63fc 100644
--- a/src/components/Headline/Headline.module.scss
+++ b/src/components/Headline/Headline.module.scss
@@ -276,8 +276,6 @@
@media (min-width: 1921px) {
.headline {
- height: 800px;
-
.contentWrapper {
padding-left: 0;
padding-top: 0;
@@ -286,19 +284,6 @@
.headlineInfo {
justify-content: center;
align-items: center;
-
- .videoContainer {
- .poster {
- height: 800px;
- object-fit: none;
- }
-
- .video {
- height: 800px;
- object-fit: none;
- background-color: #e7e7e7;
- }
- }
}
}
}
diff --git a/src/styles/404.module.scss b/src/styles/404.module.scss
index ef72327..29d5e0a 100644
--- a/src/styles/404.module.scss
+++ b/src/styles/404.module.scss
@@ -91,3 +91,16 @@
}
}
}
+
+:global(body.darkTheme) .pageNotFound {
+ background-image: none;
+ background-color: #1b1e26;
+
+ .content {
+ color: #dadada;
+
+ .image {
+ filter: invert(1) hue-rotate(180deg);
+ }
+ }
+}
diff --git a/src/uxcore/assets/icons/MoonIcon.tsx b/src/uxcore/assets/icons/MoonIcon.tsx
new file mode 100644
index 0000000..15fa4eb
--- /dev/null
+++ b/src/uxcore/assets/icons/MoonIcon.tsx
@@ -0,0 +1,17 @@
+const MoonIcon = () => (
+
+);
+
+export default MoonIcon;
diff --git a/src/uxcore/assets/icons/SunIcon.tsx b/src/uxcore/assets/icons/SunIcon.tsx
new file mode 100644
index 0000000..b573945
--- /dev/null
+++ b/src/uxcore/assets/icons/SunIcon.tsx
@@ -0,0 +1,18 @@
+const SunIcon = () => (
+
+);
+
+export default SunIcon;
diff --git a/src/uxcore/components/CompletionBar/CompletionBar.module.scss b/src/uxcore/components/CompletionBar/CompletionBar.module.scss
index 5d33608..5a7fc3b 100644
--- a/src/uxcore/components/CompletionBar/CompletionBar.module.scss
+++ b/src/uxcore/components/CompletionBar/CompletionBar.module.scss
@@ -537,11 +537,15 @@
}
.progressBar .levelTxt {
- color: rgba(218, 218, 218, 0.55);
+ color: #dadada;
}
.step {
- color: rgba(218, 218, 218, 0.5);
+ color: #dadada;
+ }
+
+ .step:not(.completed):not(.completedMilestone):not(.hoveredLvl):not(.singleHoveredLvl) {
+ background-image: url("data:image/svg+xml;utf8,");
}
.bar,
diff --git a/src/uxcore/components/Logos/Logos.module.scss b/src/uxcore/components/Logos/Logos.module.scss
index 1c68ee9..58ff408 100644
--- a/src/uxcore/components/Logos/Logos.module.scss
+++ b/src/uxcore/components/Logos/Logos.module.scss
@@ -67,6 +67,9 @@
// Dark theme: lift the description text, then desaturate + invert the
// partner logos so the black-on-white marks read as soft light marks on dark.
+// The mobile breakpoint above paints `.logoWrapper` solid white to give the
+// logos breathing room on the cramped mobile column — on dark that becomes
+// a bright slab mid-page, so blank the background out here.
:global(body.darkTheme) {
.title {
color: rgba(218, 218, 218, 0.65);
@@ -76,4 +79,10 @@
filter: invert(1) hue-rotate(180deg) brightness(0.95) saturate(0.85);
opacity: 0.85;
}
+
+ @media (max-width: 1010px) {
+ .logoWrapper {
+ background-color: transparent;
+ }
+ }
}
diff --git a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss
index 9a365d9..3a9e2ee 100644
--- a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss
+++ b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss
@@ -84,3 +84,35 @@ $active-color: #359eff;
grid-template-columns: 1fr;
}
}
+
+// Dark theme: default button rail is a white panel with hairline-gray
+// borders and black labels — on the dark page that becomes a bright slab
+// with invisible text. Repaint to the dark surface and lift the labels
+// and active accent to the dark-mode palette.
+:global(body.darkTheme) .PageSwitcher {
+ background-color: transparent;
+
+ & .Button {
+ border-color: #303338;
+
+ & svg path {
+ fill: #dadada;
+ }
+
+ & .Description {
+ color: #dadada;
+ }
+
+ &.Active {
+ border-color: #7fb3d5;
+
+ & svg > path {
+ fill: #7fb3d5;
+ }
+
+ & .Description {
+ color: #7fb3d5;
+ }
+ }
+ }
+}
diff --git a/src/uxcore/components/ToolHeader/ToolHeader.module.scss b/src/uxcore/components/ToolHeader/ToolHeader.module.scss
index 18c1f8a..8402696 100644
--- a/src/uxcore/components/ToolHeader/ToolHeader.module.scss
+++ b/src/uxcore/components/ToolHeader/ToolHeader.module.scss
@@ -13,7 +13,7 @@ $headerHeight: 46px;
flex-direction: row;
align-items: center;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.05);
- z-index: 2;
+ z-index: 10;
box-sizing: border-box;
justify-content: space-between;
@@ -550,6 +550,14 @@ $headerHeight: 46px;
.openLink {
filter: invert(1) brightness(2) saturate(0);
}
+
+ .PageSwitcherItem {
+ color: #dadada;
+
+ svg path {
+ fill: #dadada;
+ }
+ }
}
@media (max-width: 920px) {
diff --git a/src/uxcore/components/ToolHeader/ToolHeader.tsx b/src/uxcore/components/ToolHeader/ToolHeader.tsx
index 21de655..45b3fe9 100644
--- a/src/uxcore/components/ToolHeader/ToolHeader.tsx
+++ b/src/uxcore/components/ToolHeader/ToolHeader.tsx
@@ -3,7 +3,9 @@ import { userInfoUpdate } from '@uxcore/api/uxcat/settings';
import { getUserInfo } from '@uxcore/api/uxcat/users-me';
import CloseIcon from '@uxcore/assets/icons/CloseIcon';
import DiamondIcon from '@uxcore/assets/icons/DiamondIcon';
+import MoonIcon from '@uxcore/assets/icons/MoonIcon';
import PodcastIcon from '@uxcore/assets/icons/PodcastIcon';
+import SunIcon from '@uxcore/assets/icons/SunIcon';
import MobileHeader from '@uxcore/components/_biases/MobileHeader';
import { GlobalContext } from '@uxcore/components/Context/GlobalContext';
import LanguageSwitcher from '@uxcore/components/LanguageSwitcher';
@@ -464,34 +466,7 @@ const ToolHeader: FC = ({
aria-pressed={isDarkTheme}
data-cy="theme-toggle"
>
- {isDarkTheme ? (
-
- ) : (
-
- )}
+ {isDarkTheme ? : }
svg {
+ fill: #7fb3d5;
+ }
+ }
+ }
+ }
+ }
+
+ .a {
+ color: #dadada !important;
+ }
+}
diff --git a/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss b/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss
index 018099b..86a14d1 100644
--- a/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss
+++ b/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss
@@ -224,20 +224,20 @@ $purple-border: #8073ff;
@media (min-width: 2500px) {
.label {
- height: 1.4vh;
+ height: 0.6vw;
.txt {
- font-size: 1.2vh;
+ font-size: 0.45vw;
}
}
}
@media (min-width: 3500px) {
.label {
- height: 1vh;
+ height: 0.55vw;
.txt {
- font-size: 0.8vh;
+ font-size: 0.42vw;
}
}
}
diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss
index d8e2066..5e13dca 100644
--- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss
+++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss
@@ -26,6 +26,7 @@
padding-top: 0rem;
float: right;
display: flex;
+ align-items: center;
gap: 10px;
.PodcastWrapper {
@@ -41,6 +42,37 @@
& a {
font-size: 21px;
}
+
+ .themeToggle {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ padding: 0;
+ background: transparent;
+ border: 0;
+ border-radius: 50%;
+ color: #4a4a4a;
+ cursor: pointer;
+ transition:
+ background-color 0.18s ease,
+ color 0.18s ease;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.06);
+ color: #131313;
+ }
+
+ &:focus-visible {
+ outline: 2px solid rgba(76, 140, 193, 0.6);
+ outline-offset: 2px;
+ }
+
+ svg {
+ display: block;
+ }
+ }
}
}
@@ -48,3 +80,36 @@
position: relative;
z-index: 5;
}
+
+// Dark theme: the sticky header defaults to white bg + brand-blue title,
+// which reads as a hard white bar across the top of the dark mobile page.
+// Repaint the bar to the dark surface, lift the accent so it still reads
+// as the brand color, and replace the soft light shadow with a darker
+// drop so the header still feels lifted from the page.
+:global(body.darkTheme) {
+ .MobileHeader,
+ .disablePageSwitcher {
+ background-color: #1b1e26;
+ color: #7fb3d5;
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.5);
+
+ & .Actions {
+ .PodcastWrapper > svg {
+ fill: #dadada;
+ }
+
+ .active > svg {
+ fill: #7fb3d5;
+ }
+
+ .themeToggle {
+ color: #dadada;
+
+ &:hover {
+ background-color: rgba(255, 255, 255, 0.08);
+ color: #ffffff;
+ }
+ }
+ }
+ }
+}
diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx
index 0f22363..a1d58dd 100644
--- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx
+++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx
@@ -1,12 +1,15 @@
import { getMyInfo } from '@uxcore/api/strapi';
import { userInfoUpdate } from '@uxcore/api/uxcat/settings';
import { getUserInfo } from '@uxcore/api/uxcat/users-me';
+import MoonIcon from '@uxcore/assets/icons/MoonIcon';
import PodcastIcon from '@uxcore/assets/icons/PodcastIcon';
+import SunIcon from '@uxcore/assets/icons/SunIcon';
import { GlobalContext } from '@uxcore/components/Context/GlobalContext';
import LanguageSwitcher from '@uxcore/components/LanguageSwitcher';
import SettingsModal from '@uxcore/components/SettingsModal';
import UserDropdown from '@uxcore/components/UserDropdown';
import toolHeaderData from '@uxcore/data/toolHeader';
+import useGlobals from '@uxcore/hooks/useGlobals';
import { isLevelMilestone } from '@uxcore/lib/uxcat-helpers';
import type { TRouter } from '@uxcore/local-types/global';
import { UserTypes } from '@uxcore/local-types/uxcat-types/types';
@@ -46,6 +49,7 @@ const MobileHeader: FC = ({
const router = useRouter();
const { locale } = router as TRouter;
const { accountData, setAccountData } = useContext(GlobalContext);
+ const [{ toggleIsDarkTheme }, { isDarkTheme }] = useGlobals();
const { usernameIsTaken, settingsTxt, myProfileTxt } = toolHeaderData[locale];
const imageSrc = useMemo(() => accountData?.picture, [accountData]);
const [showDropdown, setShowDropdown] = useState(false);
@@ -151,7 +155,11 @@ const MobileHeader: FC = ({
)}
+