/* The site's shared chrome: palette, header, page container, cards, search
   and footer.
 *
 * It exists because it did not. Every template carried its own copy of these
 * rules -- thirty-nine selectors repeated across seventeen pages -- so each
 * page drifted on its own: the header links stopped matching, the search box
 * was capped at a width that suited none of the columns, and detail pages
 * ended up in three different widths. Fixing any of them meant editing every
 * file, and the fix reached only the files someone remembered.
 *
 * Page-specific rules still live in the page. Anything that decides what the
 * site looks like belongs here. */

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

:root {
  --bg: #0a0e17; --bg-card: #111827; --bg-card-hover: #1a2332; --border: #1e293b;
  --accent-dim: #0c4a6e;
  --text: #e2e8f0; --text-dim: #94a3b8; --accent: #38bdf8;
  --green: #34d399; --amber: #fbbf24; --red: #f87171; --purple: #a78bfa;
  --font-body: "Space Grotesk", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", monospace;
  /* One column width for the whole site -- the width the map page proved --
     and the one knob for it: the header and footer align their padding to
     the same value so all three edges line up. */
  --measure: 92rem;
}

body { font-family: var(--font-body); background: var(--bg); color: var(--text);
       line-height: 1.6; }

/* Header ------------------------------------------------------------------ */

nav { position: fixed; top: 0; width: 100%; z-index: 100;
      background: rgba(10,14,23,0.85); backdrop-filter: blur(12px);
      border-bottom: 1px solid var(--border); padding: 1rem 2rem;
      display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
      /* The links sit on the page centre rather than the centre of what is
         left beside the logo. When they outgrow the space both fr columns
         collapse to zero and the first link lands against the wordmark --
         "dfirskills.comSkills". This gap is the one the grid cannot take. */
      column-gap: 1.75rem; row-gap: 0.4rem; }
.logo { font-family: var(--font-mono); font-weight: 600; font-size: 1.1rem;
        color: var(--accent); letter-spacing: -0.5px; }
.logo a { color: inherit; text-decoration: none; }
.logo span { color: var(--text-dim); }
.nav-links { display: flex; gap: 2rem; justify-content: center;
             flex-wrap: wrap; row-gap: 0.35rem; }
.nav-links a { color: var(--text-dim); text-decoration: none;
               font-size: 0.9rem; font-weight: 500; }
.nav-links a:hover, .nav-links a.active { color: var(--accent); }

@media (max-width: 1000px) {
  nav { grid-template-columns: 1fr; justify-items: center; }
  .nav-links { justify-content: center; gap: 1rem; }
}
@media (max-width: 640px) {
  nav { padding-top: 0.7rem; padding-bottom: 0.7rem; }
  .nav-links { gap: 0.75rem; font-size: 0.82rem; }
  .nav-links a { font-size: inherit; }
}

/* Page --------------------------------------------------------------------- */

main { max-width: var(--measure); margin: 0 auto; padding: 7rem 1.5rem 4rem; }
h1 { font-size: 2rem; margin-bottom: 0.5rem; letter-spacing: -0.5px; }
h2 { font-size: 1.15rem; font-weight: 600; margin-bottom: 0.4rem; }
h2 a { color: var(--text); text-decoration: none; }
h2 a:hover { color: var(--accent); }
/* The lede runs the width of the page it introduces. Capped at 42rem it
   wrapped into three short lines under a heading four times as wide, which
   read as a column that had been left behind rather than a deliberate one. */
.lede { color: var(--text-dim); margin-bottom: 2.5rem; }
.lede a { color: var(--accent); }

/* Cards -------------------------------------------------------------------- */

ul { list-style: none; display: grid; gap: 1rem;
     /* min() so a 28rem track never overflows a 375px phone. */
     grid-template-columns: repeat(auto-fill, minmax(min(28rem, 100%), 1fr)); }
li { background: var(--bg-card); border: 1px solid var(--border);
     border-radius: 12px; padding: 1.5rem;
     transition: background 0.2s, border-color 0.2s;
     /* Whole card is the click target, not just the heading. */
     position: relative; cursor: pointer; }
