/* =============================================================
   MANDROCK — mandrock.me
   Single source of truth for design tokens is :root below.
   A reskin must touch nothing outside that block.
   ============================================================= */

:root {
  /* ---- colour: base ---------------------------------------- */
  --c-bg:        #07080a;   /* near-black page base                */
  --c-panel:     #0d1014;   /* row / lit surface                   */
  --c-panel-hi:  #12161c;   /* hover surface                       */

  /* ---- colour: ink (all pass >= 4.5:1 on --c-bg) ------------ */
  --c-ink:       #dfe4ea;   /* 15.7:1  body + link names           */
  --c-ink-mute:  #98a2b0;   /*  7.8:1  metadata, descriptions      */

  /* ---- colour: accents -------------------------------------- */
  --c-acid:      #8bff5a;   /* 15.8:1  PRIMARY voice: structure,
                               section numbers, markers, focus     */
  --c-mag:       #ff3ea5;   /*  6.2:1  SECOND voice, used sparingly:
                               [AUTH] tag + glitch channel only    */

  /* ---- colour: non-text only (below 4.5:1 — NEVER for copy) -- */
  --c-rule:      #1c2129;   /* hairlines, section rules            */
  --c-edge:      #748094;   /* 5.0:1 — renders real glyphs (the ":"
                               in the readout, "/" separators), so it has
                               to clear 4.5:1, not the 3:1 non-text bar   */

  /* ---- colour: derived washes ------------------------------- */
  --c-acid-8:    rgba(139, 255, 90, .08);
  --c-acid-16:   rgba(139, 255, 90, .16);
  --c-acid-30:   rgba(139, 255, 90, .30);
  --c-mag-14:    rgba(255, 62, 165, .14);
  --c-grid:      rgba(139, 255, 90, .055);
  --c-scan:      rgba(0, 0, 0, .38);
  --c-vig:       rgba(0, 0, 0, .72);

  /* ---- colour: print inversion ------------------------------ */
  --c-print-bg:  #ffffff;
  --c-print-ink: #000000;

  /* ---- type -------------------------------------------------- */
  --ff: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;
  --fs-2xs: .6875rem;  /* 11px — tags                             */
  --fs-xs:  .75rem;    /* 12px — index numbers, readout           */
  --fs-sm:  .875rem;   /* 14px — descriptions                     */
  --fs-md:  1rem;      /* 16px — link names                       */
  --fs-lg:  1.125rem;  /* 18px — section headings                 */
  --fs-mark: clamp(2.25rem, 11vw, 5rem);
  --ls-tight: -.01em;
  --ls-wide:   .08em;
  --ls-mark:   .06em;
  --lh-tight: 1.15;
  --lh-body:  1.5;

  /* ---- space ------------------------------------------------- */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 72px;
  --shell-max: 900px;
  --gutter: clamp(16px, 4vw, 40px);
  --row-min: 56px;          /* >= 44px touch target + breathing   */

  /* ---- shape ------------------------------------------------- */
  --r-sm: 2px;
  --r-md: 4px;
  --hair: 1px;

  /* ---- motion ------------------------------------------------ */
  --t-fast: 120ms;
  --t-glitch: 200ms;
  --ease: cubic-bezier(.2, .7, .3, 1);

  /* ---- runtime channels (written by main.js, never elsewhere) - */
  --px: 0;      /* pointer x, normalised -1..1                    */
  --py: 0;      /* pointer y, normalised -1..1                    */
  --mx: 50%;    /* per-section pointer x, set on .sec             */
  --my: 50%;    /* per-section pointer y, set on .sec             */
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--ff);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  overflow-x: clip;              /* safety net; nothing should overflow */
  -webkit-font-smoothing: antialiased;
}

h1, h2, p, dl, dd, dt { margin: 0; }

/* Custom cursor. Pure CSS so it survives JS being off.
   ~20px, hotspot 4 4 = the bracket's vertex. Angular bracket +
   magenta dot marking the exact hit point. NOT a blob. */
