- globals.css: eine Basisregel :where(:focus-visible) mit --focus-width und --focus-offset (Sonne 3 px), Firefox-:-moz-focusring gleichgezogen; --text-xs 0.8125rem. - Fokus-Codemod (scripts/codemod-t5-focus.mjs): eigene Ringe und outline-none raus, sm:h-/sm:size- zu pointer-fine:, Label-Zeilen mit focus-ring-within; Skript-Fokus (Lücken-Liste, „Gespeichert“) bleibt. - Button/Input 44 px, kompakt nur mit Maus; Icon-Knöpfe mit unsichtbarer 44-px-Trefferfläche bei Touch, Nachbarn mit genug Abstand. - 16 px in Feldern, Labels, Auswahl, Leerzuständen, Listentiteln. - .holo-stage auf allen Beute-Bühnen, .stage-card holt den Seitenring. - Baukasten-Wächter (src/styles/baukasten-guard.spec.ts) mit den Regeln aus A3–A5, Ausnahmen mit Grund; Kalender-Auswahl als Inset-Ring. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
714 lines
25 KiB
CSS
714 lines
25 KiB
CSS
@import "tailwindcss";
|
|
@import "tw-animate-css";
|
|
@import "shadcn/tailwind.css";
|
|
|
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
@custom-variant sun (&:where([data-contrast="sun"] *));
|
|
@custom-variant pointer-fine (@media (pointer: fine));
|
|
@custom-variant pointer-coarse (@media (pointer: coarse));
|
|
|
|
/* Type scale (spec 4.5): text-xs is 13 px (sun: 14 px), only for axes, legends and footers. */
|
|
@theme {
|
|
--text-xs: 0.8125rem;
|
|
--text-xs--line-height: calc(1.125 / 0.8125);
|
|
}
|
|
|
|
@theme inline {
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--font-sans: var(--font-body);
|
|
--font-mono: var(--font-data);
|
|
--font-heading: var(--font-heading);
|
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
--color-sidebar-border: var(--sidebar-border);
|
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
--color-sidebar-accent: var(--sidebar-accent);
|
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
--color-sidebar-primary: var(--sidebar-primary);
|
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
--color-sidebar: var(--sidebar);
|
|
--color-chart-5: var(--chart-5);
|
|
--color-chart-4: var(--chart-4);
|
|
--color-chart-3: var(--chart-3);
|
|
--color-chart-2: var(--chart-2);
|
|
--color-chart-1: var(--chart-1);
|
|
--color-ring: var(--ring);
|
|
--color-input: var(--input);
|
|
--color-border: var(--border);
|
|
--color-destructive: var(--destructive);
|
|
--color-warning: var(--warning);
|
|
--color-warning-foreground: var(--warning-foreground);
|
|
--color-success: var(--success);
|
|
--color-success-foreground: var(--success-foreground);
|
|
--color-condition-excellent: var(--condition-excellent);
|
|
--color-condition-excellent-foreground: var(--condition-excellent-foreground);
|
|
--color-condition-good: var(--condition-good);
|
|
--color-condition-good-foreground: var(--condition-good-foreground);
|
|
--color-condition-average: var(--condition-average);
|
|
--color-condition-average-foreground: var(--condition-average-foreground);
|
|
--color-condition-weak: var(--condition-weak);
|
|
--color-condition-weak-foreground: var(--condition-weak-foreground);
|
|
--color-condition-critical: var(--condition-critical);
|
|
--color-condition-critical-foreground: var(--condition-critical-foreground);
|
|
--color-holo-bg: var(--holo-bg);
|
|
--color-holo-edge: var(--holo-edge);
|
|
--color-holo-edge-strong: var(--holo-edge-strong);
|
|
--color-holo-fill: var(--holo-fill);
|
|
--color-holo-label-bg: var(--holo-label-bg);
|
|
--color-holo-label-fg: var(--holo-label-fg);
|
|
--color-primary-ink: var(--primary-ink);
|
|
--color-warning-ink: var(--warning-ink);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
--color-condition-excellent-ink: var(--condition-excellent-ink);
|
|
--color-condition-good-ink: var(--condition-good-ink);
|
|
--color-condition-average-ink: var(--condition-average-ink);
|
|
--color-condition-weak-ink: var(--condition-weak-ink);
|
|
--color-condition-critical-ink: var(--condition-critical-ink);
|
|
--color-area-betrieb: var(--area-betrieb);
|
|
--color-area-erfassung: var(--area-erfassung);
|
|
--color-area-arbeit: var(--area-arbeit);
|
|
--color-area-ernte: var(--area-ernte);
|
|
--color-area-neutral: var(--area-neutral);
|
|
--color-queen-white: var(--queen-white);
|
|
--color-queen-yellow: var(--queen-yellow);
|
|
--color-queen-red: var(--queen-red);
|
|
--color-queen-green: var(--queen-green);
|
|
--color-queen-blue: var(--queen-blue);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
--color-accent: var(--accent);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
--color-muted: var(--muted);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
--color-secondary: var(--secondary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
--color-primary: var(--primary);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
--color-popover: var(--popover);
|
|
--color-card-foreground: var(--card-foreground);
|
|
--color-card: var(--card);
|
|
--radius-sm: calc(var(--radius) * 0.6);
|
|
--radius-md: calc(var(--radius) * 0.8);
|
|
--radius-lg: var(--radius);
|
|
--radius-xl: calc(var(--radius) * 1.4);
|
|
--radius-2xl: calc(var(--radius) * 1.8);
|
|
--radius-3xl: calc(var(--radius) * 2.2);
|
|
--radius-4xl: calc(var(--radius) * 2.6);
|
|
--animate-page-in: page-in 260ms ease-out;
|
|
}
|
|
|
|
@keyframes page-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(6px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
:root {
|
|
--background: oklch(0.968 0.014 85);
|
|
--foreground: oklch(0.21 0.03 55);
|
|
--card: oklch(0.995 0.004 90);
|
|
--card-foreground: oklch(0.21 0.03 55);
|
|
--popover: oklch(0.995 0.004 90);
|
|
--popover-foreground: oklch(0.21 0.03 55);
|
|
--primary: oklch(0.8 0.145 78);
|
|
--primary-foreground: oklch(0.21 0.035 55);
|
|
--secondary: oklch(0.44 0.07 145);
|
|
--secondary-foreground: oklch(0.98 0.015 100);
|
|
--muted: oklch(0.925 0.018 82);
|
|
--muted-foreground: oklch(0.44 0.03 60);
|
|
--accent: oklch(0.935 0.03 78);
|
|
--accent-foreground: oklch(0.25 0.045 50);
|
|
--destructive: oklch(0.5 0.17 28);
|
|
--border: oklch(0.86 0.022 78);
|
|
--input: oklch(0.6 0.035 65);
|
|
--ring: oklch(0.47 0.115 55);
|
|
--warning: oklch(0.79 0.15 80);
|
|
--warning-foreground: oklch(0.23 0.04 60);
|
|
--success: oklch(0.46 0.08 145);
|
|
--success-foreground: oklch(0.98 0.015 100);
|
|
--condition-excellent: oklch(0.62 0.13 150);
|
|
--condition-excellent-foreground: oklch(0.15 0.04 150);
|
|
--condition-good: oklch(0.645 0.13 125);
|
|
--condition-good-foreground: oklch(0.17 0.04 125);
|
|
--condition-average: oklch(0.665 0.125 88);
|
|
--condition-average-foreground: oklch(0.19 0.04 90);
|
|
--condition-weak: oklch(0.665 0.14 58);
|
|
--condition-weak-foreground: oklch(0.18 0.04 55);
|
|
--condition-critical: oklch(0.62 0.17 30);
|
|
--condition-critical-foreground: oklch(0.15 0.04 30);
|
|
--chart-1: oklch(0.56 0.13 55);
|
|
--chart-2: oklch(0.46 0.08 145);
|
|
--chart-3: oklch(0.6 0.12 85);
|
|
--chart-4: oklch(0.5 0.17 28);
|
|
--chart-5: oklch(0.52 0.08 250);
|
|
--radius: 0.75rem;
|
|
--sidebar: oklch(0.995 0.004 90);
|
|
--sidebar-foreground: oklch(0.21 0.03 55);
|
|
--sidebar-primary: oklch(0.8 0.145 78);
|
|
--sidebar-primary-foreground: oklch(0.21 0.035 55);
|
|
--sidebar-accent: oklch(0.935 0.03 78);
|
|
--sidebar-accent-foreground: oklch(0.25 0.045 50);
|
|
--sidebar-border: oklch(0.86 0.022 78);
|
|
--sidebar-ring: oklch(0.47 0.115 55);
|
|
--shadow-elevated: 0 1px 2px -1px oklch(0.3 0.05 50 / 8%), 0 8px 24px -8px oklch(0.3 0.05 50 / 16%);
|
|
--shadow-soft: 0 1px 2px -1px oklch(0.3 0.05 50 / 6%), 0 4px 12px -4px oklch(0.3 0.05 50 / 10%);
|
|
/* Hive "screen": always dark, in light and dark mode (spec 9.3). */
|
|
--holo-bg: oklch(0.18 0.03 250);
|
|
--holo-edge: oklch(0.72 0.15 243);
|
|
--holo-edge-strong: oklch(0.87 0.07 238);
|
|
--holo-fill: oklch(0.78 0.14 220 / 10%);
|
|
--holo-label-bg: oklch(0.26 0.04 250);
|
|
--holo-label-fg: oklch(0.95 0.02 230);
|
|
/* T5 tokens (spec 4.2). */
|
|
--primary-ink: oklch(0.47 0.115 55);
|
|
--warning-ink: oklch(0.5 0.11 65);
|
|
--destructive-foreground: oklch(0.985 0.005 30);
|
|
--condition-excellent-ink: oklch(0.4 0.09 150);
|
|
--condition-good-ink: oklch(0.41 0.09 125);
|
|
--condition-average-ink: oklch(0.44 0.09 85);
|
|
--condition-weak-ink: oklch(0.46 0.12 52);
|
|
--condition-critical-ink: oklch(0.47 0.16 28);
|
|
--area-betrieb: oklch(0.46 0.08 150);
|
|
--area-erfassung: oklch(0.5 0.12 60);
|
|
--area-arbeit: oklch(0.48 0.08 250);
|
|
--area-ernte: oklch(0.52 0.11 75);
|
|
--area-neutral: oklch(0.45 0.02 60);
|
|
--queen-white: oklch(0.97 0.005 90);
|
|
--queen-yellow: oklch(0.86 0.17 95);
|
|
--queen-red: oklch(0.58 0.2 27);
|
|
--queen-green: oklch(0.58 0.15 145);
|
|
--queen-blue: oklch(0.52 0.15 255);
|
|
--focus-width: 2px;
|
|
--focus-offset: 2px;
|
|
--control-border-width: 1px;
|
|
--comb-stroke-1: 2px;
|
|
--comb-stroke-2: 4px;
|
|
--comb-stroke-3: 6px;
|
|
}
|
|
|
|
.dark {
|
|
--background: oklch(0.19 0.016 55);
|
|
--foreground: oklch(0.95 0.018 80);
|
|
--card: oklch(0.235 0.018 55);
|
|
--card-foreground: oklch(0.95 0.018 80);
|
|
--popover: oklch(0.235 0.018 55);
|
|
--popover-foreground: oklch(0.95 0.018 80);
|
|
--primary: oklch(0.8 0.14 78);
|
|
--primary-foreground: oklch(0.19 0.03 55);
|
|
--secondary: oklch(0.66 0.08 145);
|
|
--secondary-foreground: oklch(0.16 0.02 145);
|
|
--muted: oklch(0.28 0.018 55);
|
|
--muted-foreground: oklch(0.76 0.025 75);
|
|
--accent: oklch(0.31 0.03 60);
|
|
--accent-foreground: oklch(0.95 0.018 80);
|
|
--destructive: oklch(0.7 0.15 28);
|
|
--border: oklch(0.34 0.02 60);
|
|
--input: oklch(0.56 0.025 70);
|
|
--ring: oklch(0.82 0.13 80);
|
|
--warning: oklch(0.8 0.14 80);
|
|
--warning-foreground: oklch(0.2 0.03 60);
|
|
--success: oklch(0.7 0.09 145);
|
|
--success-foreground: oklch(0.16 0.02 145);
|
|
--condition-excellent: oklch(0.68 0.12 150);
|
|
--condition-excellent-foreground: oklch(0.17 0.04 150);
|
|
--condition-good: oklch(0.72 0.12 125);
|
|
--condition-good-foreground: oklch(0.18 0.04 125);
|
|
--condition-average: oklch(0.77 0.13 90);
|
|
--condition-average-foreground: oklch(0.2 0.04 90);
|
|
--condition-weak: oklch(0.74 0.13 60);
|
|
--condition-weak-foreground: oklch(0.19 0.04 55);
|
|
--condition-critical: oklch(0.68 0.16 28);
|
|
--condition-critical-foreground: oklch(0.16 0.04 30);
|
|
--chart-1: oklch(0.78 0.13 70);
|
|
--chart-2: oklch(0.7 0.09 145);
|
|
--chart-3: oklch(0.82 0.12 90);
|
|
--chart-4: oklch(0.7 0.15 28);
|
|
--chart-5: oklch(0.72 0.08 250);
|
|
--sidebar: oklch(0.235 0.018 55);
|
|
--sidebar-foreground: oklch(0.95 0.018 80);
|
|
--sidebar-primary: oklch(0.8 0.14 78);
|
|
--sidebar-primary-foreground: oklch(0.19 0.03 55);
|
|
--sidebar-accent: oklch(0.31 0.03 60);
|
|
--sidebar-accent-foreground: oklch(0.95 0.018 80);
|
|
--sidebar-border: oklch(0.34 0.02 60);
|
|
--sidebar-ring: oklch(0.82 0.13 80);
|
|
--shadow-elevated: 0 1px 2px -1px oklch(0 0 0 / 30%), 0 8px 24px -8px oklch(0 0 0 / 45%);
|
|
--shadow-soft: 0 1px 2px -1px oklch(0 0 0 / 25%), 0 4px 12px -4px oklch(0 0 0 / 30%);
|
|
/* Hive "screen": always dark, in light and dark mode (spec 9.3). */
|
|
--holo-bg: oklch(0.18 0.03 250);
|
|
--holo-edge: oklch(0.72 0.15 243);
|
|
--holo-edge-strong: oklch(0.87 0.07 238);
|
|
--holo-fill: oklch(0.78 0.14 220 / 10%);
|
|
--holo-label-bg: oklch(0.26 0.04 250);
|
|
--holo-label-fg: oklch(0.95 0.02 230);
|
|
/* T5 tokens (spec 4.2). */
|
|
--primary-ink: oklch(0.82 0.13 80);
|
|
--warning-ink: oklch(0.82 0.13 82);
|
|
--destructive-foreground: oklch(0.17 0.03 30);
|
|
--condition-excellent-ink: oklch(0.8 0.11 150);
|
|
--condition-good-ink: oklch(0.83 0.11 125);
|
|
--condition-average-ink: oklch(0.86 0.11 90);
|
|
--condition-weak-ink: oklch(0.82 0.11 60);
|
|
--condition-critical-ink: oklch(0.78 0.11 28);
|
|
--area-betrieb: oklch(0.74 0.09 150);
|
|
--area-erfassung: oklch(0.8 0.12 70);
|
|
--area-arbeit: oklch(0.76 0.07 250);
|
|
--area-ernte: oklch(0.8 0.1 80);
|
|
--area-neutral: oklch(0.76 0.02 70);
|
|
--queen-white: oklch(0.97 0.005 90);
|
|
--queen-yellow: oklch(0.86 0.17 95);
|
|
--queen-red: oklch(0.62 0.2 27);
|
|
--queen-green: oklch(0.66 0.15 145);
|
|
--queen-blue: oklch(0.62 0.15 255);
|
|
}
|
|
|
|
/* Sun ("Sonne"): maximum luminance difference outdoors (spec 4.3). The two sets follow the
|
|
order light, dark, sun-light, sun-dark; sun-dark restates everything sun-light sets. */
|
|
:root[data-contrast="sun"] {
|
|
--background: oklch(1 0 0);
|
|
--card: oklch(1 0 0);
|
|
--popover: oklch(1 0 0);
|
|
--sidebar: oklch(1 0 0);
|
|
--foreground: oklch(0.13 0.02 55);
|
|
--card-foreground: oklch(0.13 0.02 55);
|
|
--popover-foreground: oklch(0.13 0.02 55);
|
|
--sidebar-foreground: oklch(0.13 0.02 55);
|
|
--primary-foreground: oklch(0.13 0.02 55);
|
|
--ring: oklch(0.13 0.02 55);
|
|
--muted: oklch(0.95 0.01 80);
|
|
--muted-foreground: oklch(0.32 0.03 60);
|
|
--border: oklch(0.4 0.03 60);
|
|
--input: oklch(0.2 0.03 55);
|
|
--primary-ink: oklch(0.38 0.1 52);
|
|
--text-sm: 1rem;
|
|
--text-xs: 0.875rem;
|
|
--focus-width: 3px;
|
|
--control-border-width: 2px;
|
|
--comb-stroke-1: 3px;
|
|
--comb-stroke-2: 5px;
|
|
--comb-stroke-3: 7px;
|
|
--shadow-soft: none;
|
|
--shadow-elevated: none;
|
|
/* Hive stage: black screen, pure white edges and label text. */
|
|
--holo-bg: oklch(0 0 0);
|
|
--holo-edge: oklch(1 0 0);
|
|
--holo-edge-strong: oklch(1 0 0);
|
|
--holo-label-fg: oklch(1 0 0);
|
|
--holo-label-bg: oklch(0.12 0 0);
|
|
}
|
|
|
|
.dark[data-contrast="sun"] {
|
|
--background: oklch(0.1 0.005 55);
|
|
--card: oklch(0.1 0.005 55);
|
|
--popover: oklch(0.1 0.005 55);
|
|
--sidebar: oklch(0.1 0.005 55);
|
|
--foreground: oklch(0.99 0.005 85);
|
|
--card-foreground: oklch(0.99 0.005 85);
|
|
--popover-foreground: oklch(0.99 0.005 85);
|
|
--sidebar-foreground: oklch(0.99 0.005 85);
|
|
--primary-foreground: oklch(0.19 0.03 55);
|
|
--ring: oklch(0.99 0.005 85);
|
|
--muted: oklch(0.2 0.01 55);
|
|
--muted-foreground: oklch(0.88 0.02 80);
|
|
--border: oklch(0.7 0.02 70);
|
|
--input: oklch(0.92 0.01 80);
|
|
--primary-ink: oklch(0.82 0.13 80);
|
|
--text-sm: 1rem;
|
|
--text-xs: 0.875rem;
|
|
--focus-width: 3px;
|
|
--control-border-width: 2px;
|
|
--comb-stroke-1: 3px;
|
|
--comb-stroke-2: 5px;
|
|
--comb-stroke-3: 7px;
|
|
--shadow-soft: none;
|
|
--shadow-elevated: none;
|
|
--holo-bg: oklch(0 0 0);
|
|
--holo-edge: oklch(1 0 0);
|
|
--holo-edge-strong: oklch(1 0 0);
|
|
--holo-label-fg: oklch(1 0 0);
|
|
--holo-label-bg: oklch(0.12 0 0);
|
|
}
|
|
|
|
/* The hive stage is its own always-dark surface; the page focus ring (--primary-ink) has less
|
|
than 3:1 on it (spec 17.8), so the stage draws the ring in its strong edge colour. */
|
|
.holo-stage {
|
|
--ring: var(--holo-edge-strong);
|
|
}
|
|
/* A page-coloured card on the stage (the outline panel) takes the page ring back. The root
|
|
keeps a copy of its ring for that, resolved for the current set (light, dark, sun). */
|
|
html {
|
|
--page-ring: var(--ring);
|
|
}
|
|
.holo-stage .stage-card {
|
|
--ring: var(--page-ring);
|
|
}
|
|
|
|
/* Tinted surfaces: set --tint (and --tint-ink) on the element. In sun the tint becomes the
|
|
plain card with a 2 px border in the ink instead of a 15 % wash (spec 4.3). */
|
|
@layer components {
|
|
.tint {
|
|
--tint: var(--primary);
|
|
--tint-ink: var(--primary-ink);
|
|
background-color: color-mix(in oklch, var(--tint) 15%, transparent);
|
|
}
|
|
}
|
|
:root[data-contrast="sun"] .tint {
|
|
background-color: var(--card);
|
|
border: var(--control-border-width) solid var(--tint-ink);
|
|
}
|
|
:root[data-contrast="sun"] body header.sticky {
|
|
background-color: var(--card);
|
|
backdrop-filter: none;
|
|
}
|
|
|
|
/* Print and PDF preview always use the light set (spec 4.1). Kept in step with :root by
|
|
contrast.spec.ts. */
|
|
@media print {
|
|
:root,
|
|
.dark,
|
|
:root[data-contrast="sun"],
|
|
.dark[data-contrast="sun"] {
|
|
--background: oklch(0.968 0.014 85);
|
|
--foreground: oklch(0.21 0.03 55);
|
|
--card: oklch(0.995 0.004 90);
|
|
--card-foreground: oklch(0.21 0.03 55);
|
|
--popover: oklch(0.995 0.004 90);
|
|
--popover-foreground: oklch(0.21 0.03 55);
|
|
--primary: oklch(0.8 0.145 78);
|
|
--primary-foreground: oklch(0.21 0.035 55);
|
|
--secondary: oklch(0.44 0.07 145);
|
|
--secondary-foreground: oklch(0.98 0.015 100);
|
|
--muted: oklch(0.925 0.018 82);
|
|
--muted-foreground: oklch(0.44 0.03 60);
|
|
--accent: oklch(0.935 0.03 78);
|
|
--accent-foreground: oklch(0.25 0.045 50);
|
|
--destructive: oklch(0.5 0.17 28);
|
|
--border: oklch(0.86 0.022 78);
|
|
--input: oklch(0.6 0.035 65);
|
|
--ring: oklch(0.47 0.115 55);
|
|
--warning: oklch(0.79 0.15 80);
|
|
--warning-foreground: oklch(0.23 0.04 60);
|
|
--success: oklch(0.46 0.08 145);
|
|
--success-foreground: oklch(0.98 0.015 100);
|
|
--condition-excellent: oklch(0.62 0.13 150);
|
|
--condition-excellent-foreground: oklch(0.15 0.04 150);
|
|
--condition-good: oklch(0.645 0.13 125);
|
|
--condition-good-foreground: oklch(0.17 0.04 125);
|
|
--condition-average: oklch(0.665 0.125 88);
|
|
--condition-average-foreground: oklch(0.19 0.04 90);
|
|
--condition-weak: oklch(0.665 0.14 58);
|
|
--condition-weak-foreground: oklch(0.18 0.04 55);
|
|
--condition-critical: oklch(0.62 0.17 30);
|
|
--condition-critical-foreground: oklch(0.15 0.04 30);
|
|
--chart-1: oklch(0.56 0.13 55);
|
|
--chart-2: oklch(0.46 0.08 145);
|
|
--chart-3: oklch(0.6 0.12 85);
|
|
--chart-4: oklch(0.5 0.17 28);
|
|
--chart-5: oklch(0.52 0.08 250);
|
|
--sidebar: oklch(0.995 0.004 90);
|
|
--sidebar-foreground: oklch(0.21 0.03 55);
|
|
--sidebar-primary: oklch(0.8 0.145 78);
|
|
--sidebar-primary-foreground: oklch(0.21 0.035 55);
|
|
--sidebar-accent: oklch(0.935 0.03 78);
|
|
--sidebar-accent-foreground: oklch(0.25 0.045 50);
|
|
--sidebar-border: oklch(0.86 0.022 78);
|
|
--sidebar-ring: oklch(0.47 0.115 55);
|
|
--shadow-elevated: 0 1px 2px -1px oklch(0.3 0.05 50 / 8%), 0 8px 24px -8px oklch(0.3 0.05 50 / 16%);
|
|
--shadow-soft: 0 1px 2px -1px oklch(0.3 0.05 50 / 6%), 0 4px 12px -4px oklch(0.3 0.05 50 / 10%);
|
|
--holo-bg: oklch(0.18 0.03 250);
|
|
--holo-edge: oklch(0.72 0.15 243);
|
|
--holo-edge-strong: oklch(0.87 0.07 238);
|
|
--holo-fill: oklch(0.78 0.14 220 / 10%);
|
|
--holo-label-bg: oklch(0.26 0.04 250);
|
|
--holo-label-fg: oklch(0.95 0.02 230);
|
|
--primary-ink: oklch(0.47 0.115 55);
|
|
--warning-ink: oklch(0.5 0.11 65);
|
|
--destructive-foreground: oklch(0.985 0.005 30);
|
|
--condition-excellent-ink: oklch(0.4 0.09 150);
|
|
--condition-good-ink: oklch(0.41 0.09 125);
|
|
--condition-average-ink: oklch(0.44 0.09 85);
|
|
--condition-weak-ink: oklch(0.46 0.12 52);
|
|
--condition-critical-ink: oklch(0.47 0.16 28);
|
|
--area-betrieb: oklch(0.46 0.08 150);
|
|
--area-erfassung: oklch(0.5 0.12 60);
|
|
--area-arbeit: oklch(0.48 0.08 250);
|
|
--area-ernte: oklch(0.52 0.11 75);
|
|
--area-neutral: oklch(0.45 0.02 60);
|
|
--queen-white: oklch(0.97 0.005 90);
|
|
--queen-yellow: oklch(0.86 0.17 95);
|
|
--queen-red: oklch(0.58 0.2 27);
|
|
--queen-green: oklch(0.58 0.15 145);
|
|
--queen-blue: oklch(0.52 0.15 255);
|
|
--text-sm: 0.875rem;
|
|
--text-xs: 0.8125rem;
|
|
--focus-width: 2px;
|
|
--control-border-width: 1px;
|
|
--comb-stroke-1: 2px;
|
|
--comb-stroke-2: 4px;
|
|
--comb-stroke-3: 6px;
|
|
}
|
|
}
|
|
|
|
/* Forced colours: the system palette wins; strokes use CanvasText so shapes stay visible. */
|
|
@media (forced-colors: active) {
|
|
:root,
|
|
.dark,
|
|
:root[data-contrast="sun"],
|
|
.dark[data-contrast="sun"] {
|
|
--ring: CanvasText;
|
|
--border: CanvasText;
|
|
--input: CanvasText;
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
App chrome (see app/(app)/layout.tsx)
|
|
The page scrolls on the window. On phones a fixed bottom nav sits over its
|
|
lower edge, on iOS above the home indicator (needs viewport-fit=cover).
|
|
Content padding, the sticky save bar, the quick-add button and the focus
|
|
scroll-padding below all derive from these values, so they stay in step.
|
|
------------------------------------------------------------------------ */
|
|
:root {
|
|
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
|
|
--safe-area-left: env(safe-area-inset-left, 0px);
|
|
--safe-area-right: env(safe-area-inset-right, 0px);
|
|
--bottom-nav-height: calc(4rem + var(--safe-area-bottom));
|
|
/* Sticky header (3.5rem) plus breathing room. */
|
|
--header-clearance: 4.5rem;
|
|
/* StickySubmit with its 48px button (~4.6rem) plus breathing room. */
|
|
--sticky-submit-clearance: 5.5rem;
|
|
/*
|
|
Toasts sit above the sticky save bar. Below sm also above the bottom nav,
|
|
which carries the quick-add button (nav + 1rem + 3rem, less than the bar).
|
|
*/
|
|
--toast-offset-bottom: calc(var(--bottom-nav-height) + var(--sticky-submit-clearance) + 0.5rem);
|
|
|
|
@variant sm {
|
|
--toast-offset-bottom: calc(var(--safe-area-bottom) + var(--sticky-submit-clearance) + 0.5rem);
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border;
|
|
}
|
|
/* One focus style for everything (spec 4.6): a solid ring in --ring with a gap, 3 px in sun.
|
|
Components add no focus classes; a row whose focus target sits inside uses
|
|
focus-ring-within. */
|
|
:where(:focus-visible) {
|
|
outline: var(--focus-width) solid var(--ring);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
/* Firefox: the preflight sets `:-moz-focusring:where(:not(iframe)) { outline: auto }` (0,1,0),
|
|
which beats the rule above. Firefox matches :-moz-focusring exactly where it matches
|
|
:focus-visible (keyboard, not a mouse click), so restating the ring here adds nothing else. */
|
|
:-moz-focusring:where(:not(iframe)) {
|
|
outline: var(--focus-width) solid var(--ring);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
}
|
|
html {
|
|
@apply font-sans;
|
|
/* WCAG 2.4.11: a field scrolled into view by focus must not end up under
|
|
the sticky header, the bottom nav / quick-add button or the save bar. */
|
|
scroll-padding-top: var(--header-clearance);
|
|
scroll-padding-bottom: calc(var(--bottom-nav-height) + var(--sticky-submit-clearance));
|
|
|
|
@variant sm {
|
|
scroll-padding-bottom: calc(var(--sticky-submit-clearance) + var(--safe-area-bottom));
|
|
}
|
|
}
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4 {
|
|
font-family: var(--font-heading);
|
|
letter-spacing: -0.01em;
|
|
}
|
|
::selection {
|
|
background: color-mix(in oklch, var(--primary) 28%, transparent);
|
|
color: var(--foreground);
|
|
}
|
|
input,
|
|
textarea {
|
|
caret-color: var(--primary-ink);
|
|
}
|
|
}
|
|
|
|
/* A row whose focus target sits inside (a label with its checkbox, radio or a visually hidden
|
|
input) also rings the whole row, so the focus is easy to spot from arm's length (spec 4.6). */
|
|
@utility focus-ring-within {
|
|
&:has(:focus-visible) {
|
|
outline: var(--focus-width) solid var(--ring);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Motion levels (see lib/motion/motion-preference.ts)
|
|
html[data-motion] = full | subtle | off, chosen per device in the profile.
|
|
The OS "reduce motion" setting always wins over "full".
|
|
`motion-full:` = spatial movement allowed (level full AND system allows).
|
|
------------------------------------------------------------------------ */
|
|
@custom-variant motion-full {
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
&:where(:root:not([data-motion="subtle"]):not([data-motion="off"]) *) {
|
|
@slot;
|
|
}
|
|
}
|
|
}
|
|
|
|
:root {
|
|
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
}
|
|
|
|
/* Off: every state change is instant. Colour and icon still carry the state. */
|
|
:root[data-motion="off"] *,
|
|
:root[data-motion="off"] *::before,
|
|
:root[data-motion="off"] *::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
transition-delay: 0ms !important;
|
|
}
|
|
|
|
/* Subtle / system reduce: keep fades, drop movement. */
|
|
:root[data-motion="subtle"] .motion-safe\:animate-page-in {
|
|
animation-name: fade-in;
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.motion-safe\:animate-page-in {
|
|
animation: fade-in 160ms ease-out;
|
|
}
|
|
}
|
|
:root[data-motion="subtle"] [data-slot="card"] {
|
|
translate: none !important;
|
|
}
|
|
|
|
@keyframes fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
/* --- Task completion: the one authored moment ------------------------------
|
|
The honey cell fills, the tick draws itself, then the row folds away. */
|
|
.honey-check {
|
|
position: relative;
|
|
display: inline-grid;
|
|
place-items: center;
|
|
flex-shrink: 0;
|
|
width: 2.75rem;
|
|
height: 2.75rem;
|
|
border-radius: 9999px;
|
|
color: var(--primary-foreground);
|
|
}
|
|
.honey-check::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0.375rem;
|
|
border-radius: 0.6rem;
|
|
border: 2px solid var(--input);
|
|
background: var(--card);
|
|
transition:
|
|
border-color 150ms ease-out,
|
|
background-color 150ms ease-out;
|
|
}
|
|
.honey-check::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0.375rem;
|
|
border-radius: 0.6rem;
|
|
background: var(--primary);
|
|
clip-path: circle(0% at 50% 60%);
|
|
transition: clip-path 420ms var(--ease-out-expo);
|
|
}
|
|
.honey-check:hover::before {
|
|
border-color: var(--primary);
|
|
background: color-mix(in oklch, var(--primary) 8%, var(--card));
|
|
}
|
|
.honey-check svg {
|
|
position: relative;
|
|
z-index: 1;
|
|
width: 1.1rem;
|
|
height: 1.1rem;
|
|
stroke-dasharray: 24;
|
|
stroke-dashoffset: 24;
|
|
transition: stroke-dashoffset 260ms var(--ease-out-expo) 160ms;
|
|
}
|
|
.honey-check[aria-checked="true"]::after {
|
|
clip-path: circle(75% at 50% 60%);
|
|
}
|
|
.honey-check[aria-checked="true"] svg {
|
|
stroke-dashoffset: 0;
|
|
}
|
|
|
|
.today-row {
|
|
display: grid;
|
|
grid-template-rows: 1fr;
|
|
opacity: 1;
|
|
transition:
|
|
grid-template-rows 320ms var(--ease-out-expo) 380ms,
|
|
opacity 220ms ease-out 360ms;
|
|
}
|
|
.today-row > * {
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
.today-row[data-leaving="true"] {
|
|
grid-template-rows: 0fr;
|
|
opacity: 0;
|
|
}
|
|
|
|
/* The next step changes: bring the new one in with a short focus pull. */
|
|
@keyframes next-step-in {
|
|
from {
|
|
opacity: 0;
|
|
filter: blur(6px);
|
|
transform: translateY(8px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
filter: blur(0);
|
|
transform: none;
|
|
}
|
|
}
|
|
@keyframes next-step-fade {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
.next-step-enter {
|
|
animation: next-step-in 480ms var(--ease-out-expo);
|
|
}
|
|
:root[data-motion="subtle"] .next-step-enter {
|
|
animation: next-step-fade 200ms ease-out;
|
|
}
|
|
:root[data-motion="subtle"] .today-row,
|
|
:root[data-motion="subtle"] .honey-check::after {
|
|
transition-duration: 120ms;
|
|
transition-delay: 0ms;
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.next-step-enter {
|
|
animation: next-step-fade 200ms ease-out;
|
|
}
|
|
.today-row,
|
|
.honey-check::after,
|
|
.honey-check svg {
|
|
transition-duration: 120ms;
|
|
transition-delay: 0ms;
|
|
}
|
|
} |