console: flat single-canvas design language, in the Zurich Kotak brand

The real problem was never the font or the shadows — it was the design LANGUAGE.
Floating white cards on a grey-blue ground is the generic admin-template look,
and no restyle escapes it. This ports the approved mockup: one canvas, sections
set off by hairlines and space, the activity feed as the hero.

- ONE CANVAS. The content ground is white; the sidebar is the only tinted
  surface. Panels drop their border, radius and shadow and become plain
  sections under their own headings.
- The metric strips (lead + overview) stop being caged tiles and become an
  inline stat row between two hairlines — money at display size, the rest
  quieter.
- The stage rail loses its card and becomes a slim inline stepper.
- The property rail flattens: Customer / Vehicle / Documents are hairline-
  divided groups aligned to the edge, headings at label size — it is
  reference, and should not shout over the story.
- "Who holds it" drops from a filled pill to a coloured dot and a line of text.
- Bricolage is gone. Display and body are both Zurich Sans, the brand face;
  headings and figures lean on weight and tracking, not a second family. The
  palette is the ZK blues throughout.

Same data, same functionality — only the surface. Revertible in one push.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yashas 2026-09-09 01:21:55 +05:30
parent 83b5795b22
commit adef7838fc
5 changed files with 82 additions and 76 deletions

View File

@ -13,13 +13,6 @@
<!--BASE_HREF--> <!--BASE_HREF-->
<link rel="icon" type="image/webp" href="./brand/zurich_logo.webp" /> <link rel="icon" type="image/webp" href="./brand/zurich_logo.webp" />
<title>Zurich Kotak | Lead Desk</title> <title>Zurich Kotak | Lead Desk</title>
<!-- Display face for headings and figures. Zurich Sans (the brand face,
loaded from ./brand) stays the body voice; this gives the numbers and
titles the tighter, more current character the flat corporate grotesque
could not. Falls back to Zurich Sans if the CDN is blocked. -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,500;12..96,600;12..96,700&display=swap" />
<!-- Written next to the artifact at placement; carries this environment's <!-- Written next to the artifact at placement; carries this environment's
VITE_ZINO_API_URL, which src/runtimeConfig.js reads off VITE_ZINO_API_URL, which src/runtimeConfig.js reads off
window.__RUNTIME_CONFIG__. Without it requireConfigValue throws and the window.__RUNTIME_CONFIG__. Without it requireConfigValue throws and the

View File

@ -5,12 +5,11 @@
align-items: center; align-items: center;
gap: var(--sp-6); gap: var(--sp-6);
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: var(--sp-5); margin: var(--sp-6) 0;
padding: var(--sp-6) var(--sp-7); padding: var(--sp-2) 0 var(--sp-5);
border-radius: var(--r-lg); border: 0;
border: 1px solid var(--zk-line-soft); border-bottom: 1px solid var(--zk-line);
box-shadow: var(--sh-sm); background: transparent;
background: var(--zk-white);
} }
.rail ol { .rail ol {

View File

@ -124,7 +124,10 @@
--sp-8: 40px; --sp-8: 40px;
--sp-9: 56px; --sp-9: 56px;
--font-display: 'Bricolage Grotesque', 'Zurich Sans', 'Trebuchet MS', sans-serif; /* 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: 'Zurich Sans', Arial, Helvetica, sans-serif;
--font-zurich: 'Zurich Sans', Arial, Helvetica, sans-serif; --font-zurich: 'Zurich Sans', Arial, Helvetica, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace; --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
@ -134,7 +137,11 @@
font-size: 16px; font-size: 16px;
line-height: var(--lh-normal); line-height: var(--lh-normal);
color: var(--zk-ink); color: var(--zk-ink);
background: var(--zk-tint); /* 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; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
@ -152,7 +159,7 @@ body,
body { body {
margin: 0; margin: 0;
background: var(--zk-tint); background: var(--zk-white);
} }
button, button,

View File

@ -16,10 +16,8 @@
gap: var(--sp-6); gap: var(--sp-6);
height: 72px; height: 72px;
padding: 0 var(--sp-7); padding: 0 var(--sp-7);
background: rgba(255, 255, 255, 0.82); background: var(--zk-white);
backdrop-filter: saturate(180%) blur(18px); border-bottom: 1px solid var(--zk-line);
-webkit-backdrop-filter: saturate(180%) blur(18px);
border-bottom: 1px solid var(--zk-line-soft);
} }
.shell__brand { .shell__brand {
@ -77,8 +75,8 @@
max-height: calc(100vh - 72px); max-height: calc(100vh - 72px);
overflow-y: auto; overflow-y: auto;
overscroll-behavior: contain; overscroll-behavior: contain;
background: var(--zk-white); background: var(--zk-tint);
border-right: 1px solid var(--zk-line-soft); border-right: 1px solid var(--zk-line);
padding: var(--sp-6) var(--sp-4) var(--sp-8); padding: var(--sp-6) var(--sp-4) var(--sp-8);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -187,6 +185,7 @@
.shell__main { .shell__main {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
background: var(--zk-white);
width: 100%; width: 100%;
max-width: 1460px; max-width: 1460px;
margin: 0 auto; margin: 0 auto;

View File

@ -309,12 +309,14 @@
/* ---- panel ---- */ /* ---- panel ---- */
.panel { .panel {
background: var(--zk-white); /* FLAT. Was a shadowed white card; now a plain section on the white
border: 1px solid var(--zk-line-soft); canvas, set off by its heading and by space, not by a box. */
border-radius: var(--r-xl); background: transparent;
box-shadow: var(--sh-md); border: 0;
padding: var(--sp-7); border-radius: 0;
margin-bottom: var(--sp-5); box-shadow: none;
padding: 0;
margin-bottom: var(--sp-8);
} }
.panel__head { .panel__head {
@ -616,9 +618,19 @@
/* Rail panels are tighter than main panels a 340px measure cannot afford /* Rail panels are tighter than main panels a 340px measure cannot afford
32px of padding on each side. */ 32px of padding on each side. */
.lead__side .panel { padding: var(--sp-5) 0 0; margin-bottom: var(--sp-4); } .lead__side .panel { padding: 0; margin-bottom: var(--sp-6); }
.lead__side .panel > .panel__head { padding: 0 var(--sp-6); margin-bottom: var(--sp-4); } .lead__side .panel > .panel__head { padding: 0; margin-bottom: var(--sp-4); }
.lead__side .panel--crew { padding: var(--sp-5) var(--sp-6); } .lead__side .panel--crew { padding: 0 0 var(--sp-6); border-bottom: 1px solid var(--zk-line); }
/* rail headings sit at label size, not the big panel-title size the rail is
reference, and a 18px "Customer" heading would shout over the facts. */
.lead__side .panel__title {
font-size: var(--fs-3xs);
font-weight: var(--fw-semi);
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--zk-blue-dark);
}
.lead__side .panel__sub { display: none; }
.panel--rail { .panel--rail {
padding: 0; padding: 0;
@ -932,14 +944,12 @@
/* KPI strip. Whitespace rather than rules see .lmetrics for why the cage /* KPI strip. Whitespace rather than rules see .lmetrics for why the cage
went. Tabular figures so the row does not jitter as it refreshes. */ went. Tabular figures so the row does not jitter as it refreshes. */
.kpis { .kpis {
display: grid; display: flex;
grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); flex-wrap: wrap;
gap: var(--sp-5) var(--sp-7); gap: var(--sp-6) var(--sp-8);
padding: var(--sp-6) var(--sp-7); padding: var(--sp-6) 0;
background: var(--zk-white); border-top: 1px solid var(--zk-line);
border: 1px solid var(--zk-line-soft); border-bottom: 1px solid var(--zk-line);
border-radius: var(--r-lg);
box-shadow: var(--sh-sm);
margin-bottom: var(--sp-6); margin-bottom: var(--sp-6);
} }
@ -1085,15 +1095,13 @@
22px against 12px labels. Premium and commission the two numbers 22px against 12px labels. Premium and commission the two numbers
anyone actually came for are bigger again. */ anyone actually came for are bigger again. */
.lmetrics { .lmetrics {
display: grid; display: flex;
grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); flex-wrap: wrap;
gap: var(--sp-5) var(--sp-7); gap: var(--sp-6) var(--sp-8);
padding: var(--sp-6) var(--sp-7); padding: var(--sp-6) 0;
background: var(--zk-white); border-top: 1px solid var(--zk-line);
border: 1px solid var(--zk-line-soft); border-bottom: 1px solid var(--zk-line);
border-radius: var(--r-xl); margin-bottom: 0;
box-shadow: var(--sh-md);
margin-bottom: var(--sp-5);
} }
.lm { min-width: 0; } .lm { min-width: 0; }
@ -1507,10 +1515,11 @@
} }
.fgroup { .fgroup {
padding: var(--sp-5); padding: var(--sp-5) 0;
border: 1px solid var(--zk-line-soft); border: 0;
border-radius: var(--r-md); border-bottom: 1px solid var(--zk-line);
background: var(--zk-white); border-radius: 0;
background: transparent;
} }
.fgroup h3 { .fgroup h3 {
@ -1617,8 +1626,8 @@
.glance { .glance {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: var(--sp-3); gap: 0;
padding: 0 var(--sp-6) var(--sp-4); padding: 0;
} }
.glance .props { display: block; padding: 0; } .glance .props { display: block; padding: 0; }
@ -1746,20 +1755,23 @@
flex: none; flex: none;
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--sp-3); gap: var(--sp-2);
padding: var(--sp-2) var(--sp-5) var(--sp-2) var(--sp-2); padding: 0;
border-radius: var(--r-pill); border: 0;
border: 1px solid var(--zk-teal-line); background: transparent;
background: var(--zk-teal-tint);
} }
.holds__puck { .holds__puck {
flex: none; flex: none;
width: 40px; height: 40px; width: 10px; height: 10px;
border-radius: 50%; border-radius: 50%;
display: grid; place-items: center; background: var(--zk-teal);
background: var(--zk-teal); color: #fff; box-shadow: 0 0 0 4px var(--zk-teal-tint);
} }
.holds__txt { display: flex; flex-direction: column; line-height: 1.15; } /* the icon inside the disc is dropped in the flat treatment the dot alone
carries the tone, and the label says the rest. */
.holds__puck svg { display: none; }
.holds__txt { display: inline; line-height: 1.3; }
.holds__txt small { display: inline; }
.holds__txt small { .holds__txt small {
font-size: var(--fs-3xs); font-size: var(--fs-3xs);
font-weight: var(--fw-semi); font-weight: var(--fw-semi);
@ -1769,24 +1781,20 @@
opacity: .9; opacity: .9;
} }
.holds__txt b { .holds__txt b {
font-family: var(--font-display);
font-weight: var(--fw-semi); font-weight: var(--fw-semi);
font-size: var(--fs-md); font-size: var(--fs-sm);
color: var(--zk-ink); color: var(--zk-ink);
margin-left: var(--sp-1);
} }
.holds--ai { background: var(--zk-tint-blue); border-color: var(--zk-blue-light); } .holds--ai .holds__puck { background: var(--zk-blue); box-shadow: 0 0 0 4px var(--zk-tint-blue); }
.holds--ai .holds__puck { background: var(--zk-blue); }
.holds--ai .holds__txt small { color: var(--zk-blue-dark); } .holds--ai .holds__txt small { color: var(--zk-blue-dark); }
.holds--person { background: var(--zk-amber-tint); border-color: var(--zk-amber-line); } .holds--person .holds__puck { background: var(--zk-amber); box-shadow: 0 0 0 4px var(--zk-amber-tint); }
.holds--person .holds__puck { background: var(--zk-amber); }
.holds--person .holds__txt small { color: var(--zk-amber-ink); } .holds--person .holds__txt small { color: var(--zk-amber-ink); }
.holds--grey { background: var(--zk-tint); border-color: var(--zk-line); } .holds--grey .holds__puck { background: var(--zk-grey); box-shadow: 0 0 0 4px var(--zk-tint); }
.holds--grey .holds__puck { background: var(--zk-grey); }
.holds--grey .holds__txt small { color: var(--zk-muted); } .holds--grey .holds__txt small { color: var(--zk-muted); }
.holds--cust { background: var(--zk-teal-tint); border-color: var(--zk-teal-line); } .holds--cust .holds__puck { background: var(--zk-teal); box-shadow: 0 0 0 4px var(--zk-teal-tint); }
.holds--cust .holds__puck { background: var(--zk-teal); }
.holds--cust .holds__txt small { color: var(--zk-teal-ink); } .holds--cust .holds__txt small { color: var(--zk-teal-ink); }