diff --git a/mo/web/org_round.py b/mo/web/org_round.py
index 8b749771c77899a3387f766d0dd8808b36a1385e..4ceccd8bfdaa46f9b96103a5344e238bb8e52ced 100644
--- a/mo/web/org_round.py
+++ b/mo/web/org_round.py
@@ -49,8 +49,12 @@ def get_task(round: db.Round, task_id: int) -> db.Task:
 def org_rounds():
     sess = db.get_session()
 
-    rounds = sess.query(db.Round).filter_by(year=mo.current_year).order_by(db.Round.year, db.Round.category, db.Round.seq)
-    return render_template('org_rounds.html', rounds=rounds, level_names=mo.db.place_level_names)
+    rounds = sess.query(db.Round).filter_by(year=mo.current_year).order_by(db.Round.year, db.Round.category, db.Round.seq, db.Round.round_id)
+    subround_counts = {round.round_id: 0 for round in rounds}
+    for round in rounds:
+        if round.is_subround():
+            subround_counts[round.master_round_id] += 1
+    return render_template('org_rounds.html', rounds=rounds, subround_counts=subround_counts, level_names=mo.db.place_level_names)
 
 
 class TaskDeleteForm(FlaskForm):
@@ -90,6 +94,42 @@ def delete_task(round_id: int, form: TaskDeleteForm) -> bool:
     return False
 
 
+class SubroundDeleteForm(FlaskForm):
+    delete_subround_id = wtforms.IntegerField()
+    delete_subround = wtforms.SubmitField('Smazat podkolo')
+
+
+def delete_subround(round_id: int, form: SubroundDeleteForm) -> bool:
+    if not (request.method == 'POST' and 'delete_subround_id' in request.form and form.validate_on_submit()):
+        return False
+
+    sess = db.get_session()
+    delete_round = sess.query(db.Round).get(form.delete_subround_id.data)
+
+    if not delete_round:
+        flash('Podkolo s daným ID neexistuje', 'danger')
+    elif delete_round.master_round_id != round_id:
+        flash('Toto není podkolo tohoto kola!', 'danger')
+    elif sess.query(db.Task).filter_by(round_id=delete_round.round_id).first() is not None:
+        flash(f'Podkolo {delete_task.name} nelze smazat, existují úlohy na něj vázané', 'danger')
+    else:
+        # Smažeme všechny vytvořené podsoutěže, bez úloh by na ně nemělo být nic navázané
+        sess.query(db.Contest).filter_by(round_id=delete_round.round_id).delete()
+
+        sess.delete(delete_round)
+        mo.util.log(
+            type=db.LogType.round,
+            what=delete_round.round_id,
+            details={'action': 'delete', 'round': db.row2dict(delete_round)},
+        )
+        app.logger.info(f"Podkolo {delete_round.round_id} kola {round_id} smazáno: {db.row2dict(delete_round)}")
+        sess.commit()
+        flash('Podkolo úspěšně smazáno', 'success')
+        return True
+
+    return False
+
+
 class AddContestForm(FlaskForm):
     place_code = wtforms.StringField('Nová soutěž v oblasti:', validators=[validators.Required()])
     create_contest = wtforms.SubmitField('Založit')
@@ -121,12 +161,25 @@ def add_contest(round: db.Round, form: AddContestForm) -> bool:
 
     sess.add(contest)
     sess.flush()
+    contest.master_contest_id = contest.contest_id
+    sess.add(contest)
+    sess.flush()
 
     mo.util.log(
         type=db.LogType.contest,
         what=contest.contest_id,
         details={'action': 'add', 'contest': db.row2dict(contest)},
     )
+
+    # Přidání soutěže do všech podkol
+    subrounds = sess.query(db.Round).filter_by(master=round).all()
+    for subround in subrounds:
+        sess.add(db.Contest(
+            round_id=subround.round_id,
+            master_contest_id=contest.contest_id,
+            place_id=contest.place_id,
+        ))
+
     app.logger.info(f"Soutěž #{contest.contest_id} založena: {db.row2dict(contest)}")
     sess.commit()
 
