@import 'tailwindcss'; @import 'tw-animate-css'; @custom-variant dark (&:is(.dark *)); :root { --radius: 0.625rem; --background: oklch(0.985 0.002 90); --foreground: oklch(0.205 0.02 60); --card: oklch(1 0 0); --card-foreground: oklch(0.205 0.02 60); --popover: oklch(1 0 0); --popover-foreground: oklch(0.205 0.02 60); --primary: oklch(0.65 0.17 55); --primary-foreground: oklch(1 0 0); --secondary: oklch(0.965 0.01 85); --secondary-foreground: oklch(0.25 0.02 60); --muted: oklch(0.96 0.008 85); --muted-foreground: oklch(0.5 0.02 60); --accent: oklch(0.95 0.02 70); --accent-foreground: oklch(0.25 0.02 60); --destructive: oklch(0.577 0.245 27.325); --border: oklch(0.91 0.01 80); --input: oklch(0.91 0.01 80); --ring: oklch(0.65 0.17 55); --chart-1: oklch(0.65 0.17 55); --chart-2: oklch(0.62 0.16 250); --chart-3: oklch(0.75 0.15 75); --chart-4: oklch(0.55 0.12 250); --chart-5: oklch(0.8 0.14 65); --sidebar-foreground: oklch(0.3 0.02 60); --sidebar-primary: oklch(0.65 0.17 55); --sidebar-primary-foreground: oklch(1 0 0); --sidebar-accent: oklch(0.95 0.03 70); --sidebar-accent-foreground: oklch(0.3 0.02 60); --sidebar-border: oklch(0.92 0.01 80); --sidebar-ring: oklch(0.65 0.17 55); --sidebar: oklch(0.99 0.003 85); --topbar-bg: oklch(1 0 0); --topbar-border: oklch(0.92 0.01 80); } .dark { --background: oklch(0.17 0.015 60); --foreground: oklch(0.96 0.005 85); --card: oklch(0.22 0.015 60); --card-foreground: oklch(0.96 0.005 85); --popover: oklch(0.22 0.015 60); --popover-foreground: oklch(0.96 0.005 85); --primary: oklch(0.72 0.17 55); --primary-foreground: oklch(0.15 0.02 60); --secondary: oklch(0.26 0.015 60); --secondary-foreground: oklch(0.96 0.005 85); --muted: oklch(0.26 0.015 60); --muted-foreground: oklch(0.65 0.02 60); --accent: oklch(0.65 0.16 250); --accent-foreground: oklch(0.96 0.005 85); --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); --ring: oklch(0.72 0.17 55); --chart-1: oklch(0.72 0.17 55); --chart-2: oklch(0.65 0.16 250); --chart-3: oklch(0.8 0.14 65); --chart-4: oklch(0.6 0.2 300); --chart-5: oklch(0.7 0.22 20); --sidebar-foreground: oklch(0.96 0.005 85); --sidebar-primary: oklch(0.72 0.17 55); --sidebar-primary-foreground: oklch(0.15 0.02 60); --sidebar-accent: oklch(0.26 0.02 55); --sidebar-accent-foreground: oklch(0.96 0.005 85); --sidebar-border: oklch(1 0 0 / 10%); --sidebar-ring: oklch(0.72 0.17 55); --sidebar: oklch(0.19 0.015 60); --topbar-bg: oklch(0.2 0.015 60); --topbar-border: oklch(1 0 0 / 10%); } @theme inline { --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); --color-topbar: var(--topbar-bg); --color-topbar-border: var(--topbar-border); } @layer base { /* color-scheme drives native widgets AND propagates into embedded iframes (the open-meteo map reads it via prefers-color-scheme) */ :root { color-scheme: light; } .dark { color-scheme: dark; } * { @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; } /* Page cross-fade: driven from routes/+layout.svelte, revealed when the new page reports its data has arrived. */ .page-fade { transition: opacity 320ms ease; } .page-fade-hidden { opacity: 0; } @media (prefers-reduced-motion: reduce) { .page-fade { transition: none; } .page-fade-hidden { opacity: 1; } } /* ── Day switching ──────────────────────────────────────────────────────── Only the three regions whose content depends on the selected day take part in the cross-fade. Everything else keeps its pixels: the `day-switch` class cancels the root animation, so the strip, header and page chrome do not so much as flicker while the table, summary and charts swap over. */ .day-region-table { view-transition-name: day-table; } .day-region-summary { view-transition-name: day-summary; } .day-region-charts { view-transition-name: day-charts; } /* The sticky day strip never changes during a day switch, but it has to be captured too: view-transition snapshots all paint in one layer above the page, so without its own group (and a higher z-index in that layer) the fading table and charts would slide over the top of it. */ .daystrip { view-transition-name: daystrip; } ::view-transition-group(daystrip) { z-index: 20; } /* Same for the topbar: a captured region's snapshot is painted at its layout position, including the part normally scrolled up behind the chrome. */ .topbar { view-transition-name: topbar; } ::view-transition-group(topbar) { z-index: 30; } ::view-transition-old(day-table), ::view-transition-new(day-table), ::view-transition-old(day-summary), ::view-transition-new(day-summary), ::view-transition-old(day-charts), ::view-transition-new(day-charts) { animation-duration: 420ms; animation-timing-function: ease; } :root.day-switch::view-transition-old(root), :root.day-switch::view-transition-new(root) { animation: none; } @media (prefers-reduced-motion: reduce) { .day-region-table, .day-region-summary, .day-region-charts, .daystrip, .topbar { view-transition-name: none; } } /* Theme changes cross-fade the whole document in one pass (see routes/+layout.svelte). Doing it as a view transition instead of a blanket `* { transition }` matters: that blanket rule also stretched every component's own hover and focus transitions to 400ms for the duration of the switch, which read as lag on interactive controls. */ ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 400ms; animation-timing-function: ease; } /* Fallback for browsers without view transitions: fade the colours only. */ :root.theme-transition, :root.theme-transition *, :root.theme-transition *::before, :root.theme-transition *::after { transition: background-color 400ms ease, border-color 400ms ease, color 400ms ease, fill 400ms ease, stroke 400ms ease; } @media (prefers-reduced-motion: reduce) { ::view-transition-old(root), ::view-transition-new(root) { animation: none; } :root.theme-transition, :root.theme-transition *, :root.theme-transition *::before, :root.theme-transition *::after { transition: none; } } }