- Refactored navigation with grouped sections (Operations, Cultivation, Analytics, etc.) - Added RBAC-based navigation filtering by user role - Created DevTools panel for quick user switching during testing - Added collapsible sidebar sections on desktop - Mobile: bottom nav bar (4 items + More) with slide-up sheet - Enhanced seed data with [DEMO] prefix markers - Added multiple demo users: Owner, Manager, Cultivator, Worker - Fixed domain to runfoo.run - Added Audit Log and SOP Library pages to navigation - Created usePermissions hook and RoleBadge component
360 lines
No EOL
7.2 KiB
CSS
360 lines
No EOL
7.2 KiB
CSS
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');
|
|
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
|
|
/* Root variables */
|
|
:root {
|
|
--font-sans: 'Space Grotesk', 'SF Pro Display', system-ui, -apple-system, sans-serif;
|
|
--font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
|
|
}
|
|
|
|
/* Base styles - Using 100% honors browser/OS text size settings */
|
|
html {
|
|
font-size: 100%;
|
|
/* Respects user's browser settings (typically 16px default) */
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
scroll-behavior: smooth;
|
|
/* Allow up to 200% zoom without horizontal scroll */
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* Scale up base font for users with larger text preferences */
|
|
@media screen and (min-resolution: 1dppx) {
|
|
html {
|
|
/* Uses browser's default, which respects system accessibility settings */
|
|
font-size: clamp(100%, 1vw + 0.75rem, 125%);
|
|
}
|
|
}
|
|
|
|
/* High contrast mode support */
|
|
@media (prefers-contrast: high) {
|
|
:root {
|
|
--contrast-multiplier: 1.25;
|
|
}
|
|
}
|
|
|
|
/* Forced colors (Windows High Contrast) */
|
|
@media (forced-colors: active) {
|
|
* {
|
|
border-color: currentColor !important;
|
|
}
|
|
}
|
|
|
|
body {
|
|
@apply bg-slate-50 dark:bg-slate-900 text-slate-900 dark:text-slate-50;
|
|
font-family: var(--font-sans);
|
|
font-feature-settings: 'ss01' 1, 'ss02' 1;
|
|
letter-spacing: -0.011em;
|
|
transition: background-color 0.3s ease, color 0.3s ease;
|
|
}
|
|
|
|
/* Code */
|
|
code,
|
|
pre,
|
|
kbd,
|
|
samp {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* Touch targets */
|
|
button,
|
|
input,
|
|
select,
|
|
textarea,
|
|
a {
|
|
min-height: 44px;
|
|
min-width: 44px;
|
|
-webkit-tap-highlight-color: transparent;
|
|
touch-action: manipulation;
|
|
}
|
|
|
|
/* Focus */
|
|
*:focus-visible {
|
|
@apply outline-none ring-2 ring-emerald-500 ring-offset-2;
|
|
transition: box-shadow 0.2s ease;
|
|
}
|
|
|
|
/* Skip link */
|
|
.skip-to-main {
|
|
@apply absolute left-0 top-0 -translate-y-full bg-emerald-600 text-white px-4 py-2 rounded-br-lg font-medium;
|
|
@apply focus:translate-y-0 z-50;
|
|
transition: transform 0.2s ease;
|
|
}
|
|
|
|
/* Reduced motion */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|
|
|
|
/* Headings */
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
@apply font-bold tracking-tight;
|
|
letter-spacing: -0.025em;
|
|
}
|
|
|
|
h1 {
|
|
@apply text-4xl md:text-5xl;
|
|
}
|
|
|
|
h2 {
|
|
@apply text-3xl md:text-4xl;
|
|
}
|
|
|
|
h3 {
|
|
@apply text-2xl md:text-3xl;
|
|
}
|
|
|
|
h4 {
|
|
@apply text-xl md:text-2xl;
|
|
}
|
|
|
|
/* Links */
|
|
a {
|
|
@apply text-emerald-600 dark:text-emerald-400;
|
|
transition: color 0.15s ease;
|
|
}
|
|
|
|
a:hover {
|
|
@apply text-emerald-700 dark:text-emerald-300;
|
|
}
|
|
|
|
/* Selection */
|
|
::selection {
|
|
@apply bg-emerald-500/20 text-emerald-900 dark:text-emerald-100;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
|
|
/* Scrollbar */
|
|
.custom-scrollbar::-webkit-scrollbar {
|
|
@apply w-2 h-2;
|
|
}
|
|
|
|
.custom-scrollbar::-webkit-scrollbar-track {
|
|
@apply bg-slate-100 dark:bg-slate-800;
|
|
}
|
|
|
|
.custom-scrollbar::-webkit-scrollbar-thumb {
|
|
@apply bg-emerald-400 dark:bg-emerald-600 rounded-full;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
@apply bg-emerald-500;
|
|
}
|
|
|
|
/* Fade in animation */
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(10px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.animate-fade-in {
|
|
animation: fadeIn 0.3s ease-out;
|
|
}
|
|
|
|
/* Slide in animation */
|
|
@keyframes slideIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(-20px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.animate-slide-in {
|
|
animation: slideIn 0.3s ease-out;
|
|
}
|
|
|
|
/* Scale in animation */
|
|
@keyframes scaleIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
|
|
.animate-scale-in {
|
|
animation: scaleIn 0.2s ease-out;
|
|
}
|
|
|
|
/* Slide up animation for mobile sheets */
|
|
@keyframes slideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(100%);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.animate-slide-up {
|
|
animation: slideUp 0.3s ease-out;
|
|
}
|
|
|
|
/* No scrollbar utility */
|
|
.no-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.no-scrollbar {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
/* Shimmer effect */
|
|
@keyframes shimmer {
|
|
0% {
|
|
background-position: -1000px 0;
|
|
}
|
|
|
|
100% {
|
|
background-position: 1000px 0;
|
|
}
|
|
}
|
|
|
|
.animate-shimmer {
|
|
background: linear-gradient(90deg,
|
|
rgba(255, 255, 255, 0) 0%,
|
|
rgba(255, 255, 255, 0.2) 50%,
|
|
rgba(255, 255, 255, 0) 100%);
|
|
background-size: 1000px 100%;
|
|
animation: shimmer 2s infinite;
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
|
|
/* Screen reader only - visually hidden but accessible */
|
|
.sr-only {
|
|
position: absolute !important;
|
|
width: 1px !important;
|
|
height: 1px !important;
|
|
padding: 0 !important;
|
|
margin: -1px !important;
|
|
overflow: hidden !important;
|
|
clip: rect(0, 0, 0, 0) !important;
|
|
white-space: nowrap !important;
|
|
border: 0 !important;
|
|
}
|
|
|
|
/* Not screen reader only - opposite of sr-only */
|
|
.not-sr-only {
|
|
position: static !important;
|
|
width: auto !important;
|
|
height: auto !important;
|
|
padding: 0 !important;
|
|
margin: 0 !important;
|
|
overflow: visible !important;
|
|
clip: auto !important;
|
|
white-space: normal !important;
|
|
}
|
|
|
|
/* Focus visible only (hide when not keyboard focused) */
|
|
.focus-visible-only:not(:focus-visible) {
|
|
@apply sr-only;
|
|
}
|
|
|
|
/* High contrast mode enhancements */
|
|
@media (prefers-contrast: more) {
|
|
.high-contrast-border {
|
|
@apply border-2 border-current;
|
|
}
|
|
|
|
.high-contrast-text {
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Increase button contrast */
|
|
button:not([disabled]),
|
|
[role="button"]:not([disabled]) {
|
|
@apply border border-current;
|
|
}
|
|
|
|
/* Stronger focus indicator */
|
|
*:focus-visible {
|
|
@apply ring-4 ring-offset-4;
|
|
}
|
|
}
|
|
|
|
/* Large text mode support */
|
|
.text-scalable {
|
|
font-size: clamp(1rem, 2vw, 1.25rem);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* Respect user motion preferences */
|
|
.motion-safe {
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
transition: all 0.3s ease;
|
|
}
|
|
}
|
|
|
|
.motion-reduce {
|
|
@media (prefers-reduced-motion: reduce) {
|
|
transition: none;
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
/* Touch-friendly spacing */
|
|
.touch-target {
|
|
min-height: 44px;
|
|
min-width: 44px;
|
|
@apply flex items-center justify-center;
|
|
}
|
|
|
|
/* Color blind friendly patterns */
|
|
.pattern-stripe {
|
|
background-image: repeating-linear-gradient(45deg,
|
|
transparent,
|
|
transparent 5px,
|
|
currentColor 5px,
|
|
currentColor 10px);
|
|
opacity: 0.1;
|
|
}
|
|
|
|
.pattern-dots {
|
|
background-image: radial-gradient(currentColor 1px,
|
|
transparent 1px);
|
|
background-size: 8px 8px;
|
|
opacity: 0.1;
|
|
}
|
|
} |