astro-component-kit 0.4.0 → 0.4.1

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 (180) hide show
  1. package/README.md +105 -27
  2. package/package.json +16 -3
  3. package/src/components/index.ts +2 -0
  4. package/src/components/lib/Galaxy3D.astro +249 -137
  5. package/src/components/lib/app/AppSidebar.astro +249 -0
  6. package/src/components/lib/app/AppTopbar.astro +284 -0
  7. package/src/components/lib/app/ArrivalsBoard.astro +176 -0
  8. package/src/components/lib/app/AuthCard.astro +213 -0
  9. package/src/components/lib/app/DataTable.astro +346 -0
  10. package/src/components/lib/app/GuestProfileCard.astro +133 -0
  11. package/src/components/lib/app/HousekeepingBoard.astro +189 -0
  12. package/src/components/lib/app/PageHeader.astro +157 -0
  13. package/src/components/lib/app/PlanUsageCard.astro +112 -0
  14. package/src/components/lib/app/RoomRack.astro +207 -0
  15. package/src/components/lib/app/SettingsSection.astro +96 -0
  16. package/src/components/lib/app/SwitchRow.astro +71 -0
  17. package/src/components/lib/app/TeamMembers.astro +190 -0
  18. package/src/components/lib/app/app-icons.ts +52 -0
  19. package/src/components/lib/app/index.ts +19 -0
  20. package/src/components/lib/charts/AreaChart.astro +4 -4
  21. package/src/components/lib/charts/BarChart.astro +3 -3
  22. package/src/components/lib/charts/ChartFrame.astro +10 -10
  23. package/src/components/lib/charts/DonutChart.astro +2 -2
  24. package/src/components/lib/charts/DumbbellChart.astro +1 -1
  25. package/src/components/lib/charts/ForecastLineChart.astro +1 -1
  26. package/src/components/lib/charts/GaugeChart.astro +1 -1
  27. package/src/components/lib/charts/HeatmapChart.astro +1 -1
  28. package/src/components/lib/charts/HorizontalBarChart.astro +2 -2
  29. package/src/components/lib/charts/KpiStatTile.astro +4 -4
  30. package/src/components/lib/charts/LinearProgressGauge.astro +4 -4
  31. package/src/components/lib/charts/MetricDeltaTable.astro +3 -3
  32. package/src/components/lib/charts/RadarMetricChart.astro +4 -4
  33. package/src/components/lib/charts/RadialBarChart.astro +1 -1
  34. package/src/components/lib/charts/RetentionCohortTable.astro +2 -2
  35. package/src/components/lib/charts/TreemapChart.astro +1 -1
  36. package/src/components/lib/ecommerce/CartDrawer.astro +483 -0
  37. package/src/components/lib/ecommerce/CartPageList.astro +290 -0
  38. package/src/components/lib/ecommerce/CartToast.astro +276 -0
  39. package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
  40. package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
  41. package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
  42. package/src/components/lib/ecommerce/FilterBar.astro +278 -0
  43. package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
  44. package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
  45. package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
  46. package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
  47. package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
  48. package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
  49. package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
  50. package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
  51. package/src/components/lib/ecommerce/ProductRating.astro +78 -0
  52. package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
  53. package/src/components/lib/ecommerce/PromoBar.astro +145 -0
  54. package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
  55. package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
  56. package/src/components/lib/ecommerce/StoreHero.astro +260 -0
  57. package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
  58. package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
  59. package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
  60. package/src/components/lib/ecommerce/cart-store.ts +151 -0
  61. package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
  62. package/src/components/lib/ecommerce/index.ts +34 -0
  63. package/src/components/lib/ecommerce/product-icons.ts +28 -0
  64. package/src/components/lib/ecommerce/types.ts +70 -0
  65. package/src/components/lib/forms/AnimatedInput.astro +4 -2
  66. package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
  67. package/src/components/lib/index.ts +2 -0
  68. package/src/components/lib/layout/BentoGrid3.astro +6 -4
  69. package/src/components/lib/layout/CenterFixedBox.astro +2 -2
  70. package/src/components/lib/layout/CenteredContainer.astro +4 -2
  71. package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
  72. package/src/components/lib/layout/FeatureHero.astro +4 -2
  73. package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
  74. package/src/components/lib/layout/FullBleedSection.astro +2 -2
  75. package/src/components/lib/layout/GalleryGrid4.astro +2 -2
  76. package/src/components/lib/layout/HolyGrailGrid.astro +11 -9
  77. package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
  78. package/src/components/lib/layout/MasonryGrid.astro +2 -2
  79. package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
  80. package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
  81. package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
  82. package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
  83. package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
  84. package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
  85. package/src/components/lib/sections/AgencyContactBrief.astro +194 -0
  86. package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
  87. package/src/components/lib/sections/AgencyHeader.astro +161 -0
  88. package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
  89. package/src/components/lib/sections/AgencyServicesList.astro +113 -0
  90. package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
  91. package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
  92. package/src/components/lib/sections/BlogGridSection.astro +9 -7
  93. package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
  94. package/src/components/lib/sections/CardsShowcase.astro +28 -26
  95. package/src/components/lib/sections/CareersOpenings.astro +10 -8
  96. package/src/components/lib/sections/ChangelogSection.astro +14 -7
  97. package/src/components/lib/sections/ContactGlassForm.astro +10 -8
  98. package/src/components/lib/sections/ContactSplitMap.astro +11 -9
  99. package/src/components/lib/sections/CtaAppDownload.astro +13 -11
  100. package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
  101. package/src/components/lib/sections/CtaNewsletterSection.astro +13 -11
  102. package/src/components/lib/sections/CtaSplitImage.astro +13 -11
  103. package/src/components/lib/sections/DataShowcase.astro +23 -21
  104. package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
  105. package/src/components/lib/sections/FaqTwoColumn.astro +9 -7
  106. package/src/components/lib/sections/FeatureAlternatingRows.astro +10 -8
  107. package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
  108. package/src/components/lib/sections/FeatureIconGrid.astro +6 -6
  109. package/src/components/lib/sections/FeatureTabsShowcase.astro +13 -11
  110. package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
  111. package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
  112. package/src/components/lib/sections/FooterMegaSection.astro +13 -11
  113. package/src/components/lib/sections/FormsShowcase.astro +22 -20
  114. package/src/components/lib/sections/HeroDashboardPreview.astro +11 -9
  115. package/src/components/lib/sections/HeroGlass.astro +22 -20
  116. package/src/components/lib/sections/HeroGradient.astro +15 -13
  117. package/src/components/lib/sections/HeroMinimalCentered.astro +10 -10
  118. package/src/components/lib/sections/HeroShowcaseSplit.astro +18 -16
  119. package/src/components/lib/sections/HeroSplit.astro +13 -11
  120. package/src/components/lib/sections/HeroTerminal.astro +14 -12
  121. package/src/components/lib/sections/HeroWaitlist.astro +10 -8
  122. package/src/components/lib/sections/HowItWorksSteps.astro +12 -10
  123. package/src/components/lib/sections/IntegrationsGrid.astro +7 -7
  124. package/src/components/lib/sections/LayoutShowcase.astro +21 -19
  125. package/src/components/lib/sections/LogoCloudSection.astro +4 -4
  126. package/src/components/lib/sections/LogoWallGrid.astro +6 -4
  127. package/src/components/lib/sections/NavigationShowcase.astro +15 -13
  128. package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
  129. package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
  130. package/src/components/lib/sections/PricingSinglePlan.astro +13 -11
  131. package/src/components/lib/sections/PricingTierCards.astro +11 -9
  132. package/src/components/lib/sections/PricingToggleCards.astro +13 -13
  133. package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
  134. package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
  135. package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
  136. package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
  137. package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
  138. package/src/components/lib/sections/ShopLookbook.astro +250 -0
  139. package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
  140. package/src/components/lib/sections/ShopProductRail.astro +150 -0
  141. package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
  142. package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
  143. package/src/components/lib/sections/StatsCounterBand.astro +9 -7
  144. package/src/components/lib/sections/StatsDashboardSection.astro +4 -2
  145. package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
  146. package/src/components/lib/sections/TeamGridSection.astro +12 -10
  147. package/src/components/lib/sections/TestimonialCarousel.astro +10 -8
  148. package/src/components/lib/sections/TestimonialFeatured.astro +7 -5
  149. package/src/components/lib/sections/TestimonialGridSection.astro +7 -7
  150. package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
  151. package/src/components/lib/sections/TypographyShowcase.astro +10 -8
  152. package/src/components/lib/sections/index.ts +10 -0
  153. package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
  154. package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
  155. package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
  156. package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
  157. package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
  158. package/src/components/lib/templates/ecommerce/data.ts +187 -0
  159. package/src/components/lib/templates/ecommerce/index.ts +14 -0
  160. package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
  161. package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
  162. package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
  163. package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
  164. package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
  165. package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
  166. package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
  167. package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
  168. package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
  169. package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
  170. package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
  171. package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
  172. package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
  173. package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
  174. package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
  175. package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
  176. package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
  177. package/src/components/lib/templates/saas-hotel/data.ts +229 -0
  178. package/src/components/lib/templates/saas-hotel/index.ts +19 -0
  179. package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -0
  180. package/src/styles/global.css +95 -0
