/* Align the first left-column section header with the sidebar's first heading.
   The global rule `section { margin: 2.4rem 0 }` would otherwise push the
   first section ~2.4rem below the sticky aside, which has no top spacing. */
.grid-2 > .reveal > section:first-of-type { margin-top: 0; }

/* Upstream-source link in the sidebar metadata. The arrow nudges on hover
   to confirm external navigation. */
.upstream-link {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25em;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  word-break: break-all;
  transition: color 120ms ease, border-color 120ms ease;
}
.upstream-link:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
  text-decoration: none;
}
.upstream-link .ext-arrow {
  font-family: var(--font-sans);
  font-size: 0.85em;
  color: var(--ink-faint);
  transition: color 120ms ease, transform 200ms cubic-bezier(.2,.7,.2,1);
}
.upstream-link:hover .ext-arrow {
  color: var(--accent);
  transform: translate(1px, -1px);
}

/* Right-column metadata panel.
   Vertical label/value rows so multi-value badges can wrap freely on a
   narrow column — the horizontal `.kv` pattern cramps them. The faint
   uppercase eyebrow on each row reads as a spec-sheet attribute label,
   subordinate to the panel's heading ("Metadata"). */
.meta-list {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.meta-list > div { display: flex; flex-direction: column; gap: 0.4rem; }

/* Single-value facts sit on one line with their label — twelve of them
   stacked cost 827px of a 280px column, most of it air. The label column is
   `max-content`, so it is as wide as the longest label and no wider, and the
   rows share one alignment down the whole block.
   `display: contents` puts each dt/dd straight into that grid; the wrapper
   divs stay in the markup because a `dl` needs them for the pairing. */
.meta-list.pairs {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 0.85rem;
  row-gap: 0.5rem;
  align-items: baseline;
}
.meta-list.pairs > div { display: contents; }
/* Anything that can hold more than one value keeps its own line: a badge
   list wrapping inside a 160px cell is taller than it was stacked. */
.meta-list.pairs > div.stacked {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  grid-column: 1 / -1;
  margin: 0.2rem 0;
}
.meta-list dt {
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.meta-list dd { margin: 0; color: var(--ink); font-size: 0.88rem; line-height: 1.45; }
.meta-list dd .badges { gap: 0.3rem; }
.meta-list dd code.inline { font-size: 0.8rem; word-break: break-all; }
/* A badge is `white-space: nowrap`, and this column is 280px — or 160px once
   a value shares its line with a label. Unwrapped, a long source name, license
   or Wazuh tag runs out of the aside and takes the page sideways with it.
   `anywhere` rather than `break-word` because it also shrinks the min-content
   width: `reversinglabs/reversinglabs-yara-rules` carries no break Chrome
   will take on its own. */
.margin-stack .badge {
  white-space: normal;
  overflow-wrap: anywhere;
}
/* The ATT&CK ids sit straight under their heading with no label of their own,
   so they carry the aside's badge spacing themselves. */
.attack-ids { gap: 0.3rem; }
.attack-ids + .meta-list { margin-top: 0.9rem; }

/* A value list longer than three clamps to three, with the rest behind a
   count. Done in script rather than markup on purpose: the template renders
   every value, so with JavaScript off the list is simply complete rather
   than silently short. */
.clamp > [hidden] { display: none; }

/* Reference urls run to 120 characters. One per line, each clipped — the full
   value is in the title, and following the link is what a reference is for. */
.ref-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  min-width: 0;
  max-width: 100%;
}
.ref-list a,
.ref-list span {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8rem;
}
.clamp-more {
  all: unset;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 0.74rem;
  line-height: 1.3;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--rule);
  transition: color 120ms ease, border-color 120ms ease;
}
/* Same `all: unset` caveat as `.id-copy` below — without a background here,
   `button:hover` fills this indigo. */
.clamp-more:hover {
  color: var(--accent);
  background: none;
  border-bottom-color: var(--accent);
}
.clamp-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Source ids are a 36-character UUID as often as they are `3303`, and wrapped
   they were the second-tallest row in the block. Clipped to one line like the
   path below them — but a clipped id you cannot get back out is worse than a
   wrapped one, so the whole thing is a copy control: click copies the full
   value, the title carries it, and `user-select` keeps hand-selection working
   (buttons suppress it by default) for anyone with JavaScript off. */
.id-copy {
  all: unset;
  display: flex;
  align-items: baseline;
  gap: 0.4em;
  max-width: 100%;
  min-width: 0;
  cursor: pointer;
  user-select: text;
}
.id-copy code {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  word-break: normal;
  transition: color 120ms ease;
}
/* `all: unset` clears the site's base button styling but not its
   `button:hover`, which fills the control indigo and turns the text white —
   visible here as a block behind the "copy" hint. Both hover states below
   name their own background for that reason. */
.id-copy:hover { background: none; color: var(--ink); }
.id-copy:hover code { color: var(--accent); }
.id-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.id-copy::after {
  content: "copy";
  flex: none;
  font-family: var(--font-sans);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  opacity: 0;
  transition: opacity 120ms ease;
}
.id-copy:hover::after,
.id-copy:focus-visible::after { opacity: 1; }
.id-copy[data-copied]::after { content: "copied"; opacity: 1; color: var(--accent); }

