@import 'tailwindcss'; /* * perinco CRM - Corporate Identity * Farben direkt aus dem perinco Logo gesampelt: * Gruen #6BA04A (Akzent #68A33F) * Grau #6E6E6E * Schrift: perinco.de nutzt Avenir LT (Light 35 / Heavy 85). Ist Avenir lokal * installiert, wird es verwendet, sonst Nunito Sans als freies Aequivalent. */ /* * Vier Farbwelten, jede in hell und dunkel. Sie haengen an einer Klasse am * (theme-pixel, theme-outdoor, theme-cyberpunk); ohne Klasse gilt * perinco. Der Modus bleibt die vorhandene Klasse "dark". * * Warum das ohne Aenderung an den Komponenten geht: im Markup steht nirgends * eine feste Farbe, sondern durchgaengig ink-*, brand-*, canvas und surface - * und Tailwind v4 loest auch Eckenradien (--radius-*), Schatten und Schriften * ueber Variablen auf. Ein Theme tauscht also nur Werte. * * Die Rollen der Skalen sind ueber die ganze App gleich (nachgezaehlt, damit * ein Theme nichts unlesbar macht): * ink-50/100 Flaechen und Hover * ink-200 Rahmen (224 von 225 Verwendungen) * ink-300-900 Text, 400 traegt die Hinweistexte * ink-950 liegt nur unter Dialog-Overlays, bleibt immer dunkel * brand-50/100 getoente Flaechen * brand-200-400 Rahmen * brand-500/600 gefuellte Knoepfe - hier steht WEISSE Schrift drauf, jedes * Theme braucht dort also einen ausreichend dunklen Ton * brand-600-800 Text auf getoenten Flaechen */ @theme { --font-sans: 'Avenir Next', 'Avenir', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; /* * Zweite Schrift fuer Ueberschriften und Feldbeschriftungen. Meist ist sie mit * der Grundschrift identisch; nur "Pixel Art" setzt hier eine andere ein - die * Pixelschrift bleibt damit aus dem Fliesstext heraus, ohne dass es dafuer * eigene Selektoren braucht. */ --font-display: 'Avenir Next', 'Avenir', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; /* * Flaechen sind bewusst semantisch benannt statt "weiss": im Dark Mode werden * unten nur diese Variablen umgesetzt, die Utility-Klassen in den Komponenten * bleiben unveraendert. * canvas = Seitenhintergrund * surface = Karten, Leisten, Dialoge */ --color-canvas: #f7f7f7; --color-surface: #ffffff; --color-brand-50: #f2f8ee; --color-brand-100: #e2efd9; --color-brand-200: #c6e0b6; --color-brand-300: #a3cd8a; --color-brand-400: #85ba66; --color-brand-500: #6ba04a; --color-brand-600: #58873b; --color-brand-700: #456a2f; --color-brand-800: #375427; --color-brand-900: #2d4421; --color-brand-accent: #68a33f; --color-ink-50: #f7f7f7; --color-ink-100: #ededed; --color-ink-200: #dcdcdc; --color-ink-300: #c2c2c2; --color-ink-400: #9a9a9a; --color-ink-500: #6e6e6e; --color-ink-600: #5a5a5a; --color-ink-700: #464646; --color-ink-800: #333333; --color-ink-900: #1f1f1f; --color-ink-950: #141414; --shadow-card: 0 1px 2px rgb(31 31 31 / 0.04), 0 4px 16px rgb(31 31 31 / 0.06); --shadow-lift: 0 8px 28px rgb(31 31 31 / 0.1); } /* * Dark Mode. Die Komponenten benutzen durchgaengig die Skalen ink-* und brand-* * sowie canvas/surface - hier werden nur deren Werte getauscht, deshalb braucht * es keine dark:-Varianten im Markup. * * Zwei Ausnahmen bleiben absichtlich in beiden Modi gleich: * ink-950 - liegt nur unter Dialog-Overlays, muss also dunkel bleiben * text-white - steht immer auf farbigen Flaechen (Buttons, Termin-Chips) */ .dark { --color-canvas: #141414; --color-surface: #1c1c1c; /* Neutrale Skala gedreht: 50 = dunkelste Flaeche, 900 = hellster Text */ --color-ink-50: #1f1f1f; --color-ink-100: #292929; --color-ink-200: #383838; /* Nicht die exakte Umkehrung von #c2c2c2: dunkler waeren Hinweistexte (text-ink-300) auf der Flaeche kaum noch zu lesen. */ --color-ink-300: #6e6e6e; --color-ink-400: #909090; --color-ink-500: #a8a8a8; --color-ink-600: #bdbdbd; --color-ink-700: #d2d2d2; --color-ink-800: #e6e6e6; --color-ink-900: #f5f5f5; --color-ink-950: #000000; /* * brand-500 bleibt das CI-Gruen (Buttons). Die hellen Stufen werden zu * dunklen Tints (Hintergruende), die dunklen zu hellen Toenen (Text) - 600 * dient beidem: als hellerer Button-Hover und als lesbare Textfarbe. */ --color-brand-50: #1d2b15; --color-brand-100: #26381c; --color-brand-200: #3a5a29; --color-brand-300: #4e7739; --color-brand-400: #6b9f4f; --color-brand-600: #7fb75c; --color-brand-700: #a3cd8a; --color-brand-800: #c6e0b6; --color-brand-900: #e2efd9; /* * Statusfarben der Kontakte und Toasts sind getoente Pillen: helle Flaeche mit * dunklem Text. Im Dark Mode wird das gedreht. Die Stufen 500/600 bleiben * unberuehrt - dort steht weisse Schrift drauf (Loeschen-Button). */ --color-sky-50: #0d2537; --color-sky-200: #1d4a6b; --color-sky-700: #7cc4ef; --color-amber-50: #2e2008; --color-amber-200: #5c4210; --color-amber-700: #f0b356; --color-violet-50: #241a3d; --color-violet-200: #3f2f66; --color-violet-700: #b49bf2; --color-red-50: #2e1414; --color-red-200: #5e2626; --color-red-700: #f28b8b; } /* =========================================================================== * Outdoor * * Wanderkarte und Bergsee: Sandpapier als Flaeche, Seeblau-Gruen als Akzent, * warme Lehmgrautoene fuer Text. Bewusst kein zweites Blattgruen - das haette * neben perinco wie ein Versehen gewirkt. Der Unterschied faellt an drei * Stellen auf: die Flaeche ist warm statt neutral, die Ecken sind runder und * die Schatten weicher. * * Der helle Block ist mit :not(.dark) abgegrenzt. Ohne das gewinnt er gegen * .dark (eine Klasse mehr in der Spezifitaet) und der Dunkelmodus waere * kaputt - genau das ist der Grund fuer die Schreibweise in allen Themes. * =========================================================================== */ html.theme-outdoor:not(.dark) { --color-canvas: #f2eee3; --color-surface: #fdfbf6; --color-brand-50: #e8f2f1; --color-brand-100: #d2e6e3; --color-brand-200: #a8cfca; --color-brand-300: #74b3ac; --color-brand-400: #3f938b; --color-brand-500: #12736c; --color-brand-600: #0d5d57; --color-brand-700: #0a4a45; --color-brand-800: #073833; --color-brand-900: #052b27; --color-brand-accent: #12736c; /* Lehmgrau: dieselbe Helligkeitstreppe wie perinco, nur mit warmem Stich. */ --color-ink-50: #f4f0e6; --color-ink-100: #e9e3d4; --color-ink-200: #d6cdb8; --color-ink-300: #a1977f; /* Hinweistexte (text-ink-400, 241 Stellen) muessen auf dem Sand lesbar bleiben - deshalb dunkler als die reine Umkehrung. */ --color-ink-400: #6f6650; --color-ink-500: #5c5344; --color-ink-600: #4b4436; --color-ink-700: #3b352a; --color-ink-800: #2b271e; --color-ink-900: #1d1a14; --color-ink-950: #100e0a; /* Runder und weicher als perinco - der zweite Wiedererkennungswert. */ --radius-sm: 0.3rem; --radius-md: 0.45rem; --radius-lg: 0.65rem; --radius-xl: 0.9rem; --radius-2xl: 1.25rem; --shadow-card: 0 2px 4px rgb(61 53 42 / 0.06), 0 8px 24px rgb(61 53 42 / 0.1); --shadow-lift: 0 12px 32px rgb(61 53 42 / 0.16); --font-sans: 'Cabin', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; --font-display: 'Cabin', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; } /* * Outdoor, dunkel: Waldnacht. Die Flaechen sind nicht neutral schwarz, sondern * ins Tannengruen gezogen; der Text bekommt einen warmen Stich, damit es nicht * nach kaltem Terminal aussieht. */ html.theme-outdoor.dark { --color-canvas: #12170f; --color-surface: #1a2016; --color-brand-50: #0c2b28; --color-brand-100: #103833; --color-brand-200: #17544d; --color-brand-300: #1d6d65; --color-brand-400: #2f9187; --color-brand-500: #14837a; --color-brand-600: #1f9c91; --color-brand-700: #74b3ac; --color-brand-800: #a8cfca; --color-brand-900: #d2e6e3; --color-brand-accent: #1f9c91; --color-ink-50: #1d2419; --color-ink-100: #26301f; --color-ink-200: #35412c; --color-ink-300: #6f7a63; --color-ink-400: #8e9a81; --color-ink-500: #a7b39a; --color-ink-600: #bdc7b2; --color-ink-700: #d3dbca; --color-ink-800: #e6ebe0; --color-ink-900: #f4f7f0; --color-ink-950: #000000; --radius-sm: 0.3rem; --radius-md: 0.45rem; --radius-lg: 0.65rem; --radius-xl: 0.9rem; --radius-2xl: 1.25rem; --shadow-card: 0 2px 4px rgb(0 0 0 / 0.4), 0 8px 24px rgb(0 0 0 / 0.45); --shadow-lift: 0 12px 32px rgb(0 0 0 / 0.6); --font-sans: 'Cabin', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; --font-display: 'Cabin', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; /* Die Statusfarben kommen aus .dark und passen dort schon - hier nur die Pillen leicht ins Warme gezogen, damit sie nicht herausfallen. */ --color-amber-50: #2c2109; --color-amber-200: #574112; } /* =========================================================================== * Pixel Art * * 8-bit: keine runden Ecken, harte Schatten ohne Weichzeichnung, Rahmen als * schwarze Outlines, gesaettigtes Arcade-Gruen. * * Die Pixelschrift steckt nur in --font-display (Ueberschriften und * Feldbeschriftungen). Der Fliesstext bleibt bewusst Nunito Sans: die * Akquise-Tabelle hat acht Spalten bei 11-13 px, und eine Pixelschrift waere * darin nicht mehr zu lesen - ein Design, das die Arbeit behindert, waere ein * schlechtes Design. * =========================================================================== */ html.theme-pixel:not(.dark) { /* Deutlich dunkler als die Karten: Pixelgrafik lebt von harten Kanten, und bei zu aehnlichen Toenen verschwimmen Karte und Grund. */ --color-canvas: #cdd8c2; --color-surface: #f6f8f1; --color-brand-50: #e0f2d4; --color-brand-100: #c8e8b4; /* Rahmen sind hier keine Andeutung, sondern Kontur - deshalb dunkel. */ --color-brand-200: #2b7a1c; --color-brand-300: #256b18; --color-brand-400: #35931f; --color-brand-500: #2e8b22; --color-brand-600: #24701a; --color-brand-700: #1b5613; --color-brand-800: #143f0e; --color-brand-900: #0e2f0a; --color-brand-accent: #2e8b22; --color-ink-50: #eef2e8; --color-ink-100: #dde4d4; /* Der Kniff des Themes: ink-200 ist fast ausschliesslich Rahmen, wird hier also zur schwarzen Outline - 224 Stellen ohne eine Zeile im Markup. */ --color-ink-200: #1f2a1a; --color-ink-300: #5a6653; --color-ink-400: #47523f; --color-ink-500: #38412f; --color-ink-600: #2c3425; --color-ink-700: #22291c; --color-ink-800: #182015; --color-ink-900: #0e140c; --color-ink-950: #000000; --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-xl: 0; --radius-2xl: 0; /* Versetzt statt weichgezeichnet - so sehen Schatten in Pixelgrafik aus. */ --shadow-card: 4px 4px 0 0 #1f2a1a; --shadow-lift: 6px 6px 0 0 #1f2a1a; --font-display: 'Silkscreen', 'Courier New', ui-monospace, monospace; } /* * Pixel Art, dunkel: Arcade-Automat im dunklen Raum. Flaechen fast schwarz mit * blauem Stich, Konturen in gedecktem Gruen (schwarze Outlines waeren auf * schwarzem Grund unsichtbar), das Gruen der Knoepfe leuchtet kraeftiger. */ html.theme-pixel.dark { --color-canvas: #0d0f14; --color-surface: #151a22; --color-brand-50: #0f2a0c; --color-brand-100: #163c11; --color-brand-200: #2c7a1f; --color-brand-300: #35931f; --color-brand-400: #3aa524; --color-brand-500: #3aa524; --color-brand-600: #49bf30; --color-brand-700: #7fdc63; --color-brand-800: #b0ec9c; --color-brand-900: #d8f7cd; --color-brand-accent: #49bf30; --color-ink-50: #1a2029; --color-ink-100: #232b36; --color-ink-200: #33734a; --color-ink-300: #6f7f92; --color-ink-400: #93a3b5; --color-ink-500: #adbccb; --color-ink-600: #c2cfdb; --color-ink-700: #d6e0ea; --color-ink-800: #e9eff5; --color-ink-900: #f6f9fc; --color-ink-950: #000000; --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-xl: 0; --radius-2xl: 0; --shadow-card: 4px 4px 0 0 #000000; --shadow-lift: 6px 6px 0 0 #000000; --font-display: 'Silkscreen', 'Courier New', ui-monospace, monospace; } /* =========================================================================== * Cyberpunk * * Neon in der Nacht: fast schwarze Flaechen mit blauem Stich, violettes * Leuchten, Kanten so scharf, dass die Karten wie HUD-Elemente wirken (2 px * statt 12 px Radius - nicht ganz eckig, das ist schon Pixel Art). * * Der Akzent ist bewusst Violett und nicht Neon-Cyan: auf brand-500 und * brand-600 steht 69 Mal weisse Schrift, und auf Cyan waere die nicht zu lesen. * Cyan sitzt deshalb nur in --color-brand-accent und in den Statusfarben, wo * dunkler Text drauf steht. * * Schatten sind hier kein Schatten, sondern ein Schein: eine farbige Kontur * plus weicher Halo in der Markenfarbe. * =========================================================================== */ html.theme-cyberpunk.dark { --color-canvas: #07080f; --color-surface: #0f1120; --color-brand-50: #1a0e2e; --color-brand-100: #24123f; --color-brand-200: #4a1f7a; --color-brand-300: #5f27a0; --color-brand-400: #7a30cc; --color-brand-500: #8b31f0; --color-brand-600: #a24cff; --color-brand-700: #c79bff; --color-brand-800: #ddc4ff; --color-brand-900: #efe3ff; --color-brand-accent: #00e5ff; /* Blaustahl statt Neutralgrau - Grau waere hier zu brav. */ --color-ink-50: #141728; --color-ink-100: #1c2135; --color-ink-200: #2b4560; --color-ink-300: #6b7899; --color-ink-400: #8e9bbd; --color-ink-500: #a9b5d4; --color-ink-600: #c1cbe4; --color-ink-700: #d6ddf0; --color-ink-800: #e9eefa; --color-ink-900: #f7f9ff; --color-ink-950: #000000; --radius-sm: 0.125rem; --radius-md: 0.125rem; --radius-lg: 0.1875rem; --radius-xl: 0.25rem; --radius-2xl: 0.375rem; --shadow-card: 0 0 0 1px rgb(139 49 240 / 0.16), 0 0 22px rgb(139 49 240 / 0.2); --shadow-lift: 0 0 0 1px rgb(139 49 240 / 0.3), 0 0 40px rgb(139 49 240 / 0.35); --font-sans: 'Chakra Petch', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; --font-display: 'Chakra Petch', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; /* Die getoenten Pillen aus .dark ins Neon gezogen. */ --color-sky-50: #04202e; --color-sky-200: #0b4a63; --color-sky-700: #22d3ee; --color-amber-50: #2b1f04; --color-amber-200: #57400a; --color-amber-700: #ffcc4d; --color-violet-50: #1d1140; --color-violet-200: #382068; --color-violet-700: #d0a2ff; --color-red-50: #2c0e1c; --color-red-200: #5c1c34; --color-red-700: #ff6b8a; } /* * Cyberpunk, hell: Konzern bei Tageslicht. Kuehles Blaugrau statt warmem * Weiss, dasselbe Violett - nur dunkler, damit weisse Schrift darauf haelt. * Die scharfen Kanten bleiben, das Leuchten wird zu einem knappen kalten * Schatten: ein Halo auf hellem Grund sieht nach Fehler aus, nicht nach Neon. */ html.theme-cyberpunk:not(.dark) { --color-canvas: #eceff7; --color-surface: #ffffff; --color-brand-50: #f3ecff; --color-brand-100: #e6d9ff; --color-brand-200: #c9adff; --color-brand-300: #a97bff; --color-brand-400: #8d4df0; --color-brand-500: #7326d6; --color-brand-600: #5d1cb0; --color-brand-700: #4a1590; --color-brand-800: #380f6e; --color-brand-900: #290a52; --color-brand-accent: #7326d6; --color-ink-50: #f2f4fb; --color-ink-100: #e4e8f4; --color-ink-200: #c3cbe0; --color-ink-300: #98a2bd; --color-ink-400: #5d6786; --color-ink-500: #4a5473; --color-ink-600: #3a4260; --color-ink-700: #2c334d; --color-ink-800: #1e2438; --color-ink-900: #121728; --color-ink-950: #0a0d18; --radius-sm: 0.125rem; --radius-md: 0.125rem; --radius-lg: 0.1875rem; --radius-xl: 0.25rem; --radius-2xl: 0.375rem; --shadow-card: 0 1px 2px rgb(18 23 40 / 0.06), 0 6px 18px rgb(115 38 214 / 0.1); --shadow-lift: 0 12px 30px rgb(115 38 214 / 0.18); --font-sans: 'Chakra Petch', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; --font-display: 'Chakra Petch', 'Avenir Next', 'Nunito Sans', ui-sans-serif, system-ui, sans-serif; } @layer base { html, body { height: 100%; } body { background-color: var(--color-canvas); color: var(--color-ink-900); font-family: var(--font-sans); font-weight: 400; -webkit-font-smoothing: antialiased; /* Farbwechsel beim Umschalten laeuft weich, ohne Layout zu bewegen */ transition: background-color 0.2s ease, color 0.2s ease; } h1, h2, h3, h4, h5, h6 { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.015em; } /* * Die Feldbeschriftungen (labelClass in components/leads/leadUi.tsx) tragen * dieselbe Klasse, damit ein Theme sie mit einer Regel erreicht. Bei perinco * und Outdoor ist --font-display die Grundschrift, hier aendert sich also * nichts. */ .field-label { font-family: var(--font-display); } /* * Pixelschrift hat eine feste Zeichenbreite und traegt ihre Sperrung selbst; * die negative Laufweite der Ueberschriften wuerde die Buchstaben ineinander * schieben. Ausserdem kein Kantenglaetten - Pixel sollen Pixel bleiben. */ html.theme-pixel h1, html.theme-pixel h2, html.theme-pixel h3, html.theme-pixel h4, html.theme-pixel h5, html.theme-pixel h6, html.theme-pixel .field-label { letter-spacing: 0; -webkit-font-smoothing: none; font-smooth: never; } /* * Cyberpunk laesst die Ueberschriften atmen: die negative Laufweite zieht * Chakra Petch unangenehm zusammen, gesperrt liest es sich nach Anzeigetafel. */ html.theme-cyberpunk h1, html.theme-cyberpunk h2, html.theme-cyberpunk h3, html.theme-cyberpunk h4, html.theme-cyberpunk h5, html.theme-cyberpunk h6 { letter-spacing: 0.015em; } html.theme-cyberpunk .field-label { letter-spacing: 0.12em; } /* Fokus-Ring durchgaengig in CI-Gruen */ :focus-visible { outline: 2px solid var(--color-brand-500); outline-offset: 2px; } } @layer utilities { /* * Das perinco Logo ist fuer helle Hintergruende gemacht - der Zusatz unter * dem Wortzeichen ist dunkelgrau und waere im Dark Mode unsichtbar. invert * dreht die Helligkeit, hue-rotate holt das CI-Gruen zurueck. */ .dark .logo-adaptive { filter: invert(1) hue-rotate(180deg); } /* * "rounded-full" laesst sich nicht ueber eine Variable abschalten - Tailwind * schreibt dort einen festen Wert. Fuer Pixel Art muss es aber weg: runde * Punkte, Pillen und Bilder neben eckigen Karten waeren ein Bruch. Der * Attributselektor greift genau das eine Klassenwort und ist mit dem * vorangestellten html spezifischer als die Utility-Klasse, deshalb ohne * !important. */ html.theme-pixel [class~='rounded-full'] { border-radius: 0; } .scrollbar-slim::-webkit-scrollbar { width: 8px; height: 8px; } .scrollbar-slim::-webkit-scrollbar-track { background: transparent; } .scrollbar-slim::-webkit-scrollbar-thumb { background: var(--color-ink-200); border-radius: 999px; } .scrollbar-slim::-webkit-scrollbar-thumb:hover { background: var(--color-ink-300); } .line-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } }