/* dedsec.css — shared grayscale "DedSec" theme for eigencat.org
 *
 * Grayscale first. Each page may set --ds-accent (and --ds-accent-soft) to its
 * own dark, muted color; the accent is meant to appear rarely — focus rings,
 * an active state, one highlighted word — never as a fill for whole surfaces.
 *
 * Pages opt in with class="ds-body" on <body> and use the ds-*
 * classes below. Titles get the typewriter display font (Special Elite);
 * everything else stays on the plain monospace typewriter stack.
 */

:root {
    --ds-bg: #000000;
    --ds-bg-1: #0a0a0a;
    --ds-bg-2: #141414;
    --ds-line: #2e2e2e;
    --ds-line-bright: #4a4a4a;
    --ds-text: #cfcfcf;
    --ds-muted: #7f7f7f;
    --ds-bright: #f5f5f5;
    --ds-accent: #a9a9a9;
    --ds-accent-soft: rgba(169, 169, 169, 0.12);
    --ds-font-display: 'Special Elite', 'Courier New', monospace;
    --ds-font-mono: 'Courier New', Courier, monospace;
}

/* Pages add ds-js to <html> from an inline head script; typed lines are then
 * hidden until dedsec.js reveals them, but stay visible if JS never runs. */
.ds-js [data-typewriter] { visibility: hidden; }

.ds-body {
    background: var(--ds-bg);
    color: var(--ds-text);
    font-family: var(--ds-font-mono);
    margin: 0;
}

.ds-body ::selection {
    background: var(--ds-accent);
    color: var(--ds-bg);
}

/* ---------- Type ---------- */

.ds-title {
    font-family: var(--ds-font-display);
    font-weight: normal;
    letter-spacing: 0.04em;
    color: var(--ds-bright);
}

.ds-label {
    font-family: var(--ds-font-mono);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ds-muted);
}

.ds-muted { color: var(--ds-muted); }

/* Blinking typewriter caret, for typed lines and titles. */
.ds-caret::after {
    content: "_";
    margin-left: 0.1em;
    color: var(--ds-accent);
    animation: ds-blink 1.1s steps(1) infinite;
}

@keyframes ds-blink {
    0%, 55% { opacity: 1; }
    56%, 100% { opacity: 0; }
}

/* ---------- Glitch title ----------
 * Usage: <h1 class="ds-title ds-glitch" data-text="SAME TEXT">SAME TEXT</h1>
 * dedsec.js toggles .ds-glitching for ~300ms at random intervals; the effect
 * is off the rest of the time, and off entirely for reduced-motion users.
 */
.ds-glitch { position: relative; display: inline-block; }

/* ::after is shared with .ds-caret (the blinking "_", whose blink animates
 * opacity back up). A caret-bearing element must never get the glitch's
 * full-text ::after copy or the caret's blink makes it flash on permanently —
 * so carets keep their ::after and glitch uses ::before alone there. */
.ds-glitch::before,
.ds-glitch:not(.ds-caret)::after {
    content: attr(data-text);
    position: absolute;
    inset: 0;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
}

/* Ghost copies fall down-and-right like a loose drop shadow so the word
 * itself stays readable while it glitches. */
.ds-glitch.ds-glitching::before {
    opacity: 0.55;
    color: var(--ds-muted);
    transform: translate(3px, 3px);
    clip-path: inset(12% 0 40% 0);
    animation: ds-glitch-shift 0.28s steps(3) both;
}

.ds-glitch.ds-glitching:not(.ds-caret)::after {
    opacity: 0.35;
    color: var(--ds-muted);
    transform: translate(6px, 5px);
    clip-path: inset(52% 0 8% 0);
    animation: ds-glitch-shift 0.28s steps(3) reverse both;
}

@keyframes ds-glitch-shift {
    0%   { clip-path: inset(8% 0 52% 0);  transform: translate(3px, 2px); }
    34%  { clip-path: inset(42% 0 22% 0); transform: translate(5px, 4px); }
    67%  { clip-path: inset(60% 0 4% 0);  transform: translate(4px, 3px); }
    100% { clip-path: inset(24% 0 38% 0); transform: translate(2px, 2px); }
}

@media (prefers-reduced-motion: reduce) {
    .ds-glitch.ds-glitching::before,
    .ds-glitch.ds-glitching:not(.ds-caret)::after { animation: none; opacity: 0; }
    .ds-caret::after { animation: none; }
}

/* ---------- Surfaces & controls ---------- */

.ds-panel {
    background: var(--ds-bg-1);
    border: 1px solid var(--ds-line);
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.55);
}

.ds-btn {
    display: inline-block;
    font-family: var(--ds-font-mono);
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ds-text);
    background: var(--ds-bg-2);
    border: 1px solid var(--ds-line-bright);
    padding: 8px 16px;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.ds-btn:hover,
.ds-btn:focus-visible {
    background: var(--ds-bright);
    color: var(--ds-bg);
    border-color: var(--ds-bright);
    outline: none;
}

.ds-btn:active { transform: translate(1px, 1px); }

.ds-input {
    font-family: var(--ds-font-mono);
    font-size: 14px;
    color: var(--ds-bright);
    background: var(--ds-bg-1);
    border: 1px solid var(--ds-line);
    padding: 9px 12px;
    caret-color: var(--ds-accent);
}

.ds-input::placeholder { color: var(--ds-muted); }

.ds-input:focus {
    outline: none;
    border-color: var(--ds-accent);
    box-shadow: 0 0 0 1px var(--ds-accent-soft), inset 0 0 0 1px var(--ds-accent-soft);
}

.ds-link {
    color: var(--ds-text);
    text-decoration: none;
    border-bottom: 1px solid var(--ds-line);
    transition: color 0.15s, border-color 0.15s;
}

.ds-link:hover,
.ds-link:focus-visible {
    color: var(--ds-bright);
    border-color: var(--ds-accent);
    outline: none;
}
