ledgerlens / apps /web /src /app /globals.css
Abdr007's picture
LedgerLens — deployed tree
c7bece7
Raw
History Blame Contribute Delete
10.9 kB
@import "tailwindcss";
/* ---------------------------------------------------------------------------
LedgerLens — "Instrument of record"
Second identity. The first ("Obsidian & Acid") was a near-black ground with a
single acid-lime accent, chosen to avoid colliding with a sibling project — a
good reason that happened to land on the most-generated look there is. Neon on
black is the house style of every AI-built dashboard, so adding more glow to it
would have made this page *more* templated, not more futuristic.
The futurism here is borrowed from the subject instead. This product's promise
is a record that cannot be forged or rewritten, and that world already has a
visual language: security printing, assay marks, engraved instruments,
oxidised metal. Verdigris and copper are the colours of metal that has proven
it is old; bone is the colour of the paper such things are printed on.
Three axes, each derived from the product rather than from a mood:
hue metallurgical — verdigris, copper, bone on slate-teal black
geometry engraved rules and machined chamfers; no blur, no rounding
argument verification is quiet, exception is loud (see --color-pass)
The inversion is the point. Most dashboards shout green for success, which
trains the eye to skip the only state that needs a person. Here DONE is nearly
silent and NEEDS REVIEW carries the sodium flare.
--------------------------------------------------------------------------- */
@theme {
--color-base: #050b0a;
--color-base-raised: #0a1614;
--color-base-sunken: #020605;
--color-panel: #0a1513;
--color-panel-top: #0f1f1c;
/* Verdigris: oxidised copper, the colour of security ink and proven age.
Desaturated and blue-shifted on purpose — it must never read as neon. */
--color-accent: #4fd1a5;
--color-accent-dim: #2a6b56;
--color-accent-glow: rgb(79 209 165 / 0.34);
/* Copper does the structural work: engraved rules, seals, chamfer ticks. */
--color-copper: #b87333;
--color-copper-dim: rgb(184 115 51 / 0.32);
--color-ink: #e6e2d3;
--color-ink-muted: #9aa39c;
--color-ink-faint: #5d6a64;
/* State only — never decoration. `pass` is deliberately the quietest colour on
the page: a verified document is the uninteresting outcome and must not
compete with the one asking for a human. */
--color-pass: #6f9c88;
--color-flag: #e2564d;
--color-warn: #e8a33d;
--color-hairline: rgb(154 163 156 / 0.16);
--color-hairline-strong: rgb(184 115 51 / 0.34);
--font-engraved: var(--font-instrument-serif), ui-serif, Georgia, serif;
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
--font-mono: var(--font-geist-mono), ui-monospace, "SF Mono", monospace;
}
:root {
color-scheme: dark;
/* The machined corner cut, shared by every panel so the silhouette is
consistent: top-right and bottom-left are chamfered, the other two are
square. Asymmetry reads as engineered rather than merely rounded-off. */
--bevel: polygon(
0 0,
calc(100% - 15px) 0,
100% 15px,
100% 100%,
15px 100%,
0 calc(100% - 15px)
);
--bevel-sm: polygon(
0 0,
calc(100% - 8px) 0,
100% 8px,
100% 100%,
8px 100%,
0 calc(100% - 8px)
);
}
html,
body {
background-color: var(--color-base);
color: var(--color-ink);
}
body {
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
min-height: 100dvh;
}
/* --------------------------------------------------------------------------
Backdrop: a technical grid, one violet wash, and a fine scanline field.
No blur anywhere in this design.
-------------------------------------------------------------------------- */
.backdrop-grid {
position: fixed;
inset: 0;
z-index: -2;
pointer-events: none;
background-color: var(--color-base);
background-image:
radial-gradient(1100px 560px at 50% -12%, rgb(79 209 165 / 0.055), transparent 62%),
radial-gradient(760px 460px at 88% 4%, rgb(184 115 51 / 0.11), transparent 60%),
linear-gradient(to right, rgb(79 209 165 / 0.035) 1px, transparent 1px),
linear-gradient(to bottom, rgb(79 209 165 / 0.035) 1px, transparent 1px);
background-size:
100% 100%,
100% 100%,
64px 64px,
64px 64px;
mask-image: radial-gradient(ellipse 110% 74% at 50% 0%, #000 52%, transparent 100%);
}
/* Engine-turning. The interference of two fine arcs is what guilloché is — the
pattern on a banknote or a share certificate, difficult to reproduce and
therefore used to prove a document is the original. Kept at a very low
amplitude: it should read as the texture of the surface, not as an effect. */
.scanlines {
position: fixed;
inset: 0;
z-index: 1;
pointer-events: none;
background-image:
repeating-radial-gradient(
circle at 18% -10%,
rgb(184 115 51 / 0.028) 0 1px,
transparent 1px 9px
),
repeating-radial-gradient(
circle at 84% 118%,
rgb(79 209 165 / 0.022) 0 1px,
transparent 1px 11px
);
}
/* An engraved rule: a bright hairline sitting on its own shadow, the way an
intaglio line sits proud of the paper. */
.engraved {
border-top: 1px solid rgb(184 115 51 / 0.22);
box-shadow: 0 -1px 0 rgb(0 0 0 / 0.55);
}
/* --------------------------------------------------------------------------
Panels: hard-edged, chamfered, solid. `clip-path` removes the border on the
cut edges, so contrast does the work a border would — the panel fill is
deliberately lighter than the base rather than translucent.
-------------------------------------------------------------------------- */
.panel {
position: relative;
background: linear-gradient(180deg, var(--color-panel-top) 0%, var(--color-panel) 100%);
clip-path: var(--bevel);
}
.panel-hover {
transition:
background 200ms ease,
transform 200ms ease;
}
.panel-hover:hover {
background: linear-gradient(180deg, #142b26 0%, #0d1c19 100%);
}
/* An acid hairline along the top edge, and a machined tick in the chamfer. */
.edge-light::before {
content: "";
position: absolute;
inset-inline: 0;
top: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent,
var(--color-accent-glow) 30%,
var(--color-accent-glow) 70%,
transparent
);
}
.edge-light::after {
content: "";
position: absolute;
top: 0;
right: 0;
width: 15px;
height: 15px;
background: linear-gradient(45deg, transparent 49%, var(--color-copper) 49% 52%, transparent 52%);
opacity: 0.65;
}
/* Corner brackets — the HUD tell. */
.ticks::before,
.ticks::after {
content: "";
position: absolute;
width: 9px;
height: 9px;
border-color: var(--color-copper);
opacity: 0.55;
}
.ticks::before {
left: 7px;
top: 7px;
border-left: 1px solid;
border-top: 1px solid;
}
.ticks::after {
right: 7px;
bottom: 7px;
border-right: 1px solid;
border-bottom: 1px solid;
}
.bevel {
clip-path: var(--bevel);
}
.bevel-sm {
clip-path: var(--bevel-sm);
}
/* --------------------------------------------------------------------------
Glows — flat rings, no soft blur halo.
-------------------------------------------------------------------------- */
.glow-accent {
box-shadow:
inset 0 0 0 1px rgb(79 209 165 / 0.45),
0 0 22px -8px rgb(79 209 165 / 0.7);
}
.glow-pass {
box-shadow:
inset 0 0 0 1px rgb(111 156 136 / 0.4),
0 0 20px -10px rgb(111 156 136 / 0.6);
}
.glow-flag {
box-shadow:
inset 0 0 0 1px rgb(226 86 77 / 0.45),
0 0 24px -8px rgb(226 86 77 / 0.65);
}
.glow-warn {
box-shadow:
inset 0 0 0 1px rgb(232 163 61 / 0.4),
0 0 20px -10px rgb(232 163 61 / 0.6);
}
/* --------------------------------------------------------------------------
Typography
-------------------------------------------------------------------------- */
.tabular {
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum";
}
/* The engraved face, declared here rather than left to the generated utility.
Everything in this file is unlayered, and unlayered declarations beat anything
in `@layer utilities` — so a rule here is the one that actually lands. Used on
the hero and panel titles only: the page is mono-dominant, and the serif is
the human voice among the machine output. */
.font-engraved {
font-family: var(--font-instrument-serif), ui-serif, Georgia, serif;
font-weight: 400;
}
/* Mono-forward: this is a ledger, so labels read as machine output. */
.eyebrow {
font-family: var(--font-mono);
font-size: 0.625rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--color-ink-faint);
font-weight: 500;
}
.stat {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
letter-spacing: -0.02em;
}
/* --------------------------------------------------------------------------
Segmented meter — the ▓▓▓░░ bar. A discrete readout suits a ledger better
than a continuous progress bar.
-------------------------------------------------------------------------- */
.meter {
display: flex;
gap: 2px;
height: 4px;
}
.meter-cell {
flex: 1;
background: rgb(154 163 156 / 0.16);
}
.meter-cell[data-on="true"] {
background: var(--color-accent);
}
.meter-cell[data-tone="pass"][data-on="true"] {
background: var(--color-pass);
}
.meter-cell[data-tone="flag"][data-on="true"] {
background: var(--color-flag);
}
.meter-cell[data-tone="warn"][data-on="true"] {
background: var(--color-warn);
}
/* --------------------------------------------------------------------------
Pipeline motion
-------------------------------------------------------------------------- */
@keyframes chevron-run {
from {
background-position: 0 0;
}
to {
background-position: 16px 0;
}
}
/* Marching chevrons instead of a sweeping gradient. */
.connector-active {
background-image: repeating-linear-gradient(
90deg,
var(--color-accent) 0px,
var(--color-accent) 5px,
transparent 5px,
transparent 16px
);
animation: chevron-run 0.55s linear infinite;
}
@keyframes breathe {
0%,
100% {
opacity: 0.5;
}
50% {
opacity: 1;
}
}
.breathe {
animation: breathe 1.4s steps(8, end) infinite;
}
::selection {
background: rgb(79 209 165 / 0.3);
color: #050b0a;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgb(154 163 156 / 0.22);
border: 3px solid transparent;
background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
background: rgb(79 209 165 / 0.4);
background-clip: content-box;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}