diff --git a/hledger-web/src/Widget/Common.hs b/hledger-web/src/Widget/Common.hs
index 8be72ae63..092aef5f9 100644
--- a/hledger-web/src/Widget/Common.hs
+++ b/hledger-web/src/Widget/Common.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Widget.Common
   ( accountQuery
@@ -24,6 +25,7 @@ import Text.Blaze ((!), textValue)
 import qualified Text.Blaze.Html5 as H
 import qualified Text.Blaze.Html5.Attributes as A
 import Text.Blaze.Internal (preEscapedString)
+import Text.Hamlet (hamletFile)
 import Yesod
 
 import Hledger
@@ -57,39 +59,13 @@ helplink topic label _ = H.a ! A.href u ! A.target "hledgerhelp" $ toHtml label
 
 -- | Render a "BalanceReport" as html.
 balanceReportAsHtml :: Eq r => (r, r) -> r -> Bool -> Journal -> [QueryOpt] -> BalanceReport -> HtmlUrl r
-balanceReportAsHtml (journalR, registerR) here hideEmpty j qopts (items, total) = [hamlet|
-
-  | -    
-      Journal
- | -$forall (acct, adisplay, aindent, abal) <- items
- | 
-    | - 
-        \#{indent aindent}
-        -          #{adisplay}
-        $if hasSubs acct
-          only
- -      ^{mixedAmountAsHtml abal}
- | 
-  | - | -    ^{mixedAmountAsHtml total}
-|] where
-  l = ledgerFromJournal Any j
-  inacctClass acct = case inAccountQuery qopts of
-    Just m' -> if m' `matchesAccount` acct then "inacct" else ""
-    Nothing -> "" :: Text
-  hasSubs acct = maybe True (not . null . asubs) (ledgerAccount l acct)
-  indent a = preEscapedString $ concat $ replicate (2 + 2 * a) " "
-  acctLink acct = (registerR, [("q", accountQuery acct)])
-  acctOnlyLink acct = (registerR, [("q", accountOnlyQuery acct)])
+balanceReportAsHtml (journalR, registerR) here hideEmpty j qopts (items, total) =
+  $(hamletFile "templates/balance-report.hamlet")
+  where
+    l = ledgerFromJournal Any j
+    indent a = preEscapedString $ concat $ replicate (2 + 2 * a) " "
+    hasSubAccounts acct = maybe True (not . null . asubs) (ledgerAccount l acct)
+    matchesAcctSelector acct = Just True == ((`matchesAccount` acct) <$> inAccountQuery qopts)
 
 accountQuery :: AccountName -> Text
 accountQuery = ("inacct:" <>) .  quoteIfSpaced
diff --git a/hledger-web/static/hledger.css b/hledger-web/static/hledger.css
index ec8d65c74..7864ec1b4 100644
--- a/hledger-web/static/hledger.css
+++ b/hledger-web/static/hledger.css
@@ -39,9 +39,6 @@
   max-height:300px;
 }
 
-.tt-suggestions {
-}
-
 .tt-suggestion {
   padding: 3px 20px;
   font-size: 18px;
@@ -51,7 +48,6 @@
 .tt-suggestion.tt-cursor {
   color: #fff;
   background-color: #0097cf;
-
 }
 
 .tt-suggestion p {
@@ -105,51 +101,37 @@ ul {
 
 #sidebar-menu .main-menu a {
     display: inline;
-	  font-size: 16px;
-	  font-weight: 500;
-	  color: #2F2F2F;
-	  padding: 4px 20px;
+    font-size: 16px;
+    font-weight: 500;
+    color: #2F2F2F;
+    padding: 4px 20px;
 }
 
 #sidebar-menu .main-menu a:hover {
-	  color: #11427D;
-	  text-decoration: none;
-	  background-color: transparent;
+    color: #11427D;
+    text-decoration: none;
+    background-color: transparent;
 }
 
-#sidebar-menu .main-menu .only{
+#sidebar-menu .main-menu .only {
     visibility: hidden;
     padding: 1px;
 }
 
-#sidebar-menu .main-menu tr:hover > td > div > .only {
+#sidebar-menu .main-menu tr:hover .only {
     visibility: visible;
 }
 
-#sidebar-menu .main-menu .only:hover{
-    border-left: none;
-}
-#sidebar-menu .main-menu .balance {
-    float: right;
-}
-
-#sidebar-menu .main-menu .total {
-    border-left: none;
-    border-right: none;
-    border-bottom: none;
-    border-top: 1px solid black;
-}
-
-#sidebar-menu .main-menu .inacct {
+#sidebar-menu .main-menu .inacct, #sidebar-menu .main-menu .inacct .acct-name {
     font-weight: bold;
-	  color: #11427D;
+    color: #11427D;
     background-color: #f9f9f9;
 }
 
 #sidebar-menu .main-menu .amount {
     float: right;
     overflow-x:auto;
-	  font-weight: 500 !important;
+    font-weight: 500 !important;
 }
 
 #sidebar-menu .main-menu .acct {
@@ -157,7 +139,7 @@ ul {
     vertical-align:bottom;
 }
 
-.transactionsreport .nonhead {
+.transactionsreport .posting td {
     border: none !important;
 }
 
diff --git a/hledger-web/static/hledger.js b/hledger-web/static/hledger.js
index 212ff263f..88647dae5 100644
--- a/hledger-web/static/hledger.js
+++ b/hledger-web/static/hledger.js
@@ -167,7 +167,7 @@ function addformAddPosting() {
     return;
   }
 
-  var prevLastRow = $('.amount-input:last');
+  var prevLastRow = $('#addform .account-group:last');
   prevLastRow.off('keypress');
 
   // Clone the currently last row
@@ -201,8 +201,8 @@ function addformDeletePosting() {
     || $('.amount-input:last').is(':focus');
   // delete last row
   $('#addform .account-group:last').remove();
-  if(focuslost){
-    focus($('account-input:last'));
+  if (focuslost) {
+    focus($('.account-input:last'));
   }
   // Rebind keypress
   $('.amount-input:last').keypress(addformAddPosting);
diff --git a/hledger-web/templates/add-form.hamlet b/hledger-web/templates/add-form.hamlet
index d23b3c6c3..4faa7d962 100644
--- a/hledger-web/templates/add-form.hamlet
+++ b/hledger-web/templates/add-form.hamlet
@@ -41,7 +41,7 @@ |  |