@nexub/themes 3.0.0 → 3.2.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.
@@ -0,0 +1,194 @@
1
+ /* @nexub/themes — marketing.css
2
+ Marketing mode: the look of nexub.com on the same tokens and components as
3
+ the apps. Everything here applies only under [data-mode="marketing"]; an app
4
+ that never sets the attribute sees no change. Values come from the
5
+ `marketing` token group (@nexub/tokens), so dark mode, data-contrast and
6
+ data-product keep working.
7
+
8
+ Guidelines (docs: /foundations/marketing-mode): gradients only on the hero,
9
+ the main button and the CTA band; at most one glowing button per screen;
10
+ product accents only for product-specific content; motion stays within the
11
+ budget and stops under prefers-reduced-motion. */
12
+
13
+ [data-mode='marketing'] {
14
+ /* Heavier headings: display 800, headline 700. */
15
+ --type-display-xl-weight: var(--font-weight-extrabold);
16
+ --type-display-lg-weight: var(--font-weight-extrabold);
17
+ --type-display-md-weight: var(--font-weight-extrabold);
18
+ --type-display-sm-weight: var(--font-weight-extrabold);
19
+ --type-headline-lg-weight: var(--font-weight-bold);
20
+ --type-headline-md-weight: var(--font-weight-bold);
21
+ --type-headline-sm-weight: var(--font-weight-bold);
22
+ --nx-mkt-ease: var(--ease-out-expo);
23
+ --nx-mkt-spring: var(--motion-spring-spatial-default-easing);
24
+ --nx-mkt-spring-duration: var(--motion-spring-spatial-default-duration);
25
+ }
26
+
27
+ /* ─── Hero backdrop and brand accent line ─────────────────────────────────── */
28
+ [data-mode='marketing'] .nx-mkt-hero-backdrop {
29
+ background-image: var(--marketing-hero-ambient);
30
+ }
31
+ [data-mode='marketing'] .nx-mkt-accent-line {
32
+ height: 3px;
33
+ background-image: var(--marketing-accent-line);
34
+ }
35
+
36
+ /* ─── Button variant="hero" ───────────────────────────────────────────────
37
+ Outside marketing mode it is a filled button. The focus ring (core.css) is
38
+ an outline outside the button, so it stays visible over the gradient. */
39
+ [data-mode='marketing'] .nx-mkt-hero-button {
40
+ background-color: var(--color-palette-primary-40);
41
+ background-image: var(--marketing-button-gradient);
42
+ color: var(--marketing-button-fg);
43
+ box-shadow: var(--marketing-button-shadow);
44
+ transition:
45
+ translate var(--nx-mkt-spring-duration) var(--nx-mkt-spring),
46
+ box-shadow var(--nx-mkt-spring-duration) var(--nx-mkt-ease);
47
+ }
48
+ [data-mode='marketing'] .nx-mkt-hero-button:hover:not(:disabled, [aria-disabled='true']) {
49
+ background-image: var(--marketing-button-gradient-hover);
50
+ box-shadow: var(--marketing-button-shadow-hover);
51
+ translate: 0 var(--marketing-button-lift);
52
+ }
53
+
54
+ /* ─── CTA band (@nexub/marketing CTABand) ─────────────────────────────────
55
+ The closing band: same gradient and text colour as the hero button. */
56
+ [data-mode='marketing'] .nx-mkt-cta-band {
57
+ background-color: var(--color-palette-primary-40);
58
+ background-image: var(--marketing-button-gradient);
59
+ color: var(--marketing-button-fg);
60
+ }
61
+
62
+ /* ─── Card variant="showcase" ─────────────────────────────────────────────
63
+ accent="leap|bookub|payub|founderub" sets data-product on the card, so
64
+ --color-tertiary is that product's colour: a top edge and a light tint. */
65
+ [data-mode='marketing'] .nx-mkt-showcase {
66
+ --card-radius: var(--marketing-card-radius);
67
+ --card-border: transparent;
68
+ box-shadow: var(--marketing-card-shadow);
69
+ transition:
70
+ translate var(--nx-mkt-spring-duration) var(--nx-mkt-spring),
71
+ box-shadow var(--nx-mkt-spring-duration) var(--nx-mkt-ease);
72
+ }
73
+ [data-mode='marketing'] .nx-mkt-showcase[data-product] {
74
+ --card-bg: color-mix(in srgb, var(--color-tertiary) 5%, var(--color-surface-container-lowest));
75
+ border-top: 3px solid var(--color-tertiary);
76
+ }
77
+ [data-mode='marketing'] .nx-mkt-showcase:is(:hover, :focus-within) {
78
+ box-shadow: var(--marketing-card-shadow-hover);
79
+ translate: 0 var(--marketing-lift);
80
+ }
81
+ [data-mode='marketing'] .nx-mkt-float-card {
82
+ box-shadow: var(--marketing-float-shadow);
83
+ }
84
+
85
+ /* ─── EyebrowChip variant="gradient" ──────────────────────────────────────── */
86
+ [data-mode='marketing'] .nx-mkt-eyebrow {
87
+ background-image: var(--marketing-eyebrow-gradient);
88
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 14%, transparent);
89
+ }
90
+ .nx-mkt-live-dot {
91
+ position: relative;
92
+ display: inline-flex;
93
+ width: 0.5rem;
94
+ height: 0.5rem;
95
+ border-radius: var(--shape-full, 9999px);
96
+ background: var(--color-success);
97
+ }
98
+ [data-mode='marketing'] .nx-mkt-live-dot::after {
99
+ content: '';
100
+ position: absolute;
101
+ inset: 0;
102
+ border-radius: inherit;
103
+ background: inherit;
104
+ animation: nx-mkt-ping 1.6s cubic-bezier(0, 0, 0.2, 1) infinite;
105
+ }
106
+
107
+ /* ─── Motion helpers: Reveal, Float, Marquee, rise, drift, bar fill ──────── */
108
+ [data-mode='marketing'] .nx-mkt-rise {
109
+ animation: nx-mkt-rise 800ms var(--nx-mkt-ease) both;
110
+ }
111
+ /* Staggers (classes, not style attributes, so a strict CSP allows them). */
112
+ [data-mode='marketing'] .nx-mkt-delay-1 { animation-delay: 120ms; }
113
+ [data-mode='marketing'] .nx-mkt-delay-2 { animation-delay: 240ms; }
114
+ [data-mode='marketing'] .nx-mkt-delay-3 { animation-delay: 360ms; }
115
+ /* Reveal: CSS scroll-driven where supported; elsewhere <Reveal> sets
116
+ data-reveal="pending" on elements below the fold and "done" when they
117
+ scroll into view (IntersectionObserver). Without JS nothing is hidden. */
118
+ @supports (animation-timeline: view()) {
119
+ [data-mode='marketing'] .nx-mkt-reveal {
120
+ animation: nx-mkt-rise linear both;
121
+ animation-timeline: view();
122
+ animation-range: entry 0% entry 100%;
123
+ }
124
+ }
125
+ [data-mode='marketing'] .nx-mkt-reveal[data-reveal='pending'] {
126
+ opacity: 0;
127
+ translate: 0 28px;
128
+ }
129
+ [data-mode='marketing'] .nx-mkt-reveal[data-reveal='done'] {
130
+ animation: nx-mkt-rise 800ms var(--nx-mkt-ease) both;
131
+ }
132
+ [data-mode='marketing'] .nx-mkt-float {
133
+ animation: nx-mkt-float 6s ease-in-out infinite;
134
+ }
135
+ [data-mode='marketing'] .nx-mkt-float[data-speed='slow'] {
136
+ animation-duration: 7s;
137
+ animation-direction: reverse;
138
+ }
139
+ [data-mode='marketing'] .nx-mkt-drift {
140
+ animation: nx-mkt-drift 14s ease-in-out infinite;
141
+ }
142
+ [data-mode='marketing'] .nx-mkt-bar {
143
+ animation: nx-mkt-bar 1.6s var(--nx-mkt-ease) 300ms both;
144
+ }
145
+ /* Marquee: the track holds the items twice and moves by half its width. It
146
+ pauses on hover and while anything inside has focus. */
147
+ .nx-mkt-marquee {
148
+ overflow: hidden;
149
+ mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
150
+ }
151
+ .nx-mkt-marquee-track {
152
+ display: flex;
153
+ width: max-content;
154
+ }
155
+ [data-mode='marketing'] .nx-mkt-marquee-track {
156
+ animation: nx-mkt-marquee 28s linear infinite;
157
+ }
158
+ [data-mode='marketing'] .nx-mkt-marquee[data-speed='slow'] .nx-mkt-marquee-track { animation-duration: 44s; }
159
+ [data-mode='marketing'] .nx-mkt-marquee[data-speed='fast'] .nx-mkt-marquee-track { animation-duration: 18s; }
160
+ [data-mode='marketing'] .nx-mkt-marquee:is(:hover, :focus-within) .nx-mkt-marquee-track {
161
+ animation-play-state: paused;
162
+ }
163
+
164
+ @keyframes nx-mkt-rise { from { opacity: 0; translate: 0 28px; } to { opacity: 1; translate: 0 0; } }
165
+ @keyframes nx-mkt-float {
166
+ 0%, 100% { translate: 0 0; rotate: 0deg; }
167
+ 33% { translate: 0 -10px; rotate: 0.5deg; }
168
+ 66% { translate: 0 -5px; rotate: -0.3deg; }
169
+ }
170
+ @keyframes nx-mkt-drift {
171
+ 0%, 100% { translate: 0 0; scale: 1; }
172
+ 25% { translate: 4% -3%; scale: 1.06; }
173
+ 50% { translate: -3% 4%; scale: 0.97; }
174
+ 75% { translate: 2% 2%; scale: 1.03; }
175
+ }
176
+ @keyframes nx-mkt-ping { 75%, 100% { scale: 2.4; opacity: 0; } }
177
+ @keyframes nx-mkt-marquee { to { translate: -50% 0; } }
178
+ @keyframes nx-mkt-bar { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
179
+
180
+ /* Reduced motion: no travel, no loops; revealed content is simply shown. */
181
+ @media (prefers-reduced-motion: reduce) {
182
+ [data-mode='marketing'] :is(.nx-mkt-rise, .nx-mkt-reveal, .nx-mkt-float, .nx-mkt-drift, .nx-mkt-bar, .nx-mkt-marquee-track),
183
+ [data-mode='marketing'] .nx-mkt-live-dot::after {
184
+ animation: none !important;
185
+ }
186
+ [data-mode='marketing'] .nx-mkt-reveal[data-reveal] {
187
+ opacity: 1;
188
+ translate: none;
189
+ }
190
+ [data-mode='marketing'] :is(.nx-mkt-hero-button, .nx-mkt-showcase) {
191
+ transition: none;
192
+ translate: none !important;
193
+ }
194
+ }