diff --git a/helios/templates/election_not_started.html b/helios/templates/election_not_started.html
new file mode 100644
index 0000000000000000000000000000000000000000..22eec6cba18ac1bb0f9781a5a4f572194fd6c03c
--- /dev/null
+++ b/helios/templates/election_not_started.html
@@ -0,0 +1,14 @@
+{% extends TEMPLATE_BASE %}
+
+{% block content %}
+
+  <h2 class="title">Election {{election.name}} Not Yet Open</h2>
+
+  <p>
+      This election is not yet open. You probably got here from the Ballot Preview.
+  </p>
+  
+  <p>
+      <a href="{% url helios.views.one_election_view election.uuid %}">back to the election</a>
+  </p>
+{% endblock %}
diff --git a/helios/templates/election_view.html b/helios/templates/election_view.html
index 288029fbbdacd81e01c27db5601f5befb87ff971..0e783535e0e0a3a5958496dcf2ce49da386d34de 100644
--- a/helios/templates/election_view.html
+++ b/helios/templates/election_view.html
@@ -265,14 +265,14 @@ Anyone can vote in this election.
 <a href="{% url helios.views.one_election_audited_ballots election.uuid %}">Audited Ballots</a>
 </p>
 
+{% endif %}
+
 {% if not election.voting_has_started %}
 <p style="font-size: 1.2em;">
   <a href="{{SECURE_URL_HOST}/booth/vote.html?election_url={% url helios.views.one_election election.uuid %}">preview booth</a>
 </p>
 {% endif %}  
 
-{% endif %}
-
 {% if election.voting_has_stopped %}
 <p style="font-size: 1.2em;">
 {% if election.result %}
diff --git a/helios/views.py b/helios/views.py
index 80df7696a7a0440655f165f736c6dcb063509704..40da9a1286624c89c4e7fb775fa5fb7af01080f7 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -522,7 +522,8 @@ def post_audited_ballot(request, election):
     return SUCCESS
     
 
-@election_view(frozen=True)
+# we don't require frozen election to allow for ballot preview
+@election_view()
 def one_election_cast(request, election):
   """
   on a GET, this is a cancellation, on a POST it's a cast
@@ -593,7 +594,7 @@ def password_voter_login(request, election):
   
   return HttpResponseRedirect(settings.SECURE_URL_HOST + return_url)
 
-@election_view(frozen=True)
+@election_view()
 def one_election_cast_confirm(request, election):
   user = get_user(request)    
 
@@ -601,6 +602,10 @@ def one_election_cast_confirm(request, election):
   if not request.session.has_key('encrypted_vote'):
     return HttpResponseRedirect(settings.URL_HOST)
 
+  # election not frozen or started
+  if not election.voting_has_started():
+    return render_template(request, 'election_not_started', {'election': election})
+
   voter = get_voter(request, user, election)
 
   # auto-register this person if the election is openreg
diff --git a/heliosbooth/templates/seal.html b/heliosbooth/templates/seal.html
index cdf4f2ad95f338a3a73dd44cf09ee3b270e3f15e..5070e0c52b9394d1be11ee0bbf85f56c7161dc9b 100644
--- a/heliosbooth/templates/seal.html
+++ b/heliosbooth/templates/seal.html
@@ -18,7 +18,7 @@ You will then be guided to re-encrypt your choices for final casting.
 <h3>Your ballot is ready to be submitted</h3>
 
 <p>
-<em>Don't forget to click "Proceed to Cast" below!</em>
+<em>Don't forget to click "Proceed to Submission" below!</em>
 </p>
 
 <p>Please <b><u>keep a record</u></b> of your smart ballot tracker [<a onclick="BOOTH.show_receipt(); return false;" href="#">print</a>]:<br /><br />