ultimate-jekyll-manager 1.4.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/CLAUDE-ATTRIBUTION.md +215 -0
  3. package/CLAUDE.md +7 -6
  4. package/README.md +1 -0
  5. package/dist/assets/css/pages/test/libraries/layers/index.scss +28 -0
  6. package/dist/assets/js/core/auth.js +24 -39
  7. package/dist/assets/js/modules/redirect.js +5 -4
  8. package/dist/assets/js/pages/download/index.js +1 -1
  9. package/dist/assets/js/pages/feedback/index.js +7 -1
  10. package/dist/assets/js/pages/test/libraries/layers/index.js +11 -0
  11. package/dist/assets/themes/_template/README.md +50 -0
  12. package/dist/assets/themes/_template/_config.scss +60 -0
  13. package/dist/assets/themes/_template/_theme.js +13 -4
  14. package/dist/assets/themes/_template/_theme.scss +16 -4
  15. package/dist/assets/themes/_template/css/base/_root.scss +19 -0
  16. package/dist/assets/themes/_template/css/components/_components.scss +23 -0
  17. package/dist/assets/themes/classy/README.md +18 -6
  18. package/dist/assets/themes/neobrutalism/README.md +98 -0
  19. package/dist/assets/themes/neobrutalism/_config.scss +139 -0
  20. package/dist/assets/themes/neobrutalism/_theme.js +27 -0
  21. package/dist/assets/themes/neobrutalism/_theme.scss +33 -0
  22. package/dist/assets/themes/neobrutalism/css/base/_mixins.scss +46 -0
  23. package/dist/assets/themes/neobrutalism/css/base/_root.scss +80 -0
  24. package/dist/assets/themes/neobrutalism/css/base/_typography.scss +77 -0
  25. package/dist/assets/themes/neobrutalism/css/base/_utilities.scss +25 -0
  26. package/dist/assets/themes/neobrutalism/css/components/_buttons.scss +148 -0
  27. package/dist/assets/themes/neobrutalism/css/components/_cards.scss +69 -0
  28. package/dist/assets/themes/neobrutalism/css/components/_forms.scss +88 -0
  29. package/dist/assets/themes/neobrutalism/css/components/_infinite-scroll.scss +94 -0
  30. package/dist/assets/themes/neobrutalism/css/layout/_general.scss +200 -0
  31. package/dist/assets/themes/neobrutalism/css/layout/_navigation.scss +153 -0
  32. package/dist/assets/themes/neobrutalism/js/initialize-tooltips.js +20 -0
  33. package/dist/assets/themes/neobrutalism/js/navbar-scroll.js +29 -0
  34. package/dist/assets/themes/neobrutalism/pages/index.scss +227 -0
  35. package/dist/assets/themes/neobrutalism/pages/pricing/index.scss +267 -0
  36. package/dist/assets/themes/neobrutalism/pages/test/libraries/layers/index.js +9 -0
  37. package/dist/assets/themes/neobrutalism/pages/test/libraries/layers/index.scss +7 -0
  38. package/dist/build.js +2 -5
  39. package/dist/commands/install.js +1 -1
  40. package/dist/commands/setup.js +41 -0
  41. package/dist/defaults/CLAUDE.md +5 -1
  42. package/dist/defaults/dist/_alternatives/example-competitor.md +6 -6
  43. package/dist/defaults/dist/_includes/admin/sections/sidebar.json +2 -2
  44. package/dist/defaults/dist/_includes/core/head.html +17 -0
  45. package/dist/defaults/dist/_includes/themes/classy/backend/sections/topbar.html +1 -1
  46. package/dist/defaults/dist/_includes/themes/classy/frontend/sections/footer.html +9 -6
  47. package/dist/defaults/dist/_layouts/blueprint/admin/calendar/index.html +13 -13
  48. package/dist/defaults/dist/_layouts/blueprint/admin/firebase/index.html +1 -1
  49. package/dist/defaults/dist/_layouts/blueprint/admin/users/index.html +1 -1
  50. package/dist/defaults/dist/_layouts/blueprint/admin/users/new.html +5 -5
  51. package/dist/defaults/dist/_layouts/blueprint/auth/oauth2.html +1 -1
  52. package/dist/defaults/dist/_layouts/themes/classy/backend/pages/dashboard/index.html +12 -12
  53. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/about.html +1 -1
  54. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/alternative.html +4 -4
  55. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/index.html +5 -5
  56. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +4 -2
  57. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/feedback.html +7 -3
  58. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/confirmation.html +1 -1
  59. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +3 -3
  60. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/team/index.html +2 -2
  61. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/core/base.html +31 -0
  62. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/index.html +345 -0
  63. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/pricing.html +483 -0
  64. package/dist/defaults/dist/_updates/v0.0.1.md +3 -0
  65. package/dist/defaults/dist/pages/test/account/dashboard.html +1 -1
  66. package/dist/defaults/dist/pages/test/libraries/ads.html +9 -9
  67. package/dist/defaults/dist/pages/test/libraries/bootstrap.html +6 -6
  68. package/dist/defaults/dist/pages/test/libraries/firestore.html +1 -1
  69. package/dist/defaults/dist/pages/test/libraries/form-manager.html +2 -2
  70. package/dist/defaults/dist/pages/test/libraries/layers.html +57 -0
  71. package/dist/defaults/dist/pages/test/libraries/lazy-loading.html +8 -8
  72. package/dist/defaults/dist/sitemap.html +2 -2
  73. package/dist/defaults/src/_config.yml +2 -0
  74. package/dist/defaults/test/_init.js +10 -0
  75. package/dist/gulp/tasks/defaults.js +8 -0
  76. package/dist/gulp/tasks/imagemin.js +30 -5
  77. package/dist/gulp/tasks/sass.js +43 -2
  78. package/dist/gulp/tasks/translation.js +11 -0
  79. package/dist/gulp/tasks/utils/manage-test-layers.js +97 -0
  80. package/dist/index.js +30 -4
  81. package/dist/test/runner.js +62 -0
  82. package/dist/test/suites/build/manager.test.js +11 -4
  83. package/dist/test/suites/build/mode-helpers.test.js +54 -2
  84. package/dist/utils/attach-log-file.js +24 -16
  85. package/dist/utils/mode-helpers.js +65 -40
  86. package/docs/assets.md +6 -1
  87. package/docs/environment-detection.md +85 -0
  88. package/docs/test-framework.md +48 -3
  89. package/docs/themes.md +451 -0
  90. package/package.json +2 -1
  91. package/docs/cross-context-helpers.md +0 -75
