Files
CyberpunkStyleGuide/night-grid.css
T
bgrollemanandClaude Opus 5.5 94832d861b Night Grid cyberpunk style guide
Spec, stylesheet, glitch script, Claude Code skill and the design
canvas source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:21:37 +01:00

229 lines
7.5 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Night Grid — dark neon HUD style for dashboards.
Guide: https://claude.ai/artifact/AT2mCxMkeLFzkife1rAuLk
Fonts: <link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
Random glitch: <script src="night-grid.js" defer></script> */
:root {
--ng-void: #050508; /* page ground */
--ng-panel: #0E1016; /* cards, panels */
--ng-raise: #1C2029; /* tracks, grid, hover */
--ng-line: #2A2F3A; /* 1px borders */
--ng-text: #E6E8EC;
--ng-soft: #C3C8D1; /* secondary body text */
--ng-dim: #8A93A3; /* labels */
--ng-yellow: #FCEE0A; /* action, focus */
--ng-cyan: #02D7F2; /* info, live data */
--ng-red: #FF003C; /* danger fill/border */
--ng-red-txt: #FF3B5C; /* danger text */
--ng-green: #00FF9F; /* ok */
--ng-font-ui: 'Rajdhani', sans-serif;
--ng-font-data: 'JetBrains Mono', monospace;
--ng-cut: 16px;
--ng-speed: 120ms;
}
body {
margin: 0;
background: var(--ng-void);
color: var(--ng-text);
font: 500 18px/1.5 var(--ng-font-ui);
}
a { color: var(--ng-cyan); }
a:hover { color: var(--ng-yellow); }
h1, h2, h3 { font-weight: 700; text-transform: uppercase; line-height: 1.1; }
h1 { color: var(--ng-yellow); }
/* Mono machine-style label: "CPU LOAD", "01 // COLOR" */
.ng-label {
font: 600 12px/1.4 var(--ng-font-data);
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--ng-dim);
}
.ng-data { font-family: var(--ng-font-data); font-variant-numeric: tabular-nums; }
/* Panel with one clipped top-right corner */
.ng-panel {
background: var(--ng-panel);
border: 1px solid var(--ng-line);
padding: 20px 24px;
clip-path: polygon(0 0, calc(100% - var(--ng-cut)) 0, 100% var(--ng-cut), 100% 100%, 0 100%);
}
/* Buttons: one primary (yellow) per view */
.ng-btn {
min-height: 48px;
padding: 0 28px;
border: 1px solid var(--ng-line);
background: transparent;
color: var(--ng-dim);
font: 700 18px var(--ng-font-ui);
letter-spacing: 0.08em;
text-transform: uppercase;
cursor: pointer;
transition: filter var(--ng-speed) linear;
}
.ng-btn:hover { filter: brightness(1.2); }
.ng-btn:focus-visible { outline: 2px solid var(--ng-yellow); outline-offset: 3px; }
.ng-btn--primary {
background: var(--ng-yellow);
color: var(--ng-void);
border: 0;
clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
}
.ng-btn--info { color: var(--ng-cyan); border-color: var(--ng-cyan); }
.ng-btn--danger { color: var(--ng-red-txt); border-color: var(--ng-red); }
/* Tags */
.ng-tag {
display: inline-block;
padding: 4px 10px;
border: 1px solid var(--ng-line);
color: var(--ng-dim);
font: 600 12px var(--ng-font-data);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.ng-tag--priority { background: var(--ng-yellow); color: var(--ng-void); border-color: var(--ng-yellow); }
.ng-tag--live { color: var(--ng-cyan); border-color: var(--ng-cyan); }
.ng-tag--ok { color: var(--ng-green); border-color: var(--ng-green); }
.ng-tag--breach { background: var(--ng-red); color: #fff; border-color: var(--ng-red); }
/* Segmented meter: <div class="ng-meter"><i class="on"></i>…10×</div> */
.ng-meter { display: flex; gap: 3px; }
.ng-meter > i { flex: 1; height: 6px; background: var(--ng-raise); }
.ng-meter > i.on { background: var(--ng-cyan); }
.ng-meter--danger > i.on { background: var(--ng-red); }
/* Alert banner */
.ng-alert {
background: rgb(255 0 60 / 0.08);
border: 1px solid var(--ng-red);
padding: 20px 24px;
}
.ng-alert .ng-label { color: var(--ng-red-txt); }
/* Input: yellow underline on focus */
.ng-input {
min-height: 48px;
padding: 0 16px;
background: var(--ng-void);
color: var(--ng-text);
border: 1px solid var(--ng-line);
font: 16px var(--ng-font-data);
}
.ng-input:focus { outline: none; border-bottom: 2px solid var(--ng-yellow); }
.ng-input[aria-invalid="true"] { border-bottom: 2px solid var(--ng-red); }
/* Glow: the single most important value only */
.ng-glow { text-shadow: 0 0 12px rgb(252 238 10 / 0.6); }
/* --- Diagonal structure --- */
/* Multi-notch panel: cut top-left, step in the top edge, cut bottom-right */
.ng-panel--notched {
clip-path: polygon(0 16px, 16px 0, 55% 0, calc(55% + 12px) 12px, 100% 12px,
100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%);
padding-top: 28px;
}
/* Heading underline: thick bar that steps down diagonally into a hairline */
.ng-rule { position: relative; padding-bottom: 16px; }
.ng-rule::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 8px;
background: var(--ng-rule, var(--ng-yellow));
clip-path: polygon(0 0, 72px 0, 78px 5px, 100% 5px, 100% 6px, 76px 6px, 70px 8px, 0 8px);
}
/* Stepped edge band along the bottom of a section */
.ng-edge { position: relative; padding-bottom: 40px; }
.ng-edge::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 14px;
background: var(--ng-edge, var(--ng-line));
clip-path: polygon(0 100%, 0 0, 22% 0, calc(22% + 14px) 100%, 52% 100%, calc(52% + 7px) 50%,
70% 50%, calc(70% + 7px) 100%, 90% 100%, calc(90% + 14px) 0, 100% 0, 100% 100%);
}
.ng-edge--hot { --ng-edge: var(--ng-yellow); }
/* --- Glitch --- */
/* .ng-glitch marks candidates; night-grid.js adds .is-glitching to one at random every 6–14s */
.ng-glitch.is-glitching { animation: ng-glitch 360ms steps(1, end); }
@keyframes ng-glitch {
20% { transform: translateX(-3px) skewX(-12deg); text-shadow: 2px 0 var(--ng-red), -2px 0 var(--ng-cyan); clip-path: inset(10% 0 55% 0); }
40% { transform: translateX(3px) skewX(8deg); clip-path: inset(60% 0 8% 0); }
60% { transform: translateX(-1px); text-shadow: -2px 0 var(--ng-red), 2px 0 var(--ng-cyan); clip-path: inset(30% 0 35% 0); }
80% { transform: none; text-shadow: 1px 0 var(--ng-red), -1px 0 var(--ng-cyan); }
}
/* --- Fold / unfold ---
<details class="ng-fold" open><summary>Title</summary>…content…</details>
Corner chip shows » pointing down (unfold) when closed, up (fold) when open. */
.ng-fold {
position: relative;
background: var(--ng-panel);
border: 1px solid var(--ng-line);
}
.ng-fold > summary {
list-style: none;
cursor: pointer;
min-height: 44px;
padding: 10px 64px 10px 24px;
display: flex;
align-items: center;
font: 700 24px/1.1 var(--ng-font-ui);
text-transform: uppercase;
}
.ng-fold > summary::-webkit-details-marker { display: none; }
.ng-fold > summary:focus-visible { outline: 2px solid var(--ng-yellow); outline-offset: -2px; }
.ng-fold > summary::before {
content: "";
position: absolute;
top: 0;
right: 0;
width: 44px;
height: 44px;
background: var(--ng-yellow);
clip-path: polygon(0 0, 100% 0, 100% 100%, 12px 100%, 0 calc(100% - 12px));
}
.ng-fold > summary::after {
content: "»";
position: absolute;
top: 0;
right: 0;
width: 44px;
height: 44px;
display: grid;
place-items: center;
color: var(--ng-void);
font: 700 24px/1 var(--ng-font-data);
transform: rotate(90deg);
transition: transform var(--ng-speed) steps(2);
}
.ng-fold[open] > summary::after { transform: rotate(-90deg); }
.ng-fold > :not(summary) { margin: 0; padding: 0 24px 20px; }
/* Scanline overlay: add class to <body> */
.ng-scanlines::after {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
background: repeating-linear-gradient(0deg, rgb(255 255 255 / 0.025) 0 1px, transparent 1px 3px);
}
@media (prefers-reduced-motion: reduce) {
.ng-scanlines::after { display: none; }
* { transition: none !important; animation: none !important; }
}