feat(adminsite): scaffold and site/'s token system
A fifth Next.js app, built like web/ and site/: App Router, React 18, Tailwind 3, TanStack Query, standalone output. app/globals.css carries site/app/globals.css's token blocks copied verbatim rather than retyped, so the two cannot drift by transcription. Tailwind holds var() references only -- no component or config entry may contain a hex value. The semantic three are aliased: site/'s --up/--pend/--down become valid/warn/expired, so each app names the colours for what it shows. Unlike web/, there is no rewrite proxy: the browser calls admin directly, so NEXT_PUBLIC_ADMIN_API_URL must be browser-reachable and listed in admin's ADMIN_ORIGIN. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* ==========================================================================
|
||||
Vantage admin console design tokens.
|
||||
|
||||
Lines 8-97 below are site/app/globals.css's token blocks, copied verbatim:
|
||||
the marketing site and this console are one visual system. Change them in
|
||||
both apps in the same commit — nothing enforces the match automatically.
|
||||
|
||||
Light is the default because web/ is locked to dark, and telling the two
|
||||
apart at a glance is what stops a Reissue landing in the wrong tab. In dark
|
||||
mode the accent lifts to #5b9be8, which is nearer web/'s indigo, so the
|
||||
distinction leans on the ground rather than the hue.
|
||||
========================================================================== */
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
|
||||
--ground: #eaedf3;
|
||||
--panel: #ffffff;
|
||||
--panel-2: #f4f6fa;
|
||||
--ink: #0a1b33;
|
||||
--ink-2: #41556f;
|
||||
--ink-3: #6c7f96;
|
||||
--rule: #cdd6e2;
|
||||
--rule-soft: #e0e6ef;
|
||||
--accent: #0b2a58;
|
||||
--accent-ink: #ffffff;
|
||||
--up: #2f8a60;
|
||||
--down: #c6462f;
|
||||
--pend: #b0801f;
|
||||
--shadow: 0 1px 0 rgba(10, 27, 51, 0.05), 0 18px 40px -26px rgba(10, 27, 51, 0.45);
|
||||
--logo: #0b2a58;
|
||||
|
||||
--sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
--mono: ui-monospace, "Cascadia Mono", "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
|
||||
|
||||
--s--1: clamp(0.76rem, 0.74rem + 0.1vw, 0.81rem);
|
||||
--s-0: clamp(1rem, 0.97rem + 0.14vw, 1.05rem);
|
||||
--s-1: clamp(1.16rem, 1.09rem + 0.32vw, 1.36rem);
|
||||
--s-2: clamp(1.5rem, 1.34rem + 0.74vw, 2rem);
|
||||
--s-3: clamp(2rem, 1.66rem + 1.6vw, 3.1rem);
|
||||
--s-4: clamp(2.6rem, 1.9rem + 3.3vw, 4.9rem);
|
||||
|
||||
--rail: 1200px;
|
||||
}
|
||||
|
||||
/* Dark tokens are defined once and applied through three selectors: the OS
|
||||
preference, and both explicit values of data-theme so the in-page toggle
|
||||
wins in either direction. */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--ground: #071628;
|
||||
--panel: #0d2138;
|
||||
--panel-2: #102842;
|
||||
--ink: #e4ecf6;
|
||||
--ink-2: #9fb3ca;
|
||||
--ink-3: #71879f;
|
||||
--rule: #1e3855;
|
||||
--rule-soft: #172c44;
|
||||
--accent: #5b9be8;
|
||||
--accent-ink: #04101f;
|
||||
--up: #4fb484;
|
||||
--down: #e2705a;
|
||||
--pend: #d6a63f;
|
||||
--shadow: 0 1px 0 rgba(0, 0, 0, 0.35), 0 20px 44px -26px rgba(0, 0, 0, 0.85);
|
||||
--logo: #7fb2f0;
|
||||
}
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--ground: #071628;
|
||||
--panel: #0d2138;
|
||||
--panel-2: #102842;
|
||||
--ink: #e4ecf6;
|
||||
--ink-2: #9fb3ca;
|
||||
--ink-3: #71879f;
|
||||
--rule: #1e3855;
|
||||
--rule-soft: #172c44;
|
||||
--accent: #5b9be8;
|
||||
--accent-ink: #04101f;
|
||||
--up: #4fb484;
|
||||
--down: #e2705a;
|
||||
--pend: #d6a63f;
|
||||
--shadow: 0 1px 0 rgba(0, 0, 0, 0.35), 0 20px 44px -26px rgba(0, 0, 0, 0.85);
|
||||
--logo: #7fb2f0;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
--ground: #eaedf3;
|
||||
--panel: #ffffff;
|
||||
--panel-2: #f4f6fa;
|
||||
--ink: #0a1b33;
|
||||
--ink-2: #41556f;
|
||||
--ink-3: #6c7f96;
|
||||
--rule: #cdd6e2;
|
||||
--rule-soft: #e0e6ef;
|
||||
--accent: #0b2a58;
|
||||
--accent-ink: #ffffff;
|
||||
--up: #2f8a60;
|
||||
--down: #c6462f;
|
||||
--pend: #b0801f;
|
||||
--shadow: 0 1px 0 rgba(10, 27, 51, 0.05), 0 18px 40px -26px rgba(10, 27, 51, 0.45);
|
||||
--logo: #0b2a58;
|
||||
}
|
||||
|
||||
/* Not in site/: the hatched sandbox badge and hover washes need a tinted fill,
|
||||
and deriving it at each use would drift. */
|
||||
:root {
|
||||
--accent-wash: rgba(11, 42, 88, 0.07);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--accent-wash: rgba(91, 155, 232, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--accent-wash: rgba(91, 155, 232, 0.1);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
--accent-wash: rgba(11, 42, 88, 0.07);
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--ground);
|
||||
color: var(--ink);
|
||||
font-family: var(--sans);
|
||||
font-size: var(--s-0);
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* site/'s heading treatment, which is what replaces a display face. */
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-weight: 800;
|
||||
line-height: 1.03;
|
||||
letter-spacing: -0.03em;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: var(--mono);
|
||||
font-size: 0.92em;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.001ms !important;
|
||||
transition-duration: 0.001ms !important;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user