@@ -0,0 +1,115 @@
1
+ ---
2
+ /**
3
+ * SettingsPage — Account & workspace settings: profile, property details, notification switches,
4
+ * team management with roles and invites, and plan usage / billing.
5
+ *
6
+ * Usage (src/pages/app/settings.astro):
7
+ * import { SettingsPage } from 'astro-component-kit/templates/saas-hotel';
8
+ * <SettingsPage />
9
+ *
10
+ * @param {LobbyData} data - Workspace data.
11
+ * @param {SaasRoutes} routes - Page URLs.
12
+ * @param {string} theme - Initial theme (light|dark|auto). Default 'light'.
13
+ */
14
+ import AppLayout from './AppLayout.astro';
15
+ import PageHeader from '../../app/PageHeader.astro';
16
+ import SettingsSection from '../../app/SettingsSection.astro';
17
+ import SwitchRow from '../../app/SwitchRow.astro';
18
+ import TeamMembers from '../../app/TeamMembers.astro';
19
+ import PlanUsageCard from '../../app/PlanUsageCard.astro';
20
+ import AnimatedInput from '../../forms/AnimatedInput.astro';
21
+ import ModernSelect from '../../forms/ModernSelect.astro';
22
+ import { lobbyData, saasRoutes, type LobbyData, type SaasRoutes } from './data';
23
+
24
+ interface Props {
25
+ data?: LobbyData;
26
+ routes?: SaasRoutes;
27
+ theme?: 'light' | 'dark' | 'auto';
28
+ }
29
+
30
+ const { data = lobbyData, routes = saasRoutes, theme = 'light' } = Astro.props;
31
+ ---
32
+
33
+ <AppLayout title="Settings" current="settings" data={data} routes={routes} theme={theme}>
34
+ <PageHeader
35
+ title="Settings"
36
+ description="Manage your profile, property, team and billing."
37
+ breadcrumb={[{ label: data.workspace.name, href: routes.dashboard }, { label: 'Settings' }]}
38
+ actions={[]}
39
+ periods={[]}
40
+ tabs={[
41
+ { label: 'Profile', href: '#profile' },
42
+ { label: 'Property', href: '#property' },
43
+ { label: 'Notifications', href: '#notifications' },
44
+ { label: 'Team', href: '#team', count: data.team.length },
45
+ { label: 'Billing', href: '#billing' },
46
+ ]}
47
+ currentTab="#profile"
48
+ />
49
+
50
+ <div class="settings">
51
+ <div id="profile">
52
+ <SettingsSection id="set-profile" title="Your profile" description="How you appear to your team and in guest messages.">
53
+ <div class="settings__row">
54
+ <AnimatedInput label="Full name" id="set-name" name="name" required autocomplete="name" placeholder=" " />
55
+ <AnimatedInput label="Email" id="set-email" name="email" type="email" required autocomplete="email" />
56
+ </div>
57
+ <div class="settings__row">
58
+ <AnimatedInput label="Job title" id="set-role" name="role" autocomplete="organization-title" />
59
+ <ModernSelect label="Language" id="set-lang" name="lang" options={[{ label: 'English', value: 'en' }, { label: 'Español', value: 'es' }, { label: 'Русский', value: 'ru' }]} />
60
+ </div>
61
+ </SettingsSection>
62
+ </div>
63
+
64
+ <div id="property">
65
+ <SettingsSection id="set-property" title="Property" description="Details used on invoices, confirmations and your booking engine.">
66
+ <div class="settings__row">
67
+ <AnimatedInput label="Property name" id="set-prop" name="property" required />
68
+ <ModernSelect label="Currency" id="set-cur" name="currency" options={[{ label: 'Euro (€)', value: 'EUR' }, { label: 'US dollar ($)', value: 'USD' }, { label: 'Pound (£)', value: 'GBP' }]} />
69
+ </div>
70
+ <div class="settings__row">
71
+ <ModernSelect label="Check-in time" id="set-in" name="checkin" options={[{ label: '14:00', value: '14' }, { label: '15:00', value: '15' }, { label: '16:00', value: '16' }]} />
72
+ <ModernSelect label="Check-out time" id="set-out" name="checkout" options={[{ label: '11:00', value: '11' }, { label: '12:00', value: '12' }]} />
73
+ </div>
74
+ </SettingsSection>
75
+ </div>
76
+
77
+ <div id="notifications">
78
+ <SettingsSection id="set-notes" title="Notifications" description="Choose what reaches your inbox and phone.">
79
+ <SwitchRow name="n-bookings" label="New bookings & cancellations" description="Instant email for every change from any channel." checked />
80
+ <SwitchRow name="n-house" label="Housekeeping alerts" description="Push notification when a room is out of order." checked />
81
+ <SwitchRow name="n-reviews" label="New guest reviews" description="Daily digest at 9:00." checked={false} />
82
+ <SwitchRow name="n-report" label="Weekly performance report" description="Occupancy, ADR and RevPAR every Monday." checked />
83
+ </SettingsSection>
84
+ </div>
85
+
86
+ <div id="team" class="settings__block">
87
+ <div class="settings__intro">
88
+ <h2>Team</h2>
89
+ <p>Invite colleagues and choose what each role can see and do.</p>
90
+ </div>
91
+ <TeamMembers members={data.team} seats={10} />
92
+ </div>
93
+
94
+ <div id="billing" class="settings__block">
95
+ <div class="settings__intro">
96
+ <h2>Plan & billing</h2>
97
+ <p>Your subscription renews automatically. Change or cancel any time.</p>
98
+ </div>
99
+ <PlanUsageCard variant="accent" upgrade={{ label: 'Upgrade to Business', href: routes.landing + '#pricing' }} />
100
+ </div>
101
+ </div>
102
+ </AppLayout>
103
+
104
+ <style>
105
+ .settings { display: grid; max-width: 1040px; }
106
+ .settings > div { scroll-margin-top: 84px; }
107
+ .settings__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
108
+ .settings__block { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 2fr); gap: var(--sp-6); padding-block: var(--sp-6); border-bottom: 1px solid var(--c-border); }
109
+ .settings__intro h2 { margin: 0; font-size: 1rem; font-weight: 700; color: var(--c-text-1); }
110
+ .settings__intro p { margin: 4px 0 0; font-size: 0.85rem; line-height: 1.55; }
111
+ @media (max-width: 900px) {
112
+ .settings__block { grid-template-columns: 1fr; }
113
+ .settings__row { grid-template-columns: 1fr; }
114
+ }
115
+ </style>
@@ -0,0 +1,50 @@
1
+ ---
2
+ /**
3
+ * SignInPage — Split-screen sign-in (or sign-up) for the hotel SaaS using AuthCard.
4
+ *
5
+ * Usage (src/pages/sign-in.astro):
6
+ * import { SignInPage } from 'astro-component-kit/templates/saas-hotel';
7
+ * <SignInPage />
8
+ *
9
+ * @param {string} mode - 'signin' or 'signup'. Default 'signin'.
10
+ * @param {SaasRoutes} routes - Page URLs (demo sign-in goes to `routes.dashboard`).
11
+ * @param {string} theme - Initial theme (light|dark|auto). Default 'light'.
12
+ * @param {boolean} noindex - Add robots noindex. Default true.
13
+ */
14
+ import '../../../../styles/global.css';
15
+ import './lobby-theme.css';
16
+ import AuthCard from '../../app/AuthCard.astro';
17
+ import { saasRoutes, type SaasRoutes } from './data';
18
+
19
+ interface Props {
20
+ mode?: 'signin' | 'signup';
21
+ routes?: SaasRoutes;
22
+ theme?: 'light' | 'dark' | 'auto';
23
+ noindex?: boolean;
24
+ }
25
+
26
+ const { mode = 'signin', routes = saasRoutes, theme = 'light', noindex = true } = Astro.props;
27
+ ---
28
+
29
+ <!doctype html>
30
+ <html lang="en" class="theme-lobby" data-theme={theme === 'auto' ? 'light' : theme}>
31
+ <head>
32
+ <meta charset="utf-8" />
33
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
34
+ <title>{mode === 'signin' ? 'Sign in' : 'Start your free trial'} — Lobby</title>
35
+ {noindex && <meta name="robots" content="noindex, follow" />}
36
+ <script is:inline define:vars={{ initial: theme }}>
37
+ (function () {
38
+ var t = initial;
39
+ try { t = localStorage.getItem('ack-theme') || t; } catch (e) {}
40
+ if (t === 'auto') t = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
41
+ document.documentElement.dataset.theme = t;
42
+ })();
43
+ </script>
44
+ </head>
45
+ <body class="lobby">
46
+ <main>
47
+ <AuthCard mode={mode} brand="Lobby" successHref={routes.dashboard} switchHref={routes.landing} />
48
+ </main>
49
+ </body>
50
+ </html>
@@ -0,0 +1,229 @@
1
+ // src/components/lib/templates/saas-hotel/data.ts
2
+ // Demo data for the hotel SaaS template ("Lobby · Hotel OS" with the Hotel Mirador workspace).
3
+ // Replace with your API data; every page reads from this shape.
4
+
5
+ export interface SaasRoutes {
6
+ landing: string;
7
+ signIn: string;
8
+ dashboard: string;
9
+ reservations: string;
10
+ rooms: string;
11
+ guests: string;
12
+ reports: string;
13
+ settings: string;
14
+ }
15
+
16
+ export const saasRoutes: SaasRoutes = {
17
+ landing: '/',
18
+ signIn: '/sign-in/',
19
+ dashboard: '/app/',
20
+ reservations: '/app/reservations/',
21
+ rooms: '/app/rooms/',
22
+ guests: '/app/guests/',
23
+ reports: '/app/reports/',
24
+ settings: '/app/settings/',
25
+ };
26
+
27
+ type Status = 'Confirmed' | 'Checked in' | 'Checked out' | 'Pending' | 'Cancelled';
28
+ type RoomStatus = 'clean' | 'dirty' | 'inspecting' | 'occupied' | 'ooo';
29
+
30
+ const GUESTS = [
31
+ ['Elena Duarte', 'Spain'], ['James Whitfield', 'UK'], ['Aiko Tanaka', 'Japan'], ['Marco Bellini', 'Italy'],
32
+ ['Sofía Ramos', 'Mexico'], ['Hans Müller', 'Germany'], ['Priya Nair', 'India'], ['The Okafor family', 'Nigeria'],
33
+ ['Chloé Martin', 'France'], ['Tom Becker', 'Austria'], ['Ana Costa', 'Portugal'], ['Liam O’Connor', 'Ireland'],
34
+ ['Mei Chen', 'Singapore'], ['Lucas Silva', 'Brazil'], ['Nora Lindqvist', 'Sweden'], ['David Cohen', 'USA'],
35
+ ] as const;
36
+ const CHANNELS = ['Direct', 'Booking.com', 'Expedia', 'Airbnb', 'Direct', 'Booking.com'];
37
+ const PRICES: Record<string, number> = { Standard: 118, Deluxe: 176, Suite: 312 };
38
+
39
+ const rooms = [
40
+ ...['101', '102', '103', '104', '105', '106'].map((n) => ({ id: n, name: n, type: 'Standard', floor: 'Floor 1' })),
41
+ ...['201', '202', '203', '204', '205', '206'].map((n) => ({ id: n, name: n, type: 'Deluxe', floor: 'Floor 2' })),
42
+ ...['301', '302', '303', '304'].map((n) => ({ id: n, name: n, type: 'Suite', floor: 'Floor 3' })),
43
+ ];
44
+
45
+ /** Day labels starting yesterday (built at build time; demo data only). */
46
+ function buildDays(count: number, locale: string): { labels: string[]; iso: string[] } {
47
+ const start = new Date();
48
+ start.setUTCHours(0, 0, 0, 0);
49
+ start.setUTCDate(start.getUTCDate() - 1);
50
+ const fmt = new Intl.DateTimeFormat(locale, { weekday: 'short', day: 'numeric', timeZone: 'UTC' });
51
+ const labels: string[] = [];
52
+ const iso: string[] = [];
53
+ for (let i = 0; i < count; i++) {
54
+ const d = new Date(start);
55
+ d.setUTCDate(start.getUTCDate() + i);
56
+ labels.push(fmt.format(d).replace(',', ''));
57
+ iso.push(d.toISOString().slice(0, 10));
58
+ }
59
+ return { labels, iso };
60
+ }
61
+
62
+ const locale = 'en-GB';
63
+ const days = buildDays(14, locale);
64
+
65
+ // Deterministic bookings across the rack.
66
+ const rackBookings = [
67
+ ['101', 0, 3, 'checked-in'], ['101', 4, 2, 'confirmed'], ['101', 8, 4, 'pending'],
68
+ ['102', 1, 5, 'confirmed'], ['102', 7, 3, 'confirmed'],
69
+ ['103', 0, 2, 'checked-in'], ['103', 3, 6, 'confirmed'],
70
+ ['104', 2, 2, 'blocked'], ['104', 5, 4, 'confirmed'],
71
+ ['105', 0, 4, 'checked-in'], ['105', 6, 3, 'pending'], ['105', 10, 3, 'confirmed'],
72
+ ['106', 1, 2, 'confirmed'], ['106', 4, 5, 'confirmed'],
73
+ ['201', 0, 6, 'checked-in'], ['201', 7, 2, 'confirmed'],
74
+ ['202', 2, 3, 'confirmed'], ['202', 6, 5, 'pending'],
75
+ ['203', 0, 1, 'checked-in'], ['203', 3, 4, 'confirmed'], ['203', 9, 3, 'confirmed'],
76
+ ['204', 1, 3, 'confirmed'], ['204', 5, 2, 'blocked'],
77
+ ['205', 0, 3, 'checked-in'], ['205', 4, 4, 'confirmed'],
78
+ ['206', 2, 6, 'confirmed'],
79
+ ['301', 1, 6, 'confirmed'], ['301', 9, 3, 'pending'],
80
+ ['302', 0, 2, 'checked-in'], ['302', 4, 4, 'confirmed'],
81
+ ['303', 3, 3, 'confirmed'],
82
+ ['304', 0, 5, 'checked-in'], ['304', 8, 4, 'confirmed'],
83
+ ] as const;
84
+
85
+ const bookings = rackBookings.map(([room, start, nights, status], i) => {
86
+ const [guest] = GUESTS[i % GUESTS.length];
87
+ return { room, guest: status === 'blocked' ? 'Maintenance' : guest, start, nights, status, ref: status === 'blocked' ? undefined : `MR-${2810 + i}`, channel: status === 'blocked' ? undefined : CHANNELS[i % CHANNELS.length] };
88
+ });
89
+
90
+ const tableStatus = (s: string, i: number): Status =>
91
+ s === 'checked-in' ? 'Checked in' : s === 'pending' ? 'Pending' : i % 9 === 4 ? 'Cancelled' : 'Confirmed';
92
+
93
+ const reservations = bookings
94
+ .filter((b) => b.status !== 'blocked')
95
+ .map((b, i) => {
96
+ const room = rooms.find((r) => r.id === b.room)!;
97
+ const st = tableStatus(b.status, i);
98
+ return {
99
+ ref: b.ref!,
100
+ guest: { name: b.guest, sub: b.channel },
101
+ room: `${room.name} · ${room.type}`,
102
+ checkIn: days.iso[b.start],
103
+ nights: b.nights,
104
+ status: st,
105
+ total: st === 'Cancelled' ? 0 : b.nights * PRICES[room.type],
106
+ };
107
+ });
108
+
109
+ const housekeeping: Array<{ number: string; floor: string; type: string; status: RoomStatus; guest?: string; note?: string; assignee?: string }> = rooms.map((r, i) => {
110
+ const occ = bookings.find((b) => b.room === r.id && b.status === 'checked-in');
111
+ const cycle: RoomStatus[] = ['clean', 'dirty', 'inspecting', 'clean', 'dirty'];
112
+ if (r.id === '104') return { number: r.name, floor: r.floor, type: r.type, status: 'ooo', note: 'Plumbing repair' };
113
+ if (occ) return { number: r.name, floor: r.floor, type: r.type, status: 'occupied', guest: occ.guest.split(' ').slice(-1)[0] };
114
+ const status = cycle[i % cycle.length];
115
+ return { number: r.name, floor: r.floor, type: r.type, status, assignee: status !== 'clean' ? ['Rosa', 'Luis', 'Inés'][i % 3] : undefined };
116
+ });
117
+
118
+ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
119
+
120
+ export const lobbyData = {
121
+ product: 'Lobby',
122
+ workspace: { name: 'Hotel Mirador', plan: 'Pro plan', initials: 'HM' },
123
+ user: { name: 'Lucía Ortega', role: 'General manager', email: 'lucia@mirador.com' },
124
+ currency: 'EUR',
125
+ locale,
126
+ days: days.labels,
127
+ rooms,
128
+ bookings,
129
+ reservations,
130
+ housekeeping,
131
+ kpis: [
132
+ { label: 'Occupancy', value: '84%', change: 6.2, trend: [62, 66, 70, 68, 74, 78, 80, 84] },
133
+ { label: 'ADR', value: '€168', change: 3.4, trend: [150, 152, 158, 155, 160, 162, 165, 168] },
134
+ { label: 'RevPAR', value: '€141', change: 9.1, trend: [98, 104, 110, 106, 118, 124, 132, 141] },
135
+ { label: 'Cancellations', value: '3.1%', change: -1.2, invert: true, trend: [5, 4.6, 4.8, 4.1, 3.9, 3.6, 3.4, 3.1] },
136
+ ],
137
+ revenue: {
138
+ categories: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8', 'W9', 'W10', 'W11', 'W12'],
139
+ series: [
140
+ { name: 'Rooms', data: [38, 41, 39, 44, 47, 52, 49, 55, 58, 61, 57, 64] },
141
+ { name: 'F&B', data: [9, 10, 9, 11, 12, 13, 12, 14, 15, 16, 15, 17] },
142
+ { name: 'Spa & extras', data: [4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9] },
143
+ ],
144
+ },
145
+ occupancyByType: {
146
+ categories: months.slice(4, 11),
147
+ series: [
148
+ { name: 'Standard', data: [72, 78, 88, 91, 84, 76, 81] },
149
+ { name: 'Deluxe', data: [64, 71, 85, 89, 79, 70, 77] },
150
+ { name: 'Suite', data: [48, 55, 74, 80, 66, 58, 63] },
151
+ ],
152
+ },
153
+ channels: [
154
+ { label: 'Direct', value: 38 },
155
+ { label: 'Booking.com', value: 31 },
156
+ { label: 'Expedia', value: 17 },
157
+ { label: 'Airbnb', value: 9 },
158
+ { label: 'Corporate', value: 5 },
159
+ ],
160
+ forecast: {
161
+ categories: ['Oct 28', 'Oct 31', 'Nov 3', 'Nov 6', 'Nov 9', 'Nov 12', 'Nov 15', 'Nov 18', 'Nov 21', 'Nov 24'],
162
+ actual: [71, 74, 80, 84],
163
+ forecast: [84, 82, 79, 86, 91, 88, 76, 72],
164
+ },
165
+ pace: {
166
+ rows: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
167
+ columns: ['0–7d', '8–14d', '15–30d', '31–60d', '61–90d', '90d+'],
168
+ values: [
169
+ [12, 9, 14, 8, 4, 2], [10, 8, 12, 7, 3, 2], [11, 10, 13, 9, 4, 3], [14, 12, 15, 10, 6, 3],
170
+ [22, 18, 20, 14, 9, 5], [26, 21, 22, 16, 10, 6], [15, 11, 12, 8, 5, 3],
171
+ ],
172
+ },
173
+ funnel: [
174
+ { label: 'Website visits', value: 18400 },
175
+ { label: 'Searched dates', value: 7350 },
176
+ { label: 'Viewed rooms', value: 3920 },
177
+ { label: 'Started booking', value: 1180 },
178
+ { label: 'Booked', value: 612 },
179
+ ],
180
+ segments: [
181
+ { label: 'Leisure', value: 46 },
182
+ { label: 'Business', value: 28 },
183
+ { label: 'Groups', value: 14 },
184
+ { label: 'Long stay', value: 12 },
185
+ ],
186
+ arrivals: [
187
+ { guest: 'Elena Duarte', room: '204', time: '14:00', nights: 3, vip: true, note: 'Anniversary, late arrival' },
188
+ { guest: 'Aiko Tanaka', room: '102', time: '15:30', nights: 5 },
189
+ { guest: 'The Okafor family', room: '301', time: '16:00', nights: 6, note: 'Baby cot', done: true },
190
+ { guest: 'David Cohen', room: '106', time: '18:45', nights: 2 },
191
+ ],
192
+ departures: [
193
+ { guest: 'Hans Müller', room: '203', time: '11:00', balance: '€0', done: true },
194
+ { guest: 'Priya Nair', room: '302', time: '12:00', balance: '€48' },
195
+ { guest: 'Lucas Silva', room: '105', time: '12:00', balance: '€0' },
196
+ ],
197
+ inHouse: [
198
+ { guest: 'James Whitfield', room: '201', until: days.labels[6] },
199
+ { guest: 'Mei Chen', room: '304', until: days.labels[5] },
200
+ { guest: 'Nora Lindqvist', room: '205', until: days.labels[3] },
201
+ ],
202
+ activity: [
203
+ { title: 'Check-in completed', desc: 'The Okafor family · Suite 301', time: '09:42', status: 'done' as const },
204
+ { title: 'Payment captured', desc: 'MR-2840 · €890 · Visa', time: '09:15', status: 'done' as const },
205
+ { title: 'Room 104 out of order', desc: 'Plumbing — technician on site', time: '08:50', status: 'active' as const },
206
+ { title: 'Rate update pushed', desc: 'Weekend +8% on all channels', time: '08:05', status: 'pending' as const },
207
+ ],
208
+ notifications: [
209
+ { title: 'New booking from Booking.com', text: 'Deluxe King · 3 nights · €528', time: '2 min ago', unread: true, tone: 'success' as const },
210
+ { title: 'Room 104 out of order', text: 'Plumbing repair scheduled', time: '1 h ago', unread: true, tone: 'warning' as const },
211
+ { title: 'Weekly report ready', text: 'Occupancy up 6.2% vs last week', time: 'Yesterday', tone: 'info' as const },
212
+ ],
213
+ guests: GUESTS.slice(0, 12).map(([name, country], i) => ({
214
+ guest: { name, sub: `${name.toLowerCase().replace(/[^a-z]+/g, '.').replace(/^\.|\.$/g, '')}@mail.com` },
215
+ country,
216
+ stays: [7, 3, 1, 2, 4, 9, 1, 2, 5, 1, 3, 6][i],
217
+ spend: [4820, 2140, 476, 980, 1730, 6120, 290, 1880, 2410, 340, 1290, 3980][i],
218
+ tier: ['Gold', 'Silver', 'Member', 'Member', 'Silver', 'Platinum', 'Member', 'Silver', 'Gold', 'Member', 'Silver', 'Gold'][i],
219
+ tags: [['VIP', 'Anniversary'], ['Business'], ['First stay'], ['Repeat'], ['Spa'], ['VIP', 'Long stay'], [], ['Family'], ['Business'], [], ['Repeat'], ['VIP']][i],
220
+ })),
221
+ team: [
222
+ { name: 'Lucía Ortega', email: 'lucia@mirador.com', role: 'Owner', status: 'active' as const, you: true },
223
+ { name: 'Daniel Kim', email: 'daniel@mirador.com', role: 'Manager', status: 'active' as const },
224
+ { name: 'Rosa Jiménez', email: 'rosa@mirador.com', role: 'Housekeeping', status: 'active' as const },
225
+ { name: 'Omar Haddad', email: 'omar@mirador.com', role: 'Front desk', status: 'invited' as const },
226
+ ],
227
+ };
228
+
229
+ export type LobbyData = typeof lobbyData;
@@ -0,0 +1,19 @@
1
+ // src/components/lib/templates/saas-hotel/index.ts
2
+ // Hotel SaaS template ("Lobby · Hotel OS"): marketing landing, sign-in and a complete app
3
+ // (dashboard, reservations, rooms, guests, reports, settings) built from library components.
4
+ //
5
+ // import { DashboardPage } from 'astro-component-kit/templates/saas-hotel';
6
+ // <DashboardPage theme="light" />
7
+
8
+ export { default as AppLayout } from './AppLayout.astro';
9
+ export { default as LandingPage } from './LandingPage.astro';
10
+ export { default as SignInPage } from './SignInPage.astro';
11
+ export { default as DashboardPage } from './DashboardPage.astro';
12
+ export { default as ReservationsPage } from './ReservationsPage.astro';
13
+ export { default as RoomsPage } from './RoomsPage.astro';
14
+ export { default as GuestsPage } from './GuestsPage.astro';
15
+ export { default as ReportsPage } from './ReportsPage.astro';
16
+ export { default as SettingsPage } from './SettingsPage.astro';
17
+
18
+ export { lobbyData, saasRoutes } from './data';
19
+ export type { LobbyData, SaasRoutes } from './data';
@@ -0,0 +1,90 @@
1
+ /* Lobby · Hotel OS — theme tokens shared by the landing, sign-in and app pages. */
2
+ .theme-lobby {
3
+ --r-sm: 8px;
4
+ --r-md: 10px;
5
+ --r-lg: 14px;
6
+ --r-xl: 18px;
7
+ }
8
+ .theme-lobby[data-theme='light'] {
9
+ --c-bg: #f4f6fa;
10
+ --c-bg-1: #ffffff;
11
+ --c-bg-2: #eef1f6;
12
+ --c-surface: rgba(15, 23, 42, 0.025);
13
+ --c-border: rgba(15, 23, 42, 0.1);
14
+ --c-text-1: #0f172a;
15
+ --c-text-2: #475569;
16
+ --c-text-3: #64748b;
17
+ --c-primary: #2557d6;
18
+ --c-primary-light: #2557d6;
19
+ --c-primary-glow: rgba(37, 87, 214, 0.14);
20
+ --c-accent: #1e40af;
21
+ --app-accent: #2557d6;
22
+ --c-on-primary: #ffffff;
23
+ --ink-rgb: 15 23 42;
24
+ --paper-rgb: 255 255 255;
25
+ --c-success: #047857;
26
+ --c-warning: #a16207;
27
+ --c-danger: #b91c1c;
28
+ --chart-surface: #ffffff;
29
+ --chart-grid: rgba(15, 23, 42, 0.08);
30
+ --chart-axis: rgba(15, 23, 42, 0.22);
31
+ color-scheme: light;
32
+ }
33
+ .theme-lobby[data-theme='dark'] {
34
+ --c-bg: #0b0f17;
35
+ --c-bg-1: #111827;
36
+ --c-bg-2: #1a2232;
37
+ --c-surface: rgba(148, 163, 184, 0.04);
38
+ --c-border: rgba(148, 163, 184, 0.16);
39
+ --c-text-1: #f1f5f9;
40
+ --c-text-2: #a9b3c4;
41
+ --c-text-3: #8a96aa;
42
+ --c-primary: #7aa2ff;
43
+ --c-primary-light: #7aa2ff;
44
+ --c-primary-glow: rgba(122, 162, 255, 0.16);
45
+ --c-accent: #c7d7ff;
46
+ --app-accent: #7aa2ff;
47
+ --c-on-primary: #0b1020;
48
+ --ink-rgb: 241 245 249;
49
+ --paper-rgb: 11 15 23;
50
+ --c-success: #4ade80;
51
+ --c-warning: #fbbf24;
52
+ --c-danger: #f87171;
53
+ --chart-surface: #111827;
54
+ --chart-grid: rgba(148, 163, 184, 0.12);
55
+ --chart-axis: rgba(148, 163, 184, 0.3);
56
+ color-scheme: dark;
57
+ }
58
+ body.lobby { background: var(--c-bg); color: var(--c-text-2); }
59
+ body.lobby--site { overflow-x: clip; }
60
+ body.lobby::before { display: none; }
61
+ .lobby__skip { position: fixed; top: -60px; left: 12px; z-index: 2000; padding: 0.6rem 1rem; border-radius: 10px; background: var(--app-accent); color: var(--c-on-primary); font-weight: 700; }
62
+ .lobby__skip:focus { top: 12px; color: var(--c-on-primary); }
63
+ .lobby__shell { display: grid; grid-template-columns: auto minmax(0, 1fr); min-height: 100dvh; }
64
+ .lobby__main { min-width: 0; display: flex; flex-direction: column; }
65
+ .lobby__content { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--sp-5); padding: var(--sp-6) clamp(1rem, 3vw, 2rem) var(--sp-12); outline: none; min-width: 0; }
66
+ .lobby-grid { display: grid; gap: var(--sp-5); min-width: 0; }
67
+ .lobby-grid--kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
68
+ .lobby-grid--2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
69
+ .lobby-grid--1-1 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
70
+ .lobby-grid--1-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
71
+ .lobby-grid > * { min-width: 0; }
72
+ /* Charts sit on solid app cards */
73
+ .lobby .cf--glass { backdrop-filter: none; background: var(--c-bg-1); }
74
+ .lobby .cf, .lobby .kpi { border-radius: var(--r-lg); }
75
+ @media (max-width: 1200px) {
76
+ .lobby-grid--kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
77
+ .lobby-grid--2-1, .lobby-grid--1-2 { grid-template-columns: 1fr; }
78
+ }
79
+ @media (max-width: 720px) {
80
+ .lobby-grid--kpis, .lobby-grid--1-1 { grid-template-columns: 1fr; }
81
+ }
82
+
83
+ /* App cards used by template pages */
84
+ .lobby-card { padding: var(--sp-5); border-radius: var(--r-lg); border: 1px solid var(--c-border); background: var(--c-bg-1); min-width: 0; }
85
+ .lobby-card__title { margin: 0 0 var(--sp-4); font-size: 1rem; font-weight: 700; color: var(--c-text-1); }
86
+ .lobby .status-feed { max-width: none; }
87
+ .lobby .status-feed__line { background: var(--c-border); }
88
+ .lobby .anim-input, .lobby .custom-select { background: var(--c-bg); border-color: var(--c-border); border-radius: var(--r-md); }
89
+ .lobby .anim-input:focus, .lobby .custom-select:focus { border-color: var(--app-accent); box-shadow: 0 0 0 3px var(--c-primary-glow); background: var(--c-bg); }
90
+ .lobby .anim-input:focus ~ .anim-input-label, .lobby .anim-input:not(:placeholder-shown) ~ .anim-input-label { color: var(--app-accent); }
@@ -64,11 +64,54 @@
64
64
  --r-xl: 28px;
