Showing form on btn click - preventDefault of submit btn, then remove listener
Event delegation can be used to improve efficiency. Instead of adding a click handler to every single element with the class download, an event handler could be added to the entire document or a sub-element that contains all elements with class download.

document.addEventListener('click', e =&gt; {
  let node = e.target;
  do {
    if (node.classList.contains('download') &amp;&amp; !node.classList.contains('is-open')) {
      e.preventDefault();
      const btn = node.querySelector('.btn');

      btn.classList.remove('is-style-outline');
      btn.classList.add('is-style-default');

      node.classList.add('is-open');
      break;
    } 
    node = node.parentNode;
  } while (node &amp;&amp; node.classList !== undefined);
});


In the example above, the click handler inspects the target element to see if it or a parent node has the class download and if such an element doesn't have class is-open before modifying class names for the elements. 

I noticed that I wasn't able to click on the div element with class download without clicking the button, despite the container element having space on the sides of the button, and in the original code the click event is bubbled up from the button to the div. Instead of needing to use the do while loop to go up the DOM chain, the click handler could check to see if the target element has class name btn and in that case if it has an ancestor up three levels that matches the specified class names then modify the class names.

document.addEventListener('click', e =&gt; {
  const node = e.target;
  if (node.classList.contains('btn')) {
    if (node.parentNode &amp;&amp; node.parentNode.parentNode &amp;&amp; node.parentNode.parentNode.parentNode) {
      const ancestorDiv = node.parentNode.parentNode.parentNode;
      if (ancestorDiv.classList &amp;&amp; ancestorDiv.classList.contains('download') &amp;&amp; !ancestorDiv.classList.contains('is-open')) {
        e.preventDefault();

        node.classList.remove('is-style-outline');
        node.classList.add('is-style-default');

        ancestorDiv.classList.add('is-open');
      }
    }
  }
});


Because the code above contains multiple 'if' statements that lead to multiple indentation levels, the logic could be switched to return early instead:

document.addEventListener('click', e =&gt; {
  const node = e.target;
  if (!node.classList.contains('btn')) {
    return;
  }
  if (!(node.parentNode &amp;&amp; node.parentNode.parentNode &amp;&amp; node.parentNode.parentNode.parentNode)) {
    return;
  }
  const ancestorDiv = node.parentNode.parentNode.parentNode;
  if (ancestorDiv.classList &amp;&amp; ancestorDiv.classList.contains('download') &amp;&amp; !ancestorDiv.classList.contains('is-open')) {
    e.preventDefault();

    node.classList.remove('is-style-outline');
    node.classList.add('is-style-default');

    ancestorDiv.classList.add('is-open');
  }
});




I presume the classes is-style-outline and is-style-default are styled by a library (e.g. wordpress) but the styles could be incorporated based on whether the container div (i.e. with class download) contains class is-open, in the same way the inputs are displayed depending on those class names.



Indentation in this code is fairly uniform, though one CSS ruleset (i.e. .download.is-open .inputs) contains rules indented by four spaces instead of two