alouette
Version:
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
633 lines (598 loc) • 26.1 kB
CSS
/* Generated by scripts/build-css.ts. DO NOT EDIT. */
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/preflight.css' layer(base);
@import 'tailwindcss/utilities.css';
@import 'nativewind/theme';
@theme {
/* unified alouette type scale — standard Tailwind names, exact pixel values preserved.
The paired --text-*--line-height modifier is what makes the text-* utility carry a
default line-height (Tailwind v4 convention). Without it, line-height stays unset.
Ratios are unitless: web treats them as font-size-relative; on native NativeWind
multiplies any unitless lineHeight by fontSize, so they behave identically on both platforms.
Body default is 1.4 (matches the old Tamagui body font); the heading-only display
sizes (32/40/64px) use the old heading ratios. For headings at shared sizes
(text-lg/text-xl), add an explicit leading-* class to tighten. */
--text-xs: 0.75rem; /* 12px */
--text-xs--line-height: 1.4;
--text-sm: 0.875rem; /* 14px */
--text-sm--line-height: 1.4;
--text-base: 1rem; /* 16px */
--text-base--line-height: 1.4;
--text-lg: 1.125rem; /* 18px */
--text-lg--line-height: 1.4;
--text-xl: 1.5rem; /* 24px */
--text-xl--line-height: 1.4;
--text-2xl: 2rem; /* 32px */
--text-2xl--line-height: 1.2;
--text-3xl: 2.5rem; /* 40px */
--text-3xl--line-height: 1.1;
--text-4xl: 3rem; /* 48px */
--text-4xl--line-height: 1.1;
--text-5xl: 4rem; /* 64px */
--text-5xl--line-height: 1.1;
--text-6xl: 5rem; /* 80px */
--text-6xl--line-height: 1.1;
/* radius — alouette scale (16px base) */
--radius-xs: 0.5rem;
--radius-sm: 1rem;
--radius-md: 2rem;
--radius-lg: 3rem;
/* box-shadows — multi-layer with inset highlight, matches original
containers/variants.ts. Names map to Tailwind's shadow-{name} utilities. */
--shadow-s: inset 0 1px 2px #ffffff40, 0 1px 2px #00000040, 0 2px 4px #00000025;
--shadow-m: inset 0 1px 2px #ffffff40, 0 2px 4px #00000040, 0 4px 8px #00000025;
--shadow-l: inset 0 1px 2px #ffffff40, 0 4px 6px #00000040, 0 6px 10px #00000025;
--shadow-lowered: inset 0 1px 2px #00000040, inset 0 -2px 2px #ffffff15;
/* spacing — named scale matching the old $N.N token names */
--spacing-xxs: 4px;
--spacing-xs: 8px; /* previous $0.5 */
--spacing-sm: 12px;
--spacing-m: 16px; /* previous $1.0 */
--spacing-l: 24px;
--spacing-xl: 32px; /* previous $2.0 */
--spacing-xxl: 48px;
--spacing-3xl: 64px; /* previous $3.0 */
--spacing-4xl: 128px;
/* breakpoints — match Breakpoints.ts */
--breakpoint-sm: 480px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
--breakpoint-xl: 1280px;
/* animations — Tailwind v4 names the utility after the --animate-* key
(animate-slide-in) and NativeWind runs the @keyframes on native via
Reanimated. Names are generic motions, not component-specific. CSS
animations are enter-only on their own; pair the exit animation with
<Presence> (keeps the outgoing child mounted) for an AnimatePresence-style
swap without an animation library. */
--animate-slide-in: slide-in 600ms cubic-bezier(0.16, 1, 0.3, 1);
--animate-slide-out: slide-out 600ms cubic-bezier(0.16, 1, 0.3, 1);
--animate-collapse-in: collapse-in 800ms ease-out;
--animate-collapse-out: collapse-out 800ms ease-out;
/* color tokens — light theme as defaults, enabling bg-*, text-*, border-* utilities.
Other themes override via :root { @variant <theme> { ... } } below. */
--color-translucent: #ffffff66;
--color-screen: #EEEEEE;
--color-highlight: #FFFFFF;
--color-disabled-sharp: #5D5D5D;
--color-disabled-muted: #838383;
--color-disabled-interactive: #BABABA;
--color-disabled-interactive-muted: #DBDBDB;
--color-sharp: #262626;
--color-muted: #4D4D4D;
--color-form-border-disabled: #BABABA;
--color-form-placeholder: #5D5D5D;
--color-form-disabled-text: #4D4D4D;
--color-interactive-contained-disabled: #BABABA;
--color-interactive-outlined-disabled: #BABABA;
--color-interactive-accent-outlined-disabled: #BABABA;
--color-surface: #F8F8F8;
--color-enabled: #5D5D5D;
--color-highlight-accent: #DBDBDB;
--color-lowered: #DBDBDB;
--color-screen-gradient-start: #DBDBDB;
--color-screen-gradient-middle: #CECECE;
--color-screen-gradient-end: #BABABA;
--color-border-muted: #CECECE;
--color-border-sharp: #5D5D5D;
--color-interactive-contained-pressable: #FFFFFF;
--color-interactive-contained-hover: #F8F8F8;
--color-interactive-contained-focus: #F8F8F8;
--color-interactive-contained-active: #EEEEEE;
--color-interactive-outlined-pressable: #5D5D5D;
--color-interactive-outlined-hover: #838383;
--color-interactive-outlined-focus: #838383;
--color-interactive-outlined-active: #838383;
--color-interactive-outlined-outline-focus: #838383;
--color-interactive-active: #5D5D5D;
--color-interactive-pressable: #4D4D4D;
--color-interactive-hover: #262626;
--color-accent: #262626;
--color-on-accent: #262626;
--color-on-accent-muted: #5D5D5D;
--color-selection: #4D4D4D40;
}
@layer theme {
/* font-family tokens — consumers can override these in their own @layer theme :root to swap fonts.
The base holds WEB values as a fallback list, because the two web targets load different
families:
- Expo web (react-native-web): expo-font registers weight-specific families
('SoraRegular'/'SoraBold'/'SoraExtraBold', 'ChivoMono*') — 'Sora' is NOT available.
- Vite Storybook: Google Fonts loads the single 'Sora'/'Chivo Mono' families, weight via
font-weight.
Leading with the weight-specific name (matched on Expo web) and falling back to 'Sora'/'ChivoMono'
(matched on Vite) makes both work from one declaration. Native uses single names (RN has no
fallbacks) under @variant native (NativeWind's native: variant, from nativewind/theme).
NB: the base holds the web values and the @variant native block overrides them on native only —
the native: variant is dropped on web and applied by NativeWind's runtime on native, so the
platform font split lives there. */
:root {
--font-body: 'SoraRegular', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-body-bold: 'SoraBold', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-body-extrabold: 'SoraExtraBold', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-heading: 'SoraRegular', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-heading-bold: 'SoraBold', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-heading-extrabold: 'SoraExtraBold', 'Sora', ui-sans-serif, system-ui, sans-serif;
--font-mono: 'ChivoMonoRegular', 'ChivoMono', 'Chivo Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--font-mono-bold: 'ChivoMonoBold', 'ChivoMono', 'Chivo Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--font-mono-extrabold: 'ChivoMonoExtraBold', 'ChivoMono', 'Chivo Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
@variant native {
--font-body: 'SoraRegular';
--font-body-bold: 'SoraBold';
--font-body-extrabold: 'SoraExtraBold';
--font-heading: 'SoraRegular';
--font-heading-bold: 'SoraBold';
--font-heading-extrabold: 'SoraExtraBold';
--font-mono: 'ChivoMonoRegular';
--font-mono-bold: 'ChivoMonoBold';
--font-mono-extrabold: 'ChivoMonoExtraBold';
}
}
:where(.light, .light *) {
--color-translucent: #ffffff66;
--color-screen: #EEEEEE;
--color-highlight: #FFFFFF;
--color-disabled-sharp: #5D5D5D;
--color-disabled-muted: #838383;
--color-disabled-interactive: #BABABA;
--color-disabled-interactive-muted: #DBDBDB;
--color-sharp: #262626;
--color-muted: #4D4D4D;
--color-form-border-disabled: #BABABA;
--color-form-placeholder: #5D5D5D;
--color-form-disabled-text: #4D4D4D;
--color-interactive-contained-disabled: #BABABA;
--color-interactive-outlined-disabled: #BABABA;
--color-interactive-accent-outlined-disabled: #BABABA;
--color-surface: #F8F8F8;
--color-enabled: #5D5D5D;
--color-highlight-accent: #DBDBDB;
--color-lowered: #DBDBDB;
--color-screen-gradient-start: #DBDBDB;
--color-screen-gradient-middle: #CECECE;
--color-screen-gradient-end: #BABABA;
--color-border-muted: #CECECE;
--color-border-sharp: #5D5D5D;
--color-interactive-contained-pressable: #FFFFFF;
--color-interactive-contained-hover: #F8F8F8;
--color-interactive-contained-focus: #F8F8F8;
--color-interactive-contained-active: #EEEEEE;
--color-interactive-outlined-pressable: #5D5D5D;
--color-interactive-outlined-hover: #838383;
--color-interactive-outlined-focus: #838383;
--color-interactive-outlined-active: #838383;
--color-interactive-outlined-outline-focus: #838383;
--color-interactive-active: #5D5D5D;
--color-interactive-pressable: #4D4D4D;
--color-interactive-hover: #262626;
--color-accent: #262626;
--color-on-accent: #262626;
--color-on-accent-muted: #5D5D5D;
--color-selection: #4D4D4D40;
}
:where(.dark, .dark *) {
--color-translucent: #1f1e1e55;
--color-screen: #1F1F1F;
--color-highlight: #333333;
--color-disabled-sharp: #D2D2D2;
--color-disabled-muted: #D2D2D2;
--color-disabled-interactive: #555555;
--color-disabled-interactive-muted: #333333;
--color-sharp: #F2F2F2;
--color-muted: #D2D2D2;
--color-form-border-disabled: #555555;
--color-form-placeholder: #BCBCBC;
--color-form-disabled-text: #D2D2D2;
--color-interactive-contained-disabled: #3D3D3D;
--color-interactive-outlined-disabled: #484848;
--color-interactive-accent-outlined-disabled: #484848;
--color-surface: #292929;
--color-enabled: #555555;
--color-highlight-accent: #333333;
--color-lowered: #121212;
--color-screen-gradient-start: #292929;
--color-screen-gradient-middle: #1F1F1F;
--color-screen-gradient-end: #121212;
--color-border-muted: #555555;
--color-border-sharp: #BCBCBC;
--color-interactive-contained-pressable: #484848;
--color-interactive-contained-hover: #555555;
--color-interactive-contained-focus: #555555;
--color-interactive-contained-active: #555555;
--color-interactive-outlined-pressable: #555555;
--color-interactive-outlined-hover: #BCBCBC;
--color-interactive-outlined-focus: #BCBCBC;
--color-interactive-outlined-active: #BCBCBC;
--color-interactive-outlined-outline-focus: #BCBCBC;
--color-interactive-active: #D2D2D2;
--color-interactive-pressable: #F2F2F2;
--color-interactive-hover: #FFFFFF;
--color-accent: #FFFFFF;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #F2F2F2;
--color-selection: #F2F2F240;
}
:where(.light_brand, .light_brand *) {
--color-surface: #EDF6FA;
--color-enabled: #0A6783;
--color-highlight-accent: #BDE2F1;
--color-lowered: #BDE2F1;
--color-screen-gradient-start: #BDE2F1;
--color-screen-gradient-middle: #98D9F3;
--color-screen-gradient-end: #60CAF0;
--color-border-muted: #98D9F3;
--color-border-sharp: #0A6783;
--color-interactive-contained-pressable: #0A6783;
--color-interactive-contained-hover: #0E7A9A;
--color-interactive-contained-focus: #0E7A9A;
--color-interactive-contained-active: #2493B7;
--color-interactive-outlined-pressable: #0A6783;
--color-interactive-outlined-hover: #2493B7;
--color-interactive-outlined-focus: #2493B7;
--color-interactive-outlined-active: #2493B7;
--color-interactive-outlined-outline-focus: #2493B7;
--color-interactive-active: #0A6783;
--color-interactive-pressable: #07556D;
--color-interactive-hover: #032B38;
--color-accent: #07556D;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #BDE2F1;
--color-selection: #07556D40;
}
:where(.light_info, .light_info *) {
--color-surface: #EFF6FA;
--color-enabled: #0A668B;
--color-highlight-accent: #C3E0F1;
--color-lowered: #C3E0F1;
--color-screen-gradient-start: #C3E0F1;
--color-screen-gradient-middle: #A2D6F3;
--color-screen-gradient-end: #75C6F0;
--color-border-muted: #A2D6F3;
--color-border-sharp: #0A668B;
--color-interactive-contained-pressable: #0A668B;
--color-interactive-contained-hover: #0D78A3;
--color-interactive-contained-focus: #0D78A3;
--color-interactive-contained-active: #2391C1;
--color-interactive-outlined-pressable: #0A668B;
--color-interactive-outlined-hover: #2391C1;
--color-interactive-outlined-focus: #2391C1;
--color-interactive-outlined-active: #2391C1;
--color-interactive-outlined-outline-focus: #2391C1;
--color-interactive-active: #0A668B;
--color-interactive-pressable: #065473;
--color-interactive-hover: #032A3C;
--color-accent: #065473;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #C3E0F1;
--color-selection: #06547340;
}
:where(.light_success, .light_success *) {
--color-surface: #E9FAE9;
--color-enabled: #0A721F;
--color-highlight-accent: #A2F2A4;
--color-lowered: #A2F2A4;
--color-screen-gradient-start: #A2F2A4;
--color-screen-gradient-middle: #6AEF75;
--color-screen-gradient-end: #5ADA65;
--color-border-muted: #6AEF75;
--color-border-sharp: #0A721F;
--color-interactive-contained-pressable: #0A721F;
--color-interactive-contained-hover: #0E8626;
--color-interactive-contained-focus: #0E8626;
--color-interactive-contained-active: #24A037;
--color-interactive-outlined-pressable: #0A721F;
--color-interactive-outlined-hover: #24A037;
--color-interactive-outlined-focus: #24A037;
--color-interactive-outlined-active: #24A037;
--color-interactive-outlined-outline-focus: #24A037;
--color-interactive-active: #0A721F;
--color-interactive-pressable: #075E18;
--color-interactive-hover: #033009;
--color-accent: #075E18;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #A2F2A4;
--color-selection: #075E1840;
}
:where(.light_warning, .light_warning *) {
--color-surface: #FAF5E1;
--color-enabled: #916F0C;
--color-highlight-accent: #F5E7B7;
--color-lowered: #F5E7B7;
--color-screen-gradient-start: #F5E7B7;
--color-screen-gradient-middle: #F6D97B;
--color-screen-gradient-end: #E3C156;
--color-border-muted: #F6D97B;
--color-border-sharp: #916F0C;
--color-interactive-contained-pressable: #916F0C;
--color-interactive-contained-hover: #9F7A0F;
--color-interactive-contained-focus: #9F7A0F;
--color-interactive-contained-active: #E2B930;
--color-interactive-outlined-pressable: #916F0C;
--color-interactive-outlined-hover: #E2B930;
--color-interactive-outlined-focus: #E2B930;
--color-interactive-outlined-active: #E2B930;
--color-interactive-outlined-outline-focus: #E2B930;
--color-interactive-active: #916F0C;
--color-interactive-pressable: #694D06;
--color-interactive-hover: #342302;
--color-accent: #694D06;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #F5E7B7;
--color-selection: #694D0640;
}
:where(.light_danger, .light_danger *) {
--color-surface: #FAF2F2;
--color-enabled: #AF0D23;
--color-highlight-accent: #F1D2D1;
--color-lowered: #F1D2D1;
--color-screen-gradient-start: #F1D2D1;
--color-screen-gradient-middle: #F4BFBC;
--color-screen-gradient-end: #F1A2A0;
--color-border-muted: #F4BFBC;
--color-border-sharp: #AF0D23;
--color-interactive-contained-pressable: #AF0D23;
--color-interactive-contained-hover: #CD112C;
--color-interactive-contained-focus: #CD112C;
--color-interactive-contained-active: #F1293F;
--color-interactive-outlined-pressable: #AF0D23;
--color-interactive-outlined-hover: #F1293F;
--color-interactive-outlined-focus: #F1293F;
--color-interactive-outlined-active: #F1293F;
--color-interactive-outlined-outline-focus: #F1293F;
--color-interactive-active: #AF0D23;
--color-interactive-pressable: #92091A;
--color-interactive-hover: #4E0408;
--color-accent: #92091A;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #F1D2D1;
--color-selection: #92091A40;
}
:where(.dark_brand, .dark_brand *) {
--color-surface: #0E2831;
--color-enabled: #1F6D87;
--color-highlight-accent: #12323E;
--color-lowered: #071418;
--color-screen-gradient-start: #0E2831;
--color-screen-gradient-middle: #0A1D25;
--color-screen-gradient-end: #071418;
--color-border-muted: #1F6D87;
--color-border-sharp: #37ADD5;
--color-interactive-contained-pressable: #184F61;
--color-interactive-contained-hover: #1F6D87;
--color-interactive-contained-focus: #1F6D87;
--color-interactive-contained-active: #1F6D87;
--color-interactive-outlined-pressable: #1F6D87;
--color-interactive-outlined-hover: #37ADD5;
--color-interactive-outlined-focus: #37ADD5;
--color-interactive-outlined-active: #37ADD5;
--color-interactive-outlined-outline-focus: #37ADD5;
--color-interactive-active: #74D2F6;
--color-interactive-pressable: #9EDEF7;
--color-interactive-hover: #DFF4FD;
--color-accent: #9EDEF7;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #9EDEF7;
--color-selection: #9EDEF740;
}
:where(.dark_info, .dark_info *) {
--color-surface: #0E2734;
--color-enabled: #1F6B8E;
--color-highlight-accent: #123242;
--color-lowered: #07131A;
--color-screen-gradient-start: #0E2734;
--color-screen-gradient-middle: #0A1D27;
--color-screen-gradient-end: #07131A;
--color-border-muted: #1F6B8E;
--color-border-sharp: #36ABE0;
--color-interactive-contained-pressable: #184E67;
--color-interactive-contained-hover: #1F6B8E;
--color-interactive-contained-focus: #1F6B8E;
--color-interactive-contained-active: #1F6B8E;
--color-interactive-outlined-pressable: #1F6B8E;
--color-interactive-outlined-hover: #36ABE0;
--color-interactive-outlined-focus: #36ABE0;
--color-interactive-outlined-active: #36ABE0;
--color-interactive-outlined-outline-focus: #36ABE0;
--color-interactive-active: #85CFF6;
--color-interactive-pressable: #A8DBF7;
--color-interactive-hover: #E2F3FD;
--color-accent: #A8DBF7;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #A8DBF7;
--color-selection: #A8DBF740;
}
:where(.dark_success, .dark_success *) {
--color-surface: #0F2B11;
--color-enabled: #1F772A;
--color-highlight-accent: #123715;
--color-lowered: #071508;
--color-screen-gradient-start: #0F2B11;
--color-screen-gradient-middle: #0B200C;
--color-screen-gradient-end: #071508;
--color-border-muted: #1F772A;
--color-border-sharp: #37BC48;
--color-interactive-contained-pressable: #19561F;
--color-interactive-contained-hover: #1F772A;
--color-interactive-contained-focus: #1F772A;
--color-interactive-contained-active: #1F772A;
--color-interactive-outlined-pressable: #1F772A;
--color-interactive-outlined-hover: #37BC48;
--color-interactive-outlined-focus: #37BC48;
--color-interactive-outlined-active: #37BC48;
--color-interactive-outlined-outline-focus: #37BC48;
--color-interactive-active: #4FE760;
--color-interactive-pressable: #5DF76D;
--color-interactive-hover: #D5FDD5;
--color-accent: #5DF76D;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #5DF76D;
--color-selection: #5DF76D40;
}
:where(.dark_warning, .dark_warning *) {
--color-surface: #57451F;
--color-enabled: #8F7021;
--color-highlight-accent: #685223;
--color-lowered: #322714;
--color-screen-gradient-start: #57451F;
--color-screen-gradient-middle: #3E3016;
--color-screen-gradient-end: #322714;
--color-border-muted: #8F7021;
--color-border-sharp: #E0B93C;
--color-interactive-contained-pressable: #846724;
--color-interactive-contained-hover: #8F7021;
--color-interactive-contained-focus: #8F7021;
--color-interactive-contained-active: #8F7021;
--color-interactive-outlined-pressable: #8F7021;
--color-interactive-outlined-hover: #E0B93C;
--color-interactive-outlined-focus: #E0B93C;
--color-interactive-outlined-active: #E0B93C;
--color-interactive-outlined-outline-focus: #E0B93C;
--color-interactive-active: #F4CD4B;
--color-interactive-pressable: #F9DC7E;
--color-interactive-hover: #FDF0C4;
--color-accent: #F9DC7E;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #F9DC7E;
--color-selection: #F9DC7E40;
}
:where(.dark_danger, .dark_danger *) {
--color-surface: #421110;
--color-enabled: #B2242D;
--color-highlight-accent: #531514;
--color-lowered: #220907;
--color-screen-gradient-start: #421110;
--color-screen-gradient-middle: #320C0B;
--color-screen-gradient-end: #220907;
--color-border-muted: #B2242D;
--color-border-sharp: #F56D6D;
--color-interactive-contained-pressable: #811C20;
--color-interactive-contained-hover: #B2242D;
--color-interactive-contained-focus: #B2242D;
--color-interactive-contained-active: #B2242D;
--color-interactive-outlined-pressable: #B2242D;
--color-interactive-outlined-hover: #F56D6D;
--color-interactive-outlined-focus: #F56D6D;
--color-interactive-outlined-active: #F56D6D;
--color-interactive-outlined-outline-focus: #F56D6D;
--color-interactive-active: #F7AEAC;
--color-interactive-pressable: #F8C4C2;
--color-interactive-hover: #FDEBEB;
--color-accent: #F8C4C2;
--color-on-accent: #FFFFFF;
--color-on-accent-muted: #F8C4C2;
--color-selection: #F8C4C240;
}
}
@layer base {
/* hotpink default catches any text missing Text component use */
body { color: hotpink; }
/* let height/width keyframes interpolate to/from auto (collapse-in/out) on web */
:root { interpolate-size: allow-keywords; }
body, #root {
display: flex;
flex-direction: column;
min-height: 100vh;
}
}
/* keyframes referenced by the --animate-* theme tokens above. */
@keyframes slide-in {
from {
opacity: 0;
transform: translateX(-100%) rotateY(-90deg);
}
to {
opacity: 1;
transform: translateX(0) rotateY(0deg);
}
}
@keyframes slide-out {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}
@keyframes collapse-in {
from {
opacity: 0;
height: 0;
}
to {
opacity: 1;
height: auto;
}
}
@keyframes collapse-out {
from {
opacity: 1;
height: auto;
}
to {
opacity: 0;
height: 0;
}
}
/* named transition durations — one per animationDurationsMs entry so transition
classNames reference the same source of truth as the JS export (native drives
the same motion via Reanimated withTiming(animationDurationsMs.*)). */
@utility duration-slide { transition-duration: 600ms; }
@utility duration-collapse { transition-duration: 800ms; }
@utility duration-progress { transition-duration: 600ms; }
@utility duration-fade { transition-duration: 300ms; }
@utility duration-fast { transition-duration: 200ms; }
/* font-family + weight utilities — family×weight combinations; use with standard text-* size utilities.
font-synthesis: none — on Expo web the weight-specific family ('SoraBold') is a single registered
face, so the font-weight below must NOT trigger algorithmic (faux) bolding of already-bold glyphs.
On Vite web 'Sora' is a real variable font, so the font-weight selects the genuine weight. */
@utility font-body { font-family: var(--font-body); font-weight: 400; font-synthesis: none; }
@utility font-body-bold { font-family: var(--font-body-bold); font-weight: 700; font-synthesis: none; }
@utility font-body-extrabold { font-family: var(--font-body-extrabold); font-weight: 800; font-synthesis: none; }
@utility font-heading { font-family: var(--font-heading); font-weight: 400; font-synthesis: none; }
@utility font-heading-bold { font-family: var(--font-heading-bold); font-weight: 700; font-synthesis: none; }
@utility font-heading-extrabold { font-family: var(--font-heading-extrabold); font-weight: 800; font-synthesis: none; }
@utility font-mono { font-family: var(--font-mono); font-weight: 400; font-synthesis: none; }
@utility font-mono-bold { font-family: var(--font-mono-bold); font-weight: 700; font-synthesis: none; }
@utility font-mono-extrabold { font-family: var(--font-mono-extrabold); font-weight: 800; font-synthesis: none; }
/* tripwire — standalone Tailwind font-weight utilities are NOT valid here: weight
must be baked into the font-* family utility (font-body-bold, etc.) so it works on
native. Override them to weight 100 + crunched letter-spacing so any accidental use
renders visibly thin and cramped on web and is easy to spot. (native ignores both
font-weight and letterSpacing here, so this only affects web.) */
@utility font-thin { font-weight: 100; letter-spacing: -0.1em; }
@utility font-extralight { font-weight: 100; letter-spacing: -0.1em; }
@utility font-light { font-weight: 100; letter-spacing: -0.1em; }
@utility font-normal { font-weight: 100; letter-spacing: -0.1em; }
@utility font-medium { font-weight: 100; letter-spacing: -0.1em; }
@utility font-semibold { font-weight: 100; letter-spacing: -0.1em; }
@utility font-bold { font-weight: 100; letter-spacing: -0.1em; }
@utility font-extrabold { font-weight: 100; letter-spacing: -0.1em; }
@utility font-black { font-weight: 100; letter-spacing: -0.1em; }
/* flex-center — center children on both axes. Replaces the old Box `center`
variant. Named flex-center (not `center`) to avoid clashing with any future
text-align / place-* shorthand. */
@utility flex-center {
align-items: center;
justify-content: center;
}