@bergetai/ui 0.3.5 → 0.4.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/dist/index.d.cts CHANGED
@@ -657,4 +657,37 @@ interface WindowFrameProps extends React$1.HTMLAttributes<HTMLDivElement> {
657
657
  }
658
658
  declare const WindowFrame: React$1.ForwardRefExoticComponent<WindowFrameProps & React$1.RefAttributes<HTMLDivElement>>;
659
659
 
660
- export { Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTitleProps, Badge, type BadgeProps, BergetLogo, type BergetLogoProps, Box, type BoxProps, type SpacingScale as BoxSpacingScale, Button, type ButtonProps, COUNTRIES, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, Container, type ContainerProps, type Country, CountrySelect, type CountrySelectProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EU_COUNTRY_CODES, FeatureList, type FeatureListProps, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Grid, type GridColsScale, type GridProps, type GridRowsScale, type SpacingScale$1 as GridSpacingScale, HeroBlock, type HeroBlockProps, Icon, type IconProps, Input, type InputProps, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, type ItemProps, ItemSeparator, ItemTitle, Label, LanguageSelect, type LanguageSelectOption, type LanguageSelectProps, Link, type LinkProps, List, ListHeader, type ListHeaderProps, ListItem, type ListItemProps, type ListProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Select, type SelectOption, type SelectProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, type TerminalExample, TextArea, type TextAreaProps, type Theme, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, Typography, type TypographyProps, WindowFrame, type WindowFrameProps, type WindowTab, alertVariants, badgeVariants, boxVariants, buttonVariants, cardVariants, checkboxVariants, containerVariants, getCountryByCode, getCountryByName, gridVariants, isEUCountry, linkVariants, navigationMenuTriggerStyle, selectVariants, switchRootVariants, switchThumbVariants, textAreaVariants, typographyVariants, useTheme };
660
+ /**
661
+ * FogIllustration — a volumetric fog raymarcher rendered as chunky
662
+ * 1-bit dither in a given palette.
663
+ *
664
+ * Two GPU passes: the scene is raymarched at low internal resolution
665
+ * (ridged fbm ground, drifting fog volumes, air haze — the fog hides
666
+ * the low resolution), then a full-resolution pass thresholds the
667
+ * scene against a Bayer matrix with hash jitter: ink dots on milk,
668
+ * with moss-tinted dots where fog dominates.
669
+ *
670
+ * The canvas fills its parent element; give the parent a size.
671
+ * Pauses under prefers-reduced-motion after one frame.
672
+ */
673
+ type FogPalette = {
674
+ /** Dark terrain and dither ink. */
675
+ ink: string;
676
+ /** Background the dots sit on. */
677
+ milk: string;
678
+ /** Tint for dots where fog dominates. */
679
+ moss: string;
680
+ };
681
+ /** The Berget brand palette, as rendered sRGB. */
682
+ declare const FOG_BRAND_PALETTE: FogPalette;
683
+ interface FogIllustrationProps {
684
+ /** Colors as hex strings. Unset keys fall back to the brand palette. */
685
+ palette?: Partial<FogPalette>;
686
+ /** Flight speed multiplier @default 1 */
687
+ speed?: number;
688
+ /** Additional CSS classes for the canvas element */
689
+ className?: string;
690
+ }
691
+ declare const FogIllustration: ({ palette, speed, className }: FogIllustrationProps) => react_jsx_runtime.JSX.Element;
692
+
693
+ export { Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTitleProps, Badge, type BadgeProps, BergetLogo, type BergetLogoProps, Box, type BoxProps, type SpacingScale as BoxSpacingScale, Button, type ButtonProps, COUNTRIES, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, Container, type ContainerProps, type Country, CountrySelect, type CountrySelectProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EU_COUNTRY_CODES, FOG_BRAND_PALETTE, FeatureList, type FeatureListProps, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FogIllustration, type FogIllustrationProps, type FogPalette, Grid, type GridColsScale, type GridProps, type GridRowsScale, type SpacingScale$1 as GridSpacingScale, HeroBlock, type HeroBlockProps, Icon, type IconProps, Input, type InputProps, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, type ItemProps, ItemSeparator, ItemTitle, Label, LanguageSelect, type LanguageSelectOption, type LanguageSelectProps, Link, type LinkProps, List, ListHeader, type ListHeaderProps, ListItem, type ListItemProps, type ListProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Select, type SelectOption, type SelectProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, type TerminalExample, TextArea, type TextAreaProps, type Theme, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, Typography, type TypographyProps, WindowFrame, type WindowFrameProps, type WindowTab, alertVariants, badgeVariants, boxVariants, buttonVariants, cardVariants, checkboxVariants, containerVariants, getCountryByCode, getCountryByName, gridVariants, isEUCountry, linkVariants, navigationMenuTriggerStyle, selectVariants, switchRootVariants, switchThumbVariants, textAreaVariants, typographyVariants, useTheme };
package/dist/index.d.ts CHANGED
@@ -657,4 +657,37 @@ interface WindowFrameProps extends React$1.HTMLAttributes<HTMLDivElement> {
657
657
  }
