@import "tailwindcss"; /* Class-based dark mode (toggled on by the theme script). */ @custom-variant dark (&:where(.dark, .dark *)); @theme { /* Navy-tinted neutral scale — sampled from the app icon. ---------------- */ --color-frost-50: #f5f8fd; --color-frost-100: #eaf0fa; --color-frost-200: #d9e3f3; --color-frost-300: #c2cfe4; --color-frost-400: #92a3c0; --color-frost-500: #6a7c9b; --color-frost-600: #4e5f7d; --color-frost-700: #3c4b66; --color-frost-800: #2b3752; --color-frost-900: #1d2740; --color-frost-950: #0e1526; /* Accent: glacier cyan to ice blue — focus rings, links, highlights. ---- */ --color-accent-50: #ecf9ff; --color-accent-100: #d6f1ff; --color-accent-200: #b0e5ff; --color-accent-300: #7dd4fc; --color-accent-400: #38bdf8; --color-accent-500: #0ea5e9; --color-accent-600: #0284c7; --color-accent-700: #0369a1; --color-accent-800: #075985; --color-accent-900: #0c4a6e; /* Aurora hues used only for the frosted backdrop wash. ----------------- */ --color-aurora-mint: #9fe3d0; --color-aurora-sky: #9ccdf5; --color-aurora-lilac: #c3b6f0; --color-aurora-peach: #f6cdb4; --font-sans: -apple-system, BlinkMacSystemFont, ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"; --shadow-frost: 0 14px 34px -22px rgb(13 13 13 / 0.28); --shadow-lift: 0 4px 14px -8px rgb(13 13 13 / 0.18); --shadow-hairline: 0 1px 0 0 rgb(13 13 13 / 0.04); --animate-float: float 11s ease-in-out infinite; --animate-pop: pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); --animate-wiggle: wiggle 0.4s ease-in-out; --animate-rise: rise 0.4s cubic-bezier(0.22, 1, 0.36, 1) both; --animate-sheet: sheet 0.32s cubic-bezier(0.22, 1, 0.36, 1) both; } @keyframes float { 0%, 100% { transform: translate3d(0, 0, 0) scale(1) } 50% { transform: translate3d(0, -18px, 0) scale(1.04) } } @keyframes pop { 0% { transform: scale(0.92) } 60% { transform: scale(1.02) } 100% { transform: scale(1) } } @keyframes wiggle { 0%, 100% { transform: translateX(0) } 25% { transform: translateX(-5px) } 75% { transform: translateX(5px) } } @keyframes rise { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: translateY(0) } } @keyframes sheet { from { opacity: 0; transform: translateY(24px) } to { opacity: 1; transform: translateY(0) } } /* --------------------------------------------------------------------------- Theme tokens. Light: ChatGPT-ish neutral (page #ffffff, sidebar #f9f9f9, border #e5e5e5). Dark: page #212121, sidebar #171717, surfaces #2f2f2f, borders rgba(255,255,255,.1). Text tiers are picked to clear WCAG AA (4.5:1) on their own background. --------------------------------------------------------------------------- */ :root { color-scheme: light; --page: #eef5fd; --sidebar: #ffffff; --surface: #ffffff; --surface-raised: #ffffff; --surface-strong: rgb(255 255 255 / 0.72); /* nested glass: inputs, chips */ --card-hover-bg: rgb(255 255 255 / 0.72); --surface-sunken: rgb(12 32 62 / 0.06); --hairline: #d5e4f4; --card-border: var(--glass-border); --sidebar-divider: rgb(255 255 255 / 0.75); --hairline-soft: rgb(12 32 62 / 0.08); --glass-tint: rgb(255 255 255 / 0.55); --text: #0b1830; /* 16.6:1 on #eef5fd */ --text-muted: #46586f; /* 6.6:1 on light glass */ --text-subtle: #566a84; /* 5.0:1 on light glass */ --hover: rgb(12 32 62 / 0.05); --focus: #0ea5e9; /* Frosted ice glass — one shared recipe for every large surface. */ --glass-bg: rgb(255 255 255 / 0.55); --glass-border: rgb(255 255 255 / 0.8); --glass-highlight: rgb(255 255 255 / 0.85); --glass-shadow: 0 20px 50px -20px rgb(30 64 175 / 0.35); --glass-solid-bg: rgb(255 255 255 / 0.8); /* question card: more opaque */ --glass-fallback: rgb(247 251 255 / 0.97); /* no backdrop-filter */ --nav-active-bg: rgb(255 255 255 / 0.75); --nav-active-border: rgb(56 189 248 / 0.5); /* API-key gate: cool near-white stage with soft blue glows, tinted input. */ --gate-card: rgb(255 255 255 / 0.62); --gate-callout-bg: rgb(255 255 255 / 0.55); --gate-callout-border: rgb(56 189 248 / 0.32); --field: rgb(255 255 255 / 0.66); --field-border: rgb(255 255 255 / 0.9); --shadow-gate: 0 28px 70px -36px rgb(14 21 40 / 0.3), 0 1px 2px rgb(14 21 40 / 0.05); /* Install sheet: light variant (dark is the default, see .dark). */ --install-sheet: rgb(255 255 255 / 0.6); --install-card: rgb(255 255 255 / 0.7); --install-chip: rgb(255 255 255 / 0.55); --install-border: rgb(255 255 255 / 0.8); --shadow-card: 0 1px 2px rgb(14 21 40 / 0.06), 0 1px 3px rgb(14 21 40 / 0.04); --card-shadow: 0 1px 2px rgb(14 21 40 / 0.05), 0 5px 14px -6px rgb(14 21 40 / 0.12); --shadow-card-hover: 0 24px 60px -24px rgb(30 64 175 / 0.45), 0 2px 6px rgb(30 64 175 / 0.12); } .dark { color-scheme: dark; --page: #0a1120; --sidebar: #0b1524; --surface: #16233a; --surface-raised: #1d2c47; --surface-strong: rgb(255 255 255 / 0.08); --card-hover-bg: rgb(255 255 255 / 0.1); --surface-sunken: rgb(255 255 255 / 0.07); --hairline: rgb(255 255 255 / 0.12); --card-border: var(--glass-border); --sidebar-divider: rgb(255 255 255 / 0.12); --hairline-soft: rgb(255 255 255 / 0.08); --glass-tint: rgb(255 255 255 / 0.06); --text: #e8f0ff; /* 16.3:1 on #0a1120 */ --text-muted: #b3c4e0; /* 10.1:1 */ --text-subtle: #90a4c6; /* 6.9:1 */ --hover: rgb(255 255 255 / 0.07); --focus: #38bdf8; /* Frosted ice glass — dark: barely-there tint, brighter rim. */ --glass-bg: rgb(255 255 255 / 0.06); --glass-border: rgb(255 255 255 / 0.12); --glass-highlight: rgb(255 255 255 / 0.25); --glass-shadow: 0 20px 50px -20px rgb(30 64 175 / 0.35); --glass-solid-bg: rgb(255 255 255 / 0.1); --glass-fallback: rgb(16 26 45 / 0.97); --nav-active-bg: rgb(56 189 248 / 0.14); --nav-active-border: rgb(56 189 248 / 0.4); /* API-key gate: navy stage with the icon's blue glows, raised input. */ --gate-card: rgb(255 255 255 / 0.06); --gate-callout-bg: rgb(255 255 255 / 0.06); --gate-callout-border: rgb(56 189 248 / 0.3); --field: rgb(255 255 255 / 0.07); --field-border: rgb(255 255 255 / 0.14); --shadow-gate: 0 30px 80px -40px rgb(0 0 0 / 0.85), 0 1px 2px rgb(0 0 0 / 0.4); /* Install sheet: layered dark surfaces (default theme for the sheet). */ --install-sheet: rgb(255 255 255 / 0.06); --install-card: rgb(255 255 255 / 0.07); --install-chip: rgb(255 255 255 / 0.1); --install-border: rgb(255 255 255 / 0.14); --shadow-card: 0 1px 2px rgb(0 0 0 / 0.25); --card-shadow: var(--shadow-card); --shadow-card-hover: 0 24px 60px -24px rgb(30 64 175 / 0.55), 0 2px 8px rgb(0 0 0 / 0.3); } /* Ice scene tokens: the fixed layered background behind everything. */ :root { --ice-base-top: #f4f9ff; --ice-base-bottom: #e6f1fb; --ice-blob-opacity: 0.18; --ice-orb-opacity: 0.55; --ice-grain-opacity: 0.05; } .dark { --ice-base-top: #070b16; --ice-base-bottom: #0c1426; --ice-blob-opacity: 0.4; --ice-orb-opacity: 0.8; --ice-grain-opacity: 0.045; } html, body { height: 100%; overscroll-behavior: none; } body { font-family: var(--font-sans); -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; /* Matches the backdrop so iOS rubber-banding never shows a seam. */ background-color: var(--page); color: var(--text); overscroll-behavior-y: none; } .dark body { color: var(--color-frost-100); } /* The page backdrop now lives in ONE viewport-fixed layer (see .app-backdrop) so it can never stretch, scroll or be clipped by a content column. `.frost-bg` stays as a transparent wrapper for pages that used it. */ .frost-bg { background: transparent; } /* The key gate rides on the shared ice scene (see .ice-scene). */ /* The fixed ice scene: navy/pale base, drifting glacier blobs, glossy ice orbs and a whisper of grain. Purely decorative. */ .ice-scene { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; background: linear-gradient(180deg, var(--ice-base-top) 0%, var(--ice-base-bottom) 100%); } .ice-blob { position: absolute; border-radius: 50%; opacity: var(--ice-blob-opacity); will-change: transform; /* No filter: blur() here on purpose. A radial gradient fading to transparent is already a soft blob, and blurring a huge layer that is also being animated forces a re-rasterisation every frame (measured 150ms vs 33ms per frame in a software renderer). The falloff stops below keep the same softness. */ } .ice-blob-a { width: 52vw; height: 52vw; min-width: 24rem; min-height: 24rem; top: -14vh; left: -10vw; background: radial-gradient(circle, rgb(56 189 248 / 0.9) 0%, rgb(56 189 248 / 0.45) 38%, transparent 72%); animation: ice-drift-a 44s ease-in-out infinite; } .ice-blob-b { width: 46vw; height: 46vw; min-width: 22rem; min-height: 22rem; top: 4vh; right: -12vw; background: radial-gradient(circle, rgb(96 165 250 / 0.9) 0%, rgb(96 165 250 / 0.45) 38%, transparent 72%); animation: ice-drift-b 52s ease-in-out infinite; } .ice-blob-c { width: 48vw; height: 48vw; min-width: 22rem; min-height: 22rem; bottom: -16vh; left: 14vw; background: radial-gradient(circle, rgb(129 140 248 / 0.9) 0%, rgb(129 140 248 / 0.42) 38%, transparent 74%); animation: ice-drift-c 60s ease-in-out infinite; } .ice-blob-d { width: 34vw; height: 34vw; min-width: 16rem; min-height: 16rem; bottom: 2vh; right: 6vw; background: radial-gradient(circle, rgb(56 189 248 / 0.85) 0%, rgb(56 189 248 / 0.4) 38%, transparent 74%); animation: ice-drift-a 48s ease-in-out infinite reverse; } @keyframes ice-drift-a { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(4vw, 3vh, 0) scale(1.08); } } @keyframes ice-drift-b { 0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); } 50% { transform: translate3d(-5vw, 4vh, 0) scale(1); } } @keyframes ice-drift-c { 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } 50% { transform: translate3d(3vw, -4vh, 0) scale(1.1); } } /* Glossy ice orbs, placed so the glass panels blur them. */ .ice-orb { position: absolute; border-radius: 50%; opacity: var(--ice-orb-opacity); background: radial-gradient( circle at 30% 25%, rgb(255 255 255 / 0.95) 0%, rgb(191 227 255 / 0.55) 18%, rgb(96 165 250 / 0.35) 48%, rgb(37 99 235 / 0.45) 100% ); box-shadow: 0 18px 40px -18px rgb(30 64 175 / 0.55), inset 0 -8px 18px -10px rgb(30 64 175 / 0.6); } .ice-orb-1 { width: 190px; height: 190px; top: 14%; left: 12%; } .ice-orb-2 { width: 84px; height: 84px; top: 58%; left: 4%; } .ice-orb-3 { width: 220px; height: 220px; bottom: -70px; right: 10%; } .ice-orb-4 { width: 52px; height: 52px; top: 24%; right: 28%; } .ice-orb-5 { width: 120px; height: 120px; bottom: 16%; left: 38%; } /* Frosted grain over the whole scene. */ .ice-grain { position: absolute; inset: 0; opacity: var(--ice-grain-opacity); mix-blend-mode: overlay; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E"); } @media (prefers-reduced-motion: reduce) { .ice-blob { animation: none; } } /* Phones: fewer, softer blobs so the drift animation stays cheap. Unlayered on purpose — layered rules would lose to the .ice-blob declarations above. */ @media (max-width: 1023px) { .ice-blob-c, .ice-blob-d, .ice-orb-4, .ice-orb-5 { display: none; } .ice-orb-1 { width: 120px; height: 120px; } .ice-orb-3 { width: 150px; height: 150px; } } @layer components { /* Frosted ice glass ------------------------------------------------------ One shared recipe for the large surfaces only: translucent tint, 24px blur, a bright rim, an inner top highlight and a blue-tinted shadow. Nested glass (chips, inputs) never adds a second blur layer. Tailwind's backdrop utilities emit the -webkit- prefix too (hand-written backdrop-filter gets minified to -webkit- only, which paints nothing). */ .glass-panel, .card, .sidebar-surface, .study-chrome, .tabbar, .glass, .gate-card { @apply backdrop-blur-xl backdrop-saturate-[1.4]; background: var(--glass-bg); box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight); } .glass-panel { border: 1px solid var(--glass-border); border-radius: 1.5rem; } /* Nested glass: slightly more opaque than its parent, no extra blur. */ .glass-chip { background: var(--surface-sunken); border: 1px solid var(--glass-border); } /* More opaque glass for the study question card, where text must stay crisp. */ .glass-solid { background: var(--glass-solid-bg); } .glass-chip:hover { background: var(--hover); } .glass { border-bottom: 1px solid var(--glass-border); } /* Study-feed chrome (progress header + bottom pager): the same neutral surface as the cards, with a neutral border and shadow. */ .study-chrome { border: 1px solid var(--glass-border); } .card { border-radius: 1.5rem; /* 24px */ border: 1px solid var(--glass-border); } .gate-card { border: 1px solid var(--glass-border); border-radius: 1.75rem; /* 28px */ } /* Blur is expensive on phones: halve it, and thin out the ice scene. */ @media (max-width: 1023px) { .glass-panel, .card, .sidebar-surface, .study-chrome, .tabbar, .glass, .gate-card { @apply backdrop-blur-lg; } } /* No backdrop-filter support: fall back to a more opaque surface. */ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) { .glass-panel, .card, .sidebar-surface, .study-chrome, .tabbar, .glass, .gate-card { background: var(--glass-fallback); } } /* Opt-in hover lift for interactive cards (deck cards). Pointer devices only, so touch screens never get sticky hover states. */ .card-hover { transition: background-color 180ms ease, box-shadow 180ms ease, border-color 180ms ease, transform 180ms ease; } @media (hover: hover) and (pointer: fine) { .card-hover:hover { background: var(--card-hover-bg); border-color: var(--nav-active-border); box-shadow: var(--shadow-card-hover); transform: translateY(-2px); } } .card-hover:active { transform: translateY(0); } /* Inset grouped list ---------------------------------------------------- */ .list-group { border-radius: 1rem; @apply backdrop-blur-lg backdrop-saturate-150; background: color-mix(in oklab, var(--surface) 82%, transparent); border: 1px solid var(--hairline); overflow: hidden; } .list-group > * + * { border-top: 1px solid var(--hairline-soft); } /* iOS segmented control ------------------------------------------------- */ .segmented { display: flex; gap: 2px; padding: 3px; border-radius: 0.95rem; @apply backdrop-blur-sm; background: var(--surface-sunken); border: 1px solid var(--hairline); } .segmented > button { flex: 1; border-radius: 0.75rem; padding: 0.42rem 0.5rem; font-size: 0.875rem; font-weight: 600; color: var(--color-frost-700); transition: background-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease; } .dark .segmented > button { color: var(--color-frost-300); } .segmented > button[aria-pressed="true"], .segmented > button[aria-checked="true"] { background-image: linear-gradient(135deg, #38bdf8 0%, #60a5fa 100%); color: #06111f; box-shadow: 0 6px 16px -8px rgb(56 189 248 / 0.7); } .dark .segmented > button[aria-pressed="true"], .dark .segmented > button[aria-checked="true"] { background-image: linear-gradient(135deg, #38bdf8 0%, #60a5fa 100%); color: #06111f; } /* Ice gradient for progress bars and selected states. */ .grad-ice { background-image: linear-gradient(90deg, #38bdf8 0%, #60a5fa 100%); } /* Sheet grabber --------------------------------------------------------- */ .sheet-grabber { width: 36px; height: 5px; border-radius: 999px; background: var(--hairline-soft); margin: 0 auto 0.75rem; } .tabbar { border-top: 1px solid var(--glass-border); } /* Soft tinted chip for activity types (a hint of colour, not a rainbow) -- */ .tint-sky { background: linear-gradient(140deg, rgb(156 205 245 / 0.34), rgb(156 205 245 / 0.14)); color: #1c4e72 } .tint-mint { background: linear-gradient(140deg, rgb(159 227 208 / 0.4), rgb(159 227 208 / 0.16)); color: #1d5c4c } .tint-lilac { background: linear-gradient(140deg, rgb(195 182 240 / 0.4), rgb(195 182 240 / 0.16)); color: #47397f } .tint-peach { background: linear-gradient(140deg, rgb(246 205 180 / 0.45), rgb(246 205 180 / 0.18)); color: #7d4522 } .tint-rose { background: linear-gradient(140deg, rgb(246 178 190 / 0.4), rgb(246 178 190 / 0.16)); color: #7c2b3d } .dark .tint-sky { background: linear-gradient(140deg, rgb(74 164 220 / 0.26), rgb(74 164 220 / 0.1)); color: #bfe2fb } .dark .tint-mint { background: linear-gradient(140deg, rgb(88 201 173 / 0.26), rgb(88 201 173 / 0.1)); color: #bdf0e2 } .dark .tint-lilac { background: linear-gradient(140deg, rgb(160 140 235 / 0.26), rgb(160 140 235 / 0.1)); color: #ddd5fb } .dark .tint-peach { background: linear-gradient(140deg, rgb(230 160 118 / 0.26), rgb(230 160 118 / 0.1)); color: #fadfc9 } .dark .tint-rose { background: linear-gradient(140deg, rgb(230 130 150 / 0.26), rgb(230 130 150 / 0.1)); color: #fbd5dd } /* Sidebar surface: frosted navy glass with a real edge. */ /* Sidebar surface: one tall inset glass panel. */ .sidebar-surface { border: 1px solid var(--glass-border); border-radius: 1.5rem; } /* Sidebar nav rows */ .nav-row { display: flex; align-items: center; gap: 0.625rem; width: 100%; border-radius: 0.625rem; padding: 0.5rem 0.625rem; font-size: 13.5px; font-weight: 500; color: var(--text-muted); transition: background-color 140ms ease, color 140ms ease; } .nav-row:hover { background: var(--hover); color: var(--text); } .nav-row[aria-current="page"], .nav-row[aria-pressed="true"] { background: var(--nav-active-bg); color: var(--text); box-shadow: inset 0 0 0 1px var(--nav-active-border), inset 0 1px 0 var(--glass-highlight); } /* Shared CTA language: the icon's blue, with a deeper fill in light mode. */ .btn-primary { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; border-radius: 14px; background-image: linear-gradient(135deg, #1d4ed8 0%, #1a5fd0 55%, #0ea5e9 100%); color: #ffffff; font-weight: 500; box-shadow: 0 10px 24px -12px rgb(14 165 233 / 0.7); transition: box-shadow 180ms ease, filter 180ms ease, transform 160ms ease; } .btn-primary:hover { filter: brightness(1.07); box-shadow: 0 14px 32px -12px rgb(56 189 248 / 0.85); } .btn-primary:active { transform: scale(0.985); } .dark .btn-primary { background-image: linear-gradient(135deg, #ffffff 0%, #bfe3ff 100%); color: #0b1220; box-shadow: 0 10px 26px -14px rgb(56 189 248 / 0.6); } .dark .btn-primary:hover { filter: brightness(1.03); box-shadow: 0 14px 34px -14px rgb(56 189 248 / 0.95); } .btn-secondary { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; border-radius: 14px; background: var(--surface-strong); color: var(--text); border: 1px solid var(--glass-border); font-weight: 500; transition: background-color 160ms ease, border-color 160ms ease, transform 160ms ease; } .btn-secondary:hover { background: var(--hover); border-color: var(--nav-active-border); } .btn-secondary:active { transform: scale(0.985); } .btn-ghost { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; border-radius: 14px; background: transparent; color: var(--text-muted); font-weight: 500; transition: background-color 160ms ease, color 160ms ease; } .btn-ghost:hover { background: var(--hover); color: var(--text); } /* Difficulty: neutral pill, colour lives in the text only. */ .diff-easy { color: #16714f; } .diff-medium { color: #7a5300; } .diff-hard { color: #b4342f; } .dark .diff-easy { color: #6fd3a8; } .dark .diff-medium { color: #e3b341; } .dark .diff-hard { color: #f08a84; } /* Loading skeleton */ .skeleton { position: relative; overflow: hidden; background: var(--surface-sunken); border-radius: 0.75rem; } .skeleton::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.45), transparent); animation: shimmer 1.6s infinite; } .dark .skeleton::after { background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.06), transparent); } @keyframes shimmer { 100% { transform: translateX(100%); } } .text-balance { text-wrap: balance; } /* Focus rings ------------------------------------------------------------ */ :where(button, a, input, textarea, [tabindex]):focus-visible { outline: 2.5px solid var(--color-accent-500); outline-offset: 2px; border-radius: 0.75rem; } /* Scrollbars ------------------------------------------------------------- */ .thin-scroll { scrollbar-width: thin; scrollbar-color: color-mix(in oklab, var(--color-frost-400) 55%, transparent) transparent; } .thin-scroll::-webkit-scrollbar { width: 8px; height: 8px } .thin-scroll::-webkit-scrollbar-thumb { background: color-mix(in oklab, var(--color-frost-400) 45%, transparent); border-radius: 999px; } .no-scrollbar::-webkit-scrollbar { display: none } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none } /* Mobile safe areas ------------------------------------------------------ */ .pt-safe { padding-top: max(env(safe-area-inset-top), 0.75rem) } .pb-safe { padding-bottom: max(env(safe-area-inset-bottom), 0.75rem) } .pb-tabbar { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 5.25rem) } .pb-cta { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 9rem) } @media (display-mode: standalone) { .standalone-hide { display: none } } } /* Mobile form fields ----------------------------------------------------- */ /* iOS Safari zooms the whole page when a focused field's text is under 16px (it ignores user-scalable=no for that). Deliberately unlayered so it wins over the per-component Tailwind sizes, and only on phone-sized screens. */ @media (max-width: 639px) { input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea, select { font-size: 16px; } } /* Reduced motion --------------------------------------------------------- */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; } }