@@ -134,11 +187,65 @@ def add_contest(round: db.Round, form: AddContestForm) -> bool:
     return True
 
 
+class AddSubroundForm(FlaskForm):
+    name = wtforms.StringField('Název podkola:', validators=[validators.Required()])
+    create_subround = wtforms.SubmitField('Založit')
+
+
+def add_subround(round: db.Round, form: AddSubroundForm) -> bool:
+    if not (request.method == 'POST' and 'create_subround' in request.form and form.validate_on_submit()):
+        return False
+
+    subround = db.Round(
+        master_round_id=round.round_id,
+        year=round.year,
+        category=round.category,
+        seq=round.seq,
+        level=round.level,
+        name=form.name.data,
+        state=db.RoundState.preparing,
+    )
+
+    sess = db.get_session()
+    sess.add(subround)
+    sess.flush()
+    mo.util.log(
+        type=db.LogType.round,
+        what=subround.round_id,
+        details={'action': 'add', 'round': db.row2dict(subround)},
+    )
+
+    # Založíme podsoutěže kopií soutěží z hlavního kola
+    contests = sess.query(db.Contest).filter_by(round_id=round.round_id).all()
+    for contest in contests:
+        sess.add(db.Contest(
+            round_id=subround.round_id,
+            master_contest_id=contest.contest_id,
+            place_id=contest.place_id,
+        ))
+
+    app.logger.info(f"Kolo #{subround.round_id} založeno jako podkolo {round.round_id}: {db.row2dict(subround)}")
+    sess.commit()
+
+    flash('Podkolo založeno', 'success')
+    return True
+
+
 @app.route('/org/contest/r/<int:id>/', methods=('GET', 'POST'))
 def org_round(id: int):
     sess = db.get_session()
     round, rr = get_round_rr(id, None, True)
 
+    tasks_counts = sess.query(
+        db.Task.round_id, func.count(db.Task.round_id).label('count')
+    ).group_by(db.Task.round_id).subquery()
+    print(tasks_counts)
+    subrounds = sess.query(
+        db.Round, coalesce(tasks_counts.c.count, 0)
+    ).outerjoin(
+        tasks_counts, tasks_counts.c.round_id == db.Round.round_id
+    ).filter(db.Round.master == round).all()
+
     can_manage_round = rr.have_right(Right.manage_round)
     can_manage_contestants = rr.have_right(Right.manage_contest)
 
@@ -150,7 +257,7 @@ def org_round(id: int):
     contests_counts = (sess.query(
                     db.Contest,
                     coalesce(participants_count.c.count, 0)
-                ).outerjoin(participants_count)
+                ).outerjoin(participants_count, db.Contest.master_contest_id == participants_count.c.contest_id)
                 .filter(db.Contest.round == round)
                 .options(joinedload(db.Contest.place))
                 .all())
@@ -177,17 +284,33 @@ def org_round(id: int):
     if can_manage_round and delete_task(id, form_delete_task):
         return redirect(url_for('org_round', id=id))
 