658
658
  declare const WindowFrame: React$1.ForwardRefExoticComponent<WindowFrameProps & React$1.RefAttributes<HTMLDivElement>>;
659
659
 
660
- export { Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTitleProps, Badge, type BadgeProps, BergetLogo, type BergetLogoProps, Box, type BoxProps, type SpacingScale as BoxSpacingScale, Button, type ButtonProps, COUNTRIES, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, Container, type ContainerProps, type Country, CountrySelect, type CountrySelectProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EU_COUNTRY_CODES, FeatureList, type FeatureListProps, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Grid, type GridColsScale, type GridProps, type GridRowsScale, type SpacingScale$1 as GridSpacingScale, HeroBlock, type HeroBlockProps, Icon, type IconProps, Input, type InputProps, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, type ItemProps, ItemSeparator, ItemTitle, Label, LanguageSelect, type LanguageSelectOption, type LanguageSelectProps, Link, type LinkProps, List, ListHeader, type ListHeaderProps, ListItem, type ListItemProps, type ListProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Select, type SelectOption, type SelectProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, type TerminalExample, TextArea, type TextAreaProps, type Theme, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, Typography, type TypographyProps, WindowFrame, type WindowFrameProps, type WindowTab, alertVariants, badgeVariants, boxVariants, buttonVariants, cardVariants, checkboxVariants, containerVariants, getCountryByCode, getCountryByName, gridVariants, isEUCountry, linkVariants, navigationMenuTriggerStyle, selectVariants, switchRootVariants, switchThumbVariants, textAreaVariants, typographyVariants, useTheme };
660
+ /**
661
+ * FogIllustration — a volumetric fog raymarcher rendered as chunky
662
+ * 1-bit dither in a given palette.
663
+ *
664
+ * Two GPU passes: the scene is raymarched at low internal resolution
665
+ * (ridged fbm ground, drifting fog volumes, air haze — the fog hides
666
+ * the low resolution), then a full-resolution pass thresholds the
667
+ * scene against a Bayer matrix with hash jitter: ink dots on milk,
668
+ * with moss-tinted dots where fog dominates.
669
+ *
670
+ * The canvas fills its parent element; give the parent a size.
671
+ * Pauses under prefers-reduced-motion after one frame.
672
+ */
673
+ type FogPalette = {
674
+ /** Dark terrain and dither ink. */
675
+ ink: string;
676
+ /** Background the dots sit on. */
677
+ milk: string;
678
+ /** Tint for dots where fog dominates. */
679
+ moss: string;
680
+ };
681
+ /** The Berget brand palette, as rendered sRGB. */
682
+ declare const FOG_BRAND_PALETTE: FogPalette;
683
+ interface FogIllustrationProps {
684
+ /** Colors as hex strings. Unset keys fall back to the brand palette. */
685
+ palette?: Partial<FogPalette>;
686
+ /** Flight speed multiplier @default 1 */
687
+ speed?: number;
688
+ /** Additional CSS classes for the canvas element */
689
+ className?: string;
690
+ }
691
+ declare const FogIllustration: ({ palette, speed, className }: FogIllustrationProps) => react_jsx_runtime.JSX.Element;
692
+
693
+ export { Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTitleProps, Badge, type BadgeProps, BergetLogo, type BergetLogoProps, Box, type BoxProps, type SpacingScale as BoxSpacingScale, Button, type ButtonProps, COUNTRIES, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, Container, type ContainerProps, type Country, CountrySelect, type CountrySelectProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EU_COUNTRY_CODES, FOG_BRAND_PALETTE, FeatureList, type FeatureListProps, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FogIllustration, type FogIllustrationProps, type FogPalette, Grid, type GridColsScale, type GridProps, type GridRowsScale, type SpacingScale$1 as GridSpacingScale, HeroBlock, type HeroBlockProps, Icon, type IconProps, Input, type InputProps, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, type ItemProps, ItemSeparator, ItemTitle, Label, LanguageSelect, type LanguageSelectOption, type LanguageSelectProps, Link, type LinkProps, List, ListHeader, type ListHeaderProps, ListItem, type ListItemProps, type ListProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Select, type SelectOption, type SelectProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, type TerminalExample, TextArea, type TextAreaProps, type Theme, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, Typography, type TypographyProps, WindowFrame, type WindowFrameProps, type WindowTab, alertVariants, badgeVariants, boxVariants, buttonVariants, cardVariants, checkboxVariants, containerVariants, getCountryByCode, getCountryByName, gridVariants, isEUCountry, linkVariants, navigationMenuTriggerStyle, selectVariants, switchRootVariants, switchThumbVariants, textAreaVariants, typographyVariants, useTheme };
package/dist/index.js CHANGED
@@ -3495,6 +3495,324 @@ var WindowFrame = React43.forwardRef(
3495
3495
  }