@media (hover: hover) and (pointer: fine) {
  body,
  a, button, summary {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath d='M4 14.5V4h10.5' fill='none' stroke='%23000' stroke-width='3.5' stroke-opacity='.6' stroke-linecap='square'/%3E%3Cpath d='M4 14.5V4h10.5' fill='none' stroke='%238bff5a' stroke-width='1.5' stroke-linecap='square'/%3E%3Ccircle cx='4' cy='4' r='1.5' fill='%23ff3ea5'/%3E%3C/svg%3E") 4 4, auto;
  }
}

/* =============================================================
   FOCUS — must survive the neon theme.
   acid on near-black = 15.8:1, plus a dark offset ring so the
   outline is visible over lit/hover surfaces too.
   ============================================================= */
:focus-visible {
  outline: 2px solid var(--c-acid);
  outline-offset: 2px;
  border-radius: var(--r-sm);
  box-shadow: 0 0 0 2px var(--c-bg);
}
:focus:not(:focus-visible) { outline: none; }

/* Visually hidden, still announced. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: fixed;
  left: var(--sp-3); top: var(--sp-3);
  z-index: 20;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
  border: var(--hair) solid var(--c-acid);
  color: var(--c-acid);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus,
.skip:focus-visible { transform: translateY(0); }

/* =============================================================
   FX LAYERS — fixed, never in flow, never cause scroll or CLS
   ============================================================= */
.fx {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: layout paint;
}

.fx__grid,
.fx__dots {
  position: absolute;
  inset: -8%;
  will-change: transform;
}

/* thin structural grid — the visible skeleton of the page */
.fx__grid {
  background-image:
    repeating-linear-gradient(to right,  var(--c-grid) 0 1px, transparent 1px 72px),
    repeating-linear-gradient(to bottom, var(--c-grid) 0 1px, transparent 1px 72px);
  transform: translate3d(calc(var(--px) * 8px), calc(var(--py) * 8px), 0)
             skewX(calc(var(--px) * 0.4deg));
}

/* sparse register marks, deeper parallax */
.fx__dots {
  background-image: radial-gradient(circle, var(--c-acid-16) 0 1px, transparent 1.4px);
  background-size: 144px 144px;
  transform: translate3d(calc(var(--px) * -20px), calc(var(--py) * -20px), 0);
}

/* CRT scanlines — low opacity, must not fight body copy */
.fx__scan {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    var(--c-scan) 0 1px,
    transparent 1px 3px
  );
  opacity: .35;
  mix-blend-mode: multiply;
}

/* vignette */
.fx__vig {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 40%, transparent 40%, var(--c-vig) 100%);
}

/* =============================================================
   SHELL
   ============================================================= */
.shell {
  position: relative;
  z-index: 1;
  max-width: var(--shell-max);
  margin: 0 auto;
  padding: var(--sp-7) var(--gutter) var(--sp-6);
}

/* =============================================================
   HEADER
   ============================================================= */
.hdr { margin-bottom: var(--sp-8); }

.hdr__mark {
  font-size: var(--fs-mark);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-mark);
  font-weight: 700;
  color: var(--c-ink);
  margin-bottom: var(--sp-3);
  /* no wrap-breaking: monospace at 11vw fits 360px */
  overflow-wrap: break-word;
}

.hdr__role {
  color: var(--c-ink-mute);
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-tight);
  margin-bottom: var(--sp-4);
}
.sep { color: var(--c-edge); }

.hdr__wave {
  display: block;
  width: 100%;
  height: 24px;
  color: var(--c-acid-30);
  margin-bottom: var(--sp-4);
  border-top: var(--hair) solid var(--c-rule);
  border-bottom: var(--hair) solid var(--c-rule);
}

/* ---- readout: small metadata strips -------------------------- */
.readout {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
}
.readout__i { display: flex; gap: var(--sp-2); align-items: baseline; min-width: 0; }
.readout dt { color: var(--c-acid); }
.readout dt::after { content: ":"; color: var(--c-edge); }
.readout dd { color: var(--c-ink-mute); overflow-wrap: anywhere; }

/* =============================================================
   SECTIONS
   ============================================================= */
.sec {
  position: relative;
  margin-bottom: var(--sp-7);
  padding-top: var(--sp-4);
  border-top: var(--hair) solid var(--c-rule);
}

