astro-component-kit 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -27
- package/bin/cli.js +67 -0
- package/bin/installer.js +179 -0
- package/package.json +35 -5
- package/src/components/index.ts +2 -0
- package/src/components/lib/Galaxy3D.astro +249 -137
- package/src/components/lib/app/AppSidebar.astro +249 -0
- package/src/components/lib/app/AppTopbar.astro +284 -0
- package/src/components/lib/app/ArrivalsBoard.astro +176 -0
- package/src/components/lib/app/AuthCard.astro +213 -0
- package/src/components/lib/app/DataTable.astro +346 -0
- package/src/components/lib/app/GuestProfileCard.astro +133 -0
- package/src/components/lib/app/HousekeepingBoard.astro +189 -0
- package/src/components/lib/app/PageHeader.astro +157 -0
- package/src/components/lib/app/PlanUsageCard.astro +112 -0
- package/src/components/lib/app/RoomRack.astro +207 -0
- package/src/components/lib/app/SettingsSection.astro +96 -0
- package/src/components/lib/app/SwitchRow.astro +71 -0
- package/src/components/lib/app/TeamMembers.astro +190 -0
- package/src/components/lib/app/app-icons.ts +52 -0
- package/src/components/lib/app/index.ts +19 -0
- package/src/components/lib/charts/AreaChart.astro +4 -4
- package/src/components/lib/charts/BarChart.astro +3 -3
- package/src/components/lib/charts/ChartFrame.astro +10 -10
- package/src/components/lib/charts/DonutChart.astro +2 -2
- package/src/components/lib/charts/DumbbellChart.astro +1 -1
- package/src/components/lib/charts/ForecastLineChart.astro +1 -1
- package/src/components/lib/charts/GaugeChart.astro +1 -1
- package/src/components/lib/charts/HeatmapChart.astro +1 -1
- package/src/components/lib/charts/HorizontalBarChart.astro +2 -2
- package/src/components/lib/charts/KpiStatTile.astro +4 -4
- package/src/components/lib/charts/LinearProgressGauge.astro +4 -4
- package/src/components/lib/charts/MetricDeltaTable.astro +3 -3
- package/src/components/lib/charts/RadarMetricChart.astro +4 -4
- package/src/components/lib/charts/RadialBarChart.astro +1 -1
- package/src/components/lib/charts/RetentionCohortTable.astro +2 -2
- package/src/components/lib/charts/TreemapChart.astro +1 -1
- package/src/components/lib/ecommerce/CartDrawer.astro +483 -0
- package/src/components/lib/ecommerce/CartPageList.astro +290 -0
- package/src/components/lib/ecommerce/CartToast.astro +276 -0
- package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
- package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
- package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
- package/src/components/lib/ecommerce/FilterBar.astro +278 -0
- package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
- package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
- package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
- package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
- package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
- package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
- package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
- package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
- package/src/components/lib/ecommerce/ProductRating.astro +78 -0
- package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
- package/src/components/lib/ecommerce/PromoBar.astro +145 -0
- package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
- package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
- package/src/components/lib/ecommerce/StoreHero.astro +260 -0
- package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
- package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
- package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
- package/src/components/lib/ecommerce/cart-store.ts +151 -0
- package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
- package/src/components/lib/ecommerce/index.ts +34 -0
- package/src/components/lib/ecommerce/product-icons.ts +28 -0
- package/src/components/lib/ecommerce/types.ts +70 -0
- package/src/components/lib/forms/AnimatedInput.astro +4 -2
- package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
- package/src/components/lib/index.ts +2 -0
- package/src/components/lib/layout/BentoGrid3.astro +6 -4
- package/src/components/lib/layout/CenterFixedBox.astro +2 -2
- package/src/components/lib/layout/CenteredContainer.astro +4 -2
- package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
- package/src/components/lib/layout/FeatureHero.astro +4 -2
- package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
- package/src/components/lib/layout/FullBleedSection.astro +2 -2
- package/src/components/lib/layout/GalleryGrid4.astro +2 -2
- package/src/components/lib/layout/HolyGrailGrid.astro +11 -9
- package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
- package/src/components/lib/layout/MasonryGrid.astro +2 -2
- package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
- package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
- package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
- package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
- package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
- package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
- package/src/components/lib/sections/AgencyContactBrief.astro +194 -0
- package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
- package/src/components/lib/sections/AgencyHeader.astro +161 -0
- package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
- package/src/components/lib/sections/AgencyServicesList.astro +113 -0
- package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
- package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
- package/src/components/lib/sections/BlogGridSection.astro +9 -7
- package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
- package/src/components/lib/sections/CardsShowcase.astro +28 -26
- package/src/components/lib/sections/CareersOpenings.astro +10 -8
- package/src/components/lib/sections/ChangelogSection.astro +20 -7
- package/src/components/lib/sections/ContactGlassForm.astro +10 -8
- package/src/components/lib/sections/ContactSplitMap.astro +11 -9
- package/src/components/lib/sections/CtaAppDownload.astro +13 -11
- package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
- package/src/components/lib/sections/CtaNewsletterSection.astro +13 -11
- package/src/components/lib/sections/CtaSplitImage.astro +13 -11
- package/src/components/lib/sections/DataShowcase.astro +23 -21
- package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
- package/src/components/lib/sections/FaqTwoColumn.astro +9 -7
- package/src/components/lib/sections/FeatureAlternatingRows.astro +10 -8
- package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
- package/src/components/lib/sections/FeatureIconGrid.astro +6 -6
- package/src/components/lib/sections/FeatureTabsShowcase.astro +13 -11
- package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
- package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
- package/src/components/lib/sections/FooterMegaSection.astro +13 -11
- package/src/components/lib/sections/FormsShowcase.astro +22 -20
- package/src/components/lib/sections/HeroDashboardPreview.astro +11 -9
- package/src/components/lib/sections/HeroGlass.astro +22 -20
- package/src/components/lib/sections/HeroGradient.astro +15 -13
- package/src/components/lib/sections/HeroMinimalCentered.astro +10 -10
- package/src/components/lib/sections/HeroShowcaseSplit.astro +18 -16
- package/src/components/lib/sections/HeroSplit.astro +13 -11
- package/src/components/lib/sections/HeroTerminal.astro +14 -12
- package/src/components/lib/sections/HeroWaitlist.astro +10 -8
- package/src/components/lib/sections/HowItWorksSteps.astro +12 -10
- package/src/components/lib/sections/IntegrationsGrid.astro +7 -7
- package/src/components/lib/sections/LayoutShowcase.astro +21 -19
- package/src/components/lib/sections/LogoCloudSection.astro +4 -4
- package/src/components/lib/sections/LogoWallGrid.astro +6 -4
- package/src/components/lib/sections/NavigationShowcase.astro +15 -13
- package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
- package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
- package/src/components/lib/sections/PricingSinglePlan.astro +13 -11
- package/src/components/lib/sections/PricingTierCards.astro +11 -9
- package/src/components/lib/sections/PricingToggleCards.astro +13 -13
- package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
- package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
- package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
- package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
- package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
- package/src/components/lib/sections/ShopLookbook.astro +250 -0
- package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
- package/src/components/lib/sections/ShopProductRail.astro +150 -0
- package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
- package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
- package/src/components/lib/sections/StatsCounterBand.astro +9 -7
- package/src/components/lib/sections/StatsDashboardSection.astro +4 -2
- package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
- package/src/components/lib/sections/TeamGridSection.astro +12 -10
- package/src/components/lib/sections/TestimonialCarousel.astro +10 -8
- package/src/components/lib/sections/TestimonialFeatured.astro +7 -5
- package/src/components/lib/sections/TestimonialGridSection.astro +7 -7
- package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
- package/src/components/lib/sections/TypographyShowcase.astro +10 -8
- package/src/components/lib/sections/index.ts +10 -0
- package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
- package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
- package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
- package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
- package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
- package/src/components/lib/templates/ecommerce/data.ts +187 -0
- package/src/components/lib/templates/ecommerce/index.ts +14 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
- package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
- package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
- package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
- package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
- package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
- package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
- package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
- package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
- package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
- package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
- package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
- package/src/components/lib/templates/saas-hotel/data.ts +229 -0
- package/src/components/lib/templates/saas-hotel/index.ts +19 -0
- package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -0
- package/src/data/registry/app.ts +93 -0
- package/src/data/registry/buttons.ts +3279 -0
- package/src/data/registry/cards.ts +1753 -0
- package/src/data/registry/charts-svg.ts +557 -0
- package/src/data/registry/charts.ts +500 -0
- package/src/data/registry/data.ts +986 -0
- package/src/data/registry/ecommerce.ts +269 -0
- package/src/data/registry/feedback.ts +1824 -0
- package/src/data/registry/forms.ts +2513 -0
- package/src/data/registry/index.ts +64 -0
- package/src/data/registry/layout.ts +206 -0
- package/src/data/registry/navigation.ts +936 -0
- package/src/data/registry/overlays.ts +1133 -0
- package/src/data/registry/sections-extra.ts +397 -0
- package/src/data/registry/sections.ts +361 -0
- package/src/data/registry/sources.ts +41 -0
- package/src/data/registry/templates.ts +414 -0
- package/src/data/registry/types.ts +30 -0
- package/src/data/registry/typography.ts +777 -0
- package/src/mcp/http-server.ts +324 -0
- package/src/mcp/index.ts +67 -0
- package/src/mcp/installer.ts +178 -0
- package/src/mcp/registry-adapter.ts +278 -0
- package/src/mcp/stdio-server.ts +11 -0
- package/src/mcp/tools.ts +247 -0
- package/src/mcp/types.ts +53 -0
- package/src/styles/global.css +95 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* ShopProductRail — Horizontal, scroll-snapping product carousel of ProductCardMinimal cards with
|
|
4
|
+
* numbered items, prev/next buttons and a progress line.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} eyebrow - Small label. Default 'Just in'.
|
|
7
|
+
* @param {string} title - Heading. Default 'New this *week*'.
|
|
8
|
+
* @param {Product[]} products - Products to show.
|
|
9
|
+
* @param {string} productBase - Product URL prefix (`${productBase}${slug}/`). Default '#'.
|
|
10
|
+
* @param {{label: string, href: string}} link - "View all" link (optional).
|
|
11
|
+
* @param {boolean} numbered - Show "N° 01" on cards. Default true.
|
|
12
|
+
* @param {string} currency - ISO currency. Default 'EUR'.
|
|
13
|
+
* @param {string} locale - Number format locale. Default 'en-GB'.
|
|
14
|
+
* @param {string} cartKey - Cart storage key. Default 'ack-cart'.
|
|
15
|
+
* @param {string} id - Rail id (unique per page). Default 'product-rail'.
|
|
16
|
+
* @param {string} size - Card width (sm|md|lg). Default 'md'.
|
|
17
|
+
* @param {string} className - Extra class.
|
|
18
|
+
*
|
|
19
|
+
* Accessibility: the rail is a labelled region (role="region") scrollable with keyboard;
|
|
20
|
+
* buttons have labels and disable at the ends; snapping is disabled with reduced motion.
|
|
21
|
+
*/
|
|
22
|
+
import ProductCardMinimal from '../ecommerce/ProductCardMinimal.astro';
|
|
23
|
+
import type { Product } from '../ecommerce/types';
|
|
24
|
+
|
|
25
|
+
interface Props {
|
|
26
|
+
eyebrow?: string;
|
|
27
|
+
title?: string;
|
|
28
|
+
products?: Product[];
|
|
29
|
+
productBase?: string;
|
|
30
|
+
link?: { label: string; href: string };
|
|
31
|
+
numbered?: boolean;
|
|
32
|
+
currency?: string;
|
|
33
|
+
locale?: string;
|
|
34
|
+
cartKey?: string;
|
|
35
|
+
id?: string;
|
|
36
|
+
size?: 'sm' | 'md' | 'lg';
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
eyebrow = 'Just in',
|
|
42
|
+
title = 'New this *week*',
|
|
43
|
+
products = [
|
|
44
|
+
{ slug: 'linen-overshirt', name: 'Linen Overshirt', price: 145, category: 'clothing', badge: 'New', sizes: ['S', 'M', 'L'], colors: [{ name: 'Oat', hex: '#d9cbb3' }, { name: 'Ink', hex: '#22252b' }], icon: 'shirt', hue: 30 },
|
|
45
|
+
{ slug: 'merino-crew', name: 'Merino Crew Knit', price: 160, category: 'clothing', sizes: ['S', 'M', 'L'], colors: [{ name: 'Sage', hex: '#8a9a7b' }], icon: 'jacket', hue: 95 },
|
|
46
|
+
{ slug: 'field-tote', name: 'Field Tote', price: 120, category: 'bags', colors: [{ name: 'Rust', hex: '#9c3d1c' }], icon: 'bag', hue: 18 },
|
|
47
|
+
{ slug: 'ash-vase', name: 'Ash Vase', price: 68, category: 'objects', icon: 'bottle', hue: 40 },
|
|
48
|
+
{ slug: 'dune-loafer', name: 'Dune Loafer', price: 210, category: 'shoes', sizes: ['39', '40', '41', '42'], icon: 'sneaker', hue: 28 },
|
|
49
|
+
],
|
|
50
|
+
productBase = '#',
|
|
51
|
+
link = { label: 'View all', href: '#' },
|
|
52
|
+
numbered = true,
|
|
53
|
+
currency = 'EUR',
|
|
54
|
+
locale = 'en-GB',
|
|
55
|
+
cartKey = 'ack-cart',
|
|
56
|
+
id = 'product-rail',
|
|
57
|
+
size = 'md',
|
|
58
|
+
className = '',
|
|
59
|
+
} = Astro.props;
|
|
60
|
+
|
|
61
|
+
const parts = title.split(/\*(.+?)\*/g);
|
|
62
|
+
const plainTitle = title.replace(/\*/g, '');
|
|
63
|
+
const hrefFor = (slug: string) => (productBase === '#' ? '#' : `${productBase}${slug}/`);
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
<section class:list={['spr', `spr--${size}`, className]} data-rail>
|
|
67
|
+
<header class="spr__head">
|
|
68
|
+
<div>
|
|
69
|
+
{eyebrow && <p class="spr__eyebrow">{eyebrow}</p>}
|
|
70
|
+
<h2 class="spr__title">{parts.map((p, i) => (i % 2 ? <em>{p}</em> : p))}</h2>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="spr__controls">
|
|
73
|
+
{link && <a class="spr__all" href={link.href}>{link.label}</a>}
|
|
74
|
+
<button type="button" class="spr__arrow" aria-label="Previous products" aria-controls={id} data-prev>←</button>
|
|
75
|
+
<button type="button" class="spr__arrow" aria-label="Next products" aria-controls={id} data-next>→</button>
|
|
76
|
+
</div>
|
|
77
|
+
</header>
|
|
78
|
+
<ul class="spr__track" id={id} role="region" aria-label={plainTitle} tabindex="0" data-track>
|
|
79
|
+
{products.map((p, i) => (
|
|
80
|
+
<li class="spr__slide">
|
|
81
|
+
<ProductCardMinimal product={p} href={hrefFor(p.slug)} index={numbered ? i + 1 : undefined} currency={currency} locale={locale} cartKey={cartKey} />
|
|
82
|
+
</li>
|
|
83
|
+
))}
|
|
84
|
+
</ul>
|
|
85
|
+
<div class="spr__progress" aria-hidden="true"><span data-progress></span></div>
|
|
86
|
+
</section>
|
|
87
|
+
|
|
88
|
+
<script>
|
|
89
|
+
document.querySelectorAll<HTMLElement>('[data-rail]:not([data-bound])').forEach((rail) => {
|
|
90
|
+
rail.dataset.bound = '';
|
|
91
|
+
const track = rail.querySelector<HTMLElement>('[data-track]')!;
|
|
92
|
+
const prev = rail.querySelector<HTMLButtonElement>('[data-prev]')!;
|
|
93
|
+
const next = rail.querySelector<HTMLButtonElement>('[data-next]')!;
|
|
94
|
+
const bar = rail.querySelector<HTMLElement>('[data-progress]')!;
|
|
95
|
+
const step = () => (track.querySelector<HTMLElement>('.spr__slide')?.offsetWidth ?? 300) + 16;
|
|
96
|
+
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
97
|
+
const update = () => {
|
|
98
|
+
const max = track.scrollWidth - track.clientWidth;
|
|
99
|
+
prev.disabled = track.scrollLeft <= 2;
|
|
100
|
+
next.disabled = track.scrollLeft >= max - 2;
|
|
101
|
+
const visible = track.clientWidth / track.scrollWidth;
|
|
102
|
+
bar.style.width = `${Math.max(10, visible * 100)}%`;
|
|
103
|
+
bar.style.transform = `translateX(${max > 0 ? (track.scrollLeft / max) * ((1 / Math.max(visible, 0.1)) - 1) * 100 : 0}%)`;
|
|
104
|
+
};
|
|
105
|
+
prev.addEventListener('click', () => track.scrollBy({ left: -step(), behavior: reduced ? 'auto' : 'smooth' }));
|
|
106
|
+
next.addEventListener('click', () => track.scrollBy({ left: step(), behavior: reduced ? 'auto' : 'smooth' }));
|
|
107
|
+
track.addEventListener('scroll', update, { passive: true });
|
|
108
|
+
window.addEventListener('resize', update);
|
|
109
|
+
update();
|
|
110
|
+
});
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<style>
|
|
114
|
+
.spr { container-type: inline-size; --slide-w: clamp(220px, 24vw, 320px); color: var(--c-text-1, #fff); min-width: 0; }
|
|
115
|
+
.spr--sm { --slide-w: clamp(180px, 18vw, 240px); }
|
|
116
|
+
.spr--lg { --slide-w: clamp(260px, 30vw, 420px); }
|
|
117
|
+
.spr__head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-4, 1rem); margin-bottom: var(--sp-6, 1.5rem); }
|
|
118
|
+
.spr__eyebrow { margin: 0 0 var(--sp-2, 0.5rem); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--c-text-2, #a3a3a3); }
|
|
119
|
+
.spr__title { margin: 0; font-family: var(--font-display, Georgia, 'Times New Roman', serif); font-size: clamp(2rem, 4.5vw, 3.4rem); font-weight: 400; letter-spacing: -0.035em; line-height: 1; }
|
|
120
|
+
.spr__title em { font-style: italic; color: var(--shop-accent, var(--c-primary-light, #d4a017)); }
|
|
121
|
+
.spr__controls { display: flex; align-items: center; gap: var(--sp-2, 0.5rem); }
|
|
122
|
+
.spr__all { margin-right: var(--sp-3, 0.75rem); min-height: 44px; display: inline-flex; align-items: center; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: inherit; text-decoration: underline; text-underline-offset: 5px; }
|
|
123
|
+
.spr__arrow { width: 48px; height: 48px; border: 1px solid var(--c-border, rgba(255, 255, 255, 0.15)); border-radius: 50%; background: transparent; color: inherit; font-size: 1.1rem; cursor: pointer; transition: background 0.2s ease, color 0.2s ease, opacity 0.2s ease; }
|
|
124
|
+
.spr__arrow:hover:not(:disabled) { background: var(--c-text-1, #fff); color: var(--c-bg, #050505); }
|
|
125
|
+
.spr__arrow:disabled { opacity: 0.3; cursor: default; }
|
|
126
|
+
.spr :is(a, button):focus-visible, .spr__track:focus-visible { outline: 2px solid var(--shop-accent, var(--c-primary-light, #d4a017)); outline-offset: 3px; }
|
|
127
|
+
|
|
128
|
+
.spr__track {
|
|
129
|
+
display: grid;
|
|
130
|
+
grid-auto-flow: column;
|
|
131
|
+
grid-auto-columns: var(--slide-w);
|
|
132
|
+
gap: 16px;
|
|
133
|
+
margin: 0;
|
|
134
|
+
padding: 0 0 var(--sp-2, 0.5rem);
|
|
135
|
+
list-style: none;
|
|
136
|
+
overflow-x: auto;
|
|
137
|
+
scroll-snap-type: x mandatory;
|
|
138
|
+
scrollbar-width: none;
|
|
139
|
+
}
|
|
140
|
+
.spr__track::-webkit-scrollbar { display: none; }
|
|
141
|
+
.spr__slide { scroll-snap-align: start; min-width: 0; }
|
|
142
|
+
.spr__progress { position: relative; height: 1px; margin-top: var(--sp-5, 1.25rem); background: var(--c-border, rgba(255, 255, 255, 0.15)); overflow: hidden; }
|
|
143
|
+
.spr__progress span { position: absolute; inset: 0 auto 0 0; height: 100%; background: var(--c-text-1, #fff); transition: transform 0.15s linear; }
|
|
144
|
+
|
|
145
|
+
@container (max-width: 640px) {
|
|
146
|
+
.spr__track { grid-auto-columns: 72%; }
|
|
147
|
+
.spr__arrow, .spr__all { display: none; }
|
|
148
|
+
}
|
|
149
|
+
@media (prefers-reduced-motion: reduce) { .spr__track { scroll-snap-type: none; } }
|
|
150
|
+
</style>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* ShopReviewsEditorial — Customer voices as one large serif quote at a time, with product
|
|
4
|
+
* context, star rating, numbered pager and an overall score.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} eyebrow - Small label. Default 'Customer notes'.
|
|
7
|
+
* @param {number} score - Average rating shown on the side. Default 4.9.
|
|
8
|
+
* @param {number} count - Total reviews. Default 1284.
|
|
9
|
+
* @param {Array<{quote: string, name: string, place?: string, product?: string, rating?: number}>} reviews - Quotes.
|
|
10
|
+
* @param {number} interval - Auto-advance in ms (0 = manual only). Default 7000.
|
|
11
|
+
* @param {string} variant - Style (plain|boxed). Default 'plain'.
|
|
12
|
+
* @param {string} className - Extra class.
|
|
13
|
+
*
|
|
14
|
+
* Accessibility: a labelled carousel region; slides are figures with figcaption; auto-advance
|
|
15
|
+
* pauses on hover/focus, is off with reduced motion, and pager buttons use aria-current.
|
|
16
|
+
*/
|
|
17
|
+
import ProductRating from '../ecommerce/ProductRating.astro';
|
|
18
|
+
|
|
19
|
+
interface Review { quote: string; name: string; place?: string; product?: string; rating?: number }
|
|
20
|
+
interface Props {
|
|
21
|
+
eyebrow?: string;
|
|
22
|
+
score?: number;
|
|
23
|
+
count?: number;
|
|
24
|
+
reviews?: Review[];
|
|
25
|
+
interval?: number;
|
|
26
|
+
variant?: 'plain' | 'boxed';
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
eyebrow = 'Customer notes',
|
|
32
|
+
score = 4.9,
|
|
33
|
+
count = 1284,
|
|
34
|
+
reviews = [
|
|
35
|
+
{ quote: 'The overshirt has been washed forty times and it only gets softer. It is the first thing I reach for.', name: 'Inés M.', place: 'Valencia', product: 'Linen Overshirt', rating: 5 },
|
|
36
|
+
{ quote: 'Packaging without plastic, a handwritten note, and a mug that feels made for my hands.', name: 'Jonas P.', place: 'Hamburg', product: 'Kiln Mug', rating: 5 },
|
|
37
|
+
{ quote: 'They repaired the strap of my tote for free, two years after I bought it. That is rare.', name: 'Amira S.', place: 'Lyon', product: 'Field Tote', rating: 5 },
|
|
38
|
+
],
|
|
39
|
+
interval = 7000,
|
|
40
|
+
variant = 'plain',
|
|
41
|
+
className = '',
|
|
42
|
+
} = Astro.props;
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<div class="sre-cq">
|
|
46
|
+
<section class:list={['sre', `sre--${variant}`, className]} aria-roledescription="carousel" aria-label={eyebrow} data-reviews data-interval={interval}>
|
|
47
|
+
<div class="sre__side">
|
|
48
|
+
<p class="sre__eyebrow">{eyebrow}</p>
|
|
49
|
+
<p class="sre__score">{score.toFixed(1)}<span>/5</span></p>
|
|
50
|
+
<ProductRating value={score} count={count} showValue={false} size="md" />
|
|
51
|
+
</div>
|
|
52
|
+
<div class="sre__main">
|
|
53
|
+
<div class="sre__slides">
|
|
54
|
+
{reviews.map((r, i) => (
|
|
55
|
+
<figure class:list={['sre__slide', { 'is-active': i === 0 }]} hidden={i !== 0} aria-roledescription="slide" aria-label={`${i + 1} of ${reviews.length}`} data-slide>
|
|
56
|
+
<blockquote class="sre__quote"><p>“{r.quote}”</p></blockquote>
|
|
57
|
+
<figcaption class="sre__by">
|
|
58
|
+
<strong>{r.name}</strong>{r.place && <span>, {r.place}</span>}
|
|
59
|
+
{r.product && <span class="sre__product">on {r.product}</span>}
|
|
60
|
+
</figcaption>
|
|
61
|
+
</figure>
|
|
62
|
+
))}
|
|
63
|
+
</div>
|
|
64
|
+
{reviews.length > 1 && (
|
|
65
|
+
<div class="sre__pager" role="group" aria-label="Choose a review">
|
|
66
|
+
{reviews.map((_, i) => (
|
|
67
|
+
<button type="button" class="sre__page" aria-label={`Review ${i + 1}`} aria-current={i === 0 ? 'true' : undefined} data-page={i}>{String(i + 1).padStart(2, '0')}</button>
|
|
68
|
+
))}
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
</section>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<script>
|
|
76
|
+
document.querySelectorAll<HTMLElement>('[data-reviews]:not([data-bound])').forEach((root) => {
|
|
77
|
+
root.dataset.bound = '';
|
|
78
|
+
const slides = Array.from(root.querySelectorAll<HTMLElement>('[data-slide]'));
|
|
79
|
+
const pages = Array.from(root.querySelectorAll<HTMLButtonElement>('[data-page]'));
|
|
80
|
+
let index = 0;
|
|
81
|
+
let paused = false;
|
|
82
|
+
const go = (i: number) => {
|
|
83
|
+
index = (i + slides.length) % slides.length;
|
|
84
|
+
slides.forEach((s, n) => { s.hidden = n !== index; s.classList.toggle('is-active', n === index); });
|
|
85
|
+
pages.forEach((p, n) => { if (n === index) p.setAttribute('aria-current', 'true'); else p.removeAttribute('aria-current'); });
|
|
86
|
+
};
|
|
87
|
+
pages.forEach((p, i) => p.addEventListener('click', () => go(i)));
|
|
88
|
+
root.addEventListener('mouseenter', () => { paused = true; });
|
|
89
|
+
root.addEventListener('mouseleave', () => { paused = false; });
|
|
90
|
+
root.addEventListener('focusin', () => { paused = true; });
|
|
91
|
+
root.addEventListener('focusout', () => { paused = false; });
|
|
92
|
+
const ms = Number(root.dataset.interval) || 0;
|
|
93
|
+
if (ms > 0 && slides.length > 1 && !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
94
|
+
window.setInterval(() => { if (!paused && !document.hidden) go(index + 1); }, ms);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<style>
|
|
100
|
+
.sre-cq { container-type: inline-size; }
|
|
101
|
+
.sre {
|
|
102
|
+
display: grid;
|
|
103
|
+
grid-template-columns: 240px minmax(0, 1fr);
|
|
104
|
+
gap: clamp(1.5rem, 5vw, 5rem);
|
|
105
|
+
padding-block: clamp(2rem, 5vw, 4rem);
|
|
106
|
+
border-top: 1px solid var(--c-text-1, #fff);
|
|
107
|
+
color: var(--c-text-1, #fff);
|
|
108
|
+
}
|
|
109
|
+
.sre--boxed { padding: clamp(1.5rem, 4vw, 3.5rem); border: 1px solid var(--c-border, rgba(255, 255, 255, 0.12)); background: var(--c-bg-1, #0a0a0a); }
|
|
110
|
+
.sre__eyebrow { margin: 0 0 var(--sp-4, 1rem); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--c-text-2, #a3a3a3); }
|
|
111
|
+
.sre__score { margin: 0 0 var(--sp-2, 0.5rem); font-family: var(--font-display, Georgia, 'Times New Roman', serif); font-size: 4.5rem; line-height: 1; letter-spacing: -0.04em; }
|
|
112
|
+
.sre__score span { font-size: 1.2rem; color: var(--c-text-2, #a3a3a3); }
|
|
113
|
+
.sre__side :global(.p-rating) { --p-rating-star: var(--shop-accent, var(--c-primary-light, #d4a017)); }
|
|
114
|
+
|
|
115
|
+
.sre__slides { display: grid; min-height: 12rem; }
|
|
116
|
+
.sre__slide { grid-area: 1 / 1; margin: 0; }
|
|
117
|
+
.sre__slide[hidden] { display: none; }
|
|
118
|
+
.sre__slide.is-active { animation: sre-in 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
|
|
119
|
+
@keyframes sre-in { from { opacity: 0; transform: translateY(10px); } }
|
|
120
|
+
.sre__quote { margin: 0; }
|
|
121
|
+
.sre__quote p { margin: 0; font-family: var(--font-display, Georgia, 'Times New Roman', serif); font-size: clamp(1.6rem, 3.4vw, 2.8rem); font-weight: 400; font-style: italic; line-height: 1.2; letter-spacing: -0.02em; text-wrap: balance; }
|
|
122
|
+
.sre__by { margin-top: var(--sp-5, 1.25rem); font-size: 0.9rem; }
|
|
123
|
+
.sre__by span { color: var(--c-text-2, #a3a3a3); }
|
|
124
|
+
.sre__product { display: block; margin-top: 2px; font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase; }
|
|
125
|
+
|
|
126
|
+
.sre__pager { display: flex; gap: var(--sp-4, 1rem); margin-top: var(--sp-8, 2rem); }
|
|
127
|
+
.sre__page { min-width: 44px; min-height: 44px; padding: 0; border: 0; border-top: 1px solid var(--c-border, rgba(255, 255, 255, 0.2)); background: none; color: var(--c-text-2, #a3a3a3); font: inherit; font-size: 0.8rem; font-variant-numeric: tabular-nums; text-align: left; cursor: pointer; }
|
|
128
|
+
.sre__page[aria-current='true'] { border-top: 2px solid var(--shop-accent, var(--c-primary-light, #d4a017)); color: var(--c-text-1, #fff); }
|
|
129
|
+
.sre__page:focus-visible { outline: 2px solid var(--shop-accent, var(--c-primary-light, #d4a017)); outline-offset: 3px; }
|
|
130
|
+
|
|
131
|
+
@container (max-width: 760px) { .sre { grid-template-columns: 1fr; } }
|
|
132
|
+
@media (prefers-reduced-motion: reduce) { .sre__slide.is-active { animation: none; } }
|
|
133
|
+
</style>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* ShopValuesMarquee — Brand promise band: an oversized italic marquee followed by numbered
|
|
4
|
+
* value columns (materials, making, after-care…).
|
|
5
|
+
*
|
|
6
|
+
* @param {string[]} words - Marquee words. Empty hides the marquee.
|
|
7
|
+
* @param {Array<{title: string, text: string}>} values - 2–4 value columns.
|
|
8
|
+
* @param {number} speed - Marquee loop duration in seconds. Default 36.
|
|
9
|
+
* @param {string} variant - Style (plain|inverted). Default 'plain'.
|
|
10
|
+
* @param {string} size - Marquee scale (sm|md|lg). Default 'md'.
|
|
11
|
+
* @param {string} className - Extra class.
|
|
12
|
+
*
|
|
13
|
+
* Accessibility: the marquee is decorative (aria-hidden) and pauses on hover and with reduced
|
|
14
|
+
* motion; values are a real list with headings.
|
|
15
|
+
*/
|
|
16
|
+
interface Props {
|
|
17
|
+
words?: string[];
|
|
18
|
+
values?: Array<{ title: string; text: string }>;
|
|
19
|
+
speed?: number;
|
|
20
|
+
variant?: 'plain' | 'inverted';
|
|
21
|
+
size?: 'sm' | 'md' | 'lg';
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
words = ['Made slowly', 'Natural fibres', 'Small workshops', 'Repaired for life'],
|
|
27
|
+
values = [
|
|
28
|
+
{ title: 'Honest materials', text: 'Linen, wool, organic cotton and stoneware — traceable to the mill and the kiln.' },
|
|
29
|
+
{ title: 'Made in small runs', text: 'Each piece is produced in batches of a few hundred, never mass-manufactured.' },
|
|
30
|
+
{ title: 'Kept for years', text: 'Free repairs on everything we make, and a buy-back for pieces you have outgrown.' },
|
|
31
|
+
],
|
|
32
|
+
speed = 36,
|
|
33
|
+
variant = 'plain',
|
|
34
|
+
size = 'md',
|
|
35
|
+
className = '',
|
|
36
|
+
} = Astro.props;
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
<section class:list={['svm', `svm--${variant}`, `svm--${size}`, className]} style={`--svm-speed: ${speed}s`}>
|
|
40
|
+
{words.length > 0 && (
|
|
41
|
+
<div class="svm__marquee" aria-hidden="true">
|
|
42
|
+
<div class="svm__track">
|
|
43
|
+
{[0, 1].map(() => words.map((w) => <span>{w}<i>✺</i></span>))}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
{values.length > 0 && (
|
|
48
|
+
<ol class="svm__values">
|
|
49
|
+
{values.map((v, i) => (
|
|
50
|
+
<li>
|
|
51
|
+
<span class="svm__num" aria-hidden="true">{String(i + 1).padStart(2, '0')}</span>
|
|
52
|
+
<h3>{v.title}</h3>
|
|
53
|
+
<p>{v.text}</p>
|
|
54
|
+
</li>
|
|
55
|
+
))}
|
|
56
|
+
</ol>
|
|
57
|
+
)}
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.svm { container-type: inline-size; --svm-fs: clamp(3rem, 9vw, 7.5rem); color: var(--c-text-1, #fff); overflow: hidden; }
|
|
62
|
+
.svm--sm { --svm-fs: clamp(2rem, 6vw, 4.5rem); }
|
|
63
|
+
.svm--lg { --svm-fs: clamp(4rem, 12vw, 10rem); }
|
|
64
|
+
.svm--inverted { background: var(--c-text-1, #fff); color: var(--c-bg, #050505); }
|
|
65
|
+
.svm__marquee { border-block: 1px solid currentColor; overflow: hidden; }
|
|
66
|
+
.svm__track { display: flex; width: max-content; animation: svm-run var(--svm-speed) linear infinite; }
|
|
67
|
+
.svm:hover .svm__track { animation-play-state: paused; }
|
|
68
|
+
.svm__track span { display: inline-flex; align-items: center; gap: 0.35em; padding: 0.1em 0 0.15em 0.35em; font-family: var(--font-display, Georgia, 'Times New Roman', serif); font-size: var(--svm-fs); font-style: italic; letter-spacing: -0.04em; line-height: 1.05; white-space: nowrap; }
|
|
69
|
+
.svm__track i { font-style: normal; font-size: 0.4em; color: var(--shop-accent, var(--c-primary-light, #d4a017)); }
|
|
70
|
+
@keyframes svm-run { to { transform: translateX(-50%); } }
|
|
71
|
+
|
|
72
|
+
.svm__values {
|
|
73
|
+
display: grid;
|
|
74
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
75
|
+
margin: 0 auto;
|
|
76
|
+
max-width: 1440px;
|
|
77
|
+
padding: clamp(2rem, 5vw, 4rem) clamp(1rem, 3vw, 2.5rem);
|
|
78
|
+
list-style: none;
|
|
79
|
+
gap: 0;
|
|
80
|
+
}
|
|
81
|
+
.svm__values li { padding: 0 var(--sp-6, 1.5rem) var(--sp-4, 1rem); border-left: 1px solid var(--c-border, rgba(255, 255, 255, 0.12)); }
|
|
82
|
+
.svm--inverted .svm__values li { border-left-color: rgb(var(--paper-rgb, 5 5 5) / 0.2); }
|
|
83
|
+
.svm__num { font-size: 0.75rem; font-variant-numeric: tabular-nums; color: var(--shop-accent, var(--c-primary-light, #d4a017)); }
|
|
84
|
+
.svm__values h3 { margin: var(--sp-3, 0.75rem) 0 var(--sp-2, 0.5rem); font-family: var(--font-display, Georgia, serif); font-size: 1.5rem; font-weight: 400; letter-spacing: -0.02em; }
|
|
85
|
+
.svm__values p { margin: 0; max-width: 22rem; font-size: 0.92rem; line-height: 1.65; opacity: 0.75; }
|
|
86
|
+
|
|
87
|
+
@container (max-width: 640px) {
|
|
88
|
+
.svm__values li { padding: var(--sp-4, 1rem) 0; border-left: 0; border-top: 1px solid var(--c-border, rgba(255, 255, 255, 0.12)); }
|
|
89
|
+
}
|
|
90
|
+
@media (prefers-reduced-motion: reduce) { .svm__track { animation: none; } }
|
|
91
|
+
</style>
|
|
@@ -39,6 +39,7 @@ const id = `scb-${Math.random().toString(36).slice(2, 8)}`;
|
|
|
39
39
|
const fmt = (s: Stat) => `${s.prefix ?? ''}${s.value.toLocaleString('en-US', { minimumFractionDigits: s.decimals ?? 0, maximumFractionDigits: s.decimals ?? 0 })}${s.suffix ?? ''}`;
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
<div class="cq-stats-counter-band-cq">
|
|
42
43
|
<section class={`scb scb--${variant} scb--${size} ${className}`} aria-labelledby={id}>
|
|
43
44
|
<div class="scb__inner">
|
|
44
45
|
<h2 id={id} class:list={['scb__title', { 'scb__sr': hideTitle }]}>{title}</h2>
|
|
@@ -52,7 +53,7 @@ const fmt = (s: Stat) => `${s.prefix ?? ''}${s.value.toLocaleString('en-US', { m
|
|
|
52
53
|
</dl>
|
|
53
54
|
</div>
|
|
54
55
|
</section>
|
|
55
|
-
|
|
56
|
+
</div>
|
|
56
57
|
<script>
|
|
57
58
|
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
58
59
|
const els = document.querySelectorAll<HTMLElement>('.scb__value[data-count]');
|
|
@@ -86,10 +87,11 @@ const fmt = (s: Stat) => `${s.prefix ?? ''}${s.value.toLocaleString('en-US', { m
|
|
|
86
87
|
</script>
|
|
87
88
|
|
|
88
89
|
<style>
|
|
90
|
+
.cq-stats-counter-band-cq { container-type: inline-size; }
|
|
89
91
|
.scb {
|
|
90
92
|
--scb-py: 4.5rem;
|
|
91
93
|
padding: var(--scb-py) var(--sp-6, 1.5rem);
|
|
92
|
-
background: linear-gradient(180deg, transparent,
|
|
94
|
+
background: linear-gradient(180deg, transparent, rgb(var(--ink-rgb, 255 255 255) / 0.02) 50%, transparent), var(--c-bg, #050505);
|
|
93
95
|
}
|
|
94
96
|
.scb--sm { --scb-py: 3rem; }
|
|
95
97
|
.scb--lg { --scb-py: 6.5rem; }
|
|
@@ -98,9 +100,9 @@ const fmt = (s: Stat) => `${s.prefix ?? ''}${s.value.toLocaleString('en-US', { m
|
|
|
98
100
|
.scb__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }
|
|
99
101
|
.scb__grid { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
|
|
100
102
|
.scb__item { display: flex; flex-direction: column-reverse; align-items: center; gap: 0.5rem; padding: 1.5rem 1rem; text-align: center; }
|
|
101
|
-
.scb--divided .scb__item + .scb__item { border-left: 1px solid
|
|
103
|
+
.scb--divided .scb__item + .scb__item { border-left: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); }
|
|
102
104
|
.scb--cards .scb__grid { gap: 1rem; }
|
|
103
|
-
.scb--cards .scb__item { border-radius: var(--r-lg, 20px); background:
|
|
105
|
+
.scb--cards .scb__item { border-radius: var(--r-lg, 20px); background: rgb(var(--ink-rgb, 255 255 255) / 0.03); border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.07)); }
|
|
104
106
|
.scb__value {
|
|
105
107
|
margin: 0;
|
|
106
108
|
font-size: clamp(2.25rem, 5vw, 3.25rem);
|
|
@@ -108,15 +110,15 @@ const fmt = (s: Stat) => `${s.prefix ?? ''}${s.value.toLocaleString('en-US', { m
|
|
|
108
110
|
letter-spacing: -0.04em;
|
|
109
111
|
line-height: 1;
|
|
110
112
|
font-variant-numeric: tabular-nums;
|
|
111
|
-
background: linear-gradient(180deg, #fff,
|
|
113
|
+
background: linear-gradient(180deg, var(--c-text-1, #fff), rgb(var(--ink-rgb, 255 255 255) / 0.65));
|
|
112
114
|
-webkit-background-clip: text;
|
|
113
115
|
background-clip: text;
|
|
114
116
|
color: transparent;
|
|
115
117
|
}
|
|
116
118
|
.scb__label { font-size: 0.9375rem; color: var(--c-text-2, #a3a3a3); max-width: 220px; }
|
|
117
|
-
@
|
|
119
|
+
@container (max-width: 640px) {
|
|
118
120
|
.scb__grid { grid-template-columns: 1fr 1fr; }
|
|
119
121
|
.scb--divided .scb__item + .scb__item { border-left: 0; }
|
|
120
|
-
.scb--divided .scb__item:nth-child(even) { border-left: 1px solid
|
|
122
|
+
.scb--divided .scb__item:nth-child(even) { border-left: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); }
|
|
121
123
|
}
|
|
122
124
|
</style>
|
|
@@ -44,6 +44,7 @@ const {
|
|
|
44
44
|
const id = `sds-${Math.random().toString(36).slice(2, 8)}`;
|
|
45
45
|
---
|
|
46
46
|
|
|
47
|
+
<div class="cq-stats-dashboard-section-cq">
|
|
47
48
|
<section class={`sds sds--${size} ${className}`} aria-labelledby={id}>
|
|
48
49
|
<div class="sds__inner">
|
|
49
50
|
<header class="sds__head">
|
|
@@ -62,8 +63,9 @@ const id = `sds-${Math.random().toString(36).slice(2, 8)}`;
|
|
|
62
63
|
</div>
|
|
63
64
|
</div>
|
|
64
65
|
</section>
|
|
65
|
-
|
|
66
|
+
</div>
|
|
66
67
|
<style>
|
|
68
|
+
.cq-stats-dashboard-section-cq { container-type: inline-size; }
|
|
67
69
|
.sds {
|
|
68
70
|
--sds-py: 5.5rem;
|
|
69
71
|
padding: var(--sds-py) var(--sp-6, 1.5rem);
|
|
@@ -79,5 +81,5 @@ const id = `sds-${Math.random().toString(36).slice(2, 8)}`;
|
|
|
79
81
|
.sds__subtitle { margin: 0; font-size: 1.0625rem; color: var(--c-text-2, #a3a3a3); }
|
|
80
82
|
.sds__kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.25rem; }
|
|
81
83
|
.sds__charts { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.25rem; }
|
|
82
|
-
@
|
|
84
|
+
@container (max-width: 900px) { .sds__charts { grid-template-columns: 1fr; } }
|
|
83
85
|
</style>
|
|
@@ -52,6 +52,7 @@ const stats = [
|
|
|
52
52
|
];
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
+
<div class="cq-stats-metric-showcase-cq">
|
|
55
56
|
<section class={`stats-section ${className}`} aria-labelledby="stats-title">
|
|
56
57
|
<div class="stats-bg" aria-hidden="true">
|
|
57
58
|
<div class="stats-glow"></div>
|
|
@@ -105,8 +106,9 @@ const stats = [
|
|
|
105
106
|
</div>
|
|
106
107
|
</div>
|
|
107
108
|
</section>
|
|
108
|
-
|
|
109
|
+
</div>
|
|
109
110
|
<style>
|
|
111
|
+
.cq-stats-metric-showcase-cq { container-type: inline-size; }
|
|
110
112
|
.stats-section {
|
|
111
113
|
position: relative;
|
|
112
114
|
padding: var(--sp-20, 5rem) var(--sp-6, 1.5rem);
|
|
@@ -185,7 +187,7 @@ const stats = [
|
|
|
185
187
|
.stat-card {
|
|
186
188
|
background: rgba(15, 23, 42, 0.6);
|
|
187
189
|
backdrop-filter: blur(20px);
|
|
188
|
-
border: 1px solid
|
|
190
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
189
191
|
border-radius: var(--r-xl, 20px);
|
|
190
192
|
padding: 2rem 1.75rem;
|
|
191
193
|
display: flex;
|
|
@@ -196,7 +198,7 @@ const stats = [
|
|
|
196
198
|
|
|
197
199
|
.stat-card:hover {
|
|
198
200
|
transform: translateY(-4px);
|
|
199
|
-
border-color:
|
|
201
|
+
border-color: rgb(var(--ink-rgb, 255 255 255) / 0.2);
|
|
200
202
|
}
|
|
201
203
|
|
|
202
204
|
.stat-top {
|
|
@@ -239,7 +241,7 @@ const stats = [
|
|
|
239
241
|
|
|
240
242
|
.stat-chart-bar {
|
|
241
243
|
height: 4px;
|
|
242
|
-
background:
|
|
244
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
243
245
|
border-radius: 9999px;
|
|
244
246
|
overflow: hidden;
|
|
245
247
|
}
|
|
@@ -258,7 +260,7 @@ const stats = [
|
|
|
258
260
|
gap: 2rem;
|
|
259
261
|
padding: 1.25rem 2rem;
|
|
260
262
|
background: rgba(10, 15, 30, 0.8);
|
|
261
|
-
border: 1px solid
|
|
263
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
262
264
|
border-radius: 16px;
|
|
263
265
|
flex-wrap: wrap;
|
|
264
266
|
}
|
|
@@ -313,13 +315,13 @@ const stats = [
|
|
|
313
315
|
font-weight: 600;
|
|
314
316
|
}
|
|
315
317
|
|
|
316
|
-
@
|
|
318
|
+
@container (max-width: 1024px) {
|
|
317
319
|
.stats-grid {
|
|
318
320
|
grid-template-columns: repeat(2, 1fr);
|
|
319
321
|
}
|
|
320
322
|
}
|
|
321
323
|
|
|
322
|
-
@
|
|
324
|
+
@container (max-width: 640px) {
|
|
323
325
|
.stats-grid {
|
|
324
326
|
grid-template-columns: 1fr;
|
|
325
327
|
}
|
|
@@ -60,6 +60,7 @@ const members = [
|
|
|
60
60
|
];
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
<div class="cq-team-grid-section-cq">
|
|
63
64
|
<section class={`team-section ${className}`} aria-labelledby="team-title">
|
|
64
65
|
<div class="team-bg" aria-hidden="true">
|
|
65
66
|
<div class="team-glow"></div>
|
|
@@ -106,8 +107,9 @@ const members = [
|
|
|
106
107
|
</div>
|
|
107
108
|
</div>
|
|
108
109
|
</section>
|
|
109
|
-
|
|
110
|
+
</div>
|
|
110
111
|
<style>
|
|
112
|
+
.cq-team-grid-section-cq { container-type: inline-size; }
|
|
111
113
|
.team-section {
|
|
112
114
|
position: relative;
|
|
113
115
|
padding: var(--sp-20, 5rem) var(--sp-6, 1.5rem);
|
|
@@ -186,7 +188,7 @@ const members = [
|
|
|
186
188
|
.member-card {
|
|
187
189
|
background: rgba(15, 23, 42, 0.55);
|
|
188
190
|
backdrop-filter: blur(20px);
|
|
189
|
-
border: 1px solid
|
|
191
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
190
192
|
border-radius: var(--r-xl, 20px);
|
|
191
193
|
padding: 2rem 1.5rem;
|
|
192
194
|
text-align: center;
|
|
@@ -198,7 +200,7 @@ const members = [
|
|
|
198
200
|
|
|
199
201
|
.member-card:hover {
|
|
200
202
|
transform: translateY(-4px);
|
|
201
|
-
border-color:
|
|
203
|
+
border-color: rgb(var(--ink-rgb, 255 255 255) / 0.2);
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
.member-avatar {
|
|
@@ -211,7 +213,7 @@ const members = [
|
|
|
211
213
|
font-weight: 800;
|
|
212
214
|
color: #fff;
|
|
213
215
|
margin-bottom: 1.25rem;
|
|
214
|
-
border: 2px solid
|
|
216
|
+
border: 2px solid rgb(var(--ink-rgb, 255 255 255) / 0.2);
|
|
215
217
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
|
|
216
218
|
}
|
|
217
219
|
|
|
@@ -246,8 +248,8 @@ const members = [
|
|
|
246
248
|
width: 34px;
|
|
247
249
|
height: 34px;
|
|
248
250
|
border-radius: 8px;
|
|
249
|
-
background:
|
|
250
|
-
border: 1px solid
|
|
251
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.05);
|
|
252
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
251
253
|
display: flex;
|
|
252
254
|
align-items: center;
|
|
253
255
|
justify-content: center;
|
|
@@ -258,8 +260,8 @@ const members = [
|
|
|
258
260
|
|
|
259
261
|
.social-icon:hover {
|
|
260
262
|
color: #fff;
|
|
261
|
-
background:
|
|
262
|
-
border-color:
|
|
263
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.12);
|
|
264
|
+
border-color: rgb(var(--ink-rgb, 255 255 255) / 0.2);
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
/* Hiring Banner */
|
|
@@ -314,13 +316,13 @@ const members = [
|
|
|
314
316
|
box-shadow: 0 6px 20px rgba(168, 85, 247, 0.45);
|
|
315
317
|
}
|
|
316
318
|
|
|
317
|
-
@
|
|
319
|
+
@container (max-width: 1024px) {
|
|
318
320
|
.team-grid {
|
|
319
321
|
grid-template-columns: repeat(2, 1fr);
|
|
320
322
|
}
|
|
321
323
|
}
|
|
322
324
|
|
|
323
|
-
@
|
|
325
|
+
@container (max-width: 640px) {
|
|
324
326
|
.team-grid {
|
|
325
327
|
grid-template-columns: 1fr;
|
|
326
328
|
}
|