.meta-list.pairs .upstream-link { max-width: 100%; }
.meta-list.pairs .upstream-link .path {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.meta-list.pairs .upstream-link .ext-arrow { flex: none; }

/* Severity and risk are facts about one rule on a page about that rule —
   nobody is scanning them. The filled chip and the red number were sized for a
   results row, where they compete for attention against 24 other rules; here
   they are ordinary badges like every other value in the column. Severity keeps
   its color as a dot, which the badge's own flex gap spaces. */
.meta-list .sev::before {
  content: "";
  width: 0.45em;
  height: 0.45em;
  flex: none;
  border-radius: 50%;
  background: var(--sev-info);
}
.meta-list .sev-critical::before { background: var(--sev-critical); }
.meta-list .sev-high::before     { background: var(--sev-high); }
.meta-list .sev-medium::before   { background: var(--sev-medium); }
.meta-list .sev-low::before      { background: var(--sev-low); }

/* ── Wazuh runtime-substitution token. `$(win.eventdata.image)` is filled in
   from the event when the alert fires; unstyled it reads as a parse failure. */
.rt-token {
  font-family: var(--font-mono);
  font-size: 0.86em;
  padding: 0.05em 0.35em;
  border-radius: 3px;
  color: var(--ink-soft);
  background: var(--bg-elev);
  border: 1px dashed var(--rule);
  white-space: nowrap;
}

/* ── Evaluation chain. A vertical rail with a node per rule, current rule
   accented, so the top-down "all of these must match" reading is visual. */
.chain { list-style: none; margin: 0 0 1.4rem; padding: 0; }
.chain-step {
  position: relative;
  padding: 0 0 0.9rem 1.35rem;
  border-left: 1px solid var(--rule);
}
.chain-step:last-child { border-left-color: transparent; padding-bottom: 0; }
.chain-step::before {
  content: "";
  position: absolute;
  left: -4.5px;
  top: 0.42em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--rule);
}
.chain-step.is-current::before { border-color: var(--accent); background: var(--accent); }
.chain-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.chain-sid {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.chain-name { font-size: 0.92rem; }
.chain-step.is-current .chain-name { font-weight: 500; color: var(--ink-strong); }
.chain-level { font-size: 0.76rem; }
.chain-here {
  font-family: var(--font-sans);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}
.chain-cond { margin-top: 0.3em; font-size: 0.82rem; }
.chain-cond code { word-break: break-all; }
.chain-dependents { padding-top: 0.2rem; }

/* ── Query header row: heading on the left, raw-source trigger on the right.
   Same horizontal axis so the trigger reads as part of the section header,
   not a free-floating control. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 0.85rem;
}
.section-head h2 { margin: 0; }
/* Copy sits beside "View raw source" rather than above the block: both act on
   the same rule, and a control that floats over the code hides a line of it. */
.section-actions { display: inline-flex; align-items: center; gap: 0.5rem; flex: none; }

/* Raw-source trigger button. Ghost outline, mono "esc" hint slot kept empty
   here (only used inside the dialog) — this just opens the takeover. */
.raw-open {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.38em 0.75em;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--bg-elev);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 100ms ease, color 100ms ease, background 100ms ease, transform 80ms ease;
}
.raw-open:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.raw-open:active { transform: scale(0.98); }
.raw-open svg { width: 12px; height: 12px; stroke: currentColor; stroke-width: 1.7; fill: none; }
.raw-open .fmt {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--ink-faint);
  padding-left: 0.5em;
  margin-left: 0.1em;
  border-left: 1px solid var(--rule);
  transition: color 100ms ease, border-color 100ms ease;
}
.raw-open:hover .fmt { color: var(--accent); border-left-color: var(--accent-ring); }

/* Confirmation holds the accent for the 1.4s the label reads "Copied", so the
   button itself answers rather than only the word inside it. */
.raw-open[data-copied],
.raw-modal-close[data-copied] {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}
.copy-label { white-space: nowrap; }

/* Standalone source row for rules without a Query body — same trigger, just
   placed in its own minimal row so YARA/Wazuh/etc still expose `raw`. */