/* local illumination — lights up where the pointer is */
.sec::before {
  content: "";
  position: absolute;
  inset: -4px -12px;
  z-index: -1;
  background: radial-gradient(
    260px 200px at var(--mx) var(--my),
    var(--c-acid-8) 0%,
    transparent 70%
  );
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
  pointer-events: none;
}
.sec.is-lit::before { opacity: 1; }

.sec__h {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: var(--ls-wide);
  line-height: var(--lh-tight);
  margin-bottom: var(--sp-2);
}
.sec__n  { color: var(--c-acid); }
.sec__sl { color: var(--c-edge); font-weight: 400; }
.sec__t  { color: var(--c-ink); }

.sec__note {
  color: var(--c-ink-mute);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
}

/* =============================================================
   ROWS — the manifest listing.
   Every row is a real <a>. Affordance is carried without hover:
   index number, path-shaped name, and a persistent → / ↗ glyph.
   ============================================================= */
.rows {
  display: flex;
  flex-direction: column;
  border-top: var(--hair) solid var(--c-rule);
}

.row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "idx body go"
    ".   tags go";
  align-items: center;
  column-gap: var(--sp-3);
  min-height: var(--row-min);
  padding: var(--sp-3) var(--sp-2);
  border-bottom: var(--hair) solid var(--c-rule);
  text-decoration: none;
  color: inherit;
  background: transparent;
  transition: background-color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}

.row__i {
  grid-area: idx;
  align-self: start;
  padding-top: 2px;
  color: var(--c-ink-mute);   /* real text -> must clear 4.5:1, not --c-edge */
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  font-variant-numeric: tabular-nums;
}

.row__body { grid-area: body; min-width: 0; }

.row__name {
  display: inline-block;
  position: relative;
  color: var(--c-ink);
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: var(--ls-tight);
  overflow-wrap: anywhere;
}
/* underline on hover/focus so the link is not colour-only */
.row:hover .row__name,
.row:focus-visible .row__name { text-decoration: underline; text-underline-offset: 3px; }

.row__desc {
  display: block;
  margin-top: 2px;
  color: var(--c-ink-mute);
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}

.row__tags {
  grid-area: tags;
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.row__tags:empty { display: none; }

.row__go {
  grid-area: go;
  /* This arrow is the resting affordance: it says "this row is a link"
     with no hover required. It must be clearly visible, not a whisper. */
  color: var(--c-ink-mute);
  font-size: var(--fs-md);
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}

.row:hover  { background: var(--c-panel-hi); }
.row:hover .row__go { color: var(--c-acid); transform: translateX(3px); }
.row:focus-visible { background: var(--c-panel); }
.row:focus-visible .row__go { color: var(--c-acid); }

/* =============================================================
   TAGS — colour is an accelerator only. The literal words AUTH
   and EXT carry the meaning; brackets give them a shape; the
   position (after the name) is constant. Safe for greyscale.
   ============================================================= */
.tag {
  display: inline-block;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: var(--ls-wide);
  padding: 1px var(--sp-2);
  border: var(--hair) solid currentColor;
  border-radius: var(--r-sm);
  white-space: nowrap;
}
.tag--auth { color: var(--c-mag); background: var(--c-mag-14); }
.tag--ext  { color: var(--c-ink-mute); }

.legend {
  color: var(--c-ink-mute);
  font-size: var(--fs-xs);
  line-height: 2;
  padding-top: var(--sp-4);
  border-top: var(--hair) solid var(--c-rule);
}

/* =============================================================
   FOOTER
   ============================================================= */
.ftr { margin-top: var(--sp-8); }
.ftr__rule {
  height: 6px;
  border-top: var(--hair) solid var(--c-rule);
  border-bottom: var(--hair) solid var(--c-rule);
  background: repeating-linear-gradient(
    to right, var(--c-rule) 0 8px, transparent 8px 16px
  );
  margin-bottom: var(--sp-4);
}
.readout--ftr { margin-bottom: var(--sp-4); }

.ftr__links {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-2);
}
.lnk {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  position: relative;
  color: var(--c-ink);
  font-size: var(--fs-sm);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--c-edge);
}
.lnk:hover { text-decoration-color: var(--c-acid); }
.lnk:hover .row__go { color: var(--c-acid); }