li:hover { background: var(--bg-card-hover); border-color: var(--accent-dim); }
li h2 a::after { content: ""; position: absolute; inset: 0; border-radius: 12px; }
li:hover h2 a { color: var(--accent); }

.meta { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;
        font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.5px; }
.when { color: var(--text-dim); }
.summary { color: var(--text-dim); font-size: 0.92rem; margin-bottom: 0.9rem; }
.examples { font-family: var(--font-mono); font-size: 0.72rem;
            color: var(--text-dim); margin-bottom: 0.9rem;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tags { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tag { font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-dim);
       background: rgba(255,255,255,0.05); padding: 0.2rem 0.55rem; border-radius: 4px; }

.sev { padding: 0.2rem 0.6rem; border-radius: 4px; font-weight: 600; }
.sev-critical { background: rgba(248,113,113,0.15); color: var(--red); }
.sev-high     { background: rgba(251,191,36,0.15); color: var(--amber); }
.sev-medium   { background: rgba(56,189,248,0.15); color: var(--accent); }
.sev-low      { background: rgba(148,163,184,0.15); color: var(--text-dim); }

.empty { color: var(--text-dim); background: var(--bg-card);
         border: 1px dashed var(--border); border-radius: 12px;
         padding: 3rem 2rem; text-align: center; }

/* Rendered markdown ------------------------------------------------------- */

/* Everything the model writes lands inside .prose. The wrapper does two jobs:
   it keeps a readable line length inside the wide column -- the same thing the
   map page does with its intro -- and it takes the card styling back off the
   list elements, since a bullet list in an article is not a grid of cards. */
.prose { max-width: 52rem; }

/* A detail page is an article and its cross-links. Side by side, the
   cross-links fill the width the article does not want: a 92rem line of body
   text is unreadable, and a 52rem article alone leaves half the page empty. */
.article { display: grid; grid-template-columns: minmax(0, 52rem) minmax(0, 24rem);
           gap: 3rem; align-items: start; }
.article .prose { max-width: none; }
/* The heading block lines up with the article column, not the page. */
main > h1, main > .meta, main > .source, main > .factbox { max-width: 52rem; }

/* What a detail page states about its subject before the article starts.
   Prose, not the monospace strip a card uses: laid out as a card .meta it
   became three cramped columns of wrapped text under the title. */
.factbox { color: var(--text-dim); font-size: 0.9rem; margin-bottom: 2rem;
           border-bottom: 1px solid var(--border); padding-bottom: 1.25rem; }
.factbox p { margin-bottom: 0.35rem; }
.factbox a { color: var(--accent); }
.factbox code { font-family: var(--font-mono); font-size: 0.78rem;
                background: rgba(255,255,255,0.05); border-radius: 4px;
                padding: 0.1rem 0.4rem; }
@media (max-width: 1000px) {
  .article { grid-template-columns: 1fr; gap: 2rem; }
  .article .prose { max-width: 52rem; }
}
.prose ul, .prose ol { display: block; padding-left: 1.4rem; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { background: none; border: 0; border-radius: 0; padding: 0;
            margin-bottom: 0.55rem; cursor: auto; position: static; }
.prose li:hover { background: none; }
.prose p { margin-bottom: 0.9rem; }
.prose h2, .prose h3 { margin: 2.2rem 0 0.6rem; }
.prose a { color: var(--accent); }
.prose pre { background: var(--bg-card); border: 1px solid var(--border);
             border-radius: 8px; padding: 1rem; overflow-x: auto;
             margin-bottom: 1rem; }
.prose code { font-family: var(--font-mono); font-size: 0.9em; }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; }
.prose th, .prose td { border: 1px solid var(--border); padding: 0.5rem 0.7rem;
                       text-align: left; }

/* Cross-link panels ------------------------------------------------------- */

/* Both detail pages carried an identical copy of these rules. In the sidebar
   the first panel needs no rule above it -- the grid gap already separates it
   from the article. */
.related { margin-top: 2rem; }
.related + .related { margin-top: 2rem; border-top: 1px solid var(--border);
                      padding-top: 1.6rem; }
.article .related:first-child { margin-top: 0; }
.related h3 { font-size: 0.95rem; margin-bottom: 0.8rem; }
.related ul { list-style: none; padding: 0; display: grid; gap: 0.6rem;
              grid-template-columns: 1fr; }
.related li { background: none; border: 0; border-radius: 0; padding: 0;
              cursor: auto; position: static; }
.related li:hover { background: none; }
.related a { font-family: var(--font-mono); font-size: 0.88rem;
             text-decoration: none; color: var(--accent); }
.related a:hover { text-decoration: underline; }
.related .desc { color: var(--text-dim); font-size: 0.82rem; }
.related .rel-meta { font-family: var(--font-mono); font-size: 0.72rem;
                     color: var(--text-dim); margin-left: 0.4rem; }

/* Search ------------------------------------------------------------------- */

/* A plain GET form, so it works with scripting off; the grids upgrade it to
   live filtering. Full width, matching the column of results under it. */
.search { margin: 0 0 2rem; }
/* Both shapes, because the markup drifted: most pages wrap the form in a
   div.search, /papers put the class on the form itself, and for months that
   page alone had a search box the width of its default character count. */
.search form, form.search { display: flex; gap: 0.6rem; }
.search input[type=search] {
  flex: 1; padding: 0.7rem 1rem; border-radius: 8px;
  background: var(--bg-card); color: var(--text);
  border: 1px solid var(--border); font-family: var(--font-body); font-size: 0.95rem;
}
.search input[type=search]:focus { outline: none; border-color: var(--accent); }
.search button {
  padding: 0.7rem 1.1rem; border-radius: 8px; cursor: pointer;
  background: var(--accent-dim); color: var(--text);
  border: 1px solid var(--accent-dim); font-family: var(--font-body); font-size: 0.9rem;
}
.search button:hover { border-color: var(--accent); }
.search .clear { color: var(--text-dim); font-size: 0.8rem; margin-left: 0.5rem;
                 align-self: center; }

/* Footer ------------------------------------------------------------------- */

/* The fixed bars span the viewport while main is a centred column, so without
   this the wordmark sat at the far left and the tally at the far right, and
   neither lined up with the content between them. */
nav, footer.site {
  padding-left: max(2rem, calc(50% - var(--measure) / 2));
  padding-right: max(2rem, calc(50% - var(--measure) / 2));
}
/* Fixed, because the grids scroll infinitely: a footer in document flow is
   unreachable once new cards keep arriving at the bottom. Its height is
   reserved with padding on body so the last card is never hidden behind it. */
body { padding-bottom: 3.5rem; }
footer.site {
  position: fixed; bottom: 0; left: 0; width: 100%; z-index: 100;
  background: rgba(10, 14, 23, 0.9); backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
  padding: 0.85rem 2rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  font-size: 0.78rem; color: var(--text-dim);
}
footer.site a { color: var(--text-dim); text-decoration: none; }
footer.site a:hover { color: var(--accent); }
/* The tally lives here rather than in the header: the header already carries
   the nav, and stacking both crowded it enough that the counts were hidden
   below 900px to make room. In the footer they fit at every width. */
footer.site .stats { display: flex; gap: 1.25rem; flex-wrap: wrap;
                     font-family: var(--font-mono); letter-spacing: 0.3px; }
footer.site .stats b { color: var(--accent); font-weight: 600; font-size: 1.08em; }
footer.site .stats a { color: inherit; }
footer.site .stats a:hover b { color: var(--text); }

@media (max-width: 640px) {
  nav, footer.site { padding-left: 1rem; padding-right: 1rem; }
  footer.site { padding-top: 0.7rem; padding-bottom: 0.7rem; font-size: 0.72rem; }
  footer.site .stats { gap: 0.85rem; }
  body { padding-bottom: 4.5rem; }
}