3496
3496
  );
3497
3497
  WindowFrame.displayName = "WindowFrame";
3498
+
3499
+ // src/components/fog-illustration/FogIllustration.tsx
3500
+ import { useEffect as useEffect3, useRef } from "react";
3501
+ import { jsx as jsx44 } from "react/jsx-runtime";
3502
+ var FOG_BRAND_PALETTE = {
3503
+ ink: "#171a1a",
3504
+ milk: "#f7f5ed",
3505
+ moss: "#598c6b"
3506
+ };
3507
+ var hexToRgb = (hex) => {
3508
+ let h = hex.replace("#", "");
3509
+ if (h.length === 3)
3510
+ h = h.split("").map((c) => c + c).join("");
3511
+ const n = Number.parseInt(h, 16);
3512
+ return [(n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
3513
+ };
3514
+ var hexToRgbAll = (p) => ({
3515
+ ink: hexToRgb(p.ink),
3516
+ milk: hexToRgb(p.milk),
3517
+ moss: hexToRgb(p.moss)
3518
+ });
3519
+ var VERT = `#version 300 es
3520
+ void main() {
3521
+ vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
3522
+ gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
3523
+ }`;
3524
+ var SCENE_FRAG = `#version 300 es
3525
+ precision highp float;
3526
+ out vec4 outColor;
3527
+ uniform vec2 uRes;
3528
+ uniform float uTime;
3529
+ uniform sampler2D uNoise;
3530
+
3531
+ float noise(vec3 x) {
3532
+ // 3D value noise from the 2D random texture \u2014 iq's two-slice trick:
3533
+ // z slices are tiled into the u axis, two neighbours mixed by fract(z).
3534
+ vec3 p = floor(x), f = fract(x);
3535
+ f = f * f * (3.0 - 2.0 * f);
3536
+ vec2 uv = (p.xy + vec2(37.0, 239.0) * p.z) + f.xy;
3537
+ vec2 rg = texture(uNoise, (uv + 0.5) / 256.0).xy;
3538
+ return mix(rg.x, rg.y, f.z) * 2.0 - 1.0;
3539
+ }
3540
+
3541
+ float ground(vec3 pos, int oct) {
3542
+ float f = 0.0;
3543
+ float s = 1.4;
3544
+ vec3 p = pos * s * 0.1;
3545
+ for (int i = 0; i < 6; i++) {
3546
+ if (i >= oct) break;
3547
+ f += abs(noise(p)) * s;
3548
+ p = vec3(p.z * 5.0, p.xy * 3.0 + p.yx * 4.0 * vec2(1, -1)) * 2.0 / 5.0;
3549
+ s /= 2.0;
3550
+ }
3551
+ return (pos.y + f) * 0.8;
3552
+ }
3553
+
3554
+ float fogD(vec3 pos, int oct) {
3555
+ float f = 0.0;
3556
+ float s = 1.0;
3557
+ vec3 p = pos * 0.7;
3558
+ p += uTime * vec3(0.0, -0.02, 0.02);
3559
+ for (int i = 0; i < 6; i++) {
3560
+ if (i >= oct) break;
3561
+ f += noise(p) * s;
3562
+ p = vec3(p.z * 5.0, p.xy * 3.0 + p.yx * 4.0 * vec2(1, -1)) * 2.0 / 5.0;
3563
+ s /= 1.7;
3564
+ }
3565
+ f += smoothstep(0.2, 0.0, abs(pos.y + 1.0)) * 0.4;
3566
+ f += smoothstep(0.35, 0.15, abs(pos.y - 0.02)) * 0.7;
3567
+ f *= 1.0 - smoothstep(-0.1, 0.55, pos.y);
3568
+ f = smoothstep(0.45, 1.7, f);
3569
+ float g = ground(pos, 2);
3570
+ f *= 1.0 - g / (abs(g) + 0.04);
3571
+ return f;
3572
+ }
3573
+
3574
+ float airD(vec3 pos) { return exp2(-pos.y / 5.0 - 3.0); }
3575
+
3576
+ void main() {
3577
+ float time = uTime * 0.2;
3578
+ vec3 velocity = vec3(1.0, 0.0, 0.0);
3579
+ vec3 camPos = vec3(sin(time * 0.618) * 0.4, 0.62 + 0.08 * sin(time), 0.0) + time * velocity;
3580
+ vec3 camLook = vec3(-1.0, -0.3, 4.0) + (time - sin(time)) * velocity;
3581
+
3582
+ vec2 fc = gl_FragCoord.xy;
3583
+ vec3 ray = vec3((fc - uRes * 0.5) / uRes.x, 1.0);
3584
+ vec3 camDir = normalize(camLook - camPos);
3585
+ vec3 camRight = normalize(cross(vec3(0.0, 1.0, 0.0), camDir));
3586
+ vec3 camUp = cross(camDir, camRight);
3587
+ ray = normalize(ray.x * camRight + ray.y * camUp + ray.z * camDir);
3588
+
3589
+ vec3 sunDir = normalize(vec3(-3.0, 2.0, 1.0));
3590
+
3591
+ vec3 pos = camPos;
3592
+ float absorption = 1.0;
3593
+ float emission = 0.0;
3594
+ float fogFactor = 0.0;
3595
+ float lastStride = 0.0;
3596
+ float lastFog = 0.0;
3597
+ float lastAir = 0.0;
3598
+
3599
+ for (int i = 0; i < 80; i++) {
3600
+ float h = ground(pos, 4);
3601
+ float fog = fogD(pos, 3);
3602
+ float fogIntegral = lastStride * mix(fog, lastFog, 0.5);
3603
+ float air = airD(pos);
3604
+ float airIntegral = lastStride * mix(air, lastAir, 0.5);
3605
+
3606
+ float fogAbsDelta = pow(0.1, fogIntegral);
3607
+ float fogEmiDelta = 1.0 - fogAbsDelta;
3608
+ float shadowStep = 0.07;
3609
+ float shadow = (fog - fogD(pos + sunDir * shadowStep, 2)) / shadowStep;
3610
+ fogEmiDelta *= mix(0.2, 0.85, smoothstep(-1.0, 1.0, shadow));
3611
+
3612
+ float airAbsDelta = pow(0.55, airIntegral);
3613
+ float airEmiDelta = (1.0 - pow(0.55, airIntegral)) * 0.5;
3614
+
3615
+ float absDelta = fogAbsDelta * airAbsDelta;
3616
+ emission += absorption * sqrt(absDelta) * (fogEmiDelta + airEmiDelta);
3617
+ absorption *= absDelta;
3618
+
3619
+ fogFactor = max(fogFactor, (1.0 - absorption) * step(0.05, fog));
3620
+
3621
+ lastFog = fog;
3622
+ lastAir = air;
3623
+ h = min(h, 0.1);
3624
+ lastStride = h;
3625
+ pos += h * ray;
3626
+ if (h < 0.001) break;
3627
+ }
3628
+
3629
+ float brightness;
3630
+ if (absorption > 0.02) {
3631
+ // terrain visible \u2014 light it
3632
+ vec2 d = vec2(-1.0, 1.0) * 0.02;
3633
+ vec3 normal = normalize(
3634
+ ground(pos + d.xxx, 5) * d.xxx +
3635
+ ground(pos + d.xyy, 5) * d.xyy +
3636
+ ground(pos + d.yxy, 5) * d.yxy +
3637
+ ground(pos + d.yyx, 5) * d.yyx
3638
+ );
3639
+ float ao = smoothstep(-0.2, 1.5, ground(pos + normal * 0.3, 5) / 0.3);
3640
+ float shade = (0.5 * ao + 0.5 * max(dot(normal, sunDir), 0.0)) * 0.65;
3641
+ brightness = shade * absorption + emission;
3642
+ } else {
3643
+ brightness = emission;
3644
+ }
3645
+
3646
+ // Clear sky \u2014 rays that escape upward land on milk, whatever the
3647
+ // haze did. The poster look: light sky, dark ridges, fog between.
3648
+ float sky = smoothstep(-0.15, 0.35, ray.y) * 0.92;
3649
+ brightness = max(brightness, sky * absorption);
3650
+
3651
+ outColor = vec4(clamp(brightness, 0.0, 1.0), clamp(fogFactor, 0.0, 1.0), 0.0, 1.0);
3652
+ }`;
3653
+ var DITHER_FRAG = `#version 300 es
3654
+ precision highp float;
3655
+ out vec4 outColor;
3656
+ uniform vec2 uRes;
3657
+ uniform float uDot;
3658
+ uniform sampler2D uScene;
3659
+ uniform vec3 uInk;
3660
+ uniform vec3 uMilk;
3661
+ uniform vec3 uMoss;
3662
+
3663
+ float bayer2(vec2 a) { a = floor(a); return fract(a.x / 2.0 + a.y * a.y * 0.75); }
3664
+ float bayer4(vec2 a) { return bayer2(0.5 * a) * 0.25 + bayer2(a); }
3665
+ float hash12(vec2 p) {
3666
+ vec3 p3 = fract(vec3(p.xyx) * 0.1031);
3667
+ p3 += dot(p3, p3.yzx + 33.33);
3668
+ return fract((p3.x + p3.y) * p3.z);
3669
+ }
3670
+
3671
+ void main() {
3672
+ // Chunky cells: one dot decision per uDot\xD7uDot block \u2014 the dither
3673
+ // reads as visible pixels, not 1px noise.
3674
+ vec2 cell = floor(gl_FragCoord.xy / uDot);
3675
+ vec4 scene = texture(uScene, (cell * uDot + uDot * 0.5) / uRes);
3676
+ float darkness = 1.0 - scene.r;
3677
+ float jitter = (hash12(cell) - 0.5) * 0.3;
3678
+ float on = step(darkness, bayer4(cell) + jitter);
3679
+ vec3 col = scene.g > 0.5 ? uMoss : uInk;
3680
+ outColor = vec4(mix(col, uMilk, on), 1.0);
3681
+ }`;
3682
+ var compile = (gl, type, src) => {
3683
+ const sh = gl.createShader(type);
3684
+ if (!sh) throw new Error("shader creation failed");
3685
+ gl.shaderSource(sh, src);
3686
+ gl.compileShader(sh);
3687
+ if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
3688
+ throw new Error(gl.getShaderInfoLog(sh) || "shader compile failed");
3689
+ }
3690
+ return sh;
3691
+ };
3692
+ var program = (gl, frag) => {
3693
+ const p = gl.createProgram();
3694
+ if (!p) throw new Error("program creation failed");
3695
+ gl.attachShader(p, compile(gl, gl.VERTEX_SHADER, VERT));
3696
+ gl.attachShader(p, compile(gl, gl.FRAGMENT_SHADER, frag));
3697
+ gl.linkProgram(p);
3698
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
3699
+ throw new Error(gl.getProgramInfoLog(p) || "program link failed");
3700
+ }
3701
+ return p;
3702
+ };
3703
+ var FogIllustration = ({ palette, speed = 1, className }) => {
3704
+ const ref = useRef(null);
3705
+ const live = useRef({ palette: { ...FOG_BRAND_PALETTE, ...palette }, speed });
3706
+ live.current = { palette: { ...FOG_BRAND_PALETTE, ...palette }, speed };
3707
+ useEffect3(() => {
3708
+ const canvas = ref.current;
3709
+ const parent = canvas?.parentElement;
3710
+ if (!canvas || !parent) return;
3711
+ const gl = canvas.getContext("webgl2", {
3712
+ antialias: false,
3713
+ alpha: false,
3714
+ preserveDrawingBuffer: true
3715
+ });
3716
+ if (!gl) return;
3717
+ let sceneProg;
3718
+ let ditherProg;
3719
+ try {
3720
+ sceneProg = program(gl, SCENE_FRAG);
3721
+ ditherProg = program(gl, DITHER_FRAG);
3722
+ } catch (err) {
3723
+ console.error("fog shader failed:", err);
3724
+ return;
3725
+ }
3726
+ const noiseTex = gl.createTexture();
3727
+ gl.bindTexture(gl.TEXTURE_2D, noiseTex);
3728
+ const N = 256;
3729
+ const data = new Uint8Array(N * N * 4);
3730
+ for (let i = 0; i < data.length; i += 4) {
3731
+ data[i] = Math.random() * 256;
3732
+ data[i + 1] = Math.random() * 256;
3733
+ data[i + 2] = Math.random() * 256;
3734
+ data[i + 3] = 255;
3735
+ }
3736
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, N, N, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
3737
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
3738
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
3739
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
3740
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
3741
+ const sceneTex = gl.createTexture();
3742
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3743
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
3744
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
3745
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3746
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3747
+ const fbo = gl.createFramebuffer();
3748
+ const SCALE = 0.3;
3749
+ const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3750
+ const start = performance.now();
3751
+ let raf = 0;
3752
+ let last = 0;
3753
+ const render = (elapsed) => {
3754
+ const w = parent.clientWidth;
3755
+ const h = parent.clientHeight;
3756
+ if (w === 0 || h === 0) return;
3757
+ const dpr = Math.min(window.devicePixelRatio || 1, 2);
3758
+ if (canvas.width !== Math.round(w * dpr) || canvas.height !== Math.round(h * dpr)) {
3759
+ canvas.width = Math.round(w * dpr);
3760
+ canvas.height = Math.round(h * dpr);
3761
+ }
3762
+ const sceneW = Math.max(64, Math.round(w * SCALE));
3763
+ const sceneH = Math.max(64, Math.round(h * SCALE));
3764
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3765
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sceneW, sceneH, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
3766
+ const t = elapsed * live.current.speed;
3767
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
3768
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, sceneTex, 0);
3769
+ gl.viewport(0, 0, sceneW, sceneH);
3770
+ gl.useProgram(sceneProg);
3771
+ gl.activeTexture(gl.TEXTURE0);
3772
+ gl.bindTexture(gl.TEXTURE_2D, noiseTex);
3773
+ gl.uniform1i(gl.getUniformLocation(sceneProg, "uNoise"), 0);
3774
+ gl.uniform2f(gl.getUniformLocation(sceneProg, "uRes"), sceneW, sceneH);
3775
+ gl.uniform1f(gl.getUniformLocation(sceneProg, "uTime"), t);
3776
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
3777
+ const { ink, milk, moss } = hexToRgbAll(live.current.palette);
3778
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
3779
+ gl.viewport(0, 0, canvas.width, canvas.height);
3780
+ gl.useProgram(ditherProg);
3781
+ gl.activeTexture(gl.TEXTURE0);
3782
+ gl.bindTexture(gl.TEXTURE_2D, sceneTex);
3783
+ gl.uniform1i(gl.getUniformLocation(ditherProg, "uScene"), 0);
3784
+ gl.uniform2f(gl.getUniformLocation(ditherProg, "uRes"), canvas.width, canvas.height);
3785
+ gl.uniform1f(gl.getUniformLocation(ditherProg, "uDot"), Math.max(3, Math.round(dpr * 2)));
3786
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uInk"), ...ink);
3787
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uMilk"), ...milk);
3788
+ gl.uniform3f(gl.getUniformLocation(ditherProg, "uMoss"), ...moss);
3789
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
3790
+ };
3791
+ render(0);
3792
+ if (!reduced) {
3793
+ const frame = (now) => {
3794
+ if (now - last >= 1e3 / 30) {
3795
+ last = now;
3796
+ render((now - start) / 1e3);
3797
+ }
3798
+ raf = requestAnimationFrame(frame);
3799
+ };
3800
+ raf = requestAnimationFrame(frame);
3801
+ }
3802
+ const observer = new ResizeObserver(() => render((performance.now() - start) / 1e3));
3803
+ observer.observe(parent);
3804
+ return () => {
3805
+ cancelAnimationFrame(raf);
3806
+ observer.disconnect();
3807
+ gl.deleteProgram(sceneProg);
3808
+ gl.deleteProgram(ditherProg);
3809
+ gl.deleteTexture(noiseTex);
3810
+ gl.deleteTexture(sceneTex);
3811
+ gl.deleteFramebuffer(fbo);
3812
+ };
3813
+ }, []);
3814
+ return /* @__PURE__ */ jsx44("canvas", { ref, "aria-hidden": "true", className: cn("size-full", className) });
3815
+ };
3498
3816
  export {
3499
3817
  Alert2 as Alert,
3500
3818
  AlertDescription,
@@ -3551,6 +3869,7 @@ export {
3551
3869
  DropdownMenuSubTrigger,
3552
3870
  DropdownMenuTrigger,
3553
3871
  EU_COUNTRY_CODES,
3872
+ FOG_BRAND_PALETTE,
3554
3873
  FeatureList,
3555
3874
  Field,
3556
3875
  FieldContent,
@@ -3562,6 +3881,7 @@ export {
3562
3881
  FieldSeparator,
3563
3882
  FieldSet,
3564
3883
  FieldTitle,
3884
+ FogIllustration,
3565
3885
  Grid,
3566
3886
  HeroBlock,
3567
3887
  Icon,