.ftr__sig {
  color: var(--c-ink-mute);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
}

/* =============================================================
   LED TRAIL — created by main.js on fine-pointer devices only.
   The only element allowed to be large and glowy.
   Positioned exclusively with transform, never left/top.
   ============================================================= */
.trail {
  position: fixed;
  left: 0; top: 0;
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border-radius: 50%;
  z-index: 9999;
  pointer-events: none;
  will-change: transform;
  background: radial-gradient(circle, var(--c-acid-30) 0%, transparent 68%);
  box-shadow: 0 0 18px 2px var(--c-acid-16);
  mix-blend-mode: screen;
}

/* =============================================================
   GLITCH — hover only, ~200ms, one shot, never looping.
   RGB channel split via text-shadow + a brief clip-path jitter.
   Deliberately NOT on :focus-visible: clip-path would crop the
   focus outline, and keyboard users must never lose the ring.
   ============================================================= */
@keyframes glitch {
  0%   { clip-path: inset(0 0 0 0);     transform: translate3d(0,0,0);
         text-shadow: none; }
  25%  { clip-path: inset(38% 0 22% 0); transform: translate3d(-2px,0,0);
         text-shadow: 2px 0 var(--c-mag), -2px 0 var(--c-acid); }
  50%  { clip-path: inset(6% 0 62% 0);  transform: translate3d(2px,0,0);
         text-shadow: -2px 0 var(--c-mag), 2px 0 var(--c-acid); }
  75%  { clip-path: inset(70% 0 8% 0);  transform: translate3d(-1px,0,0);
         text-shadow: 1px 0 var(--c-mag), -1px 0 var(--c-acid); }
  100% { clip-path: inset(0 0 0 0);     transform: translate3d(0,0,0);
         text-shadow: none; }
}

@media (hover: hover) and (pointer: fine) {
  .row:hover .row__name[data-glitch],
  .lnk:hover[data-glitch],
  .sec__h[data-glitch]:hover,
  .hdr__mark[data-glitch]:hover {
    animation: glitch var(--t-glitch) steps(1, end) 1;
  }
}

/* =============================================================
   REDUCED MOTION
   Parallax, trail and glitch are removed. The custom cursor is
   NOT motion and deliberately stays.
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .fx__grid, .fx__dots { transform: none !important; }
  .trail { display: none !important; }
  .sec::before { display: none; }
  .row:hover .row__go { transform: none; }
}

/* =============================================================
   TOUCH / COARSE POINTER
   No cursor, no trail, no parallax — JS attaches nothing. These
   rules make the CSS side match, so the page is identical and
   fully usable with zero JS interaction.
   ============================================================= */
@media not all and (hover: hover) {
  .sec::before { display: none; }
  .fx__grid, .fx__dots { transform: none; }
  .fx__scan { opacity: .28; }
}

/* =============================================================
   NARROW — 360px and below stays intact, no horizontal scroll
   ============================================================= */
@media (max-width: 420px) {
  :root { --shell-max: 100%; }
  .shell { padding-top: var(--sp-6); }
  .hdr { margin-bottom: var(--sp-7); }
  .row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "idx  go"
      "body go"
      "tags go";
    align-items: start;
    row-gap: var(--sp-1);
  }
  .row__i { padding-top: 0; }
  .row__go { align-self: center; }
}

@media (min-width: 900px) {
  .sec__h { font-size: 1.25rem; }
  .row { padding-inline: var(--sp-3); }
}

/* Print: drop every decorative layer. */
@media print {
  .fx, .trail, .skip { display: none !important; }
  body { background: var(--c-print-bg); color: var(--c-print-ink); }
  .row__go { display: none; }

  /* Every colour below is tuned for a near-black background. Left alone on
     white the link names printed at 1.28:1 — i.e. the whole point of the
     page came out invisible. */
  .row__name, .sec__n, .sec__t, .sec__sl, .readout dt, .tag {
    color: var(--c-print-ink) !important;
  }
  .row__desc, .row__i, .sec__note, .legend, .ftr__sig, .hdr__role,
  .readout dd, .sep { color: #444 !important; }
  .tag { background: none !important; }
}
