472 lines
15 KiB
CSS
472 lines
15 KiB
CSS
/* ═══════════════════════════════════════════════════════════════════════
|
|
* BREAKCORE — refined-neon layer.
|
|
* Everything below is scoped to `.breakcore`; salon / salon-noir / gothic
|
|
* are untouched. Aesthetic: editorial serif body in deliberate tension with
|
|
* hard-edged web-rot chrome — RGB split, hazard tape, neon outline, hard
|
|
* offset shadows. Motion is *reactive only* (hover / focus / one-shot on
|
|
* load) and settles fast. All motion is killed by prefers-reduced-motion
|
|
* at the very end of this file.
|
|
* ═══════════════════════════════════════════════════════════════════════ */
|
|
|
|
/* CRT tube depth — static vignette layered on the existing base fill. */
|
|
.breakcore body::before {
|
|
background-image: radial-gradient(
|
|
ellipse at center,
|
|
transparent 52%,
|
|
color-mix(in srgb, var(--crust) 75%, transparent) 100%
|
|
);
|
|
}
|
|
|
|
/* Nameplate — breakcore reworks the underline: hard cyan offset + magenta
|
|
* neon glow (the layer's hard-offset chrome language) instead of the
|
|
* default two-tone rule. Plus a glitch-shear burst on hover. */
|
|
.breakcore .nameplate::after {
|
|
height: 2px;
|
|
bottom: -7px;
|
|
background: var(--mauve);
|
|
box-shadow:
|
|
2px 2px 0 var(--blue),
|
|
0 0 10px color-mix(in srgb, var(--mauve) 70%, transparent);
|
|
}
|
|
@keyframes bc-shear {
|
|
0% { clip-path: inset(0 0 0 0); transform: translateX(0);
|
|
text-shadow: -1px 0 0 var(--teal), 1px 0 0 var(--mauve); }
|
|
20% { clip-path: inset(16% 0 56% 0); transform: translateX(-5px);
|
|
text-shadow: -5px 0 0 var(--green), 5px 0 0 var(--mauve); }
|
|
40% { clip-path: inset(62% 0 10% 0); transform: translateX(5px);
|
|
text-shadow: 5px 0 0 var(--teal), -5px 0 0 var(--red); }
|
|
60% { clip-path: inset(30% 0 42% 0); transform: translateX(-3px);
|
|
text-shadow: -3px 0 0 var(--mauve), 3px 0 0 var(--green); }
|
|
80% { clip-path: inset(6% 0 78% 0); transform: translateX(2px);
|
|
text-shadow: 2px 0 0 var(--teal), -2px 0 0 var(--mauve); }
|
|
100% { clip-path: inset(0 0 0 0); transform: translateX(0);
|
|
text-shadow: -1px 0 0 var(--teal), 1px 0 0 var(--mauve); }
|
|
}
|
|
.breakcore .nameplate:hover .nameplate-title {
|
|
animation: bc-shear 200ms steps(3, jump-none) 1;
|
|
}
|
|
|
|
/* Display headings — one-shot glitch-in on page load. The static chromatic
|
|
* text-shadow (defined earlier) remains as the resting state. */
|
|
@keyframes bc-load-glitch {
|
|
0% { opacity: 0; clip-path: inset(46% 0 46% 0); transform: translateX(-9px); }
|
|
20% { opacity: 1; clip-path: inset(8% 0 70% 0); transform: translateX(7px); }
|
|
40% { clip-path: inset(68% 0 8% 0); transform: translateX(-5px); }
|
|
60% { clip-path: inset(24% 0 36% 0); transform: translateX(3px); }
|
|
80% { clip-path: inset(4% 0 84% 0); transform: translateX(-2px); }
|
|
/* End unclipped (none, not inset(0)) so italic-Fraunces descenders
|
|
* (g, y, p) aren't sliced at the box edge once the glitch settles. */
|
|
100% { opacity: 1; clip-path: none; transform: translateX(0); }
|
|
}
|
|
.breakcore .prose h1,
|
|
.breakcore h1.font-display {
|
|
/* `backwards` (not `both`): after the one-shot, props revert to base —
|
|
* clip-path: none — instead of persisting the final inset clip. */
|
|
animation: bc-load-glitch 460ms steps(5, jump-none) backwards;
|
|
}
|
|
|
|
/* Plate — hard hover (no soft lift), RGB-split image, scanline sweep. */
|
|
.breakcore .plate:hover {
|
|
transform: translateY(-3px);
|
|
}
|
|
.breakcore .plate:hover .plate-caption-title {
|
|
text-shadow: -1px 0 0 var(--teal), 1px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .plate:hover .plate-image img {
|
|
filter:
|
|
drop-shadow(-3px 0 0 color-mix(in srgb, var(--mauve) 70%, transparent))
|
|
drop-shadow(3px 0 0 color-mix(in srgb, var(--teal) 70%, transparent))
|
|
saturate(1.12) contrast(1.06);
|
|
}
|
|
.breakcore .plate .plate-image::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transform: translateY(-110%);
|
|
mix-blend-mode: screen;
|
|
background: linear-gradient(
|
|
180deg,
|
|
transparent 0%,
|
|
color-mix(in srgb, var(--sky) 28%, transparent) 46%,
|
|
color-mix(in srgb, var(--mauve) 70%, transparent) 49%,
|
|
color-mix(in srgb, var(--green) 55%, transparent) 51%,
|
|
color-mix(in srgb, var(--sky) 28%, transparent) 54%,
|
|
transparent 100%
|
|
);
|
|
}
|
|
@keyframes bc-scan {
|
|
0% { transform: translateY(-110%); opacity: 0; }
|
|
12% { opacity: 1; }
|
|
88% { opacity: 1; }
|
|
100% { transform: translateY(110%); opacity: 0; }
|
|
}
|
|
.breakcore .plate:hover .plate-image::after,
|
|
.breakcore .plate:focus-visible .plate-image::after {
|
|
animation: bc-scan 0.62s cubic-bezier(0.4, 0, 0.2, 1) 1;
|
|
}
|
|
|
|
/* Section rule — hazard tape. Used on footer, post header, 404. */
|
|
.breakcore .section-rule {
|
|
color: var(--green);
|
|
font-family: var(--font-mono);
|
|
font-style: normal;
|
|
font-size: 0.78rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.22em;
|
|
}
|
|
.breakcore .section-rule::before,
|
|
.breakcore .section-rule::after {
|
|
height: 1px;
|
|
opacity: 0.85;
|
|
background: linear-gradient(
|
|
to right,
|
|
transparent,
|
|
color-mix(in srgb, var(--mauve) 70%, transparent) 45%,
|
|
color-mix(in srgb, var(--teal) 70%, transparent) 55%,
|
|
transparent
|
|
);
|
|
}
|
|
.breakcore .section-rule .ornament {
|
|
color: var(--mauve);
|
|
}
|
|
|
|
/* Readability — `--overlay0` (#5A2D8E) is near-invisible on the breakcore
|
|
* ground. Lift the spots that use it as actual copy to the readable
|
|
* subtext ramp. */
|
|
.breakcore .prose h6,
|
|
.breakcore .prose del,
|
|
.breakcore .hljs-comment,
|
|
.breakcore .hljs-quote,
|
|
.breakcore .site-copyright,
|
|
.breakcore .slug-hint {
|
|
color: var(--subtext0);
|
|
}
|
|
|
|
/* Chips — neon outline, monospace caps. */
|
|
.breakcore .chip {
|
|
background: transparent;
|
|
border-color: color-mix(in srgb, var(--teal) 55%, transparent);
|
|
color: var(--teal);
|
|
font-family: var(--font-mono);
|
|
font-style: normal;
|
|
font-size: 0.7rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
border-radius: 0;
|
|
}
|
|
.breakcore .chip-accent {
|
|
background: var(--mauve);
|
|
color: var(--crust);
|
|
border-color: var(--mauve);
|
|
}
|
|
.breakcore .chip-draft {
|
|
background: transparent;
|
|
border-color: color-mix(in srgb, var(--green) 60%, transparent);
|
|
color: var(--green);
|
|
}
|
|
|
|
/* Plate caption meta — bracketed mono coordinates. */
|
|
.breakcore .plate-caption-meta {
|
|
font-family: var(--font-mono);
|
|
letter-spacing: 0.16em;
|
|
}
|
|
.breakcore .plate-caption-sep {
|
|
color: var(--green);
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Buttons & inputs — square, hard offset block-shadow, neon focus. */
|
|
.breakcore .btn,
|
|
.breakcore .field-input,
|
|
.breakcore .topbar-control,
|
|
.breakcore .topbar-control kbd { border-radius: 0; }
|
|
.breakcore .btn--primary {
|
|
color: var(--crust);
|
|
border-color: var(--mauve);
|
|
box-shadow: 3px 3px 0 0 var(--green);
|
|
}
|
|
.breakcore .btn--primary:hover {
|
|
background: var(--green);
|
|
border-color: var(--green);
|
|
color: var(--crust);
|
|
box-shadow: 3px 3px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .btn--primary:active {
|
|
transform: translate(2px, 2px);
|
|
box-shadow: 1px 1px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .btn--danger {
|
|
box-shadow: 3px 3px 0 0 color-mix(in srgb, var(--red) 60%, var(--crust));
|
|
}
|
|
.breakcore .btn--danger:hover {
|
|
box-shadow: 3px 3px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .btn--danger:active {
|
|
transform: translate(2px, 2px);
|
|
box-shadow: 1px 1px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .btn:focus-visible {
|
|
border-color: var(--green);
|
|
box-shadow: 0 0 0 2px var(--green);
|
|
}
|
|
.breakcore .field-input:focus {
|
|
border-color: var(--green);
|
|
background: color-mix(in srgb, var(--surface0) 85%, var(--green) 8%);
|
|
box-shadow: 0 0 0 2px color-mix(in srgb, var(--green) 35%, transparent);
|
|
}
|
|
|
|
/* Ghost had no breakcore identity — drab subtext on faint surface,
|
|
* near-invisible on the violet ground. Give it the neon outline. */
|
|
.breakcore .btn--ghost {
|
|
color: var(--teal);
|
|
border-color: color-mix(in srgb, var(--teal) 55%, transparent);
|
|
background: color-mix(in srgb, var(--surface0) 60%, transparent);
|
|
box-shadow: 3px 3px 0 0 color-mix(in srgb, var(--teal) 35%, var(--crust));
|
|
}
|
|
.breakcore .btn--ghost:hover {
|
|
color: var(--crust);
|
|
background: var(--teal);
|
|
border-color: var(--teal);
|
|
box-shadow: 3px 3px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .btn--ghost:active {
|
|
transform: translate(2px, 2px);
|
|
box-shadow: 1px 1px 0 0 var(--mauve);
|
|
}
|
|
|
|
/* Back-link → hard neon return tab. Impossible to miss against the
|
|
* CRT-violet ground; same offset-block language as .btn--primary. */
|
|
.breakcore .back-link {
|
|
font-family: var(--font-mono);
|
|
font-style: normal;
|
|
font-size: 0.7rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.16em;
|
|
color: var(--green);
|
|
padding: 7px 13px;
|
|
background: color-mix(in srgb, var(--crust) 65%, transparent);
|
|
border: 1px solid var(--mauve);
|
|
box-shadow: 3px 3px 0 0 var(--mauve);
|
|
text-shadow: 0 0 6px color-mix(in srgb, var(--green) 50%, transparent);
|
|
}
|
|
.breakcore .back-link:hover,
|
|
.breakcore .back-link:focus-visible {
|
|
color: var(--crust);
|
|
background: var(--green);
|
|
border-color: var(--green);
|
|
box-shadow: 3px 3px 0 0 var(--mauve);
|
|
text-shadow: none;
|
|
}
|
|
.breakcore .back-link:active {
|
|
transform: translate(3px, 3px);
|
|
box-shadow: 0 0 0 0 var(--mauve);
|
|
}
|
|
|
|
/* Top-bar chrome — neon UI, not drab subtext. Mono caps + hard offset. */
|
|
.breakcore .topbar-control {
|
|
font-family: var(--font-mono);
|
|
font-style: normal;
|
|
font-size: 0.72rem;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--teal);
|
|
background: color-mix(in srgb, var(--crust) 55%, transparent);
|
|
border-color: color-mix(in srgb, var(--teal) 50%, transparent);
|
|
}
|
|
.breakcore .topbar-control:hover {
|
|
color: var(--crust);
|
|
background: var(--mauve);
|
|
border-color: var(--mauve);
|
|
box-shadow: 2px 2px 0 0 var(--green);
|
|
}
|
|
.breakcore .topbar-control:focus-visible {
|
|
border-color: var(--green);
|
|
box-shadow: 0 0 0 2px var(--green);
|
|
}
|
|
.breakcore .topbar-control--danger:hover {
|
|
background: var(--red);
|
|
border-color: var(--red);
|
|
color: var(--rosewater);
|
|
box-shadow: 2px 2px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .topbar-divider {
|
|
width: 2px;
|
|
background: repeating-linear-gradient(
|
|
180deg,
|
|
var(--mauve) 0 4px,
|
|
transparent 4px 7px
|
|
);
|
|
}
|
|
|
|
/* Post prev/next nav — neon offset panels + acid eyebrow (was dim text). */
|
|
.breakcore .post-nav a { transition: box-shadow 0.15s ease, border-color 0.15s ease; }
|
|
.breakcore .post-nav a:hover {
|
|
border-color: var(--mauve);
|
|
box-shadow:
|
|
inset 0 0 0 1px color-mix(in srgb, var(--mauve) 40%, transparent),
|
|
4px 4px 0 0 var(--mauve);
|
|
}
|
|
.breakcore .post-nav .pn-eyebrow {
|
|
color: var(--green);
|
|
font-family: var(--font-mono);
|
|
letter-spacing: 0.18em;
|
|
text-shadow: 0 0 6px color-mix(in srgb, var(--green) 45%, transparent);
|
|
}
|
|
|
|
/* Prose / code — CRT pass: terminal block, hazard inline code, neon
|
|
* blockquote, hazard-tape rule. */
|
|
.breakcore .prose pre {
|
|
color: var(--teal);
|
|
background-color: color-mix(in srgb, var(--crust) 92%, transparent);
|
|
background-image: repeating-linear-gradient(
|
|
0deg,
|
|
rgba(0, 0, 0, 0) 0 2px,
|
|
color-mix(in srgb, var(--mauve) 9%, transparent) 2px 3px,
|
|
rgba(0, 0, 0, 0) 3px 4px
|
|
);
|
|
border-color: var(--mauve);
|
|
border-left-color: var(--green);
|
|
box-shadow:
|
|
0 0 0 1px color-mix(in srgb, var(--mauve) 28%, transparent),
|
|
4px 4px 0 0 color-mix(in srgb, var(--mauve) 35%, var(--crust));
|
|
}
|
|
.breakcore .prose pre code { color: inherit; }
|
|
.breakcore .prose :not(pre) code {
|
|
color: var(--yellow);
|
|
background: color-mix(in srgb, var(--yellow) 12%, transparent);
|
|
border-bottom-color: color-mix(in srgb, var(--yellow) 55%, transparent);
|
|
}
|
|
.breakcore .prose blockquote {
|
|
border-left-color: var(--mauve);
|
|
background: color-mix(in srgb, var(--mauve) 7%, transparent);
|
|
box-shadow: -3px 0 14px -5px color-mix(in srgb, var(--mauve) 55%, transparent);
|
|
padding: 0.5rem 0 0.5rem 1.4rem;
|
|
}
|
|
.breakcore .prose hr {
|
|
height: 3px;
|
|
opacity: 0.85;
|
|
background: repeating-linear-gradient(
|
|
90deg,
|
|
var(--mauve) 0 14px,
|
|
var(--green) 14px 28px
|
|
);
|
|
box-shadow: 0 0 10px color-mix(in srgb, var(--mauve) 40%, transparent);
|
|
}
|
|
.breakcore .prose hr::before {
|
|
background: var(--green);
|
|
box-shadow: 0 0 8px var(--green);
|
|
}
|
|
.breakcore .prose h3 { color: var(--pink); }
|
|
.breakcore .prose h4 { color: var(--teal); }
|
|
.breakcore .prose h5 { color: var(--green); font-family: var(--font-mono); }
|
|
|
|
/* Scrollbar + caret — full-immersion chrome (no default OS bar). */
|
|
.breakcore {
|
|
scrollbar-color: var(--mauve) var(--crust);
|
|
caret-color: var(--mauve);
|
|
}
|
|
.breakcore ::-webkit-scrollbar { width: 11px; height: 11px; }
|
|
.breakcore ::-webkit-scrollbar-track { background: var(--crust); }
|
|
.breakcore ::-webkit-scrollbar-thumb {
|
|
background: var(--mauve);
|
|
border: 2px solid var(--crust);
|
|
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--green) 50%, transparent);
|
|
}
|
|
.breakcore ::-webkit-scrollbar-thumb:hover { background: var(--green); }
|
|
.breakcore ::-webkit-scrollbar-corner { background: var(--crust); }
|
|
|
|
/* Prose links — magenta resting, acid-green on hover. */
|
|
.breakcore .prose a {
|
|
text-decoration-color: color-mix(in srgb, var(--mauve) 55%, transparent);
|
|
}
|
|
.breakcore .prose a:hover {
|
|
color: var(--green);
|
|
text-decoration-color: var(--green);
|
|
}
|
|
|
|
/* Reading progress — acid scan with bloom. */
|
|
.breakcore .reading-progress {
|
|
background: var(--green);
|
|
box-shadow: 0 0 8px var(--green), 0 0 3px var(--mauve);
|
|
}
|
|
|
|
/* ───── Confirm dialog (replaces window.confirm) ───── */
|
|
.cdialog-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 300;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 1rem;
|
|
}
|
|
.cdialog-backdrop {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: color-mix(in srgb, var(--crust) 60%, transparent);
|
|
backdrop-filter: blur(8px);
|
|
}
|
|
.cdialog-panel {
|
|
position: relative;
|
|
width: 100%;
|
|
max-width: 26rem;
|
|
padding: 1.6rem 1.6rem 1.4rem;
|
|
animation: cdialog-in 0.18s cubic-bezier(0.2, 0.7, 0.2, 1);
|
|
}
|
|
@keyframes cdialog-in {
|
|
from { opacity: 0; transform: translateY(10px) scale(0.98); }
|
|
to { opacity: 1; transform: none; }
|
|
}
|
|
.cdialog-title {
|
|
font-family: var(--font-display);
|
|
font-style: italic;
|
|
font-weight: 600;
|
|
font-size: 1.4rem;
|
|
line-height: 1.15;
|
|
color: var(--text);
|
|
letter-spacing: -0.01em;
|
|
}
|
|
.cdialog-msg {
|
|
font-family: var(--font-sans);
|
|
font-size: 0.98rem;
|
|
line-height: 1.55;
|
|
color: var(--subtext1);
|
|
margin-top: 0.6rem;
|
|
}
|
|
.cdialog-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 0.6rem;
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
/* Breakcore: hard edges + neon cap + chromatic title. */
|
|
.breakcore .cdialog-panel {
|
|
border-radius: 0;
|
|
padding-top: 1.85rem;
|
|
}
|
|
.breakcore .cdialog-panel::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 0 auto 0;
|
|
height: 2px;
|
|
background: linear-gradient(90deg, var(--mauve), var(--teal));
|
|
}
|
|
.breakcore .cdialog-title {
|
|
text-shadow: -1px 0 0 var(--teal), 1px 0 0 var(--mauve);
|
|
}
|
|
|
|
/* Toast error variant (replaces window.alert). */
|
|
.toast--error {
|
|
border-left: 3px solid var(--red);
|
|
color: var(--rosewater);
|
|
cursor: pointer;
|
|
}
|
|
.toast--error::before {
|
|
content: "⚠ ";
|
|
color: var(--red);
|
|
}
|
|
|