/* ── Zurich Kotak brand typeface ───────────────────────────── */ @font-face { font-family: 'Zurich Sans'; src: url('./assets/fonts/ZurichSans-Light.otf') format('opentype'); font-weight: 300; font-style: normal; font-display: swap; } @font-face { font-family: 'Zurich Sans'; src: url('./assets/fonts/ZurichSans-Regular.otf') format('opentype'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Zurich Sans'; src: url('./assets/fonts/ZurichSans-Medium.otf') format('opentype'); font-weight: 500; font-style: normal; font-display: swap; } :root { /* ── PALETTE — assured-inspired ────────────────────────────── A clean white ground, warm near-black ink, and ONE confident accent: a magenta-pink, reserved for action and active state. The token names keep their history (the accent still lives under the --zk-blue-* names the whole app references), but the values are the new scheme. Teal is the customer, amber a person; the pink is "act / here", nothing else. */ --zk-blue: #e5227f; /* THE ACCENT (was brand blue) — pink */ --zk-blue-dark: #c30f68; --zk-blue-deep: #c30f68; --zk-navy: #2a1d3d; /* a deep plum-ink for the logo / darkest text */ --zk-blue-mid: #ee5fa0; --zk-blue-light: #f6cfe3; /* pink hairline / ring */ --zk-cyan: #fdebf4; /* pink-soft */ --zk-teal: #0e9e8f; --zk-teal-ink: #0a6b60; --zk-teal-tint: #e2f5f2; --zk-teal-line: #bfe6e1; --zk-good: #18a558; --zk-ink: #1c1626; /* warm near-black */ --zk-muted: #645d72; --zk-grey: #a49dae; --zk-line: #e3e1ea; --zk-line-soft: #ececf1; --zk-tint: #faf9fb; /* off-white section ground */ --zk-sunk: #f5f3f8; /* a touch deeper — hover / inset */ --zk-tint-blue: #fdebf4; /* pink-soft (was tint-blue) */ --zk-white: #fff; --zk-danger: #d64545; --zk-amber: #c77d1a; --zk-amber-ink: #9a5d10; --zk-amber-tint: #fbf0dd; --zk-amber-line: #ecd3a3; --zk-danger-ink: #b23636; --zk-danger-tint: #fbeaea; --zk-danger-line: #f0c9c9; /* ── Shape, depth, motion ──────────────────────────────────── Rounder than before and softer shadows — the assured cards read as objects that float a little, on a warm plum-ink low alpha rather than generic grey haze. */ --r-xs: 8px; --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-xl: 22px; --r-pill: 999px; --sh-xs: 0 1px 2px rgba(28, 22, 38, 0.04); --sh-sm: 0 1px 2px rgba(28, 22, 38, 0.04), 0 4px 14px -8px rgba(28, 22, 38, 0.10); --sh-md: 0 1px 2px rgba(28, 22, 38, 0.04), 0 8px 24px -10px rgba(28, 22, 38, 0.12); --sh-lg: 0 2px 6px rgba(28, 22, 38, 0.06), 0 24px 48px -16px rgba(28, 22, 38, 0.22); --sh-accent: 0 6px 20px -6px rgba(229, 34, 127, 0.42); --ring: 0 0 0 3px rgba(229, 34, 127, 0.16); --ease: cubic-bezier(0.4, 0, 0.2, 1); --t-fast: 0.14s var(--ease); --t: 0.2s var(--ease); --grad-blue: linear-gradient(135deg, var(--zk-blue) 0%, var(--zk-blue-dark) 100%); --grad-blue-hover: linear-gradient(135deg, var(--zk-blue-dark) 0%, #a80c59 100%); /* ── TYPE SCALE ─────────────────────────────────────────────── The app had FIFTY-FOUR distinct font sizes, and forty of them sat between 0.58rem and 0.95rem — a three-pixel band. The most-used size was 0.78rem, which is 12.5px of body copy. That is not a hierarchy; it is a fog of small grey text, and it is exactly why the screen read as a decade-old enterprise tool. Nothing could be emphasised, because everything was already the same size. Nine steps, with real jumps between them. Body sits at 15px, labels at 14, and 12px is the FLOOR — reserved for uppercase eyebrows, never for anything a person has to read. Size does the prioritising so the reader does not have to. */ /* Shifted up one notch after an audit found 124 of ~200 sizings sitting at 12-13px — the "meta" tier had quietly become the body size, so the whole app read tiny and uniform with nothing for the eye to land on. Body is 14 now, values 15, emphasis 16; 12px stays for uppercase eyebrows only. */ --fs-3xs: 0.75rem; /* 12px — uppercase eyebrows only */ --fs-2xs: 0.875rem; /* 14px — was 13; the app's dominant size, now comfortable */ --fs-xs: 0.9375rem; /* 15px — field labels */ --fs-sm: 1rem; /* 16px — body, field values */ --fs-md: 1.0625rem; /* 17px — emphasis */ --fs-lg: 1.125rem; /* 18px — panel titles */ --fs-xl: 1.375rem; /* 22px — section headings */ --fs-2xl: 1.75rem; /* 28px — page title */ --fs-3xl: 2.25rem; /* 36px — the one number that matters */ --lh-tight: 1.25; --lh-snug: 1.4; --lh-normal: 1.55; --fw-normal: 400; --fw-medium: 500; --fw-semi: 600; --fw-bold: 700; --fw-x: 800; /* ── SPACING ────────────────────────────────────────────────── One rhythm. Panels breathe at 24-28px rather than 14-18px, which is the other half of why this felt cramped. */ --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px; --sp-7: 32px; --sp-8: 40px; --sp-9: 56px; /* Display and body are the SAME brand face — Zurich Sans has no bold, so headings and figures lean on weight 500 and tighter tracking, set per use, not on a second family. */ --font-display: 'Plus Jakarta Sans', 'Geist', system-ui, sans-serif; --font-zurich: 'Plus Jakarta Sans', 'Geist', system-ui, -apple-system, sans-serif; --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace; font-family: var(--font-zurich); /* The root MUST stay an absolute size — every --fs-* token is rem, so sizing the root from one of them is circular. */ font-size: 16px; line-height: var(--lh-normal); color: var(--zk-ink); /* ONE CANVAS. The app used to be white cards floating on a grey-blue ground — the generic admin-template look. The content ground is white now; the sidebar is the only tinted surface, and sections are separated by hairlines and space rather than boxed in shadowed cards. */ background: var(--zk-white); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } * { box-sizing: border-box; } html, body, #root { height: 100%; } body { margin: 0; background: var(--zk-white); } button, input, select, textarea { font: inherit; color: inherit; } /* One focus treatment for the whole console: a soft brand ring, never the browser's default outline halfway through a card's rounded corner. */ :focus-visible { outline: 2px solid var(--zk-blue); outline-offset: 2px; } ::selection { background: var(--zk-tint-blue); color: var(--zk-blue-dark); } /* Scrollbars, toned to the palette. Chrome/Safari take the ::-webkit rules, Firefox the standard properties. */ * { scrollbar-width: thin; scrollbar-color: var(--zk-line) transparent; } ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { border: 3px solid transparent; border-radius: var(--r-pill); background-clip: content-box; background-color: var(--zk-line); } ::-webkit-scrollbar-thumb:hover { background-color: var(--zk-grey); } @keyframes zk-rise { /* Opacity ONLY. A translateY here promoted every element it touched to a GPU layer, and text composited on a transformed layer renders blurry in Chrome on Linux — which made the whole app look soft. The fade alone gives the entrance without ever moving text onto a fractional-pixel layer. */ from { opacity: 0; } to { opacity: 1; } } @keyframes zk-shimmer { from { background-position: -420px 0; } to { background-position: 420px 0; } } /* Motion is decoration here — every animation is an entrance or a hover, so dropping them costs nothing. */ @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; } }