ultimate-jekyll-manager 0.0.125 → 0.0.127
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.
- package/.playwright-mcp/page-2025-12-03T03-53-50-384Z.png +0 -0
- package/.playwright-mcp/page-2025-12-03T04-01-07-072Z.png +0 -0
- package/dist/assets/js/libs/sale-name.js +295 -0
- package/dist/assets/js/pages/pricing/index.js +4 -24
- package/dist/assets/js/pages/reset/index.js +1 -1
- package/dist/assets/js/pages/signin/index.js +1 -1
- package/dist/assets/js/pages/signup/index.js +1 -1
- package/dist/assets/themes/classy/_theme.js +9 -8
- package/dist/assets/themes/classy/css/base/_utilities.scss +7 -56
- package/dist/assets/themes/classy/css/components/_text.scss +12 -0
- package/dist/assets/themes/classy/js/initialize-tooltips.js +20 -0
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/index.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +96 -37
- package/dist/defaults/dist/pages/test/libraries/bootstrap.html +210 -0
- package/firebase-debug.log +84 -0
- package/package.json +1 -1
- /package/dist/assets/js/libs/{auth/pages.js → auth.js} +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sale Name Helper
|
|
3
|
+
* Determines the best sale/promotion name based on the current date
|
|
4
|
+
*
|
|
5
|
+
* Holiday precedence rules:
|
|
6
|
+
* - Each holiday has a "core" date (the actual holiday)
|
|
7
|
+
* - Promo window extends 1 week before and 3 days after the core date
|
|
8
|
+
* - A new holiday only takes precedence AFTER the previous holiday's core date has passed
|
|
9
|
+
* - Example: Black Friday promo runs until Black Friday ends, then Cyber Monday takes over
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Configuration
|
|
13
|
+
const DAYS_BEFORE = 7;
|
|
14
|
+
const DAYS_AFTER = 3;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Holiday definitions
|
|
18
|
+
* Each holiday defines how to calculate its core date for a given year
|
|
19
|
+
*/
|
|
20
|
+
const HOLIDAYS = [
|
|
21
|
+
{
|
|
22
|
+
name: 'Black Friday',
|
|
23
|
+
getCoreDate: (year) => {
|
|
24
|
+
// 4th Thursday of November + 1 day (Friday)
|
|
25
|
+
const thanksgiving = getNthWeekdayOfMonth(year, 10, 4, 4);
|
|
26
|
+
const blackFriday = new Date(thanksgiving);
|
|
27
|
+
blackFriday.setDate(blackFriday.getDate() + 1);
|
|
28
|
+
return blackFriday;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'Cyber Monday',
|
|
33
|
+
getCoreDate: (year) => {
|
|
34
|
+
// Monday after Thanksgiving (4 days after Thursday)
|
|
35
|
+
const thanksgiving = getNthWeekdayOfMonth(year, 10, 4, 4);
|
|
36
|
+
const cyberMonday = new Date(thanksgiving);
|
|
37
|
+
cyberMonday.setDate(cyberMonday.getDate() + 4);
|
|
38
|
+
return cyberMonday;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'Christmas',
|
|
43
|
+
getCoreDate: (year) => new Date(year, 11, 25)
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Easter',
|
|
47
|
+
getCoreDate: (year) => calculateEaster(year)
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
// Season definitions
|
|
52
|
+
const SEASONS = [
|
|
53
|
+
{ name: 'Winter', months: [11, 0, 1], endMonth: 1, endDay: 28 },
|
|
54
|
+
{ name: 'Spring', months: [2, 3, 4], endMonth: 4, endDay: 31 },
|
|
55
|
+
{ name: 'Summer', months: [5, 6, 7], endMonth: 7, endDay: 31 },
|
|
56
|
+
{ name: 'Fall', months: [8, 9, 10], endMonth: 10, endDay: 30 }
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get the nth occurrence of a weekday in a month
|
|
61
|
+
* @param {number} year - Year
|
|
62
|
+
* @param {number} month - Month (0-indexed)
|
|
63
|
+
* @param {number} n - Which occurrence (1-5)
|
|
64
|
+
* @param {number} weekday - Day of week (0=Sunday, 4=Thursday)
|
|
65
|
+
* @returns {Date}
|
|
66
|
+
*/
|
|
67
|
+
function getNthWeekdayOfMonth(year, month, n, weekday) {
|
|
68
|
+
const firstDay = new Date(year, month, 1);
|
|
69
|
+
const firstWeekday = firstDay.getDay();
|
|
70
|
+
let dayOffset = weekday - firstWeekday;
|
|
71
|
+
|
|
72
|
+
if (dayOffset < 0) {
|
|
73
|
+
dayOffset += 7;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const nthDay = 1 + dayOffset + (n - 1) * 7;
|
|
77
|
+
return new Date(year, month, nthDay);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Calculate Easter Sunday for a given year (Anonymous Gregorian algorithm)
|
|
82
|
+
* @param {number} year
|
|
83
|
+
* @returns {Date}
|
|
84
|
+
*/
|
|
85
|
+
function calculateEaster(year) {
|
|
86
|
+
const a = year % 19;
|
|
87
|
+
const b = Math.floor(year / 100);
|
|
88
|
+
const c = year % 100;
|
|
89
|
+
const d = Math.floor(b / 4);
|
|
90
|
+
const e = b % 4;
|
|
91
|
+
const f = Math.floor((b + 8) / 25);
|
|
92
|
+
const g = Math.floor((b - f + 1) / 3);
|
|
93
|
+
const h = (19 * a + b - d - g + 15) % 30;
|
|
94
|
+
const i = Math.floor(c / 4);
|
|
95
|
+
const k = c % 4;
|
|
96
|
+
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
|
97
|
+
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
98
|
+
const month = Math.floor((h + l - 7 * m + 114) / 31) - 1;
|
|
99
|
+
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
|
100
|
+
|
|
101
|
+
return new Date(year, month, day);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the promo window for a holiday
|
|
106
|
+
* @param {Date} coreDate - The actual holiday date
|
|
107
|
+
* @returns {object} Object with promoStart, coreDate, and promoEnd
|
|
108
|
+
*/
|
|
109
|
+
function getHolidayWindow(coreDate) {
|
|
110
|
+
const promoStart = new Date(coreDate);
|
|
111
|
+
promoStart.setDate(promoStart.getDate() - DAYS_BEFORE);
|
|
112
|
+
promoStart.setHours(0, 0, 0, 0);
|
|
113
|
+
|
|
114
|
+
const promoEnd = new Date(coreDate);
|
|
115
|
+
promoEnd.setDate(promoEnd.getDate() + DAYS_AFTER);
|
|
116
|
+
promoEnd.setHours(23, 59, 59, 999);
|
|
117
|
+
|
|
118
|
+
// Core date end of day
|
|
119
|
+
const coreDateEnd = new Date(coreDate);
|
|
120
|
+
coreDateEnd.setHours(23, 59, 59, 999);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
promoStart,
|
|
124
|
+
coreDate: new Date(coreDate),
|
|
125
|
+
coreDateEnd,
|
|
126
|
+
promoEnd
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get all holidays with their windows for the relevant years
|
|
132
|
+
* @param {Date} date
|
|
133
|
+
* @returns {Array} Sorted array of holiday objects with windows
|
|
134
|
+
*/
|
|
135
|
+
function getHolidaysWithWindows(date) {
|
|
136
|
+
const year = date.getFullYear();
|
|
137
|
+
const yearsToCheck = [year - 1, year, year + 1];
|
|
138
|
+
const holidays = [];
|
|
139
|
+
|
|
140
|
+
for (const checkYear of yearsToCheck) {
|
|
141
|
+
for (const holiday of HOLIDAYS) {
|
|
142
|
+
const coreDate = holiday.getCoreDate(checkYear);
|
|
143
|
+
const window = getHolidayWindow(coreDate);
|
|
144
|
+
|
|
145
|
+
holidays.push({
|
|
146
|
+
name: holiday.name,
|
|
147
|
+
...window
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Sort by core date
|
|
153
|
+
return holidays.sort((a, b) => a.coreDate - b.coreDate);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get the current season based on date
|
|
158
|
+
* @param {Date} date
|
|
159
|
+
* @returns {object|null} Season object with name, progress, and isEndOfSeason
|
|
160
|
+
*/
|
|
161
|
+
function getCurrentSeason(date) {
|
|
162
|
+
const month = date.getMonth();
|
|
163
|
+
const season = SEASONS.find(s => s.months.includes(month));
|
|
164
|
+
|
|
165
|
+
if (!season) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const year = date.getFullYear();
|
|
170
|
+
|
|
171
|
+
// Handle winter spanning year boundary
|
|
172
|
+
let startYear = year;
|
|
173
|
+
if (season.name === 'Winter' && month <= 1) {
|
|
174
|
+
startYear = year - 1;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const seasonStartDate = new Date(startYear, season.months[0], 1);
|
|
178
|
+
|
|
179
|
+
// For winter end date, use next year if starting month is December
|
|
180
|
+
let endYear = year;
|
|
181
|
+
if (season.name === 'Winter' && season.months[0] === 11) {
|
|
182
|
+
endYear = year + 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const seasonEndDate = new Date(endYear, season.endMonth, season.endDay, 23, 59, 59);
|
|
186
|
+
const seasonDuration = seasonEndDate - seasonStartDate;
|
|
187
|
+
const progress = (date - seasonStartDate) / seasonDuration;
|
|
188
|
+
const isEndOfSeason = progress >= 0.7;
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
name: season.name,
|
|
192
|
+
progress,
|
|
193
|
+
isEndOfSeason,
|
|
194
|
+
startDate: seasonStartDate,
|
|
195
|
+
endDate: seasonEndDate
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get the best sale name for a given date
|
|
201
|
+
*
|
|
202
|
+
* Logic:
|
|
203
|
+
* 1. Find all holidays where we're in their promo window (1 week before to 3 days after)
|
|
204
|
+
* 2. If multiple holidays overlap, the one whose core date has NOT yet passed takes precedence
|
|
205
|
+
* 3. Once a holiday's core date passes, the next holiday can take over
|
|
206
|
+
*
|
|
207
|
+
* @param {Date} [date=new Date()] - Date to check (defaults to now)
|
|
208
|
+
* @returns {object} Object with saleName, endDate, and type
|
|
209
|
+
*/
|
|
210
|
+
export function getSaleName(date = new Date()) {
|
|
211
|
+
const holidays = getHolidaysWithWindows(date);
|
|
212
|
+
|
|
213
|
+
// Find all holidays where we're in their promo window
|
|
214
|
+
const activeHolidays = holidays.filter(h =>
|
|
215
|
+
date >= h.promoStart && date <= h.promoEnd
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
if (activeHolidays.length > 0) {
|
|
219
|
+
// Find the best holiday to show
|
|
220
|
+
// Priority: The holiday whose core date hasn't passed yet, or if all have passed, the most recent one
|
|
221
|
+
let bestHoliday = null;
|
|
222
|
+
|
|
223
|
+
// First, try to find a holiday whose core date hasn't passed
|
|
224
|
+
for (const holiday of activeHolidays) {
|
|
225
|
+
if (date <= holiday.coreDateEnd) {
|
|
226
|
+
bestHoliday = holiday;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// If all core dates have passed, use the one with the latest core date
|
|
232
|
+
// (we're in the "3 days after" window of the most recent holiday)
|
|
233
|
+
if (!bestHoliday) {
|
|
234
|
+
bestHoliday = activeHolidays[activeHolidays.length - 1];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
saleName: `${bestHoliday.name} Sale`,
|
|
239
|
+
endDate: bestHoliday.promoEnd,
|
|
240
|
+
coreDate: bestHoliday.coreDate,
|
|
241
|
+
type: 'holiday'
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Fall back to season
|
|
246
|
+
const season = getCurrentSeason(date);
|
|
247
|
+
|
|
248
|
+
if (!season) {
|
|
249
|
+
return {
|
|
250
|
+
saleName: 'Sale',
|
|
251
|
+
endDate: null,
|
|
252
|
+
type: 'generic'
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const saleName = season.isEndOfSeason
|
|
257
|
+
? `End of ${season.name} Sale`
|
|
258
|
+
: `${season.name} Sale`;
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
saleName,
|
|
262
|
+
endDate: season.endDate,
|
|
263
|
+
type: 'season'
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get all upcoming sales/holidays within a date range
|
|
269
|
+
* @param {Date} startDate
|
|
270
|
+
* @param {Date} endDate
|
|
271
|
+
* @returns {Array} Array of sale objects sorted by start date
|
|
272
|
+
*/
|
|
273
|
+
export function getUpcomingSales(startDate = new Date(), endDate = null) {
|
|
274
|
+
if (!endDate) {
|
|
275
|
+
endDate = new Date(startDate);
|
|
276
|
+
endDate.setFullYear(endDate.getFullYear() + 1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const holidays = getHolidaysWithWindows(startDate);
|
|
280
|
+
|
|
281
|
+
return holidays
|
|
282
|
+
.filter(h => h.promoStart >= startDate && h.promoStart <= endDate)
|
|
283
|
+
.map(h => ({
|
|
284
|
+
saleName: `${h.name} Sale`,
|
|
285
|
+
startDate: h.promoStart,
|
|
286
|
+
coreDate: h.coreDate,
|
|
287
|
+
endDate: h.promoEnd,
|
|
288
|
+
type: 'holiday'
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export default {
|
|
293
|
+
getSaleName,
|
|
294
|
+
getUpcomingSales
|
|
295
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// Libraries
|
|
2
|
+
import { getSaleName } from '__main_assets__/js/libs/sale-name.js';
|
|
3
|
+
|
|
2
4
|
let webManager = null;
|
|
3
5
|
|
|
4
6
|
// Module
|
|
@@ -287,34 +289,12 @@ function setupPromoCountdown() {
|
|
|
287
289
|
return;
|
|
288
290
|
}
|
|
289
291
|
|
|
290
|
-
const
|
|
291
|
-
const month = now.getMonth();
|
|
292
|
-
|
|
293
|
-
const seasons = [
|
|
294
|
-
{ name: 'Winter', months: [11, 0, 1], endMonth: 1, endDay: 28 },
|
|
295
|
-
{ name: 'Spring', months: [2, 3, 4], endMonth: 4, endDay: 31 },
|
|
296
|
-
{ name: 'Summer', months: [5, 6, 7], endMonth: 7, endDay: 31 },
|
|
297
|
-
{ name: 'Fall', months: [8, 9, 10], endMonth: 10, endDay: 30 }
|
|
298
|
-
];
|
|
299
|
-
|
|
300
|
-
const currentSeason = seasons.find(s => s.months.includes(month));
|
|
301
|
-
|
|
302
|
-
if (!currentSeason) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const seasonStartDate = new Date(now.getFullYear(), currentSeason.months[0], 1);
|
|
307
|
-
const seasonEndDate = new Date(now.getFullYear(), currentSeason.endMonth, currentSeason.endDay, 23, 59, 59);
|
|
308
|
-
const seasonDuration = seasonEndDate - seasonStartDate;
|
|
309
|
-
const seasonProgress = (now - seasonStartDate) / seasonDuration;
|
|
310
|
-
|
|
311
|
-
const isEndOfSeason = seasonProgress >= 0.7;
|
|
312
|
-
const saleName = isEndOfSeason ? `End of ${currentSeason.name} Sale` : `${currentSeason.name} Sale`;
|
|
292
|
+
const { saleName } = getSaleName();
|
|
313
293
|
|
|
314
294
|
$promoTextEl.textContent = saleName;
|
|
315
295
|
|
|
316
296
|
const twoDaysInMs = 2 * 24 * 60 * 60 * 1000;
|
|
317
|
-
const cycleStart = Math.floor(now
|
|
297
|
+
const cycleStart = Math.floor(Date.now() / twoDaysInMs) * twoDaysInMs;
|
|
318
298
|
const cycleEnd = cycleStart + twoDaysInMs;
|
|
319
299
|
|
|
320
300
|
function updateCountdown() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Import the theme entry point
|
|
2
2
|
import bootstrap from '../bootstrap/js/index.umd.js';
|
|
3
|
+
import { ready as domReady } from 'web-manager/modules/dom.js';
|
|
3
4
|
|
|
4
5
|
// Make Bootstrap available globally
|
|
5
6
|
window.bootstrap = bootstrap;
|
|
@@ -15,15 +16,15 @@ window.bootstrap = bootstrap;
|
|
|
15
16
|
import setupNavbarScroll from './js/navbar-scroll.js';
|
|
16
17
|
// Import logo scroll functionality
|
|
17
18
|
import setupLogoScroll from './js/logo-scroll.js';
|
|
19
|
+
// Import tooltip initialization
|
|
20
|
+
import initializeTooltips from './js/initialize-tooltips.js';
|
|
18
21
|
|
|
19
|
-
// Initialize
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
setupNavbarScroll();
|
|
23
|
-
setupLogoScroll();
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
22
|
+
// Initialize theme components when DOM is ready
|
|
23
|
+
domReady().then(() => {
|
|
24
|
+
// Classy Theme Initializations
|
|
26
25
|
setupNavbarScroll();
|
|
27
26
|
setupLogoScroll();
|
|
28
|
-
}
|
|
29
27
|
|
|
28
|
+
// Generic Bootstrap initializations
|
|
29
|
+
initializeTooltips();
|
|
30
|
+
});
|
|
@@ -1,57 +1,6 @@
|
|
|
1
1
|
// Classy Utility Classes
|
|
2
2
|
// Custom helper classes and theme-specific utilities
|
|
3
3
|
|
|
4
|
-
// ============================================
|
|
5
|
-
// Section Spacing
|
|
6
|
-
// ============================================
|
|
7
|
-
|
|
8
|
-
// Section Spacing
|
|
9
|
-
// .section {
|
|
10
|
-
// padding: $classy-spacing-4xl 0;
|
|
11
|
-
|
|
12
|
-
// &.section-sm {
|
|
13
|
-
// padding: $classy-spacing-2xl 0;
|
|
14
|
-
// }
|
|
15
|
-
|
|
16
|
-
// &.section-lg {
|
|
17
|
-
// padding: 6rem 0;
|
|
18
|
-
// }
|
|
19
|
-
|
|
20
|
-
// &.section-xl {
|
|
21
|
-
// padding: 8rem 0;
|
|
22
|
-
// }
|
|
23
|
-
// }
|
|
24
|
-
|
|
25
|
-
// Hero Sections
|
|
26
|
-
// .hero {
|
|
27
|
-
// padding: 6rem 0;
|
|
28
|
-
// position: relative;
|
|
29
|
-
// overflow: hidden;
|
|
30
|
-
|
|
31
|
-
// &.hero-gradient {
|
|
32
|
-
// background: $classy-gradient-primary;
|
|
33
|
-
// }
|
|
34
|
-
|
|
35
|
-
// &.hero-pattern {
|
|
36
|
-
// &::before {
|
|
37
|
-
// content: "";
|
|
38
|
-
// position: absolute;
|
|
39
|
-
// top: 0;
|
|
40
|
-
// left: 0;
|
|
41
|
-
// right: 0;
|
|
42
|
-
// bottom: 0;
|
|
43
|
-
// background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%235B47FB' fill-opacity='0.1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
|
44
|
-
// opacity: 0.1;
|
|
45
|
-
// z-index: 0;
|
|
46
|
-
// }
|
|
47
|
-
// }
|
|
48
|
-
|
|
49
|
-
// .hero-content {
|
|
50
|
-
// position: relative;
|
|
51
|
-
// z-index: 1;
|
|
52
|
-
// }
|
|
53
|
-
// }
|
|
54
|
-
|
|
55
4
|
// ============================================
|
|
56
5
|
// Shadow Utilities
|
|
57
6
|
// ============================================
|
|
@@ -68,10 +17,12 @@
|
|
|
68
17
|
// ============================================
|
|
69
18
|
// Cursor Utilities
|
|
70
19
|
// ============================================
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
20
|
+
.cursor-default { cursor: default !important; }
|
|
21
|
+
.cursor-pointer { cursor: pointer !important; }
|
|
22
|
+
.cursor-help { cursor: help !important; }
|
|
23
|
+
.cursor-move { cursor: move !important; }
|
|
24
|
+
.cursor-grab { cursor: grab !important; }
|
|
25
|
+
.cursor-not-allowed { cursor: not-allowed !important; }
|
|
26
|
+
.cursor-crosshair { cursor: crosshair !important; }
|
|
75
27
|
// .cursor-wait { cursor: wait !important; }
|
|
76
|
-
// .cursor-not-allowed { cursor: not-allowed !important; }
|
|
77
28
|
|
|
@@ -39,3 +39,15 @@
|
|
|
39
39
|
[data-bs-theme="dark"] .text-adaptive {
|
|
40
40
|
@extend .text-dark;
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// Text Decoration Utilities
|
|
45
|
+
// ============================================
|
|
46
|
+
.text-decoration-dotted {
|
|
47
|
+
text-decoration-style: dotted !important;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.text-decoration-dashed {
|
|
51
|
+
text-decoration-style: dashed !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initialize Bootstrap Tooltips
|
|
3
|
+
* Finds all elements with data-bs-toggle="tooltip" and initializes them
|
|
4
|
+
*/
|
|
5
|
+
export default function initializeTooltips() {
|
|
6
|
+
const $tooltipTriggers = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
7
|
+
|
|
8
|
+
// If no tooltips found, exit early
|
|
9
|
+
if ($tooltipTriggers.length === 0) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Log the number of tooltips being initialized
|
|
14
|
+
console.log(`Initializing ${$tooltipTriggers.length} tooltips`);
|
|
15
|
+
|
|
16
|
+
// Initialize each tooltip
|
|
17
|
+
$tooltipTriggers.forEach(($el) => {
|
|
18
|
+
new bootstrap.Tooltip($el);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -7,7 +7,7 @@ layout: themes/[ site.theme.id ]/frontend/core/base
|
|
|
7
7
|
hero:
|
|
8
8
|
headline: "Get in"
|
|
9
9
|
headline_accent: "touch"
|
|
10
|
-
subheadline: "
|
|
10
|
+
subheadline: "Have questions about {{ site.brand.name }}? Our support team is here to help you"
|
|
11
11
|
|
|
12
12
|
# Contact Methods Section
|
|
13
13
|
contact_methods:
|
|
@@ -11,9 +11,9 @@ theme:
|
|
|
11
11
|
# Hero Section
|
|
12
12
|
hero:
|
|
13
13
|
tagline: "Introducing {{ site.brand.name }}"
|
|
14
|
-
headline: "The #1 platform for business"
|
|
14
|
+
headline: "The #1 platform <br> for business"
|
|
15
15
|
headline_accent: "success"
|
|
16
|
-
description: "AI automation for modern businesses made simple
|
|
16
|
+
description: "AI automation for modern businesses made simple"
|
|
17
17
|
primary_button:
|
|
18
18
|
text: "Get Started Free"
|
|
19
19
|
icon: "rocket"
|
|
@@ -15,11 +15,24 @@ pricing:
|
|
|
15
15
|
enabled: true
|
|
16
16
|
feature_id: "credits" # Which feature to calculate price per unit for
|
|
17
17
|
label: "credit" # What to call the unit (e.g., "credit", "user", "GB")
|
|
18
|
+
definitions:
|
|
19
|
+
- id: "credits"
|
|
20
|
+
definition: "Credits are used to generate content. Each generation consumes 1 credit."
|
|
21
|
+
- id: "exports"
|
|
22
|
+
definition: "Export your creations in various formats. Watermarked exports include a small logo."
|
|
23
|
+
- id: "api_access"
|
|
24
|
+
definition: "Access our REST API to integrate with your own applications and workflows."
|
|
25
|
+
- id: "priority_support"
|
|
26
|
+
definition: "Get faster response times and dedicated support from our team."
|
|
27
|
+
- id: "team_collaboration"
|
|
28
|
+
definition: "Invite team members to collaborate on projects and share resources."
|
|
29
|
+
- id: "custom_branding"
|
|
30
|
+
definition: "Remove our branding and add your own logo to exports."
|
|
18
31
|
plans:
|
|
19
32
|
- id: "basic"
|
|
20
33
|
name: "Basic"
|
|
21
34
|
tagline: "best for getting started"
|
|
22
|
-
url: "/
|
|
35
|
+
url: "/dashboard" # URL for free plan signup
|
|
23
36
|
pricing:
|
|
24
37
|
monthly: 0
|
|
25
38
|
annually: 0
|
|
@@ -36,6 +49,7 @@ pricing:
|
|
|
36
49
|
- id: "starter"
|
|
37
50
|
name: "Starter"
|
|
38
51
|
tagline: "best for individuals"
|
|
52
|
+
url: null
|
|
39
53
|
pricing:
|
|
40
54
|
monthly: 28
|
|
41
55
|
annually: 276 # Total annual price (~20% off monthly)
|
|
@@ -60,6 +74,7 @@ pricing:
|
|
|
60
74
|
- id: "pro"
|
|
61
75
|
name: "Pro"
|
|
62
76
|
tagline: "best for small businesses"
|
|
77
|
+
url: null
|
|
63
78
|
popular: true
|
|
64
79
|
pricing:
|
|
65
80
|
monthly: 50
|
|
@@ -77,6 +92,7 @@ pricing:
|
|
|
77
92
|
- id: "max"
|
|
78
93
|
name: "Max"
|
|
79
94
|
tagline: "best for growing businesses"
|
|
95
|
+
url: null
|
|
80
96
|
pricing:
|
|
81
97
|
monthly: 100
|
|
82
98
|
annually: 960 # Total annual price (20% off monthly)
|
|
@@ -200,7 +216,7 @@ faqs:
|
|
|
200
216
|
Flash Sale
|
|
201
217
|
</span>
|
|
202
218
|
<span class="text-white-50">
|
|
203
|
-
|
|
219
|
+
Ending in <span id="pricing-promo-countdown" class="fw-semibold text-white">--</span>
|
|
204
220
|
</span>
|
|
205
221
|
<span class="text-white-50">
|
|
206
222
|
Use code <span id="pricing-promo-code" class="badge bg-white bg-opacity-25 px-2 py-1 fs-6">WELCOME15</span>
|
|
@@ -331,45 +347,48 @@ faqs:
|
|
|
331
347
|
</p>
|
|
332
348
|
{% endif %}
|
|
333
349
|
|
|
334
|
-
<!-- Price per unit
|
|
350
|
+
<!-- Price per unit (only shown when enabled) -->
|
|
335
351
|
{% if page.resolved.pricing.price_per_unit.enabled %}
|
|
336
|
-
|
|
337
|
-
{%
|
|
338
|
-
{%
|
|
339
|
-
{%
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
352
|
+
<p class="text-muted small mb-4">
|
|
353
|
+
{% if plan.pricing.monthly > 0 %}
|
|
354
|
+
{% for feature in plan.features %}
|
|
355
|
+
{% if feature.id == page.resolved.pricing.price_per_unit.feature_id %}
|
|
356
|
+
{% assign monthly_price_per_unit = plan.pricing.monthly | times: 1.0 | divided_by: feature.value | round: 2 %}
|
|
357
|
+
{% assign annual_monthly_price = plan.pricing.annually | divided_by: 12.0 %}
|
|
358
|
+
{% assign annual_price_per_unit = annual_monthly_price | divided_by: feature.value | round: 2 %}
|
|
343
359
|
<span class="price-per-unit" data-monthly="${{ monthly_price_per_unit }}" data-annually="${{ annual_price_per_unit }}">${{ annual_price_per_unit }}</span> per {{ page.resolved.pricing.price_per_unit.label }}
|
|
344
|
-
|
|
345
|
-
{%
|
|
346
|
-
{%
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
360
|
+
{% endif %}
|
|
361
|
+
{% endfor %}
|
|
362
|
+
{% else %}
|
|
363
|
+
<!-- Placeholder text for free plan to maintain consistent height -->
|
|
364
|
+
Perfect for trying out
|
|
365
|
+
{% endif %}
|
|
366
|
+
</p>
|
|
351
367
|
{% endif %}
|
|
352
368
|
|
|
353
369
|
<!-- Button -->
|
|
354
|
-
<div class="d-grid mb-3">
|
|
355
|
-
{% if plan.
|
|
356
|
-
|
|
357
|
-
<!-- Get started for free -->
|
|
358
|
-
Get Started
|
|
359
|
-
</a>
|
|
370
|
+
<div class="d-grid mb-3 {% unless page.resolved.pricing.price_per_unit.enabled %}mt-3{% endunless %}">
|
|
371
|
+
{% if plan.popular %}
|
|
372
|
+
{% assign btn_style = "btn-gradient-rainbow gradient-animated" %}
|
|
360
373
|
{% else %}
|
|
361
|
-
{% if plan.popular %}
|
|
362
|
-
{% assign btn_style = "btn-gradient-rainbow gradient-animated" %}
|
|
363
|
-
{% else %}
|
|
364
|
-
{% assign btn_style = "btn-primary" %}
|
|
365
|
-
{% endif %}
|
|
366
374
|
{% assign btn_style = "btn-primary" %}
|
|
375
|
+
{% endif %}
|
|
376
|
+
{% assign btn_style = "btn-primary" %}
|
|
377
|
+
|
|
378
|
+
{% iftruthy plan.url %}
|
|
379
|
+
<a href="{{ plan.url }}" class="btn {% if plan.pricing.monthly == 0 %}btn-adaptive{% else %}{{ btn_style }}{% endif %} btn-md fw-semibold px-2 fs-5">
|
|
380
|
+
{% if plan.pricing.monthly == 0 %}
|
|
381
|
+
Get Started
|
|
382
|
+
{% else %}
|
|
383
|
+
Get Free Trial
|
|
384
|
+
{% endif %}
|
|
385
|
+
</a>
|
|
386
|
+
{% endiftruthy %}
|
|
387
|
+
{% iffalsy plan.url %}
|
|
367
388
|
<button class="btn {{ btn_style }} btn-md fw-semibold px-2 fs-5" data-plan-id="{{ plan.id }}">
|
|
368
|
-
<!-- Try {{ plan.name }} for 14 days -->
|
|
369
|
-
<!-- Try free for 14 days -->
|
|
370
389
|
Get Free Trial
|
|
371
390
|
</button>
|
|
372
|
-
{%
|
|
391
|
+
{% endiffalsy %}
|
|
373
392
|
</div>
|
|
374
393
|
|
|
375
394
|
<!-- Billing info -->
|
|
@@ -391,14 +410,27 @@ faqs:
|
|
|
391
410
|
<ul class="list-unstyled mb-3">
|
|
392
411
|
{% for feature in plan.features %}
|
|
393
412
|
{% if common_feature_ids contains feature.id %}
|
|
413
|
+
{% assign feature_definition = nil %}
|
|
414
|
+
{% for def in page.resolved.pricing.definitions %}
|
|
415
|
+
{% if def.id == feature.id %}
|
|
416
|
+
{% assign feature_definition = def.definition %}
|
|
417
|
+
{% break %}
|
|
418
|
+
{% endif %}
|
|
419
|
+
{% endfor %}
|
|
394
420
|
<li class="d-flex align-items-start mb-2">
|
|
395
421
|
<span class="me-3">{% uj_icon feature.icon, "fa-md" %}</span>
|
|
396
422
|
<span>
|
|
397
423
|
{% if feature.value == "Unlimited" %}
|
|
398
|
-
Unlimited
|
|
424
|
+
Unlimited
|
|
399
425
|
{% else %}
|
|
400
|
-
{{ feature.value | uj_commaify }}
|
|
426
|
+
{{ feature.value | uj_commaify }}
|
|
401
427
|
{% endif %}
|
|
428
|
+
{% iftruthy feature_definition %}
|
|
429
|
+
<span class="text-decoration-underline text-decoration-dotted cursor-help" data-bs-toggle="tooltip" data-bs-title="{{ feature_definition }}">{{ feature.name }}</span>
|
|
430
|
+
{% endiftruthy %}
|
|
431
|
+
{% iffalsy feature_definition %}
|
|
432
|
+
{{ feature.name }}
|
|
433
|
+
{% endiffalsy %}
|
|
402
434
|
</span>
|
|
403
435
|
</li>
|
|
404
436
|
{% endif %}
|
|
@@ -435,16 +467,29 @@ faqs:
|
|
|
435
467
|
<ul class="list-unstyled mb-0">
|
|
436
468
|
{% for feature in plan.features %}
|
|
437
469
|
{% unless common_feature_ids contains feature.id %}
|
|
470
|
+
{% assign feature_definition = nil %}
|
|
471
|
+
{% for def in page.resolved.pricing.definitions %}
|
|
472
|
+
{% if def.id == feature.id %}
|
|
473
|
+
{% assign feature_definition = def.definition %}
|
|
474
|
+
{% break %}
|
|
475
|
+
{% endif %}
|
|
476
|
+
{% endfor %}
|
|
438
477
|
<li class="d-flex align-items-start mb-2 {% if forloop.last %}mb-0{% endif %}">
|
|
439
478
|
<span class="me-3">{% uj_icon feature.icon, "fa-md" %}</span>
|
|
440
479
|
<span>
|
|
441
480
|
{% if feature.value == "24/7" %}
|
|
442
|
-
{{ feature.value }}
|
|
481
|
+
{{ feature.value }}
|
|
443
482
|
{% elsif feature.value == "Included" or feature.value == "Available" or feature.value == "Full" %}
|
|
444
|
-
|
|
483
|
+
<!-- No prefix for these values -->
|
|
445
484
|
{% else %}
|
|
446
|
-
{{ feature.value | uj_commaify }}
|
|
485
|
+
{{ feature.value | uj_commaify }}
|
|
447
486
|
{% endif %}
|
|
487
|
+
{% iftruthy feature_definition %}
|
|
488
|
+
<span class="text-decoration-underline text-decoration-dotted cursor-help" data-bs-toggle="tooltip" data-bs-title="{{ feature_definition }}">{{ feature.name }}</span>
|
|
489
|
+
{% endiftruthy %}
|
|
490
|
+
{% iffalsy feature_definition %}
|
|
491
|
+
{{ feature.name }}
|
|
492
|
+
{% endiffalsy %}
|
|
448
493
|
</span>
|
|
449
494
|
</li>
|
|
450
495
|
{% endunless %}
|
|
@@ -541,8 +586,22 @@ faqs:
|
|
|
541
586
|
</thead>
|
|
542
587
|
<tbody>
|
|
543
588
|
{% for feature_def in all_features %}
|
|
589
|
+
{% assign table_feature_definition = nil %}
|
|
590
|
+
{% for def in page.resolved.pricing.definitions %}
|
|
591
|
+
{% if def.id == feature_def.id %}
|
|
592
|
+
{% assign table_feature_definition = def.definition %}
|
|
593
|
+
{% break %}
|
|
594
|
+
{% endif %}
|
|
595
|
+
{% endfor %}
|
|
544
596
|
<tr>
|
|
545
|
-
<th scope="row">
|
|
597
|
+
<th scope="row">
|
|
598
|
+
{% iftruthy table_feature_definition %}
|
|
599
|
+
<span class="text-decoration-underline text-decoration-dotted cursor-help" data-bs-toggle="tooltip" data-bs-title="{{ table_feature_definition }}">{{ feature_def.name }}</span>
|
|
600
|
+
{% endiftruthy %}
|
|
601
|
+
{% iffalsy table_feature_definition %}
|
|
602
|
+
{{ feature_def.name }}
|
|
603
|
+
{% endiffalsy %}
|
|
604
|
+
</th>
|
|
546
605
|
{% for plan in page.resolved.pricing.plans %}
|
|
547
606
|
<td>
|
|
548
607
|
{% assign has_feature = false %}
|
|
@@ -1272,6 +1272,216 @@ meta:
|
|
|
1272
1272
|
</div>
|
|
1273
1273
|
</section>
|
|
1274
1274
|
|
|
1275
|
+
<!-- Cursor Utilities -->
|
|
1276
|
+
<section>
|
|
1277
|
+
<h2 class="border-bottom pb-2 mb-4">Cursor Utilities</h2>
|
|
1278
|
+
<p class="text-muted mb-4">Test all CSS cursor classes. Hover over each box to see the cursor. If the cursor doesn't change, that class needs to be added to the theme utilities.</p>
|
|
1279
|
+
|
|
1280
|
+
<h3 class="mb-3">General</h3>
|
|
1281
|
+
<div class="row g-3 mb-4">
|
|
1282
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1283
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-auto">
|
|
1284
|
+
<code>.cursor-auto</code>
|
|
1285
|
+
</div>
|
|
1286
|
+
</div>
|
|
1287
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1288
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-default">
|
|
1289
|
+
<code>.cursor-default</code>
|
|
1290
|
+
</div>
|
|
1291
|
+
</div>
|
|
1292
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1293
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-none">
|
|
1294
|
+
<code>.cursor-none</code>
|
|
1295
|
+
</div>
|
|
1296
|
+
</div>
|
|
1297
|
+
</div>
|
|
1298
|
+
|
|
1299
|
+
<h3 class="mb-3">Links & Status</h3>
|
|
1300
|
+
<div class="row g-3 mb-4">
|
|
1301
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1302
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-context-menu">
|
|
1303
|
+
<code>.cursor-context-menu</code>
|
|
1304
|
+
</div>
|
|
1305
|
+
</div>
|
|
1306
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1307
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-help">
|
|
1308
|
+
<code>.cursor-help</code>
|
|
1309
|
+
</div>
|
|
1310
|
+
</div>
|
|
1311
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1312
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-pointer">
|
|
1313
|
+
<code>.cursor-pointer</code>
|
|
1314
|
+
</div>
|
|
1315
|
+
</div>
|
|
1316
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1317
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-progress">
|
|
1318
|
+
<code>.cursor-progress</code>
|
|
1319
|
+
</div>
|
|
1320
|
+
</div>
|
|
1321
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1322
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-wait">
|
|
1323
|
+
<code>.cursor-wait</code>
|
|
1324
|
+
</div>
|
|
1325
|
+
</div>
|
|
1326
|
+
</div>
|
|
1327
|
+
|
|
1328
|
+
<h3 class="mb-3">Selection</h3>
|
|
1329
|
+
<div class="row g-3 mb-4">
|
|
1330
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1331
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-cell">
|
|
1332
|
+
<code>.cursor-cell</code>
|
|
1333
|
+
</div>
|
|
1334
|
+
</div>
|
|
1335
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1336
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-crosshair">
|
|
1337
|
+
<code>.cursor-crosshair</code>
|
|
1338
|
+
</div>
|
|
1339
|
+
</div>
|
|
1340
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1341
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-text">
|
|
1342
|
+
<code>.cursor-text</code>
|
|
1343
|
+
</div>
|
|
1344
|
+
</div>
|
|
1345
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1346
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-vertical-text">
|
|
1347
|
+
<code>.cursor-vertical-text</code>
|
|
1348
|
+
</div>
|
|
1349
|
+
</div>
|
|
1350
|
+
</div>
|
|
1351
|
+
|
|
1352
|
+
<h3 class="mb-3">Drag & Drop</h3>
|
|
1353
|
+
<div class="row g-3 mb-4">
|
|
1354
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1355
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-alias">
|
|
1356
|
+
<code>.cursor-alias</code>
|
|
1357
|
+
</div>
|
|
1358
|
+
</div>
|
|
1359
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1360
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-copy">
|
|
1361
|
+
<code>.cursor-copy</code>
|
|
1362
|
+
</div>
|
|
1363
|
+
</div>
|
|
1364
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1365
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-move">
|
|
1366
|
+
<code>.cursor-move</code>
|
|
1367
|
+
</div>
|
|
1368
|
+
</div>
|
|
1369
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1370
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-no-drop">
|
|
1371
|
+
<code>.cursor-no-drop</code>
|
|
1372
|
+
</div>
|
|
1373
|
+
</div>
|
|
1374
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1375
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-not-allowed">
|
|
1376
|
+
<code>.cursor-not-allowed</code>
|
|
1377
|
+
</div>
|
|
1378
|
+
</div>
|
|
1379
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1380
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-grab">
|
|
1381
|
+
<code>.cursor-grab</code>
|
|
1382
|
+
</div>
|
|
1383
|
+
</div>
|
|
1384
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1385
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-grabbing">
|
|
1386
|
+
<code>.cursor-grabbing</code>
|
|
1387
|
+
</div>
|
|
1388
|
+
</div>
|
|
1389
|
+
</div>
|
|
1390
|
+
|
|
1391
|
+
<h3 class="mb-3">Resizing & Scrolling</h3>
|
|
1392
|
+
<div class="row g-3 mb-4">
|
|
1393
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1394
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-all-scroll">
|
|
1395
|
+
<code>.cursor-all-scroll</code>
|
|
1396
|
+
</div>
|
|
1397
|
+
</div>
|
|
1398
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1399
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-col-resize">
|
|
1400
|
+
<code>.cursor-col-resize</code>
|
|
1401
|
+
</div>
|
|
1402
|
+
</div>
|
|
1403
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1404
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-row-resize">
|
|
1405
|
+
<code>.cursor-row-resize</code>
|
|
1406
|
+
</div>
|
|
1407
|
+
</div>
|
|
1408
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1409
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-n-resize">
|
|
1410
|
+
<code>.cursor-n-resize</code>
|
|
1411
|
+
</div>
|
|
1412
|
+
</div>
|
|
1413
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1414
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-e-resize">
|
|
1415
|
+
<code>.cursor-e-resize</code>
|
|
1416
|
+
</div>
|
|
1417
|
+
</div>
|
|
1418
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1419
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-s-resize">
|
|
1420
|
+
<code>.cursor-s-resize</code>
|
|
1421
|
+
</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1424
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-w-resize">
|
|
1425
|
+
<code>.cursor-w-resize</code>
|
|
1426
|
+
</div>
|
|
1427
|
+
</div>
|
|
1428
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1429
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-ne-resize">
|
|
1430
|
+
<code>.cursor-ne-resize</code>
|
|
1431
|
+
</div>
|
|
1432
|
+
</div>
|
|
1433
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1434
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-nw-resize">
|
|
1435
|
+
<code>.cursor-nw-resize</code>
|
|
1436
|
+
</div>
|
|
1437
|
+
</div>
|
|
1438
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1439
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-se-resize">
|
|
1440
|
+
<code>.cursor-se-resize</code>
|
|
1441
|
+
</div>
|
|
1442
|
+
</div>
|
|
1443
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1444
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-sw-resize">
|
|
1445
|
+
<code>.cursor-sw-resize</code>
|
|
1446
|
+
</div>
|
|
1447
|
+
</div>
|
|
1448
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1449
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-ew-resize">
|
|
1450
|
+
<code>.cursor-ew-resize</code>
|
|
1451
|
+
</div>
|
|
1452
|
+
</div>
|
|
1453
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1454
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-ns-resize">
|
|
1455
|
+
<code>.cursor-ns-resize</code>
|
|
1456
|
+
</div>
|
|
1457
|
+
</div>
|
|
1458
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1459
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-nesw-resize">
|
|
1460
|
+
<code>.cursor-nesw-resize</code>
|
|
1461
|
+
</div>
|
|
1462
|
+
</div>
|
|
1463
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1464
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-nwse-resize">
|
|
1465
|
+
<code>.cursor-nwse-resize</code>
|
|
1466
|
+
</div>
|
|
1467
|
+
</div>
|
|
1468
|
+
</div>
|
|
1469
|
+
|
|
1470
|
+
<h3 class="mb-3">Zooming</h3>
|
|
1471
|
+
<div class="row g-3">
|
|
1472
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1473
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-zoom-in">
|
|
1474
|
+
<code>.cursor-zoom-in</code>
|
|
1475
|
+
</div>
|
|
1476
|
+
</div>
|
|
1477
|
+
<div class="col-6 col-md-4 col-lg-3 col-xl-2">
|
|
1478
|
+
<div class="p-3 bg-body-tertiary border rounded text-center cursor-zoom-out">
|
|
1479
|
+
<code>.cursor-zoom-out</code>
|
|
1480
|
+
</div>
|
|
1481
|
+
</div>
|
|
1482
|
+
</div>
|
|
1483
|
+
</section>
|
|
1484
|
+
|
|
1275
1485
|
<!-- Grid -->
|
|
1276
1486
|
<section>
|
|
1277
1487
|
<h2 class="border-bottom pb-2 mb-4">Grid System</h2>
|
package/firebase-debug.log
CHANGED
|
@@ -1542,3 +1542,87 @@
|
|
|
1542
1542
|
[debug] [2025-12-02T11:01:20.107Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1543
1543
|
[debug] [2025-12-02T11:01:20.107Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1544
1544
|
[debug] [2025-12-02T11:01:20.107Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1545
|
+
[debug] [2025-12-03T01:51:35.334Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1546
|
+
[debug] [2025-12-03T01:51:35.337Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1547
|
+
[debug] [2025-12-03T01:51:35.337Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1548
|
+
[debug] [2025-12-03T01:51:35.337Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1549
|
+
[debug] [2025-12-03T01:51:35.348Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1550
|
+
[debug] [2025-12-03T01:51:35.349Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1551
|
+
[debug] [2025-12-03T01:51:35.443Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1552
|
+
[debug] [2025-12-03T01:51:35.448Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1553
|
+
[debug] [2025-12-03T01:51:35.448Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1554
|
+
[debug] [2025-12-03T01:51:35.448Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1555
|
+
[debug] [2025-12-03T01:51:35.463Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1556
|
+
[debug] [2025-12-03T01:51:35.464Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1557
|
+
[debug] [2025-12-03T01:51:35.471Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1558
|
+
[debug] [2025-12-03T01:51:35.471Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1559
|
+
[debug] [2025-12-03T01:51:35.472Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1560
|
+
[debug] [2025-12-03T01:51:35.472Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1561
|
+
[debug] [2025-12-03T01:51:35.474Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1562
|
+
[debug] [2025-12-03T01:51:35.474Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1563
|
+
[debug] [2025-12-03T01:51:35.475Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1564
|
+
[debug] [2025-12-03T01:51:35.475Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1565
|
+
[debug] [2025-12-03T01:51:35.573Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1566
|
+
[debug] [2025-12-03T01:51:35.573Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1567
|
+
[debug] [2025-12-03T01:51:35.574Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1568
|
+
[debug] [2025-12-03T01:51:35.574Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1569
|
+
[debug] [2025-12-03T01:51:35.575Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1570
|
+
[debug] [2025-12-03T01:51:35.575Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1571
|
+
[debug] [2025-12-03T01:51:35.576Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1572
|
+
[debug] [2025-12-03T01:51:35.576Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1573
|
+
[debug] [2025-12-03T03:24:09.539Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1574
|
+
[debug] [2025-12-03T03:24:09.541Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1575
|
+
[debug] [2025-12-03T03:24:09.541Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1576
|
+
[debug] [2025-12-03T03:24:09.541Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1577
|
+
[debug] [2025-12-03T03:24:09.553Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1578
|
+
[debug] [2025-12-03T03:24:09.553Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1579
|
+
[debug] [2025-12-03T03:24:09.806Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1580
|
+
[debug] [2025-12-03T03:24:09.806Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1581
|
+
[debug] [2025-12-03T03:24:09.807Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1582
|
+
[debug] [2025-12-03T03:24:09.807Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1583
|
+
[debug] [2025-12-03T03:24:09.812Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1584
|
+
[debug] [2025-12-03T03:24:09.812Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1585
|
+
[debug] [2025-12-03T03:24:09.814Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1586
|
+
[debug] [2025-12-03T03:24:09.814Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1587
|
+
[debug] [2025-12-03T03:24:12.483Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1588
|
+
[debug] [2025-12-03T03:24:12.485Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1589
|
+
[debug] [2025-12-03T03:24:12.486Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1590
|
+
[debug] [2025-12-03T03:24:12.486Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1591
|
+
[debug] [2025-12-03T03:24:12.497Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1592
|
+
[debug] [2025-12-03T03:24:12.497Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1593
|
+
[debug] [2025-12-03T03:24:12.611Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1594
|
+
[debug] [2025-12-03T03:24:12.611Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1595
|
+
[debug] [2025-12-03T03:24:12.612Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1596
|
+
[debug] [2025-12-03T03:24:12.612Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1597
|
+
[debug] [2025-12-03T03:24:12.613Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1598
|
+
[debug] [2025-12-03T03:24:12.613Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1599
|
+
[debug] [2025-12-03T03:24:12.614Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1600
|
+
[debug] [2025-12-03T03:24:12.614Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1601
|
+
[debug] [2025-12-03T03:49:02.765Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1602
|
+
[debug] [2025-12-03T03:49:02.765Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1603
|
+
[debug] [2025-12-03T03:49:02.767Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1604
|
+
[debug] [2025-12-03T03:49:02.768Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1605
|
+
[debug] [2025-12-03T03:49:02.768Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1606
|
+
[debug] [2025-12-03T03:49:02.776Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1607
|
+
[debug] [2025-12-03T03:49:02.777Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1608
|
+
[debug] [2025-12-03T03:49:02.767Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1609
|
+
[debug] [2025-12-03T03:49:02.768Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1610
|
+
[debug] [2025-12-03T03:49:02.768Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1611
|
+
[debug] [2025-12-03T03:49:02.776Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1612
|
+
[debug] [2025-12-03T03:49:02.777Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1613
|
+
[debug] [2025-12-03T03:49:02.912Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1614
|
+
[debug] [2025-12-03T03:49:02.913Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1615
|
+
[debug] [2025-12-03T03:49:02.912Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1616
|
+
[debug] [2025-12-03T03:49:02.913Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1617
|
+
[debug] [2025-12-03T03:49:02.913Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1618
|
+
[debug] [2025-12-03T03:49:02.913Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1619
|
+
[debug] [2025-12-03T03:49:02.914Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1620
|
+
[debug] [2025-12-03T03:49:02.914Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1621
|
+
[debug] [2025-12-03T03:49:02.914Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1622
|
+
[debug] [2025-12-03T03:49:02.914Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1623
|
+
[debug] [2025-12-03T03:49:02.915Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1624
|
+
[debug] [2025-12-03T03:49:02.915Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1625
|
+
[debug] [2025-12-03T03:49:02.915Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1626
|
+
[debug] [2025-12-03T03:49:02.916Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
1627
|
+
[debug] [2025-12-03T03:49:02.916Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
1628
|
+
[debug] [2025-12-03T03:49:02.916Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
package/package.json
CHANGED
|
File without changes
|