diff --git a/TriasDev.Templify.Tests/Odt/OdtContainerTests.cs b/TriasDev.Templify.Tests/Odt/OdtContainerTests.cs
new file mode 100644
index 0000000..e161f7d
--- /dev/null
+++ b/TriasDev.Templify.Tests/Odt/OdtContainerTests.cs
@@ -0,0 +1,187 @@
+// Copyright (c) 2026 TriasDev GmbH & Co. KG
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Xml.Linq;
+using TriasDev.Templify.Tests.Helpers;
+
+namespace TriasDev.Templify.Tests.Odt;
+
+///
+/// Template constructs inside nested containers (text boxes, notes, sections, nested lists, headers and
+/// footers) and the uniqueness of names and ids after loop cloning.
+///
+public sealed class OdtContainerTests
+{
+ private static readonly XNamespace _text = OdtDocumentVerifier.Text;
+ private static readonly XNamespace _table = OdtDocumentVerifier.Table;
+ private static readonly XNamespace _draw = OdtDocumentVerifier.Draw;
+
+ private static List> Items(params string[] names) =>
+ names.Select(n => new Dictionary { ["Name"] = n }).ToList();
+
+ [Fact]
+ public void LoopCloningFramesTablesSectionsAndNotes_MakesNamesUnique()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder()
+ .AddParagraph("{{#foreach Items}}")
+ .AddXml(
+ "{{Name}}in box {{Name}}" +
+ "1note {{Name}}")
+ .AddXml("{{Name}}")
+ .AddXml("section {{Name}}")
+ .AddParagraph("{{/foreach}}");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary { ["Items"] = Items("a", "b", "c") });
+
+ Assert.Equal(new[] { "Box", "Box_2", "Box_3" }, output.Body.Descendants(_draw + "frame").Select(f => (string)f.Attribute(_draw + "name")!));
+ Assert.Equal(new[] { "Prices", "Prices_2", "Prices_3" }, output.Body.Descendants(_table + "table").Select(t => (string)t.Attribute(_table + "name")!));
+ Assert.Equal(new[] { "Details", "Details_2", "Details_3" }, output.Body.Descendants(_text + "section").Select(s => (string)s.Attribute(_text + "name")!));
+ Assert.Equal(new[] { "ftn1", "ftn1_2", "ftn1_3" }, output.Body.Descendants(_text + "note").Select(n => (string)n.Attribute(_text + "id")!));
+ Assert.Single(output.Body.Descendants(), e => e.Attribute(XNamespace.Xml + "id") != null);
+
+ List texts = output.GetParagraphTexts();
+ Assert.Contains("in box b", texts);
+ Assert.Contains("note c", texts);
+ Assert.Contains("section a", texts);
+ }
+
+ [Fact]
+ public void UniqueNames_AvoidExistingNames()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder()
+ .AddXml("")
+ .AddParagraph("{{#foreach Items}}")
+ .AddXml("")
+ .AddParagraph("{{/foreach}}");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary { ["Items"] = Items("a", "b") });
+
+ Assert.Equal(new[] { "F_2", "F", "F_3" }, output.Body.Descendants(_draw + "frame").Select(f => (string)f.Attribute(_draw + "name")!));
+ }
+
+ [Fact]
+ public void FramesInHeaderAndBody_ShareOneNameSpace()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder()
+ .AddXml("")
+ .AddHeaderXml("");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary());
+
+ Assert.Equal("Logo", (string?)output.Body.Descendants(_draw + "frame").Single().Attribute(_draw + "name"));
+ Assert.Equal("Logo_2", (string?)output.StylesXml!.Descendants(_draw + "frame").Single().Attribute(_draw + "name"));
+ }
+
+ [Fact]
+ public void LoopInsideTextBox_IsExpanded()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder().AddXml(
+ "" +
+ "{{#foreach Items}}- {{Name}}{{/foreach}}" +
+ "");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary { ["Items"] = Items("a", "b") });
+
+ XElement textBox = output.Body.Descendants(_draw + "text-box").Single();
+ Assert.Equal(new[] { "- a", "- b" }, textBox.Elements(_text + "p").Select(OdtDocumentVerifier.RenderText));
+ }
+
+ [Fact]
+ public void LoopInsideFootnote_IsExpanded()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder().AddXml(
+ "Texti" +
+ "{{#foreach Items}}src {{Name}}{{/foreach}}" +
+ "");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary { ["Items"] = Items("a", "b") });
+
+ XElement noteBody = output.Body.Descendants(_text + "note-body").Single();
+ Assert.Equal(new[] { "src a", "src b" }, noteBody.Elements(_text + "p").Select(OdtDocumentVerifier.RenderText));
+ }
+
+ [Fact]
+ public void EmptyLoopInsideTextBox_LeavesEmptyParagraph()
+ {
+ OdtDocumentBuilder template = new OdtDocumentBuilder().AddXml(
+ "" +
+ "{{#foreach Items}}{{Name}}{{/foreach}}" +
+ "");
+
+ (_, OdtDocumentVerifier output) = OdtTestHelper.Process(template, new Dictionary { ["Items"] = new List