diff --git a/services/web/frontend/js/features/settings/components/root.tsx b/services/web/frontend/js/features/settings/components/root.tsx
index 0e5011d8cc..b03814296b 100644
--- a/services/web/frontend/js/features/settings/components/root.tsx
+++ b/services/web/frontend/js/features/settings/components/root.tsx
@@ -22,6 +22,7 @@ import { ExposedSettings } from '../../../../../types/exposed-settings'
import { SSOAlert } from './emails/sso-alert'
import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper'
import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper'
+import CardWrapper from '@/features/ui/components/bootstrap-5/wrappers/card-wrapper'
function SettingsPageRoot() {
const { isReady } = useWaitForI18n()
@@ -50,7 +51,7 @@ function SettingsPageContent() {
return (
-
+
{t('account_settings')}
@@ -95,7 +96,7 @@ function SettingsPageContent() {
>
) : null}
-
+
)
}
diff --git a/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/card-wrapper.tsx b/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/card-wrapper.tsx
new file mode 100644
index 0000000000..11927f30ba
--- /dev/null
+++ b/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/card-wrapper.tsx
@@ -0,0 +1,21 @@
+import { Card, CardBody } from 'react-bootstrap-5'
+import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
+import { FC } from 'react'
+
+// This wraps the Bootstrap 5 Card component but is restricted to the very
+// basic way we're using it, which is as a container for page content. The
+// Bootstrap 3 equivalent in our codebase is a div with class "card"
+const CardWrapper: FC = ({ children }) => {
+ return (
+ {children}}
+ bs5={
+
+ {children}
+
+ }
+ />
+ )
+}
+
+export default CardWrapper
diff --git a/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss b/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss
index c70aa433d4..2e28678def 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss
@@ -27,3 +27,17 @@ $tooltip-max-width: 320px;
$tooltip-border-radius: $border-radius-base;
$tooltip-padding-y: $spacing-04;
$tooltip-padding-x: $spacing-06;
+
+// Links. Ideally we'd point these to CSS variables but Bootstrap performs
+// calculations on link color during compilation.
+$link-color: $link-ui;
+$link-hover-color: $link-ui-hover;
+$link-hover-decoration: none;
+
+// Headings
+$headings-font-family: $font-family-sans-serif;
+$headings-margin-bottom: $spacing-05;
+
+// Horizontal rules
+$hr-margin-y: $spacing-08;
+$hr-border-color: $border-divider;
diff --git a/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss b/services/web/frontend/stylesheets/bootstrap-5/base/bootstrap.scss
similarity index 91%
rename from services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss
rename to services/web/frontend/stylesheets/bootstrap-5/base/bootstrap.scss
index 1d78b7f7ec..0a9dd0ed8f 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/base/bootstrap.scss
@@ -7,8 +7,8 @@
// Bootstrap itself because Bootstrap uses them to create the CSS variables it
// uses, and in calculations to determine, for example, what color text to use
// on a button based on contrast.
-@import 'foundations/all';
-@import 'abstracts/all';
+@import '../foundations/all';
+@import '../abstracts/all';
// Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets)
@import 'bootstrap-5/scss/variables';
@@ -31,6 +31,7 @@
@import 'bootstrap-5/scss/modal';
@import 'bootstrap-5/scss/tooltip';
@import 'bootstrap-5/scss/spinners';
+@import 'bootstrap-5/scss/card';
// Helpers
@import 'bootstrap-5/scss/helpers';
@@ -39,4 +40,4 @@
@import 'bootstrap-5/scss/utilities/api';
// Components custom style
-@import 'components/all';
+@import '../components/all';
diff --git a/services/web/frontend/stylesheets/bootstrap-5/base/layout.scss b/services/web/frontend/stylesheets/bootstrap-5/base/layout.scss
new file mode 100644
index 0000000000..a78e3122fa
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/base/layout.scss
@@ -0,0 +1,31 @@
+$header-height: 68px;
+$footer-height: 50px;
+
+.content {
+ min-height: 100vh;
+ padding-top: $header-height + $spacing-08;
+ padding-bottom: $spacing-08;
+}
+
+.content-alt {
+ background-color: $bg-light-secondary;
+}
+
+// Page header/separator
+.page-separator,
+.page-header {
+ padding-bottom: $spacing-05;
+ border-bottom: 1px solid $border-divider;
+ margin: 0;
+
+ // Apply margin above or below this header/separator only when it has a sibling
+ * > * + &,
+ * > & + * {
+ margin-top: $spacing-08;
+ }
+}
+
+// Horizontal rule. Override Bootstrap's 25% opacity, which we don't want
+hr {
+ opacity: unset;
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/base/links.scss b/services/web/frontend/stylesheets/bootstrap-5/base/links.scss
new file mode 100644
index 0000000000..2ba62993dd
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/base/links.scss
@@ -0,0 +1,20 @@
+// Links
+
+// Use CSS variables for link colors to make it easy to override in marketing page
+:root {
+ --link-color: var(--link-ui-visited);
+ --link-hover-color: var(--link-ui-hover);
+ --link-visited-color: var(--link-ui-visited);
+}
+
+a {
+ color: var(--link-color);
+
+ &:hover {
+ color: var(--link-hover-color);
+ }
+
+ &:visited {
+ color: var(--link-visited-color);
+ }
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/base/typography.scss b/services/web/frontend/stylesheets/bootstrap-5/base/typography.scss
new file mode 100644
index 0000000000..12212d27b7
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/base/typography.scss
@@ -0,0 +1,54 @@
+// Headings
+
+// Apply margin above the heading only when it has a sibling
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ * > * + & {
+ margin-top: $spacing-08;
+ }
+}
+
+h1,
+.h1 {
+ @include heading-xl;
+}
+
+h2,
+.h2 {
+ @include heading-md;
+}
+
+h3,
+.h3 {
+ @include heading-sm;
+}
+
+h4,
+.h4 {
+ @include heading-xs;
+}
+
+h5,
+.h5 {
+ @include body-base;
+}
+
+h6,
+.h6 {
+ @include body-sm;
+}
+
+// Miscellaneous
+.small {
+ @include body-sm;
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss
index c8b62aa7a7..0bfa13246d 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss
@@ -3,3 +3,4 @@
@import 'split-button';
@import 'notifications';
@import 'tooltip';
+@import 'card';
diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/card.scss b/services/web/frontend/stylesheets/bootstrap-5/components/card.scss
new file mode 100644
index 0000000000..026fa4f462
--- /dev/null
+++ b/services/web/frontend/stylesheets/bootstrap-5/components/card.scss
@@ -0,0 +1,7 @@
+.card {
+ --bs-card-bg: var(--white);
+ --bs-card-border-width: 0;
+ --bs-card-border-radius: var(--border-radius-base);
+ --bs-card-spacer-x: var(--spacing-08);
+ --bs-card-spacer-y: var(--spacing-08);
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
index 92b2539412..a2eb32aea7 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss
@@ -17,8 +17,17 @@ $is-overleaf-light: false;
// Boostrap-related
// Note that files containing Bootstrap or Sass files that interact with
-// Bootstrap's Sass variable must use @import rather than @use because
+// Bootstrap's Sass variables must use @import rather than @use because
// Bootstrap relies on its variables, mixins etc. all being global.
// Include Bootstrap 5 itself, plus overrides and extend Bootstrap styles.
-@import 'bootstrap';
+@import 'base/bootstrap';
+
+// Typography-related
+@import 'base/typography';
+
+// Link styles
+@import 'base/links';
+
+// Page layout that isn't related to a particular component or page
+@import 'base/layout';