Kaynağa Gözat

Merge branch 'testing-module-blocks' into 'master'

Integrate module-based RuleBuilder tool

See merge request medlabboulder/communityrule!1
Nathan Schneider 4 yıl önce
ebeveyn
işleme
7690306f5a
12 değiştirilmiş dosya ile 628 ekleme ve 248 silme
  1. 1 1
      README.md
  2. 1 1
      _about/faq.md
  3. 65 0
      _data/modules.csv
  4. 6 6
      _guides/first_rule.md
  5. 2 2
      _guides/mutual_aid.md
  6. 2 1
      _includes/footer.html
  7. 40 21
      _layouts/library.html
  8. 396 156
      _layouts/rule.html
  9. 110 53
      _sass/communityrule.scss
  10. 1 1
      create.md
  11. 3 3
      index.md
  12. 1 3
      library.md

+ 1 - 1
README.md

@@ -12,4 +12,4 @@ To contribute governance templates, copy create.md at _create/[template_name].md
 
 Propose edits to existing governance templates at _create/[template_name].md.
 
-Most of CommunityRule's interactive features occur at _layouts/rule.html.
+Most of CommunityRule's interactive features occur at _layouts/rule.html. The Module data is located at _data/modules.csv.

+ 1 - 1
_about/faq.md