65
65
  --r-full: 9999px;
66
66
 
67
+ /* Theme helpers (used by e-commerce components and templates) */
68
+ --ink-rgb: 255 255 255; /* foreground for translucent lines/fills */
69
+ --paper-rgb: 5 5 5; /* background for translucent surfaces */
70
+ --c-on-primary: #050505; /* text on primary (gold) buttons */
71
+ --c-success: #34d399;
72
+ --c-danger: #f87171;
73
+ --c-warning: #fbbf24;
74
+ color-scheme: dark;
75
+
67
76
  /* Sidebar */
68
77
  --sidebar-w: 280px;
69
78
  --header-h: 85px;
70
79
  }
71
80
 
81
+ /* ── Light theme (opt-in: <html data-theme="light">) ──────── */
82
+ [data-theme='light'] {
83
+ --c-bg: #f6f5f2;
84
+ --c-bg-1: #ffffff;
85
+ --c-bg-2: #ecebe6;
86
+ --c-surface: rgba(17,17,17,0.025);
87
+ --c-border: rgba(17,17,17,0.09);
88
+
89
+ --c-primary: #8a6500;
90
+ --c-primary-light: #8a6500;
91
+ --c-primary-glow: rgba(138,101,0,0.12);
92
+ --c-accent: #5c4300;
93
+
94
+ --c-text-1: #121212;
95
+ --c-text-2: #4a4a4a;
96
+ --c-text-3: #666666;
97
+
98
+ --ink-rgb: 17 17 17;
99
+ --paper-rgb: 255 255 255;
100
+ --c-on-primary: #ffffff;
101
+ --c-success: #047857;
102
+ --c-danger: #b91c1c;
103
+ --c-warning: #92400e;
104
+ --pm-ink-s: 65%;
105
+ --pm-ink-l: 36%;
106
+ --pm-soft-s: 35%;
107
+ --pm-soft-l: 82%;
108
+ --pm-soft-a: 0.9;
109
+ --chart-grid: rgba(17,24,39,0.08);
110
+ --chart-axis: rgba(17,24,39,0.22);
111
+ --chart-surface: #ffffff;
112
+ color-scheme: light;
113
+ }
114
+
72
115
  /* ── Base ────────────────────────────────────────────────── */