-    form_add_contest = AddContestForm()
-    if add_contest(round, form_add_contest):
-        return redirect(url_for('org_round', id=id))
+    form_delete_subround: Optional[SubroundDeleteForm] = None
+    form_add_contest: Optional[AddContestForm] = None
+    form_add_subround: Optional[AddSubroundForm] = None
+    if not round.is_subround():
+        # V podkole zakazujeme operace s dalšími podkoly nebo s contesty
+
+        form_delete_subround = SubroundDeleteForm()
+        if can_manage_round and delete_subround(id, form_delete_subround):
+            return redirect(url_for('org_round', id=id))
+
+        form_add_contest = AddContestForm()
+        if add_contest(round, form_add_contest):
+            return redirect(url_for('org_round', id=id))
+
+        form_add_subround = AddSubroundForm()
+        if can_manage_round and add_subround(round, form_add_subround):
+            return redirect(url_for('org_round', id=id))
 
     return render_template(
         'org_round.html',
-        round=round,
+        round=round, subrounds=subrounds,
         roles=[r.friendly_name() for r in rr.get_roles()],
         contests_counts=contests_counts,
         tasks=tasks, form_delete_task=form_delete_task,
         form_add_contest=form_add_contest,
+        form_add_subround=form_add_subround,
+        form_delete_subround=form_delete_subround,
         level_names=mo.db.place_level_names,
         can_manage_round=can_manage_round,
         can_manage_contestants=can_manage_contestants,
@@ -357,7 +480,8 @@ class MODateTimeField(wtforms.DateTimeField):
             self.data = self.data.astimezone()
 
 
-class RoundEditForm(FlaskForm):
+class SubroundEditForm(FlaskForm):
+    name = wtforms.StringField("Název")
     state = wtforms.SelectField("Stav kola", choices=db.RoundState.choices(), coerce=db.RoundState.coerce)
     # Only the desktop Firefox does not support datetime-local field nowadays,
     # other browsers does provide date and time picker UI :(
@@ -366,6 +490,12 @@ class RoundEditForm(FlaskForm):
     pr_tasks_start = MODateTimeField("Čas zveřejnění úloh pro dozor", validators=[validators.Optional()])
     ct_submit_end = MODateTimeField("Konec odevzdávání pro účastníky", validators=[validators.Optional()])
     pr_submit_end = MODateTimeField("Konec odevzdávání pro dozor", validators=[validators.Optional()])
+
+    submit = wtforms.SubmitField('Uložit')
+
+
+class RoundEditForm(SubroundEditForm):
+    # SubroundEditForm + ...
     score_mode = wtforms.SelectField("Výsledková listina", choices=db.RoundScoreMode.choices(), coerce=db.RoundScoreMode.coerce)
     score_winner_limit = IntegerField(
         "Hranice bodů pro vítěze", validators=[validators.Optional()],
@@ -383,7 +513,11 @@ def org_round_edit(id: int):
     sess = db.get_session()
     round, rr = get_round_rr(id, Right.manage_round, True)
 
-    form = RoundEditForm(obj=round)
+    if round.is_subround():
+        form = SubroundEditForm(obj=round)
+    else:
+        form = RoundEditForm(obj=round)
+
     if form.validate_on_submit():
         form.populate_obj(round)
 
diff --git a/mo/web/templates/org_round.html b/mo/web/templates/org_round.html
index f7b53848f33b9c106bb9d3876358288c51afb2b0..29dae766b25bbd0e908ce415766c740c48fda580 100644
--- a/mo/web/templates/org_round.html
+++ b/mo/web/templates/org_round.html
@@ -1,7 +1,7 @@
 {% extends "base.html" %}
 {% import "bootstrap/wtf.html" as wtf %}
 
-{% block title %}{{ round.name }} {{ round.round_code() }}{% endblock %}
+{% block title %}{{ round.master.name }} {{ round.master.round_code() }}{% if round.is_subround() %} (podkolo {{ round.name }}){% endif %}{% endblock %}
 {% block breadcrumbs %}
 {{ contest_breadcrumbs(round=round) }}
 {% endblock %}
@@ -12,10 +12,14 @@
 	<tr><td>Ročník<td>{{ round.year }}
 	<tr><td>Kategorie<td>{{ round.category }}
 	<tr><td>Pořadí<td>{{ round.seq }}
-	<tr><td>Název<td>{{ round.name }}
 	<tr><td>Oblast<td>{{ level_names[round.level] }}
-	<tr><td>Stav<td class='rstate-{{round.state.name}}'>{{ round.state.friendly_name() }}
 	<tr><td>Vaše role<td>{% if roles %}{{ roles|join(", ") }}{% else %}–{% endif %}
+	{% if round.is_subround() %}
+	<tr><td>Nadřazené kolo:<td><a href="{{ url_for('org_round', id=round.master_round_id) }}">{{ round.master.name }} {{ round.master.round_code() }} </a>
+	{% endif %}
+	<tr><th colspan=2><h4>Nastavení kola:</h4>
+	<tr><td>Název<td>{{ round.name }}
+	<tr><td>Stav<td class='rstate-{{round.state.name}}'>{{ round.state.friendly_name() }}
 	<tr><td>Účastníci vidí zadání od<td>{{ round.ct_tasks_start|timeformat }}
 	<tr><td>Účastníci odevzdávají do<td>{{ round.ct_submit_end|timeformat }}
 	<tr><td>Dozor vidí zadání od<td>{{ round.pr_tasks_start|timeformat }}
@@ -30,12 +34,20 @@
 {% else %}
 	–
 {% endif %}
+	{% if not round.is_subround() %}
 	<tr><td>Výsledková listina<td>{{ round.score_mode.friendly_name() }}
 	<tr><td>Hranice bodů pro vítěze<td>{{ round.score_winner_limit|none_value(Markup('<i>nenastaveno</i>')) }}
 	<tr><td>Hranice bodů pro úspěšné řešitele<td>{{ round.score_successful_limit|none_value(Markup('<i>nenastaveno</i>')) }}
+	{% endif %}
 </table>
 
 <div class="btn-group">
+{% if round.is_subround() %}
+	<a class="btn btn-primary" href='{{ url_for('org_round_list', id=round.master_round_id) }}'>Seznam účastníků nadřazeného kola</a>
+	{% if round.master.state in [RoundState.grading, RoundState.closed] %}
+	<a class="btn btn-primary" href='{{ url_for('org_score', round_id=round.master_round_id) }}'>Výsledky nadřazeného kola</a>
+	{% endif %}
+{% else %}
 	<a class="btn btn-primary" href='{{ url_for('org_round_list', id=round.round_id) }}'>Seznam účastníků</a>
 	{% if round.state in [RoundState.grading, RoundState.closed] %}
 	<a class="btn btn-primary" href='{{ url_for('org_score', round_id=round.round_id) }}'>Výsledky</a>
@@ -43,6 +55,7 @@
 	{% if can_manage_contestants %}
 	<a class="btn btn-default" href='{{ url_for('org_round_import', id=round.round_id) }}'>Importovat data</a>
 	{% endif %}
+{% endif %}
 	{% if can_manage_round %}
 	<a class="btn btn-default" href='{{ url_for('org_round_edit', id=round.round_id) }}'>Editovat nastavení kola</a>
 	{% endif %}
@@ -50,8 +63,71 @@
 	<a class="btn btn-default" href='{{ log_url('round', round.round_id) }}'>Historie</a>
 	{% endif %}
 </div>
+<br><br>
 
+{% if not round.is_subround() %}
+<div class="box-frame">
+<h3>Podkola</h3>
+{% if subrounds and subrounds|length > 1 %}
+<table class=data>
+	<thead>
+		<tr>
+			<th rowspan=2>Podkolo
+			<th rowspan=2>Počet úloh
+			<th rowspan=2>Stav
+			<th colspan=2>Účastníci
+			<th colspan=2>Dozor
+			<th rowspan=2>Akce
+		<tr>
+			<th>Zadání od
+			<th>Odevzdávání do
+			<th>Zadání od
+			<th>Odevzdávání do
+	</thead>
+	{% for (subround, tasks_count) in subrounds %}
+	<tr>
+		<td>{% if subround == round %}
+			<b>Toto kolo: {{ subround.name }}</b>
+		{% else %}
+			<a href="{{ url_for('org_round', id=subround.round_id) }}">{{ subround.name }}</a>
+		{% endif %}
+		<td>{{ tasks_count }}
+		<td class='rstate-{{subround.state.name}}'>{{ subround.state.friendly_name() }}
+		<td>{{ subround.ct_tasks_start|timeformat }}
+		<td>{{ subround.ct_submit_end|timeformat }}
+		<td>{{ subround.pr_tasks_start|timeformat }}
+		<td>{{ subround.pr_submit_end|timeformat }}
+		<td><div class="btn-group">
+		{% if subround != round %}
+			<a class="btn btn-xs btn-primary" href="{{ url_for('org_round', id=subround.round_id) }}">Detail</a>
+			{% if can_manage_round and tasks_count == 0 %}
+			<form action="" method="POST" onsubmit="return confirm('Opravdu nenávratně smazat?')" class="btn-group">
+				{{ form_delete_subround.csrf_token() }}
+				<input type="hidden" name="delete_subround_id" value="{{ subround.round_id }}">
+				<button type="submit" class="btn btn-xs btn-danger">Smazat podkolo</button>
+			</form>
+			{% endif %}
+		{% endif %}
+		</div>
+	{% endfor %}
+</table>
+{% else %}
+<p><i>Žádná podkola nebyla založena, vše se koná pod hlavním kolem.</i></p>
+{% endif %}
+
+{% if can_manage_round %}
+<form action="" method="POST" class="form-inline">
+	{{ form_add_subround.csrf_token() }}
+	{{ wtf.form_field(form_add_subround.name) }}
+	{{ wtf.form_field(form_add_subround.create_subround) }}
+</form>
+{% endif %}
+</div>
+{% endif %}
+
+<div class="box-frame">
 <h3>Soutěže</h3>
+{% if round.is_subround() %}<p><i>Soutěže jsou synchronizovány s nadřazeným kolem.</i></p>{% endif %}
 {% if contests_counts %}
 <table class=data>
 	<thead>
@@ -76,14 +152,16 @@
 <p>Zatím nebyly založeny v žádné oblasti.
 {% endif %}
 
-{% if can_add_contest %}
+{% if not round.is_subround() and can_add_contest %}
 <form action="" method="POST" class="form-inline">
 	{{ form_add_contest.csrf_token() }}
 	{{ wtf.form_field(form_add_contest.place_code) }}
 	{{ wtf.form_field(form_add_contest.create_contest) }}
 </form>
 {% endif %}
+</div>
 
+<div class="box-frame">
 <h3>Úlohy</h3>
 {% if tasks %}
 <table class=data>
@@ -117,7 +195,7 @@
 			</div>
 			{% endif %}
 			{% if can_handle_submits or can_upload %}
-			<td><dic class="btn-group">
+			<td><div class="btn-group">
 				{% if can_handle_submits %}
 					<a class="btn btn-xs btn-primary" href="{{ url_for('org_round_task_download', round_id=round.round_id, task_id=task.task_id) }}">Stáhnout ZIP</a>
 				{% endif %}
@@ -138,5 +216,6 @@
 {% if can_manage_round %}
 <a class="btn btn-primary right-float" href="{{ url_for('org_round_task_new', id=round.round_id) }}">Nová úloha</a>
 {% endif %}
+</div>
 
 {% endblock %}
diff --git a/static/mo.css b/static/mo.css
index c90f0243777b1901eae4212b67a6ceb0045ee9b9..0846ee92b9d3f70d7dc66649801bfa3c0ffbc3b2 100644
--- a/static/mo.css
+++ b/static/mo.css
@@ -171,12 +171,19 @@ nav#main-menu a.active {
 	color:red;
 }
 
-.form-frame {
+.form-frame, .box-frame {
 	padding: 10px;
 	border: 1px #ddd solid;
 	border-radius: 4px 4px;
 }
 
+.box-frame {
+	margin: 10px 0px;
+}
+.box-frame > h3 {
+	margin-top: 5px;
+}
+
 .checked_toggle input.toggle:checked ~ .checked_hide {
 	display: none;
 }