@@ -41,6 +41,6 @@ A bunch of stuff, and we have a running list in the [Issues on GitLab](https://g
 **What projects does this draw upon?**
 
 * Created with [Jekyll](https://jekyllrb.com/) (MIT License), hosted on [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/)
-* Modules are from [Democratic Mediums](http://democraticmediums.info) (CC-BY)
+* Modules are drawn largely from [Democratic Mediums](http://democraticmediums.info) (CC-BY)
 * Icons are from [Tabler](https://github.com/tabler/tabler-icons) (MIT License)
 * Database runs on [Stein](https://steinhq.com/) (MIT License), using [this Google Doc](https://docs.google.com/spreadsheets/d/12IgsMWZNzPv2nS7ksU6CUozcS6YYwRn9O1iIXKat3V4/edit?usp=sharing)

+ 65 - 0
_data/modules.csv

@@ -0,0 +1,65 @@
+name,id,description,url,source,type
+Board,board,,https://democraticmediums.info/mediums/board/,Democratic Mediums,structure
+Bureaucracy,bureaucracy,,https://democraticmediums.info/mediums/bureaucracy/,Democratic Mediums,structure
+Executive,executive,,,,structure
+Federation,federation,,https://democraticmediums.info/mediums/federation/,Democratic Mediums,structure
+Judiciary,judiciary,,https://democraticmediums.info/mediums/judiciary/,Democratic Mediums,structure
+Legislative,legislative,,,,structure
+Multicameralism,multicameralism,,https://democraticmediums.info/mediums/multicameralism/,Democratic Mediums,structure
+Platform,platform,,https://democraticmediums.info/mediums/platform/,Democratic Mediums,structure
+Separation of powers,separation_of_powers,,https://democraticmediums.info/mediums/separation_of_powers/,Democratic Mediums,structure
+Audit,audit,,https://democraticmediums.info/mediums/audit/,Democratic Mediums,process
+Canvassing,canvassing,,https://democraticmediums.info/mediums/canvassing/,Democratic Mediums,process
+Caucus,caucus,,https://democraticmediums.info/mediums/caucus/,Democratic Mediums,process
+Coalition,coalition,,https://democraticmediums.info/mediums/coalition/,Democratic Mediums,process
+Consensus process,consensus,,https://democraticmediums.info/mediums/consensus/,Democratic Mediums,process
+Constitution,constitution,,https://democraticmediums.info/mediums/constitution/,Democratic Mediums,process
+Debate,debate,,https://democraticmediums.info/mediums/debate/,Democratic Mediums,process
+Delegation,delegation,,https://democraticmediums.info/mediums/delegation/,Democratic Mediums,process
+Do-ocracy,do-ocracy,,https://democraticmediums.info/mediums/do-ocracy/,Democratic Mediums,process
+Eloquence,eloquence,,https://democraticmediums.info/mediums/eloquence/,Democratic Mediums,process
+Exclusion,exclusion,,https://democraticmediums.info/mediums/exclusion/,Democratic Mediums,process
+Fact Finding,fact_finding,,https://democraticmediums.info/mediums/fact_finding/,Democratic Mediums,process
+Lobbying,lobbying,,https://democraticmediums.info/mediums/lobbying/,Democratic Mediums,process
+Membership,membership,,https://democraticmediums.info/mediums/membership/,Democratic Mediums,process
+Ownership,ownership,,https://democraticmediums.info/mediums/ownership/,Democratic Mediums,process
+Petition,petition,,https://democraticmediums.info/mediums/petition/,Democratic Mediums,process
+Polling,polling,,https://democraticmediums.info/mediums/polling/,Democratic Mediums,process
+Precedent,precedent,,https://democraticmediums.info/mediums/precedent/,Democratic Mediums,process
+Proof of work,proof_of_work,,https://democraticmediums.info/mediums/proof_of_work/,Democratic Mediums,process
+Proportional representation,proportional_representation,,https://democraticmediums.info/mediums/proportional_representation/,Democratic Mediums,process
+Refusal,refusal,,https://democraticmediums.info/mediums/refusal/,Democratic Mediums,process
+Representation,representation,,https://democraticmediums.info/mediums/representation/,Democratic Mediums,process
+Reputation,reputation,,https://democraticmediums.info/mediums/reputation/,Democratic Mediums,process
+Restorative justice,restorative_justice,,https://democraticmediums.info/mediums/restorative_justice/,Democratic Mediums,process
+Sortition,sortition,,https://democraticmediums.info/mediums/sortition/,Democratic Mediums,process
+Stake weight,stake_weight,,https://democraticmediums.info/mediums/stake_weight/,Democratic Mediums,process
+Term limits,term_limit,,https://democraticmediums.info/mediums/term_limit/,Democratic Mediums,process
+Approval voting,approval_voting,,https://democraticmediums.info/mediums/approval_voting/,Democratic Mediums,decision
+Autocratic,autocratic,,https://thedecider.app/autocratic-decision-making,The Decider,decision
+Avoidant,avoidant,,https://thedecider.app/avoidant-decision-making,The Decider,decision
+Condorcet,condorcet,,https://democraticmediums.info/mediums/condorcet/,Democratic Mediums,decision
+Consensus,consensus,,https://thedecider.app/consensus-decision-making,The Decider,decision
+Consent,consent,,https://thedecider.app/consent-decision-making,The Decider,decision
+Consultative,consultative,,https://thedecider.app/consultative-decision-making,The Decider,decision
+Continuous voting,continuous_voting,,https://democraticmediums.info/mediums/continuous_voting/,Democratic Mediums,decision
+Delegation,delegation,,https://thedecider.app/delegation-decision-making,The Decider,decision
+Democratic,democratic,,https://thedecider.app/democratic-decision-making,The Decider,decision
+Disapproval voting,disapproval_voting,,https://democraticmediums.info/mediums/disapproval_voting/,Democratic Mediums,decision
+Holographic consensus,holographic_consensus,,https://democraticmediums.info/mediums/holographic_consensus/,Democratic Mediums,decision
+Lazy consensus,lazy_consensus,,https://democraticmediums.info/mediums/lazy_consensus/,Democratic Mediums,decision
+Lottery voting,lottery_voting,,https://democraticmediums.info/mediums/lottery_voting/,Democratic Mediums,decision
+Majority voting,majority_voting,,https://democraticmediums.info/mediums/majority_voting/,Democratic Mediums,decision
+Quadratic voting,quadratic_voting,,https://democraticmediums.info/mediums/quadratic_voting/,Democratic Mediums,decision
+Range voting,range_voting,,https://democraticmediums.info/mediums/range_voting/,Democratic Mediums,decision
+Ranked choice,ranked_choice,,https://democraticmediums.info/mediums/ranked_choice/,Democratic Mediums,decision
+Referendum,referendum,,https://democraticmediums.info/mediums/referendum/,Democratic Mediums,decision
+Rough consensus,rough_consensus,,https://democraticmediums.info/mediums/rough_consensus/,Democratic Mediums,decision
+Secret ballot,secret_ballot,,https://democraticmediums.info/mediums/secret_ballot/,Democratic Mediums,decision
+Stochastic,stochastic,,https://thedecider.app/stochastic-decision-making,The Decider,decision
+Friendship,friendship,,https://democraticmediums.info/mediums/friendship/,Democratic Mediums,culture
+Recess,recess,,https://democraticmediums.info/mediums/recess/,Democratic Mediums,culture
+Ritual,ritual,,https://democraticmediums.info/mediums/ritual/,Democratic Mediums,culture
+Secrecy,secrecy,,https://democraticmediums.info/mediums/secrecy/,Democratic Mediums,culture
+Solidarity,solidarity,,https://democraticmediums.info/mediums/solidarity/,Democratic Mediums,culture
+Transparency,transparency,,https://democraticmediums.info/mediums/transparency/,Democratic Mediums,culture

+ 6 - 6
_guides/first_rule.md

@@ -12,17 +12,17 @@ Whether your community is already up and running or still just an ambition, choo
 
 **It may be easiest to start with a [template]({% link templates.md %}), but you can also [start from scratch]({% link create.md %}).** On a template, press the <span class="pushButton">Customize</span> button to get started. Even if you end up changing almost everything you find in a template, the process can spur thinking in ways that a blank canvas would not.
 
-**Press the <span class="pushButton"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></span> buttons to expand each section and start exploring.** You don't need to fill every field or even every section. If you don't leave an answer, the field will simply disappear when you publish.
+**There are two ways to build a Rule: modules or questions.** Under the community name, you can start dragging pre-defined or custom modules into your Rule. Access them via the <span class="pushButton"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" /></span> button. Below that, there are a series of questions. Press the <span class="pushButton"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Expand" /></span> buttons to see the questions in each section.
 
-**Answer the questions in complete sentences**, because the questions will disappear when you publish. Make sure what you write will make sense when the questions are no longer there.
+**Don't need fill in any more than you feel you need to.** If you leave anything blank, the field will simply disappear when you publish.
 
-**Use the Modules for inspiration.** Access them via <span class="pushButton"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" /></span> alongside a given question. These suggestions are drawn from [Democratic Mediums](https://democraticmediums.info), a sister project that aims to collect governance patterns from diverse contexts.
+**If you use the modules, be sure to explain what they mean.** When you add a module or click on its name, a field appears that allows you to describe the module in your own words. Text typed there automatically becomes part of the module, and it will appear when you hover the cursor over its name. For inspiration, you can press the icon on pre-defined modules to learn more about it at [Democratic Mediums](https://democraticmediums.info/).
 
-**Separate the Rule from its data**. Think of your Rule like a constitution as opposed to a code of laws, like a building as opposed to the people who put it to use. Don't try to include all your community's policies in your Rule; explain there how you make and change policies. Don't list out who holds what roles; just define the roles. In your Rule, make clear where people can find that data---the policies, the role-holders, and so forth.
+**If you use the questions, answer them in complete sentences.** The questions will disappear when you publish. Make sure what you write will make sense when the questions are no longer there. 
 
-**Read and re-read.** Be sure that all the terminology and processes are consistent. Inevitably there will be loopholes and bugs, but try to resolve as many of them as you can. The <span class="pushButton">Preview</span> button provides a clean display for easy reading. Just press <span class="pushButton">Customize</span> when you're ready to edit again.
+**Separate the Rule from its data**. Think of your Rule like a constitution as opposed to a code of laws, like a building as opposed to the people who put it to use. Don't try to include all your community's policies in your Rule; explain there how you make and change policies. Don't list out who holds what roles; just define the roles. In your Rule, make clear where people can find that data---the policies, the role-holders, and so forth.
 
-**When you've finished a draft, show it to your community for feedback.** Others will probably think of things that didn't occur to you. This may even raise some important issues about how different members were perceiving the community differently. Aim to reach unanimity---or something close to it---about your first Rule.
+**Read and re-read.** Be sure that all the terminology and processes are consistent. Inevitably there will be loopholes and bugs, but try to resolve as many of them as you can. The <span class="pushButton">Preview</span> button provides a clean display for easy reading. Just press <span class="pushButton">Customize</span> when you're ready to edit again. Show it to your community for feedback.
 
 **When you're ready to adopt your Rule, put it in a place where your community can easily find it.** Depending on the spaces and tools your community uses, this can mean different things. But one way or another, make your Rule accessible. CommunityRule offers two options: [Publish your Rule to the Library]({% link _guides/publish_rule.md %}) (and provide your community with a link), or export it as a Markdown file (which you can add to your own website or [Git repository]({% link _guides/git_repo.md %}).
 

+ 2 - 2
_guides/mutual_aid.md

@@ -25,7 +25,7 @@ have the rules in the background.
 
 **Make explicit where you are.** [Create your first
 Rule](https://communityrule.info/guides/first-rule/), using the
-[Create](https://communityrule.info/create/) page, to determine and
+[Create]({% link create.md %}) tool, to determine and
 articulate how your group currently functions. Pick a template that
 closely reflects where your group currently stands.
 
@@ -34,7 +34,7 @@ closely reflects where your group currently stands.
 -   Don't get stuck on utopianism, use it as a mirror
 
 **Introduce achievable commitments to strive toward.** Draw from the
-[Templates](https://communityrule.info/templates/) to think about what
+[Templates]({% link templates.md %}) to think about what
 you might like to have in your Rule in the future, filing in the current
 gaps with reasonable additions. Consider adding---either in your Rule or
 linked from it---a code of conduct, community agreement, safer space

+ 2 - 1
_includes/footer.html

@@ -37,7 +37,8 @@
 
       <div class="footer-col footer-col-3">
         <p style="text-align:right;">{{ site.description }}</p>
-        <p style="text-align:right;">Help improve CommunityRule by <br />posting an <a href="https://gitlab.com/medlabboulder/communityrule/-/issues">Issue</a> or <a href="https://gitlab.com/medlabboulder/communityrule">editing the source directly</a></p>
+        <p style="text-align:right;">Help improve CommunityRule by <br />posting an <a href="https://gitlab.com/medlabboulder/communityrule/-/issues">Issue</a> or <a href="https://gitlab.com/medlabboulder/communityrule">editing the source directly</a>,<br />
+        or donate <a href="https://opencollective.com/communityrule">on Open Collective</a></p>
         <p style="text-align:right;"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a></p>
       </div>
     </div>

+ 40 - 21
_layouts/library.html

@@ -2,44 +2,65 @@
 layout: default
 ---
 
-<style type="text/css">
-  #rulename {
-      font-size: 1.2em;
-  }
-</style>
-
 <script>
-  function printLibrary() {
+
+  // Main Library-printing function
+  function printLibrary(sheet) {
       const store = new SteinStore(
           "https://api.steinhq.com/v1/storages/5e8b937ab88d3d04ae0816a5"
       );
       var rules = "";
-      store.read("rules", { limit: 0, offset: 0 }).then(data => {
-          console.log(data);
+      store.read(sheet, { limit: 0, offset: 0 }).then(data => {
           rules = data.reverse();
           libHTML = "";
+          // iterating over all the rules
           for (var i = 0; i < rules.length; i++) {
+              libHTML += "<div class='library-item'>\n";
+              // first the titles
               var title = rules[i]["communityname"];
               if (title == null) { title = "Untitled"; }
-              libHTML += "<h2 id='rulename'>" +
+              libHTML += "<div class='library-rule-name'>" +
                   "<a href='/create/?r=" + rules[i]["ruleID"] + "'>" +
-                  title + "</a></h2>\n";
+                  title + "</a></div>\n";
+              // then the authors
+              var author = rules[i]["author-text"];
+              if (author != null) {
+                  libHTML += "<div class='library-rule-author'>" + author + "</div>";
+              }
+              // then the structures
               var structure = rules[i]["structure"];
               if (structure != null) {
-                  libHTML += "<p>" + structure;
-                  var author = rules[i]["author-text"];
-                  if (author != null) {
-                      libHTML += " (" + author + ")";
-                  }
+                  libHTML += "<p class='library-rule-structure'>" + structure;
                   libHTML += "</p>\n\n";
               }
+              // then the modules
+              var modulesRaw = rules[i]["modules"];
+              if (modulesRaw != null) {
+                  libHTML += "<div class='library-module-list'>";
+                  var modulesDOM = document.createElement("DIV");
+                  modulesDOM.innerHTML = "<div>" + modulesRaw + "</div>";
+                  var modules = modulesDOM.getElementsByClassName("module");
+                  for (var x = 0; x < modules.length; x++) {
+                      var moduleName = modules[x].children.item("module-name").innerHTML;
+                      libHTML += "<div class='module library-module'>" +
+                          moduleName + "</div>\n";
+                  }
+                  moduleName + "</div>\n";
+              }
+              libHTML += "</div>\n</div>\n";
           }
-          document.getElementById("libraryList").innerHTML = libHTML;
+          libHTML += "</div>\n";
+          document.getElementById("librarylist").innerHTML = libHTML;
       });
   }
 
+  // allows for using alt sheets (though rule.html is not equipped)
+  var source = "";
   window.onload = function() {
-      printLibrary();
+      if ((window.location.href.indexOf("/library/") != -1)) {
+          source = "rules";
+      }
+      printLibrary(source);
   }
 </script>
 
@@ -52,10 +73,8 @@ layout: default
 
   <div class="post-content">
     {{ content }}
-
-<hr /><br />
     
-    <div id="libraryList">
+    <div id="librarylist">
     </div>    
   </div>
 

+ 396 - 156
_layouts/rule.html

@@ -7,6 +7,198 @@ layout: default
 <script>
   // Enter JavaScript-land!
   // First, some functions, followed by initialization commands
+
+  // Begin BUILDER functions
+  // source: https://www.codecanal.com/html5-drag-and-copy/
+  function allowDrop(ev) {
+      ev.preventDefault();
+  }
+  function drag(ev) {
+      ev.dataTransfer.setData("text", ev.target.id);
+  }
+  function drop(ev) {
+      ev.preventDefault();
+      var target = ev.target;
+      // First, confirm target location is valid
+      function targetCheck () {
+          if (target.id == "module-input") { 
+              return true;
+          } else if (!document.getElementById("module-input").contains(target)) {
+              // Ignore destinations not in the correct area
+              return false;
+          } else if (target.id == "drag-directions") {
+              // Prevents dropping into dummy text field
+              target = target.parentElement;
+              return true;
+          } else if (target.classList[0] == "module") {
+              return true;
+          } else {
+              // be sure we're adding to module, not its children              
+              target = target.parentElement;
+              return targetCheck();
+          }
+      }
+      if (!targetCheck()) { return; } 
+      // Set up transfer
+      var data = ev.dataTransfer.getData("text");
+      // Iff module is from the menu clone it
+      var module = document.getElementById(data);
+      if (module.parentElement.id == "module-menu") {
+          module = module.cloneNode(true);
+          var name = null;
+          if (module.id == "module-custom") {
+              // For custom modules: replace the <input> with text
+              name = module.getElementsByTagName("input")[0].value;
+              module.getElementsByTagName("input")[0].remove();
+              var customText = document.createElement("span");
+              customText.onClick = "moduleEditField(this.parentNode.id)";
+              customText.id = "module-name";
+              customText.append(name);              
+              module.prepend(customText);
+          }
+          // append id with unique timestamp
+          var nowModule = new Date();
+          module.id += "-" + nowModule.getTime();
+      }
+      // display the deletion button
+      module.children[2].style.display = "inline";
+      // pop it in!
+      target.appendChild(module);
+      // set up the editing field
+      moduleEditField(module.id);
+      // be sure the dummy text is gone
+      if (document.contains(document.getElementById("drag-directions"))) {
+          document.getElementById("drag-directions").remove();
+      }
+  }
+
+  // Edits the title field of a given module based on #custom-field
+  function moduleTitleEdit(moduleID) {
+      var module = document.getElementById(moduleID).children[0];
+      var content =
+          stripHTML(document.getElementById("custom-field").innerHTML);
+      module.title = content;
+  }
+  
+  // Sets up a field for displaying and editing module details
+  function moduleEditField(moduleID) {
+      var module = document.getElementById(moduleID);
+      var moduleName = module.children[0].innerHTML;
+      var moduleTitle = module.children[0].title;
+      if (editMode) {
+          var query = "Explain how the <strong>" + moduleName
+              + "</strong> module works.";
+          var destination = document.getElementById("builder-field");
+          if (moduleName == null) { moduleName = ""; }     
+          var output = '\n<div id="custom-field-container">';
+          output += '<span class="question">' + query + '</span>';
+          output += '<div class="field-controls"><a onclick="this.parentNode.parentNode.remove()"><img src="{% link assets/tabler_icons/x.svg %}" class="delete-module" /></a></div>';
+          output += '<p contenteditable="true" class="editable" id="custom-field" oninput="moduleTitleEdit(\'' + moduleID + '\')">' + moduleTitle + '</p>';
+          output += '</div>\n';
+          destination.innerHTML = output;
+      } else {
+          var output = '\n<div id="custom-field-container">';
+          output += '<div class="field-controls"><a onclick="this.parentNode.parentNode.remove()"><img src="{% link assets/tabler_icons/x.svg %}" class="delete-module" /></a></div>';
+          output += '<p class="editable" id="custom-field">'
+              + moduleTitle + '</p>';
+      }
+  }
+
+  // Tests if the RuleBuilder is empty
+  function builderEmpty() {
+      var builder = document.getElementById("module-input");
+      var childs = builder.children;
+      if (builder.getElementsByClassName("module").length > 0) {
+          return false;
+      } else {
+          return true;
+      }
+  }
+
+  // Turns RuleBuilder contents into an output-ready nested array
+  // Returns empty array if no modules
+  function builderArray() {
+      var modules = document.getElementById("module-input").children;
+      // takes an array of children
+      // returns an array with all modules in the array, recursively nested
+      function iterateArray (childs) {
+          var moduleArray = [];
+          if (childs.length > 0) {
+              for (var i = 0; i < childs.length; i++) {
+                  module = childs[i];
+                  if (module.classList[0] == "module") {
+                      var moduleName = module.children.item("module-name");
+                      var moduleData = moduleName.title;
+                      var moduleChilds = module.children;
+                      moduleArray.push(
+                          [stripHTML(moduleName.innerHTML),
+                           stripHTML(moduleData),
+                           iterateArray(moduleChilds)]);
+                  }
+              }
+          }
+          return moduleArray;
+      } // end function
+      return iterateArray(modules);
+  }
+
+  // returns HTML version of Builder content
+  function displayBuilderHTML() {
+      var output = "";
+      var mainArray = builderArray();
+      function arrayHTML(thisArray) {
+          var thisOutput = "";
+          if (thisArray.length > 0) {
+              thisOutput += '<ul class="builder-list">\n';
+              for (var i = 0; i < thisArray.length; i++) {
+                  var item = thisArray[i];
+                  thisOutput += '<li><strong>' + item[0] + '</strong> ';
+                  thisOutput += item[1] + '</li>\n';
+                  if (item[2].length > 0) {
+                      thisOutput += arrayHTML(item[2]);
+                  }
+              }
+              thisOutput += '</ul>\n';
+          }
+          return thisOutput
+      }
+      return arrayHTML(mainArray);
+  }
+
+  // returns Markdown version of Builder content
+  function displayBuilderMD() {
+      var mainArray = builderArray();
+      var indentLevel = 0;
+      function arrayMD(thisArray) {
+          var thisOutput = "";
+          if (thisArray.length > 0) {
+              for (var i = 0; i < thisArray.length; i++) {
+                  var item = thisArray[i];
+                  for (var x = 0; x < indentLevel; x++) {
+                      thisOutput += "    ";
+                  }
+                  thisOutput += "* **" + item[0] + "** ";
+                  thisOutput += item[1] + "\n";
+                  if (item[2].length > 0) {
+                      indentLevel++;                      
+                      thisOutput += arrayMD(item[2]);
+                      indentLevel--;
+                  }
+              }
+
+          }
+          return thisOutput;
+      }
+      return arrayMD(mainArray);
+  }  
+  
+  // end RuleBuilder functions
+
+  // Removes all HTML content
+  function stripHTML(input) {
+      input = input.replace(/(<([^>]+)>)/ig,'');
+      return input;
+  }
   
   // toggleVisible(id)
   // Toggles the visibility of a given element by given ID
@@ -37,6 +229,8 @@ layout: default
           classDisplayAll("section","block");
           classDisplayAll("button","none");
           classDisplayAll("question","none");
+          classDisplayAll("metaheader","none");
+          classDisplayAll("delete-module","none");
           var editableFields = document.getElementsByClassName("editable");  
           // de-editable-ize the editable fields
           for (var i = 0; i < editableFields.length; i++) {
@@ -44,13 +238,23 @@ layout: default
               editableFields[i].style.borderStyle = "none";
               // Remove empty fields entirely
               var content = editableFields[i].innerHTML;
-              content = content.replace(/(<([^>]+)>)/ig,''); // strips stray tags
+              content = stripHTML(content);
               if (content === "") {
                   editableFields[i].style.display = "none";
               }   
           }
-          // Remove headers of empty sections
-          // Inefficient! Might be merged with the above iteration
+          // RuleBuilder sections
+          if (builderEmpty()) {
+              document.getElementById("rule-builder").style.display = "none";
+          } else {
+              document.getElementById("builder-field").innerHTML = displayBuilderHTML();
+              document.getElementById("module-input").style.border = "none";
+          }
+          if (document.contains(document.getElementById("custom-field-container"))) {
+              document.getElementById("custom-field-container").remove();
+          }
+          document.getElementById("module-menu").style.display = "none";
+          // RuleWriter: Remove headers of empty sections
           var sections = document.getElementsByClassName("section");
           for (var i = 0; i < sections.length; i++) {
               var sectionQuestions = sections[i].getElementsByClassName("editable");
@@ -65,8 +269,6 @@ layout: default
                   }
               }
           }
-          // Handle links
-          // TKTK
           // Handle author link
           var authorName = document.getElementById("author-text").value;
           var authorURL = document.getElementById("author-url").value;
@@ -91,9 +293,14 @@ layout: default
           classDisplayAll("editable","block");
           classDisplayAll("header","block");
           classDisplayAll("section","none");
+          classDisplayAll("metaheader","block");
           classDisplayAll("link-text","inline");
           classDisplayAll("link-url","inline");
-          // link handling TKTK
+          classDisplayAll("delete-module","inline");
+          // builder handling
+          document.getElementById("rule-builder").style.display = "block";
+          document.getElementById("module-input").style.border = "";
+          document.getElementById("builder-field").innerHTML = "";          
           // author handling
           document.getElementById("authorship-result").style.display = "none";
           document.getElementById("authorship-words").style.display = "none";
@@ -144,12 +351,16 @@ layout: default
       var filename = 'GOVERNANCE.md';
       // First, add title, whether there is one or not
       var content = '# '+ document.getElementById('communityname').innerHTML + '\n\n';
-      content = content.replace(/(<([^>]+)>)/ig,''); // strips stray tags
+      content = stripHTML(content);
+      // Add Builder content
+      if (!builderEmpty()) {
+          content += displayBuilderMD() + "\n\n";          
+      }
       // Now, begin adding other elements
       var elements = document.getElementsByClassName('output');
       for (var i = 1; i < elements.length; i++) {
           var thisBit = elements[i].innerHTML;
-          thisBit = thisBit.replace(/(<([^>]+)>)/ig,''); // strips stray tags
+          thisBit = stripHTML(thisBit);
           if (thisBit != "") {
               if (elements[i].classList.contains("subhead")) {
                   // Before printing subhead, make sure it's not empty
@@ -205,7 +416,7 @@ layout: default
   // BEGIN Publish tools, via SteinHQ.com
 
   // publishRule()
-  // Publishes existing fields to new page, /create/?rule=[ruleID]
+  // Publishes existing fields to new page, /builder/?rule=[ruleID]
   // Opens new page in Display mode
   function publishRule() {
       // Confirm user knows what they're getting into
@@ -224,6 +435,13 @@ layout: default
           ruleID: timeID,
           timestamp: dateTime,
       }];
+      // begin adding data
+      // first, RuleBuilder data
+      document.getElementById("builder-field").innerHTML = ""; // so it doesn't publish
+      if (!builderEmpty()) {
+          rule[0]["modules"] = document.getElementById("module-input").innerHTML;
+      }
+      // next, RuleWriter data
       var fields = document.getElementsByClassName("editable");
       for (var i = 0; i < fields.length; i++) {
           var key = fields[i].id;
@@ -250,6 +468,7 @@ layout: default
           "https://api.steinhq.com/v1/storages/5e8b937ab88d3d04ae0816a5"
       );     
       store.read("rules", { search: { ruleID: ID } }).then(data => {
+          // reads sheet variable from below
           // only runs when we have the data from Goog:
           var rule = data[0];
           var fields = document.getElementsByClassName("editable");
@@ -264,6 +483,8 @@ layout: default
                   document.getElementById(key).innerHTML = value;
               }
           }
+          // Add Builder content
+          document.getElementById("module-input").innerHTML = rule["modules"];
           // Publish timestamp to Rule
           document.getElementById('dateTime').innerHTML = rule['timestamp'];
           // Finish
@@ -324,168 +545,188 @@ layout: default
   </header>
   
   <div id="rulebox">
-    <span class="question">What is the community’s name?</span>
 
+    <span class="question">What is the community’s name?</span>
     <h1 contenteditable="true" class="editable output" id="communityname">{{ page.community-name }}</h1>
 
-    <!-- SECTION S1: BASICS -->
-    <h2 id="header-s1" class="header">
-      <img src="{% link assets/tabler_icons/info-circle.svg %}"
-           class="icons" />
-      <span class="subhead output">Basics</span>
-      <button onclick="toggleVisible('s1')" class="button plus"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></button>
-    </h2>
-    <div class="section" id="s1" style="display:none">
-    
-      <span class="question">What is the basic structure of the community?</span>
-      <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-        <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/federation/">federation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/friendship/">friendship</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/membership/">membership</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/multicameralism/">multicameralism</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/ritual/">ritual</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/separation_of_powers/">separation of powers</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/stake_weight/">stake weight</a></span>
-      </div>
-      <p contenteditable="true" class="editable output" id="structure">{{ page.structure }}</p>
+    <!-- RuleBuilder -->
 
-      <span class="question">What is the community’s mission?</span>
-      <p contenteditable="true" class="editable output" id="mission">{{ page.mission }}</p>
+    <div id="rule-builder">
 
-      <span class="question">What core values does the community hold?</span>
-      <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-        <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/secrecy/">secrecy</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/solidarity/">solidarity</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/transparency/">transparency</a></span>
+      <button id="module-toggle" onclick="toggleVisible('module-menu')"
+              class="button" title="Show/hide">
+        <img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
+      </button>
+
+      <div id="module-input"
+           ondrop="drop(event)" ondragover="allowDrop(event)">
+        <span class="question" id="drag-directions">Browse modules with the tool button and drag them here.</span>
       </div>
-      <p contenteditable="true" class="editable output" id="values">{{ page.values }}</p>
-      <span class="question">What is the legal status of the community’s assets and creations?</span>
-      <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-        <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/ownership/">ownership</a></span>
+
+      <div id="builder-field">
+      </div>
+      
+      <div id="module-menu" style="display:none;">
+        <!-- Customizable module -->
+        <span class="module" id="module-custom"
+              draggable="true" ondragstart="drag(event)">
+		  <input contenteditable="true" placeholder="Custom..."/>
+          <img src="{% link assets/tabler_icons/bulb.svg %}" class="module-logo"
+               draggable="false" />
+		  <a onclick="this.parentNode.remove()" class="delete-module"
+			 style="display:none">
+			<img src="{% link assets/tabler_icons/x.svg %}" /></a>
+		</span>
+		<!-- Load preset modules from _data/modules.csv -->
+		{% for module in site.data.modules %}
+		<span class="module" id="module-{{ module.id }}"
+			  draggable="true" ondragstart="drag(event)">
+		  <span id="module-name"
+                onclick="moduleEditField(this.parentNode.id)">{{ module.name }}</span>
+          <a target="_blank" href="{{ module.url }}">
+            <img title="{{ module.type }}" draggable="false" class="module-logo"
+                 {% if module.type == "structure" %}
+                 src="{% link assets/tabler_icons/building.svg %}" {% endif %}
+                 {% if module.type == "process" %}
+                 src="{% link assets/tabler_icons/rotate.svg %}" {% endif %}
+                 {% if module.type == "decision" %}
+                 src="{% link assets/tabler_icons/thumb-up.svg %}" {% endif %}
+                 {% if module.type == "culture" %}
+                 src="{% link assets/tabler_icons/palette.svg %}" {% endif %}
+                 /></a>
+		  <a onclick="this.parentNode.remove()" class="delete-module"
+			 style="display:none">
+			<img src="{% link assets/tabler_icons/x.svg %}" /></a>
+		</span>
+        {% endfor %}
       </div>
-      <p contenteditable="true" class="editable output" id="legal">{{ page.legal }}</p>
       
-
-    </div><!--hiding section s1-->
-
-    <!-- SECTION s2: PARTICIPANTS -->
-    <h2 id="header-s2" class="header">
-      <img src="{% link assets/tabler_icons/user.svg %}"
-           class="icons" />
-      <span class="subhead output">Participants</span>
-      <button onclick="toggleVisible('s2')" class="button plus"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></button>
-    </h2>
-  
-    <div class="section" id="s2" style="display:none">
-    
-    <span class="question">How does someone become a participant?</span>
-        <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/do-ocracy/">do-ocracy</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/friendship/">friendship</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/membership/">membership</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/reputation/">reputation</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="membership">{{ page.membership }}</p>
-  
-    <span class="question">How are participants suspended or removed?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/exclusion/">exclusion</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/friendship/">friendship</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/reputation/">reputation</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="removal">{{ page.removal }}</p>
-
-    <span class="question">What special roles can participants hold, and how are roles assigned?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/delegation/">delegation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/representation/">representation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/separation_of_powers/">separation of powers</a></span>
-    </div> 
-    <p contenteditable="true" class="editable output" id="roles">{{ page.roles }}</p>
-
-    <span class="question">Are there limits on the terms or powers of participant roles?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/fact_finding/">fact-finding</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/ranked_choice/">ranked choice</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/representation/">representation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/reputation/">reputation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/sortition/">sortition</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/term_limit/">term limits</a></span>
-    </div>
-  <p contenteditable="true" class="editable output" id="limits">{{ page.limits }}</p>
-
-    
-  </div><!--hiding section s2-->
-
-  <!--SECTION s3: POLICY-->
-  <h2 id="header-s3" class="header">
-    <img src="{% link assets/tabler_icons/news.svg %}"
-         class="icons" />
-    <span class="subhead output">Policy</span>
-    <button onclick="toggleVisible('s3')" class="button plus"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></button>
-  </h2>
-  <div class="section" id="s3" style="display:none">
-
-    <span class="question">What basic rights does this Rule guarantee?</span>
-    <p contenteditable="true" class="editable output" id="rights">{{ page.rights }}</p>
-    
-    <span class="question">Who has the capacity to decide on policies, and how do they do so?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/disapproval_voting/">disapproval voting</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/do-ocracy/">do-ocracy</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/holographic_consensus/">holographic consensus</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/quadratic_voting/">quadratic voting</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/referendum/">referendum</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/representation/">representation</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/sortition/">sortition</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="decision">{{ page.decision }}</p>
-  
-    <span class="question">How are policies implemented?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/exclusion/">exclusion</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/lazy_consensus/">lazy consensus</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/restorative_justice/">restorative justice</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="implementation">{{ page.implementation }}</p>
-  
-    <span class="question">How does the community monitor and evaluate its policy implementation? </span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/board/">board</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/disapproval_voting/">disapproval voting</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/judiciary/">jury</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/precedent/">precedent</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/refusal/">refusal</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/rough_consensus/">rough consensus</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="oversight">{{ page.oversight }}</p>
-    
-  </div><!--hiding section s3-->
-
-  <!-- SECTION s4: PROCESS -->
-  <h2 id="header-s4" class="header">
-    <img src="{% link assets/tabler_icons/refresh.svg %}"
-         class="icons" />
-    <span class="subhead output">Process</span>
-    <button onclick="toggleVisible('s4')" class="button plus"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></button>
-  </h2>
-  <div class="section" id="s4" style="display:none">
-
-    <span class="question">Where does the community deliberate about policies and governance?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/caucus/">caucus</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/coalition/">coalition</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/board/">board</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/debate/">debate</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/lobbying/">lobbying</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/recess/">recess</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/secrecy/">secrecy</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/transparency/">transparency</a></span>
-    </div>
-    <p contenteditable="true" class="editable output" id="deliberation">{{ page.deliberation }}</p>
-
-    <span class="question">How does the community manage access to administrative accounts and other tools?</span>
-    <p contenteditable="true" class="editable output" id="access">{{ page.access }}</p>
-
-    <span class="question">How does the community manage funds and economic flows?</span>
-    <p contenteditable="true" class="editable output" id="economics">{{ page.economics }}</p>
-    
-    <span class="question">How are grievances among participants addressed?</span>
-    <div class="button"><img src="{% link assets/tabler_icons/tool.svg %}" title="Modules" />
-      <span class="tooltiptext modules"><a target="_blank" class="module" href="https://democraticmediums.info/mediums/audit/">audit</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/debate/">debate</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/friendship/">friendship</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/restorative_justice/">restorative justice</a> <a target="_blank" class="module" href="https://democraticmediums.info/mediums/recess/">recess</a></span>
     </div>
-    <p contenteditable="true" class="editable output" id="grievances">{{ page.grievances }}</p>
-    
-  </div><!--hiding section s4-->
-
-  <!-- SECTION s5: EVOLUTION -->
-  <h2 id="header-s5" class="header">
-    <img src="{% link assets/tabler_icons/adjustments.svg %}"
-         class="icons" />
-    <span class="subhead output">Evolution</span>
-    <button onclick="toggleVisible('s5')" class="button plus"><img src="{% link assets/tabler_icons/plus.svg %}" title="Expand" /></button>
-  </h2>
-  <div class="section" id="s5" style="display:none">
-
-    <span class="question">Where are policies and records kept?</span>
-    <p contenteditable="true" class="editable output" id="records">{{ page.records }}</p>
-
-    <span class="question">How can this Rule be modified?</span>
-    <p contenteditable="true" class="editable output" id="modification">{{ page.modification }}</p>
-
-  </div><!--hiding section s5-->
 
+    <div id="rule-writer">
+      
+      <!-- SECTION S1: BASICS -->
+      <h2 id="header-s1" class="header">
+        <img src="{% link assets/tabler_icons/info-circle.svg %}"
+             class="icons" />
+        <span class="subhead output">Basics</span>
+        <button onclick="toggleVisible('s1')" class="button chevrons"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Show/hide" /></button>
+      </h2>
+      <div class="section" id="s1" style="display:none">
+        
+        <span class="question">What is the basic structure of the community?</span>
+        <p contenteditable="true" class="editable output" id="structure">{{ page.structure }}</p>
+
+        <span class="question">What is the community’s mission?</span>
+        <p contenteditable="true" class="editable output" id="mission">{{ page.mission }}</p>
+
+        <span class="question">What core values does the community hold?</span>
+        <p contenteditable="true" class="editable output" id="values">{{ page.values }}</p>
+
+        <span class="question">What is the legal status of the community’s assets and creations?</span>
+        <p contenteditable="true" class="editable output" id="legal">{{ page.legal }}</p>
+        
+
+      </div><!--hiding section s1-->
+
+      <!-- SECTION s2: PARTICIPANTS -->
+      <h2 id="header-s2" class="header">
+        <img src="{% link assets/tabler_icons/user.svg %}"
+             class="icons" />
+        <span class="subhead output">Participants</span>
+        <button onclick="toggleVisible('s2')" class="button chevrons"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Show/hide" /></button>
+      </h2>  
+      <div class="section" id="s2" style="display:none">
+        
+        <span class="question">How does someone become a participant?</span>
+        <p contenteditable="true" class="editable output" id="membership">{{ page.membership }}</p>
+        
+        <span class="question">How are participants suspended or removed?</span>
+        <p contenteditable="true" class="editable output" id="removal">{{ page.removal }}</p>
+
+        <span class="question">What special roles can participants hold, and how are roles assigned?</span>
+        <p contenteditable="true" class="editable output" id="roles">{{ page.roles }}</p>
+
+        <span class="question">Are there limits on the terms or powers of participant roles?</span>
+        <p contenteditable="true" class="editable output" id="limits">{{ page.limits }}</p>
+
+      </div><!--hiding section s2-->
+
+      <!--SECTION s3: POLICY-->
+      <h2 id="header-s3" class="header">
+        <img src="{% link assets/tabler_icons/news.svg %}"
+             class="icons" />
+        <span class="subhead output">Policy</span>
+        <button onclick="toggleVisible('s3')" class="button chevrons"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Show/hide" /></button>
+      </h2>
+      <div class="section" id="s3" style="display:none">
+
+        <span class="question">What basic rights does this Rule guarantee?</span>
+        <p contenteditable="true" class="editable output" id="rights">{{ page.rights }}</p>
+        
+        <span class="question">Who has the capacity to decide on policies, and how do they do so?</span>
+        <p contenteditable="true" class="editable output" id="decision">{{ page.decision }}</p>
+        
+        <span class="question">How are policies implemented?</span>
+        <p contenteditable="true" class="editable output" id="implementation">{{ page.implementation }}</p>
+        
+        <span class="question">How does the community monitor and evaluate its policy implementation? </span>
+        <p contenteditable="true" class="editable output" id="oversight">{{ page.oversight }}</p>
+        
+      </div><!--hiding section s3-->
+
+      <!-- SECTION s4: PROCESS -->
+      <h2 id="header-s4" class="header">
+        <img src="{% link assets/tabler_icons/refresh.svg %}"
+             class="icons" />
+        <span class="subhead output">Process</span>
+        <button onclick="toggleVisible('s4')" class="button chevrons"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Show/hide" /></button>
+      </h2>
+      <div class="section" id="s4" style="display:none">
+
+        <span class="question">Where does the community deliberate about policies and governance?</span>
+        <p contenteditable="true" class="editable output" id="deliberation">{{ page.deliberation }}</p>
+
+        <span class="question">How does the community manage access to administrative accounts and other tools?</span>
+        <p contenteditable="true" class="editable output" id="access">{{ page.access }}</p>
+
+        <span class="question">How does the community manage funds and economic flows?</span>
+        <p contenteditable="true" class="editable output" id="economics">{{ page.economics }}</p>
+        
+        <span class="question">How are grievances among participants addressed?</span>
+        <p contenteditable="true" class="editable output" id="grievances">{{ page.grievances }}</p>
+        
+      </div><!--hiding section s4-->
+
+      <!-- SECTION s5: EVOLUTION -->
+      <h2 id="header-s5" class="header">
+        <img src="{% link assets/tabler_icons/adjustments.svg %}"
+             class="icons" />
+        <span class="subhead output">Evolution</span>
+        <button onclick="toggleVisible('s5')" class="button chevrons"><img src="{% link assets/tabler_icons/chevrons-down.svg %}" title="Show/hide" /></button>
+      </h2>
+      <div class="section" id="s5" style="display:none">
+
+        <span class="question">Where are policies and records kept?</span>
+        <p contenteditable="true" class="editable output" id="records">{{ page.records }}</p>
+
+        <span class="question">How can this Rule be modified?</span>
+        <p contenteditable="true" class="editable output" id="modification">{{ page.modification }}</p>
+
+      </div><!--hiding section s5-->
+
+    </div><!--end: rule-writer-->
+      
   <div id="authorship" class="linkbox">
     <span id="authorship-words">Created by</span>
-    <input contenteditable="true" class="editable link-text" id="author-text" placeholder="Created by">
+    <input contenteditable="true" class="editable link-text" id="author-text" placeholder="Created by" />
     <span class="link-divider"><img src="{% link assets/tabler_icons/pencil.svg %}" title="Add link" /></span>
-    <input contenteditable="true" class="editable link-url" id="author-url" placeholder="Creator URL (http://, https://)" type="url" pattern="http://.*|https://.*">
+    <input contenteditable="true" class="editable link-url" id="author-url" placeholder="Creator URL (http://, https://)" type="url" pattern="http://.*|https://.*" />
     <span id="authorship-result"></span>
   </div>
   
   </div><!--#rulebox-->
-
-  
+ 
   <div id="attribution" style="display:none;">
     <br />
     <p><a href="https://communityrule.info">
@@ -502,7 +743,6 @@ layout: default
 
 [Creative Commons BY-SA](https://creativecommons.org/licenses/by-sa/4.0/)</div>
   
-  
   <button class="pushButton" id="publishRule" onclick="publishRule()"
     title="Add to the public Library">Publish</button>
   <button class="pushButton" id="toggleDisplayMode" onclick="toggleDisplayMode()"
@@ -516,7 +756,7 @@ layout: default
           onclick="javascript:location.href='https://www.colorado.edu/lab/medlab/content/communityrule-user-feedback'">
     Feedback
   </button>
-  
+
 </article>
 
 

+ 110 - 53
_sass/communityrule.scss

@@ -1,6 +1,17 @@
 /* BEGIN COMMUNITYRULE-SPECIFIC CSS */
 
 /* CLASSES */
+.button {
+  position: relative;
+  display: inline;
+  float: right;
+  border: 0px solid gray;
+  color: gray;
+  background-color: white;
+  text-align: center;
+  border-radius: 6px;
+  padding: 0;
+}
 .callout-text {
     font-family: serif;
     font-size:2em;
@@ -20,80 +31,96 @@
 .question {
     color: gray;
 }
+.metaheader {
+    color: gray;
+    margin-top: 30px;
+    border-bottom: 1px solid lightgray;
+}
 
-/* Tooltip for Modules
-   https://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip_right 
-   This could bear substantial improvement. */
-.button {
-  position: relative;
-  display: inline-block;
-  float: right;
-  border: 1px solid gray;
-  color: gray;
-  background-color: white;
-  text-align: center;
-  border-radius: 6px;
-  padding: 0 5px 0 5px;
+/* Modules */
+
+#module-toggle {
+    float: right;
+    position: relative;
+    margin-left: 10px;
+    padding: 5px;
 }
-.button .tooltiptext {
-  visibility: hidden;
-  width: 250px;
-  border: 1px solid black;
-  background-color: white;
-  text-align: center;
-  border-radius: 6px;
-  padding: 10px;
-  /* Position the tooltip */
-  position: absolute;
-  z-index: 1;
-  top: -5px;
-  right: 100%;
+#module-menu {
+    display: none;
+    max-height: 200px;
+    overflow-y: scroll;
+    margin: 0 0 10px 0;
+    border: 1px solid lightgray;
 }
 .button:hover {
     background-color: lightgray;
 }
-.button:hover .tooltiptext {
-    visibility: visible;
-}
-
-/* Modules */
 
+#module-input {
+    overflow: hidden;
+    border: 1px solid lightgray;
+    border-radius: 6px;
+    padding: 10px 10px 10px 10px;
+    margin: 0 0 15px 0;
+    text-align: left;
+    min-height: 1.5em;
+}
+  
 .module {
-  border: 1px solid gray;
-  color: black;
-  background-color: lightgray;
-  text-align: center;
-  border-radius: 10px;
-  padding: 5px;
-  margin: 5px;
-  display: inline-block;
+    display: block;
+    border: 1px solid gray;
+    color: black;
+    background-color: lightgray;
+    text-align: center;
+    border-radius: 10px;
+    padding: 5px;
+    margin: 5px;
+    display: inline-block;
+    font-size: .8em;
+    cursor: pointer;
 }
+
 .module:hover {
-    background-color: gray;
+    border-color: gray;
 }
-a.module:hover {
-    text-decoration: none;
-    color: white;
+.module a:hover {
 }
-a.module:visited {
-    color: black;
+.delete-module {
+    cursor: pointer;
+}
+.module-logo {
+}
+
+.builder-list {
+    list-style-type: none;
+    color: gray;
+    margin-bottom: 2em;
+}
+
+.field-controls {
+    float: right;
+    font-size: .7em;
+}
+.field-controls a {
+    cursor: pointer;
 }
 
 /* pushButton
 These are the major functional buttons*/
 .pushButton {
-  border: 1px solid gray;
-  color: gray;
-  background-color: white;
-  text-align: center;
-  border-radius: 6px;
-  padding: 5px;
-  font-size: 1.2em;
+    border: 1px solid gray;
+    color: gray;
+    background-color: white;
+    text-align: center;
+    border-radius: 6px;
+    padding: 5px;
+    margin: 0 5px 0 5px;
+    font-size: 1.2em;
 }
 .pushButton:hover {
     background-color: lightgray;
 }
-.plus { /* The maximize/minimize button */
+.chevrons { /* The maximize/minimize button */
     font-size: 1em;
 }
 .icons {
@@ -140,6 +167,36 @@ Enabling users to add links*/
     display: none;
 }
 
+/* LIBRARY */
+
+#librarylist {
+    margin: 50px 0 0 0;
+}
+.library-item {
+    margin: 0 0 30px 0;
+}
+.library-rule-name {
+    display: inline-block;
+    margin: 0;
+    font-size: 1.2em;
+    font-weight: bold;
+}
+.library-rule-author {
+    display: inline-block;    
+    margin: 0 0 0 10px;
+    font-size: .8em;
+    color: gray;
+}
+.library-rule-structure {
+    margin: 0;
+}
+.library-module {
+    font-size: .7em;
+    padding: 1px 5px 1px 5px;
+    margin: 0px;
+    cursor: default;    
+}
+
 /* VARIOUS IDs */
 #rulebox {
     border: 1px solid lightgray;

+ 1 - 1
create.md

@@ -35,4 +35,4 @@ records:
 modification: 
 ---
 
-Use the questions below to build a rule or [start with a template]({% link templates.md %}). Answer questions in complete sentences, as the questions disappear.
+Create a Rule from scratch, using modules and/or answering the questions in the drop-downs below. Answer questions in complete sentences—the questions disappear.

+ 3 - 3
index.md

@@ -23,7 +23,7 @@ permalink: /
     </div>
 
     <div class="callout-text">
-        <a href="create/">Start from scratch</a> or <a href="templates/">choose a template</a>
+        <a href="{% link create.md %}">Start from scratch</a> or <a href="{% link templates.md %}">choose a template</a>
     </div>
 
     <div class="callout-icon">
@@ -31,7 +31,7 @@ permalink: /
     </div>
 
     <div class="callout-text">
-        <a href="guides/">Tailor a Rule</a> to your community's needs and values
+        <a href="{% link guides.md %}">Tailor a Rule</a> to your community's needs and values
     </div>
 
     <div class="callout-icon">
@@ -39,7 +39,7 @@ permalink: /
     </div>
 
     <div class="callout-text">
-        Then publish your Rule and <a href="library/">share it with others</a>
+        Then publish your Rule and <a href="{% link library.md %}">share it with others</a>
     </div>
 
 </div>

+ 1 - 3
library.md

@@ -4,7 +4,5 @@ title: Library
 permalink: /library/
 ---
 
-Browse user-created rules, starting from the most recent.
-
-**This feature is experimental, and rules may be removed without notice.**
+Browse user-created rules, starting from the most recent. This feature is experimental, and rules may be removed without notice.