73
116
  html {
74
117
  font-family: var(--font-sans);
@@ -157,3 +200,55 @@ body::before {
157
200
  .anim-delay-1 { animation-delay: 0.1s; }
158
201
  .anim-delay-2 { animation-delay: 0.2s; }
159
202
  .anim-delay-3 { animation-delay: 0.3s; }
203
+
204
+ /* ── Site header: keep every nav link on one line on tablets / small laptops ── */
205
+ @media (min-width: 769px) and (max-width: 1180px) {
206
+ #site-nav a { padding-inline: 0.55rem; font-size: 0.82rem; }
207
+ #site-nav .gh-link { font-size: 0; gap: 0; }
208
+ #site-nav .gh-link svg { width: 18px; height: 18px; }
209
+ }
210
+ @media (min-width: 769px) and (max-width: 960px) {
211
+ header .docs-header__brand .brand-logo { height: 46px; }
212
+ #site-nav { gap: 0; }
213
+ #site-nav a { padding-inline: 0.45rem; font-size: 0.78rem; }
214
+ }
215
+
216
+ /* ── Light theme adapters for shared components ──────────────
217
+ Scoped component styles assume a dark surface; these overrides
218
+ (:root[data-theme='light'] wins on specificity) keep them legible. */
219
+ :root[data-theme='light'] .badge--default { background: rgba(17,17,17,0.06); color: #3f3f3f; border-color: rgba(17,17,17,0.12); }
220
+ :root[data-theme='light'] .badge--success { background: rgba(4,120,87,0.1); color: #047857; border-color: rgba(4,120,87,0.25); }
221
+ :root[data-theme='light'] .badge--warning { background: rgba(146,64,14,0.1); color: #92400e; border-color: rgba(146,64,14,0.25); }
222
+ :root[data-theme='light'] .badge--danger { background: rgba(185,28,28,0.08); color: #b91c1c; border-color: rgba(185,28,28,0.22); }
223
+ :root[data-theme='light'] .badge--info { background: rgba(29,78,216,0.08); color: #1d4ed8; border-color: rgba(29,78,216,0.22); }
224
+
225
+ :root[data-theme='light'] .cns--glass .cns__box { background: #fff; border-color: rgba(17,17,17,0.08); box-shadow: 0 30px 60px -40px rgba(17,17,17,0.35); }
226
+ :root[data-theme='light'] .cns__icon { background: rgba(17,17,17,0.04); border-color: rgba(17,17,17,0.08); }
227
+ :root[data-theme='light'] .cns__input { background: #fff; border-color: rgba(17,17,17,0.18); }
228
+ :root[data-theme='light'] .cns__btn { background: #121212; color: #fff; }
229
+ :root[data-theme='light'] .cns__btn:hover { background: var(--c-primary); }
230
+ :root[data-theme='light'] .cns__perks svg { color: #047857; }
231
+
232
+ :root[data-theme='light'] .fms { background: var(--c-bg-1); border-top-color: rgba(17,17,17,0.08); }
233
+ :root[data-theme='light'] .fms__top { border-bottom-color: rgba(17,17,17,0.08); }
234
+ :root[data-theme='light'] .fms__news-field { background: #fff; border-color: rgba(17,17,17,0.16); }
235
+ :root[data-theme='light'] .fms__news-field button { background: rgba(17,17,17,0.05); }
236
+ :root[data-theme='light'] .fms__news-field button:hover { color: #fff; }
237
+ :root[data-theme='light'] .fms__status { border-color: rgba(17,17,17,0.1); }
238
+
239
+ :root[data-theme='light'] .logo-badge { background: #fff; border-color: rgba(17,17,17,0.08); }
240
+ :root[data-theme='light'] .step-nav__line { background: rgba(17,17,17,0.1); }
241
+
242
+ :root[data-theme='light'] .anim-input,
243
+ :root[data-theme='light'] .custom-select,
244
+ :root[data-theme='light'] .stepper { background: #fff; border-color: rgba(17,17,17,0.14); }
245
+ :root[data-theme='light'] .radio-circle { border-color: rgba(17,17,17,0.3); background: #fff; }
246
+
247
+ :root[data-theme='light'] .step-nav__circle { background: #fff; border-color: rgba(17,17,17,0.18); }
248
+ :root[data-theme='light'] .step-nav__item--complete .step-nav__circle { background: rgba(4,120,87,0.1); border-color: #047857; color: #047857; }
249
+ :root[data-theme='light'] .step-nav__item--active .step-nav__circle { color: #fff; background: var(--c-primary); border-color: var(--c-primary); box-shadow: none; }
250
+ :root[data-theme='light'] .status-feed__line { background: rgba(17,24,39,0.1); }
251
+ :root[data-theme='light'] .status-feed__bullet { background: var(--c-bg-1); border-color: rgba(17,24,39,0.16); }
252
+ :root[data-theme='light'] .status-feed__item--done .status-feed__bullet { background: rgba(4,120,87,0.1); border-color: #047857; color: #047857; }
253
+ :root[data-theme='light'] .status-feed__item--active .status-feed__bullet { background: var(--c-primary-glow); border-color: var(--c-primary-light); color: var(--c-primary-light); box-shadow: none; }
254
+ :root[data-theme='light'] .status-feed__content { background: var(--c-bg-1); border-color: rgba(17,24,39,0.08); }