@@ -0,0 +1,148 @@
1
+ // Neobrutalism Theme — Buttons
2
+ // Every button is a hard-bordered block sitting on an offset shadow that
3
+ // "presses" into the page on interaction. This restyles Bootstrap's own
4
+ // .btn / .btn-* classes so all existing markup (nav CTAs, hero buttons,
5
+ // forms) inherits the look with zero HTML changes.
6
+
7
+ .btn {
8
+ font-family: $nb-font-display;
9
+ font-weight: 700;
10
+ letter-spacing: -0.01em;
11
+ border-radius: 0;
12
+ @include nb-border();
13
+ @include nb-shadow(md);
14
+ text-transform: none;
15
+ padding: 0.6rem 1.25rem;
16
+ }
17
+
18
+ // Press EXACTLY like the stat cards. These use the DOUBLED `.btn.btn` selector
19
+ // (specificity 0,2,0) on purpose: every theme page bundle re-emits Bootstrap's own
20
+ // `.btn { transition: color … }` and `.btn:hover` (because page SCSS @forwards
21
+ // Bootstrap), and those load AFTER the main bundle. The doubled class beats them so
22
+ // the press is pure transform+shadow with the stat-card timing — no color flash, no
23
+ // focus-ring fighting the offset shadow.
24
+ .btn.btn {
25
+ // Same transition the stat cards use → identical feel.
26
+ @include nb-press();
27
+
28
+ // Focus shows an OUTLINE ring (outside the box, never conflicts with the offset
29
+ // shadow). No focus box-shadow — that was the "flash of border".
30
+ &:focus { outline: 0; }
31
+ &:focus-visible {
32
+ outline: 3px solid var(--nb-border-color);
33
+ outline-offset: 3px;
34
+ }
35
+ }
36
+
37
+ .btn {
38
+
39
+ // Bootstrap adds a subtle border-color per-variant; force ink so the
40
+ // signature black/white frame is consistent across every color.
41
+ // (btn-adaptive / -inverse are the mode-flipping solids used by the nav CTA,
42
+ // auth buttons, etc. — they MUST be in this list or they'd keep Bootstrap's
43
+ // default "darken on hover" and feel different from every other button.)
44
+ &.btn-primary,
45
+ &.btn-secondary,
46
+ &.btn-success,
47
+ &.btn-info,
48
+ &.btn-warning,
49
+ &.btn-danger,
50
+ &.btn-light,
51
+ &.btn-dark,
52
+ &.btn-adaptive,
53
+ &.btn-adaptive-inverse {
54
+ border-color: var(--nb-border-color);
55
+ --bs-btn-hover-border-color: var(--nb-border-color);
56
+ --bs-btn-active-border-color: var(--nb-border-color);
57
+ }
58
+
59
+ // 3. SOLID buttons: freeze hover/active fill to the resting color so the press is
60
+ // pure transform+shadow (no color shift) — exactly the stat-card feel. Outline
61
+ // buttons are intentionally EXCLUDED so they keep their fill-on-hover.
62
+ // Freezing to `var(--bs-btn-bg)` works in BOTH modes automatically because the
63
+ // adaptive classes already set --bs-btn-bg per light/dark.
64
+ &.btn-primary, &.btn-secondary, &.btn-success,
65
+ &.btn-info, &.btn-warning, &.btn-danger,
66
+ &.btn-light, &.btn-dark,
67
+ &.btn-adaptive, &.btn-adaptive-inverse {
68
+ --bs-btn-hover-bg: var(--bs-btn-bg);
69
+ --bs-btn-hover-color: var(--bs-btn-color);
70
+ --bs-btn-active-bg: var(--bs-btn-bg);
71
+ --bs-btn-active-color: var(--bs-btn-color);
72
+ }
73
+ }
74
+
75
+ // btn-adaptive / -inverse RESTING fill. The global _buttons-adaptive.scss sets these
76
+ // via `.btn-adaptive` (0,1,0), but Bootstrap's own `.btn { --bs-btn-bg: transparent }`
77
+ // re-emission can tie/beat it on order, leaving the button transparent. Restate the
78
+ // resting fill here at `.btn.btn-adaptive` (0,2,0) so it always wins — same trick the
79
+ // press uses. Mode-flip handled by pairing with [data-bs-theme="dark"].
80
+ .btn.btn-adaptive {
81
+ --bs-btn-color: #fff;
82
+ --bs-btn-bg: var(--bs-dark);
83
+ --bs-btn-border-color: var(--nb-border-color);
84
+ }
85
+ [data-bs-theme="dark"] .btn.btn-adaptive {
86
+ --bs-btn-color: #000;
87
+ --bs-btn-bg: var(--bs-light);
88
+ }
89
+ .btn.btn-adaptive-inverse {
90
+ --bs-btn-color: #000;
91
+ --bs-btn-bg: var(--bs-light);
92
+ --bs-btn-border-color: var(--nb-border-color);
93
+ }
94
+ [data-bs-theme="dark"] .btn.btn-adaptive-inverse {
95
+ --bs-btn-color: #fff;
96
+ --bs-btn-bg: var(--bs-dark);
97
+ }
98
+
99
+ // Size variants keep the chunky proportions
100
+ .btn-lg {
101
+ padding: 0.85rem 1.75rem;
102
+ font-size: 1.1rem;
103
+ @include nb-border($nb-border-width-lg);
104
+ }
105
+
106
+ .btn-sm {
107
+ padding: 0.35rem 0.8rem;
108
+ font-size: 0.85rem;
109
+ }
110
+
111
+ // Outline buttons: transparent fill, ink frame, fill-on-hover (no fade)
112
+ [class*="btn-outline-"] {
113
+ background: transparent;
114
+ border-color: var(--nb-border-color);
115
+ color: var(--bs-body-color);
116
+
117
+ &:hover {
118
+ color: #111111;
119
+ }
120
+ }
121
+ .btn-outline-primary:hover { background: $primary; }
122
+ .btn-outline-secondary:hover { background: $secondary; }
123
+ .btn-outline-success:hover { background: $success; }
124
+ .btn-outline-danger:hover { background: $danger; }
125
+ .btn-outline-warning:hover { background: $warning; }
126
+ .btn-outline-info:hover { background: $info; }
127
+
128
+ // Link-style button stays flat (no border/shadow) but bold + underlined
129
+ .btn-link {
130
+ border: 0;
131
+ box-shadow: none;
132
+ font-weight: 700;
133
+ text-decoration: underline;
134
+ text-underline-offset: 0.2em;
135
+
136
+ &:hover,
137
+ &:active {
138
+ transform: none;
139
+ box-shadow: none;
140
+ }
141
+ }
142
+
143
+ // NOTE: There are intentionally NO theme-specific accent button classes
144
+ // (e.g. .btn-nb-yellow). Themes must restyle the STANDARD Bootstrap button
145
+ // classes so the same markup works across themes (swap theme.id, done). Need a
146
+ // yellow CTA? Use `.btn-warning` ($warning is the acid-yellow accent). Need other
147
+ // accents? Use `.btn-primary` / `.btn-success` / etc. The base `.btn` rule above
148
+ // already gives every variant the neobrutalist border + offset shadow + press.
@@ -0,0 +1,69 @@
1
+ // Neobrutalism Theme — Cards
2
+ // Cards are the canonical "box": surface + hard ink border + offset shadow.
3
+ // Restyles Bootstrap .card so feature grids, pricing tables, blog cards, and
4
+ // the account UI all pick it up automatically.
5
+
6
+ .card {
7
+ background: var(--nb-surface);
8
+ border-radius: 0;
9
+ @include nb-border();
10
+ @include nb-shadow(md);
11
+
12
+ .card-header {
13
+ background: transparent;
14
+ border-bottom: $nb-border-width solid var(--nb-border-color);
15
+ font-family: $nb-font-display;
16
+ font-weight: 800;
17
+ padding: 1.1rem 1.35rem;
18
+ }
19
+
20
+ .card-body {
21
+ padding: 1.35rem;
22
+ }
23
+
24
+ .card-footer {
25
+ background: transparent;
26
+ border-top: $nb-border-width solid var(--nb-border-color);
27
+ padding: 1rem 1.35rem;
28
+ }
29
+
30
+ // Card images sit flush against the top border
31
+ .card-img-top {
32
+ border-radius: 0;
33
+ border-bottom: $nb-border-width solid var(--nb-border-color);
34
+ }
35
+ }
36
+
37
+ // Clickable cards press like buttons
38
+ a.card,
39
+ .card.nb-pressable {
40
+ @include nb-press();
41
+ text-decoration: none;
42
+ }
43
+
44
+ // Emphasis card — thicker frame + bigger shadow (use for "featured"/popular tiers)
45
+ .card.nb-card-feature {
46
+ @include nb-border($nb-border-width-lg);
47
+ @include nb-shadow(lg);
48
+ }
49
+
50
+ // Accent-headed card: colored header strip
51
+ @each $name, $color in (
52
+ blue: $nb-accent-blue,
53
+ pink: $nb-accent-pink,
54
+ yellow: $nb-accent-yellow,
55
+ green: $nb-accent-green,
56
+ purple: $nb-accent-purple,
57
+ orange: $nb-accent-orange,
58
+ ) {
59
+ .card.nb-card-#{$name} > .card-header {
60
+ background: var(--nb-accent-#{$name});
61
+ color: #111111;
62
+ }
63
+ }
64
+
65
+ // List groups inside cards keep hard dividers
66
+ .list-group-item {
67
+ border-radius: 0;
68
+ border-color: var(--nb-border-color);
69
+ }
@@ -0,0 +1,88 @@
1
+ // Neobrutalism Theme — Forms
2
+ // Inputs are hard-bordered boxes. On focus they gain the offset shadow rather
3
+ // than a glow ring — consistent with the rest of the system. Powers auth pages
4
+ // (signin/signup), the contact form, and the hero demo form.
5
+
6
+ .form-control,
7
+ .form-select {
8
+ background-color: var(--nb-surface);
9
+ color: var(--bs-body-color);
10
+ border-radius: 0;
11
+ @include nb-border();
12
+ padding: 0.6rem 0.85rem;
13
+ font-weight: 500;
14
+ transition: $nb-transition;
15
+
16
+ &::placeholder {
17
+ color: rgba(var(--bs-body-color-rgb, 17, 17, 17), 0.45);
18
+ font-weight: 400;
19
+ }
20
+
21
+ &:focus {
22
+ background-color: var(--nb-surface);
23
+ color: var(--bs-body-color);
24
+ border-color: var(--nb-border-color);
25
+ @include nb-shadow(sm);
26
+ outline: 0;
27
+ }
28
+
29
+ &:disabled,
30
+ &[readonly] {
31
+ background-color: var(--nb-surface-alt);
32
+ opacity: 1;
33
+ }
34
+ }
35
+
36
+ // Labels: bold, slightly mono for the editorial feel
37
+ .form-label {
38
+ font-weight: 700;
39
+ margin-bottom: 0.4rem;
40
+ }
41
+
42
+ // Checkboxes / radios: square, hard-edged
43
+ .form-check-input {
44
+ border-radius: 0;
45
+ border: $nb-border-width-sm solid var(--nb-border-color);
46
+ background-color: var(--nb-surface);
47
+
48
+ &:checked {
49
+ background-color: $primary;
50
+ border-color: var(--nb-border-color);
51
+ }
52
+
53
+ &:focus {
54
+ border-color: var(--nb-border-color);
55
+ box-shadow: none;
56
+ }
57
+ }
58
+
59
+ // Switch keeps square track (intentionally un-rounded)
60
+ .form-switch .form-check-input {
61
+ border-radius: 0;
62
+ }
63
+
64
+ // Input groups: shared ink frame, no gaps
65
+ .input-group {
66
+ .form-control,
67
+ .form-select,
68
+ .btn,
69
+ .input-group-text {
70
+ border-radius: 0;
71
+ }
72
+
73
+ .input-group-text {
74
+ background: var(--nb-surface-alt);
75
+ @include nb-border();
76
+ font-weight: 700;
77
+ }
78
+ }
79
+
80
+ // Validation states use accent colors with the ink frame intact
81
+ .form-control.is-invalid,
82
+ .was-validated .form-control:invalid {
83
+ border-color: $danger;
84
+ }
85
+ .form-control.is-valid,
86
+ .was-validated .form-control:valid {
87
+ border-color: $success;
88
+ }
@@ -0,0 +1,94 @@
1
+ // Neobrutalism Theme — Infinite Scroll
2
+ // Structural marquee used by the shared layouts (trusted-by logo strip,
3
+ // testimonial scroll). Mostly layout/animation (theme-agnostic); cosmetic bits
4
+ // are tuned to the neobrutalist look (square cards, hard hover shadow).
5
+ // NOTE: this is structural behavior the inherited Classy layouts depend on —
6
+ // see docs/themes.md "Structural vs visual components".
7
+
8
+ .infinite-scroll-wrapper {
9
+ position: relative;
10
+ width: 100vw;
11
+ margin-left: calc(-50vw + 50%);
12
+ overflow: hidden;
13
+
14
+ &.infinite-scroll-fade-edges {
15
+ &::before,
16
+ &::after {
17
+ content: '';
18
+ position: absolute;
19
+ top: 0;
20
+ bottom: 0;
21
+ width: 100px;
22
+ z-index: 10;
23
+ pointer-events: none;
24
+ }
25
+ &::before { left: 0; background: linear-gradient(to right, var(--bs-body-bg), transparent); }
26
+ &::after { right: 0; background: linear-gradient(to left, var(--bs-body-bg), transparent); }
27
+ }
28
+ }
29
+
30
+ .infinite-scroll-track {
31
+ display: flex;
32
+ width: fit-content;
33
+ animation: infinite-scroll var(--infinite-scroll-duration, 30s) linear infinite;
34
+
35
+ &:hover { animation-play-state: paused; }
36
+
37
+ &.gap-sm { gap: 1rem; }
38
+ &.gap-md { gap: 1.5rem; }
39
+ &.gap-lg { gap: 2rem; }
40
+ }
41
+
42
+ .infinite-scroll-item { flex-shrink: 0; }
43
+
44
+ @keyframes infinite-scroll {
45
+ 0% { transform: translateX(0); }
46
+ 100% { transform: translateX(var(--infinite-scroll-distance, -50%)); }
47
+ }
48
+
49
+ // Logo items
50
+ .infinite-scroll-item--logo {
51
+ padding: 0 3rem;
52
+ display: flex;
53
+ align-items: center;
54
+ height: 60px;
55
+
56
+ img, svg {
57
+ height: 40px;
58
+ width: auto;
59
+ max-width: 150px;
60
+ transition: $nb-transition;
61
+ }
62
+ }
63
+
64
+ // Card items (testimonials) — square, ink frame + hard offset shadow
65
+ .infinite-scroll-item--card {
66
+ width: 320px;
67
+ padding: 0.5rem 0.5rem 0.5rem 0; // give the offset shadow room so it isn't clipped
68
+
69
+ .card {
70
+ height: 100%;
71
+ border-radius: 0;
72
+ @include nb-border();
73
+ @include nb-shadow(md);
74
+
75
+ &:hover {
76
+ @include nb-shadow(lg);
77
+ }
78
+ }
79
+ }
80
+
81
+ @media (max-width: 768px) {
82
+ .infinite-scroll-wrapper.infinite-scroll-fade-edges {
83
+ &::before,
84
+ &::after { width: 50px; }
85
+ }
86
+
87
+ .infinite-scroll-item--logo {
88
+ padding: 0 2rem;
89
+ height: 50px;
90
+ img, svg { height: 30px; }
91
+ }
92
+
93
+ .infinite-scroll-item--card { width: 280px; }
94
+ }
@@ -0,0 +1,200 @@
1
+ // Neobrutalism Theme — General Layout
2
+ // Section rhythm, the hero treatment, footer, badges, and overrides for the
3
+ // gradient/accent classes the shared (Classy-derived) layouts emit. The goal:
4
+ // the inherited homepage/pricing/auth markup renders as flat neobrutalist
5
+ // color-blocks instead of soft gradients — no layout override needed.
6
+
7
+ // ============================================
8
+ // Section rhythm
9
+ // ============================================
10
+ // Shared layouts rely on the theme to provide vertical section padding.
11
+ section {
12
+ padding-top: clamp(3rem, 7vw, 6rem);
13
+ padding-bottom: clamp(3rem, 7vw, 6rem);
14
+ }
15
+
16
+ // The navbar is fixed and overlaps the page, so the FIRST section on every page
17
+ // must add the navbar's height to its top padding — otherwise its content sits
18
+ // under the nav (cramped at the top, unbalanced vs. the section's bottom).
19
+ // Targets the first section regardless of page; the !important beats a `pt-0`
20
+ // utility that a layout may put on the first section.
21
+ main > section:first-child,
22
+ #main-content > section:first-child {
23
+ padding-top: calc(var(--nb-navbar-height) + clamp(2rem, 5vw, 4rem)) !important;
24
+ }
25
+
26
+ // ============================================
27
+ // Hero — flat color block, not a gradient
28
+ // ============================================
29
+ // The hero <section> ships with .bg-gradient-rainbow .gradient-animated etc.
30
+ // We neutralize the gradient and replace it with a solid accent block framed
31
+ // by a thick ink rule at the bottom. Decorative grain/animation are dropped.
32
+ .bg-gradient-rainbow,
33
+ .gradient-animated,
34
+ .gradient-grain {
35
+ background-image: none !important;
36
+ animation: none !important;
37
+ }
38
+
39
+ section.bg-gradient-rainbow {
40
+ background-color: var(--nb-accent-yellow) !important;
41
+ color: #111111 !important;
42
+ border-radius: 0 !important;
43
+ border-bottom: $nb-border-width-lg solid var(--nb-border-color);
44
+ box-shadow: none !important;
45
+
46
+ // Force readable ink text over the bright block
47
+ // (exclude the tagline kicker, which is ink-on-accent and styled below)
48
+ .text-light,
49
+ &.text-light,
50
+ h1, h2, h3, .lead,
51
+ p:not(.text-uppercase) {
52
+ color: #111111 !important;
53
+ }
54
+
55
+ // Tagline becomes a mono kicker chip: accent text on an ink block
56
+ .text-uppercase {
57
+ display: inline-block;
58
+ font-family: $nb-font-mono;
59
+ font-weight: 700;
60
+ background: #111111;
61
+ color: var(--nb-accent-yellow) !important;
62
+ padding: 0.4rem 0.8rem;
63
+ opacity: 1 !important;
64
+ }
65
+ }
66
+
67
+ // Accent text (headline_accent spans) — marker highlight instead of color swap
68
+ .text-accent {
69
+ background: #111111;
70
+ color: var(--nb-accent-yellow);
71
+ padding: 0 0.12em;
72
+ box-decoration-break: clone;
73
+ -webkit-box-decoration-break: clone;
74
+ }
75
+
76
+ // ============================================
77
+ // CTA / promo cards (.card.bg-gradient.bg-primary.text-white)
78
+ // ============================================
79
+ // Flatten gradient promo cards into solid accent blocks with ink frame.
80
+ .card.bg-gradient,
81
+ .card.bg-primary {
82
+ background-image: none !important;
83
+ background-color: var(--nb-accent-blue) !important;
84
+ color: #fff !important;
85
+ @include nb-border();
86
+ @include nb-shadow(lg);
87
+ }
88
+
89
+ // Glassy hero-demo card → solid surface box
90
+ .bg-glassy,
91
+ .card.bg-glassy {
92
+ background: var(--nb-surface) !important;
93
+ backdrop-filter: none !important;
94
+ -webkit-backdrop-filter: none !important;
95
+ @include nb-border();
96
+ }
97
+
98
+ // ============================================
99
+ // Shadow utility overrides → hard offset shadows
100
+ // ============================================
101
+ // Bootstrap's .shadow / .shadow-lg are soft blurs. Map them to the neobrutalist
102
+ // hard offset so inherited markup (auth cards, modals) gets the right look.
103
+ .shadow-sm { box-shadow: var(--nb-shadow-sm) !important; }
104
+ .shadow { box-shadow: var(--nb-shadow) !important; }
105
+ .shadow-lg { box-shadow: var(--nb-shadow-lg) !important; }
106
+
107
+ // Cards that ship with .border-0 (e.g. the auth card) lose Bootstrap's border;
108
+ // give the frame back so the ink outline + hard shadow read as one box.
109
+ // (Targeted to elevated cards so flat inline cards stay borderless.)
110
+ .card.border-0.shadow-sm,
111
+ .card.border-0.shadow,
112
+ .card.border-0.shadow-lg {
113
+ @include nb-border();
114
+ }
115
+
116
+ // ============================================
117
+ // Badges — sticker chips with ink frame
118
+ // ============================================
119
+ .badge {
120
+ border-radius: 0;
121
+ font-weight: 700;
122
+ letter-spacing: 0;
123
+ padding: 0.4rem 0.6rem;
124
+ @include nb-border($nb-border-width-sm);
125
+ color: #111111;
126
+ }
127
+ .badge.bg-body-tertiary { background: var(--nb-accent-yellow) !important; }
128
+ // Strip decorative gradient borders from inherited badges
129
+ .border-gradient-rainbow { border-image: none !important; }
130
+
131
+ // ============================================
132
+ // Footer
133
+ // ============================================
134
+ footer {
135
+ background: var(--nb-surface);
136
+ border-top: $nb-border-width-lg solid var(--nb-border-color);
137
+
138
+ a {
139
+ color: var(--bs-body-color);
140
+ text-decoration: none;
141
+ font-weight: 600;
142
+
143
+ &:hover {
144
+ background: var(--nb-accent-interactive);
145
+ color: var(--nb-accent-interactive-ink);
146
+ }
147
+ }
148
+ }
149
+
150
+ // ============================================
151
+ // Tables, alerts, accordions — square + framed
152
+ // ============================================
153
+ .alert {
154
+ border-radius: 0;
155
+ @include nb-border();
156
+ @include nb-shadow(sm);
157
+ }
158
+
159
+ .accordion-item {
160
+ border-radius: 0;
161
+ @include nb-border();
162
+ @include nb-shadow(sm);
163
+
164
+ // Bootstrap strips the top border on .accordion-item:not(:first-of-type) to
165
+ // avoid doubled borders in a connected stack. Our items are separated (mb-3),
166
+ // so force the full ink frame back on every item (!important beats Bootstrap's
167
+ // same-specificity reset that may load after this via bootstrap/overrides).
168
+ &:not(:first-of-type) {
169
+ border-top: $nb-border-width solid var(--nb-border-color) !important;
170
+ }
171
+ }
172
+ .accordion-button {
173
+ border-radius: 0;
174
+ font-weight: 700;
175
+
176
+ &:not(.collapsed) {
177
+ background: var(--nb-accent-yellow);
178
+ color: #111111;
179
+ box-shadow: none;
180
+ }
181
+ &:focus {
182
+ box-shadow: none;
183
+ border-color: var(--nb-border-color);
184
+ }
185
+ }
186
+
187
+ .modal-content,
188
+ .toast,
189
+ .offcanvas {
190
+ border-radius: 0;
191
+ @include nb-border();
192
+ @include nb-shadow(lg);
193
+ }
194
+
195
+ // Back-to-top / floating action buttons stay on-brand
196
+ .btn-back-to-top {
197
+ border-radius: 0;
198
+ @include nb-border();
199
+ @include nb-shadow(sm);
200
+ }