/* ------------------------------------------------------------------
   DG//OS core: the shared visual system.

   Linked by the landing page (styles.css) and by every app (snake/...).
   A change here changes all of them, which is the point: tokens and the
   signature parts live in exactly one place. Page-specific layout does not
   belong in this file. The rules behind these choices are in
   ../STYLE-GUIDE.md.

   Palette is three neons on near-black: volt leads, hot and cyan are
   accents only. Keep it that way: when all three compete on one element
   the page stops reading as designed and starts reading as noise.
   ------------------------------------------------------------------ */

:root {
  --bg: #06070b;
  --bg-2: #0b0d14;
  --panel: #0e111a;
  --screen: #05060a;  /* behind any canvas scene; darker than the page */
  --line: #1e2433;
  --line-2: #323a50;
  --text: #d9deea;
  --muted: #7a839b;
  --dim: #454c61;

  --volt: #e6ff2b;
  --hot: #ff2a6d;
  --cyan: #22e3ee;

  --font-display: 'Chakra Petch', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --wrap: 1240px;
  --gutter: clamp(16px, 4vw, 48px);
  --hud-h: 60px;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--bg); }

body {
  margin: 0;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 17px;
  line-height: 1.6;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
p { margin: 0 0 1em; }
h1, h2, h3 { margin: 0; line-height: 1; }
::selection { background: var(--volt); color: #000; }

:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 3px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* An author display rule (flex, grid) would otherwise beat the hidden attribute. */
[hidden] { display: none !important; }

/* ---------- Chamfered panel ----------
   clip-path cuts the corners, which also cuts off any CSS border. So the
   element's own background is the border colour and ::before, inset 1px,
   paints the fill on top of it. Change --bd / --fill, not `border`. */
.chamfer {
  --c: 16px;
  --bd: var(--line-2);
  --fill: var(--panel);
  position: relative;
  isolation: isolate;
  background: var(--bd);
  clip-path: polygon(0 0, calc(100% - var(--c)) 0, 100% var(--c), 100% 100%, var(--c) 100%, 0 calc(100% - var(--c)));
}
.chamfer::before {
  content: '';
  position: absolute;
  inset: 1px;
  z-index: -1;
  background: var(--fill);
  clip-path: polygon(0 0, calc(100% - var(--c)) 0, 100% var(--c), 100% 100%, var(--c) 100%, 0 calc(100% - var(--c)));
}

/* ---------- Scanlines ---------- */
.fx-scanlines {
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0) 0 2px, rgba(0, 0, 0, .16) 2px 3px);
  mix-blend-mode: multiply;
}

/* ---------- Logo mark ---------- */
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  background: var(--volt); color: #000;
  font: 700 15px/1 var(--font-display);
  letter-spacing: 0;
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px));
  transition: background .15s;
}
.brand:hover .brand-mark { background: var(--hot); }
.brand-name { color: var(--text); }
.brand-name em { font-style: normal; color: var(--muted); }

/* ---------- Status dot ---------- */
.pulse {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--volt);
  box-shadow: 0 0 10px var(--volt);
  animation: pulse 1.6s ease-in-out infinite;
}
.pulse--hot { background: var(--hot); box-shadow: 0 0 10px var(--hot); }
@keyframes pulse { 50% { opacity: .25; } }

/* ---------- Eyebrow label ---------- */
.eyebrow {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 18px;
  font: 500 12px/1 var(--font-mono);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
}
.eyebrow-bar { width: 36px; height: 2px; background: var(--hot); box-shadow: 0 0 10px var(--hot); }

/* ---------- Two-line display title with glitch bursts ----------
   Font size is set by whoever uses it. */
.name {
  font-weight: 700;
  line-height: .84;
  letter-spacing: -.02em;
  text-transform: uppercase;
  user-select: none;
}
.name-line { position: relative; display: block; width: max-content; }
.name-line--solid { color: var(--volt); text-shadow: 0 0 60px rgba(230, 255, 43, .28); }
.name-line--outline {
  color: transparent;
  -webkit-text-stroke: 2px var(--text);
}
/* Glitch layers. Hidden until JS adds .glitching for a short burst; a
   permanent glitch loop on type this size is unreadable and exhausting. */
