ids theme: reliably render "Authors (Year):" as bold first line in bibliography

The old CSS hack inserted a line break before the FIRST ELEMENT CHILD of
each .csl-entry, plus a ::first-line tint. Which part of an entry
citeproc wraps in spans anchors depends on the entry type, so the break
landed arbitrarily -- e.g. mid-title in the DeLiKo entry or before the
final URL. Replace it with an explicit wrap: the theme template walks
the leading text nodes of each entry to the first "):" and marks them
as .csl-authors-year (display: block; bold; mid blue-gray), which is
both the bold first line and the line break. Entries without a year
marker are left untouched; spacing between entries is restored with a
0.5em margin (pandoc's div.csl-entry pins it to 0em otherwise). The
demo bibliography gains the DeLiKo citation as a regression case.

Change-Id: I196368e631a8870d63fe2022fb5cda3a0ad30072
diff --git a/inst/reveal.js-5.1.0/css/theme/source/ids.scss b/inst/reveal.js-5.1.0/css/theme/source/ids.scss
index 20e9416..2f65834 100644
--- a/inst/reveal.js-5.1.0/css/theme/source/ids.scss
+++ b/inst/reveal.js-5.1.0/css/theme/source/ids.scss
@@ -612,18 +612,21 @@
   text-indent: -22px ;
 }
 
-.csl-entry::first-line {
-  color: #253b43;
-}
-
-.csl-entry {
+// .references scopes these above pandoc's CSL defaults (div.csl-entry), which
+// otherwise win on specificity and pin margin-bottom to 0em.
+.references .csl-entry {
   color: #888888;
+  margin-bottom: 0.5em;
 }
 
-/* Add line break after authors and year*/
-.csl-entry :first-child::before {
-  content: "\a";
-  white-space: pre;
+// "Authors (Year):" as a bold dark first line; the theme template's JS wraps
+// the leading text of each entry in .csl-authors-year (see default.html) --
+// which part of an entry citeproc wraps in spans depends on the entry type, so
+// a CSS-only break cannot place it reliably.
+.csl-entry .csl-authors-year {
+  display: block;
+  font-weight: bold;
+  color: #4d616b;
 }
 
 .reveal code.sourceCode:last-child + pre {
diff --git a/inst/reveal.js-5.1.0/dist/theme/ids.css b/inst/reveal.js-5.1.0/dist/theme/ids.css
index b8c44f3..da527dd 100644
--- a/inst/reveal.js-5.1.0/dist/theme/ids.css
+++ b/inst/reveal.js-5.1.0/dist/theme/ids.css
@@ -808,18 +808,21 @@
   text-indent: -22px;
 }
 
-.csl-entry::first-line {
-  color: #253b43;
-}
-
-.csl-entry {
+/* .references scopes this above pandoc's CSL defaults (div.csl-entry), which
+   otherwise win on specificity and pin margin-bottom to 0em. */
+.references .csl-entry {
   color: #888888;
+  margin-bottom: 0.5em;
 }
 
-/* Add line break after authors and year*/
-.csl-entry :first-child::before {
-  content: "\a";
-  white-space: pre;
+/* "Authors (Year):" as a bold dark first line; the theme template's JS wraps
+   the leading text of each entry in .csl-authors-year (see default.html) --
+   which part of an entry citeproc wraps in spans depends on the entry type, so
+   a CSS-only break cannot place it reliably. */
+.csl-entry .csl-authors-year {
+  display: block;
+  font-weight: bold;
+  color: #4d616b;
 }
 
 .reveal code.sourceCode:last-child+pre {
diff --git a/inst/rmarkdown/templates/revealjs_presentation/resources/default.html b/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
index 2d8b497..1854ae0 100644
--- a/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
+++ b/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
@@ -740,6 +740,45 @@
 $endif$
 
 $if(theme-ids)$
+<script>
+  // IDS theme: in the bibliography, "Authors (Year):" should form a bold first
+  // line, followed by a line break. Which part of an entry citeproc wraps in
+  // spans/links depends on the entry type, so a CSS "break before first child
+  // element" hack cannot place the break reliably. Wrap the leading text up to
+  // and including the first "):" explicitly instead; entries without a year
+  // marker are left untouched.
+  (function () {
+    document.querySelectorAll('.csl-entry').forEach(function (entry) {
+      var textNodes = [];
+      var accumulated = '';
+      var children = Array.prototype.slice.call(entry.childNodes);
+      for (var i = 0; i < children.length; i++) {
+        var node = children[i];
+        if (node.nodeType !== Node.TEXT_NODE) break; // year marker only valid in leading text
+        textNodes.push(node);
+        accumulated += node.textContent;
+        var idx = accumulated.indexOf('):');
+        if (idx < 0) continue;
+        var remainder = accumulated.length - (idx + 2);
+        var span = document.createElement('span');
+        span.className = 'csl-authors-year';
+        textNodes.slice(0, -1).forEach(function (n) { span.appendChild(n); });
+        var last = textNodes[textNodes.length - 1];
+        if (remainder > 0) {
+          span.appendChild(document.createTextNode(last.textContent.slice(0, -remainder)));
+          last.textContent = last.textContent.slice(-remainder);
+        } else {
+          span.appendChild(last);
+        }
+        entry.insertBefore(span, entry.firstChild);
+        break;
+      }
+    });
+  })();
+</script>
+$endif$
+
+$if(theme-ids)$
     <footer id="ids-footer"><span>
       $for(author)$$if(author.name)$$author.name$$else$$author$$endif$${ sep }, $endfor$ · $title$ · $date$</span></footer>
 $endif$