.source-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.source-row .label {
  font-family: var(--font-sans);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ── Raw-source dialog. Native <dialog> for Esc-to-close + a11y for free.
   Visually echoes the coverage fullscreen takeover: indigo-tinted radial
   backdrop, corner brackets, blur-in entry, but constrained to a centered
   panel rather than full-bleed so the rest of the page peeks through. */
dialog.raw-modal {
  width: min(960px, 92vw);
  height: min(82vh, 880px);
  max-width: none;
  max-height: none;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--bg-elev);
  color: var(--ink);
  box-shadow: 0 30px 80px -20px rgba(12, 14, 18, 0.32), 0 8px 24px -10px rgba(12, 14, 18, 0.18);
  overflow: hidden;
}
dialog.raw-modal::backdrop {
  background:
    radial-gradient(60% 50% at 50% 30%, rgba(67, 56, 202, 0.18), transparent 70%),
    rgba(12, 14, 18, 0.42);
  backdrop-filter: blur(2px);
}
dialog.raw-modal[open] { animation: raw-enter 220ms cubic-bezier(.2,.7,.2,1); }
dialog.raw-modal[open]::backdrop { animation: raw-fade 220ms ease forwards; }
@keyframes raw-enter {
  from { opacity: 0; transform: translateY(8px) scale(0.985); filter: blur(2px); }
  to   { opacity: 1; transform: translateY(0)    scale(1);     filter: blur(0); }
}
@keyframes raw-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.raw-modal-inner {
  display: grid;
  grid-template-rows: auto auto 1fr;
  height: 100%;
  position: relative;
}
/* Attribution sits between the header and the rule text, not inside it. The
   licenses here ask that the notice travel with any copy of the rule; putting
   it in the chrome discharges that without editing the rule itself, which for
   several formats would mean injecting a comment into someone's syntax. */
.raw-modal-attrib {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.5rem;
  padding: 0.5rem 1.1rem;
  border-bottom: 1px solid var(--rule-soft);
  background: var(--bg-sunken);
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--ink-soft);
}
.raw-modal-attrib a { color: var(--accent); font-weight: 500; }
.raw-modal-attrib a:hover { text-decoration: underline; text-underline-offset: 2px; }
.raw-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
}
.raw-modal-title {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
  min-width: 0;
}
.raw-modal-title .eyebrow {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.raw-modal-title .name {
  font-family: var(--font-sans);
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink-strong);
  letter-spacing: -0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.raw-modal-title .fmt {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ink-faint);
}

.raw-modal-actions { display: inline-flex; gap: 0.5rem; align-items: center; }
.raw-modal-actions .kbd {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  padding: 0.08em 0.42em;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--bg-elev);
  line-height: 1.3;
}
.raw-modal-close {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34em 0.7em;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 100ms ease, border-color 100ms ease, background 100ms ease;
}
.raw-modal-close:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.raw-modal-close svg { width: 11px; height: 11px; stroke: currentColor; stroke-width: 1.8; fill: none; }

.raw-modal-body {
  overflow: auto;
  padding: 0;
  background: var(--bg);
}
.raw-modal-body pre {
  margin: 0;
  padding: 1rem 1.25rem 1.5rem;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--ink);
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 100%;
  box-sizing: border-box;
}

/* Corner brackets — match the coverage takeover's command-center accent. */
.raw-corner {
  position: absolute;
  width: 12px;
  height: 12px;
  border: 1.5px solid var(--accent);
  opacity: 0.5;
  pointer-events: none;
}
.raw-corner.tl { top: 6px;    left: 6px;    border-right: 0;  border-bottom: 0; }
.raw-corner.tr { top: 6px;    right: 6px;   border-left: 0;   border-bottom: 0; }
.raw-corner.bl { bottom: 6px; left: 6px;    border-right: 0;  border-top: 0; }
.raw-corner.br { bottom: 6px; right: 6px;   border-left: 0;   border-top: 0; }

body.raw-modal-open { overflow: hidden; }

/* Detection tier ladder — all four rungs, this rule's highlighted.
   Inactive rungs are muted and unclickable, matching the site's badge rule
   that only bordered/accent elements navigate.

   Scoped under .margin-stack to outrank `.margin-stack ul` (0,1,1), which
   lays the sidebar's badge rows out as a wrapping flex line — inherited here
   it shrink-wraps each rung to its text and the highlight stops mid-row. */
.margin-stack .tier-ladder {
  display: grid;
  gap: 0.15rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.margin-stack .tier-rung {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0.3rem 0.5rem;
  border-left: 2px solid transparent;
  border-radius: 3px;
  font-size: 0.86rem;
  line-height: 1.35;

  /* Rungs this rule is not on. Recede via `--ink-faint` rather than an opacity
     wash: the token is defined per theme and stays above the contrast floor in
     both, where fading toward the page background does not. The gap is widened
     from the other end too — the active rung goes to `--ink-strong` — so the
     unmatched rungs read as clearly secondary without becoming unreadable. */
  color: var(--ink-faint);
  font-weight: 400;
}

.margin-stack .tier-rung > span:first-child,
.margin-stack .tier-rung > a { white-space: nowrap; }

.margin-stack .tier-rung.is-active {
  border-left-color: var(--accent);
  background: var(--accent-soft);
  color: var(--ink-strong);
}

.margin-stack .tier-rung.is-active > span:first-child,
.margin-stack .tier-rung.is-active > a { font-weight: 600; }

.margin-stack .tier-rung.is-active > a { color: var(--accent); text-decoration: none; }
.margin-stack .tier-rung.is-active > a:hover { text-decoration: underline; }


/* Not a detection — a statement, not a rung. Deliberately unlike the ladder:
   the reader should not scan for a highlighted row that is not there. */
.margin-stack .tier-none { margin: 0; font-size: 0.9rem; color: var(--ink-strong); }
.margin-stack .tier-none-why {
  margin: 0.3rem 0 0;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