.name-line::before, .name-line::after {
  content: attr(data-text);
  position: absolute; inset: 0;
  opacity: 0; pointer-events: none;
  -webkit-text-stroke: 0;
}
.name.glitching .name-line::before { opacity: .9; color: var(--hot); animation: glitch-a .42s steps(1) both; }
.name.glitching .name-line::after { opacity: .9; color: var(--cyan); animation: glitch-b .42s steps(1) both; }
.name.glitching { animation: glitch-shake .42s steps(1) both; }
@keyframes glitch-a {
  0% { clip-path: inset(8% 0 62% 0); transform: translate(-8px, 2px); }
  25% { clip-path: inset(56% 0 18% 0); transform: translate(6px, -2px); }
  50% { clip-path: inset(28% 0 48% 0); transform: translate(-5px, 0); }
  75% { clip-path: inset(78% 0 4% 0); transform: translate(8px, 1px); }
  100% { clip-path: inset(0 0 100% 0); transform: none; }
}
@keyframes glitch-b {
  0% { clip-path: inset(66% 0 10% 0); transform: translate(8px, -1px); }
  25% { clip-path: inset(12% 0 70% 0); transform: translate(-6px, 2px); }
  50% { clip-path: inset(44% 0 30% 0); transform: translate(5px, 0); }
  75% { clip-path: inset(2% 0 84% 0); transform: translate(-8px, -2px); }
  100% { clip-path: inset(0 0 100% 0); transform: none; }
}
@keyframes glitch-shake {
  0% { transform: translateX(3px) skewX(-2deg); }
  33% { transform: translateX(-3px) skewX(1.5deg); }
  66% { transform: translateX(1px); }
  100% { transform: none; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 14px;
  padding: 16px 22px;
  background: var(--volt); color: #000;
  font: 700 13px/1 var(--font-mono);
  letter-spacing: .12em; text-transform: uppercase;
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
  transition: background .15s, transform .15s;
}
.btn i { font-style: normal; transition: transform .2s; }
.btn:hover { background: #fff; transform: translate(-2px, -2px); }
.btn:hover i { transform: translateX(5px); }
.btn:active { transform: none; }
.btn--ghost { background: var(--line-2); color: var(--text); position: relative; isolation: isolate; }
.btn--ghost::before {
  content: ''; position: absolute; inset: 1px; z-index: -1;
  background: var(--bg-2);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
  transition: background .15s;
}
.btn--ghost:hover { background: var(--cyan); color: var(--cyan); }
.btn--ghost:hover::before { background: #071a1d; }
button.btn { border: 0; cursor: pointer; }
/* clip-path cuts off the global :focus-visible outline, so a .btn draws its
   ring inside the chamfer. -8px is the smallest inset whose corners clear
   the 12px cut; at -6px the top-right corner of the ring is clipped. */
.btn:focus-visible { outline: 2px solid #000; outline-offset: -8px; }
.btn--ghost:focus-visible { outline-color: var(--volt); }

/* ---------- Chips and tags ---------- */
.chip {
  padding: 12px 16px;
  border: 1px solid var(--line-2);
  font: 700 12px/1 var(--font-mono);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--text);
  transition: background .12s, color .12s, border-color .12s, transform .12s;
}
.chip::before { content: '> '; color: var(--volt); transition: color .12s; }
.chip:hover { background: var(--hot); border-color: var(--hot); color: #000; transform: translate(-2px, -2px); }
.chip:hover::before { color: #000; }

.card-tags { display: flex; gap: 8px; margin-bottom: 16px; }
.card-tags span {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--cyan);
  border: 1px solid rgba(34, 227, 238, .35);
  padding: 5px 8px;
}

/* ---------- Stepped effects ---------- */
.shake { animation: shake .36s steps(1); }
@keyframes shake {
  0% { transform: translateX(-7px); }
  25% { transform: translateX(7px); }
  50% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
  100% { transform: none; }
}

/* Whole-view glitch. Put .page-glitch-fx on the element that should tear. */
.page-glitch-fx { animation: page-glitch .5s steps(1); }
@keyframes page-glitch {
  0% { transform: translateX(-10px) skewX(3deg); filter: hue-rotate(90deg) saturate(2); }
  25% { transform: translateX(8px) skewX(-2deg); filter: invert(1); }
  50% { transform: translateY(6px); filter: hue-rotate(-120deg); }
  75% { transform: translateX(-4px); filter: none; }
  100% { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
