diff --git a/Changes b/Changes
index 80a5ed3..a5366f3 100644
--- a/Changes
+++ b/Changes
@@ -1,11 +1,13 @@
-0.65.1 2026-06-10
+0.65.1 2026-06-16
     - [feature] Prevent indexation of documents without
       a token stream (diewald; AI-assisted Claude Opus 4.6)
     - [bugfix] Fix "force" in commit method
       (diewald; AI-assisted Claude Opus 4.6)
     - [tool] Add standalone MetaExporter tool
       (kupietz; AI-assistend Claude Opus 4.8)
-
+    - [bugfix] Fix cross-doc leakage in nested WithinSpans
+      (diewald; AI-assisted Claude Opus 4.6)
+      
 0.65 2026-05-12
     - [bugfix] Keep highlights that extend beyond a cut match
       (diewald; fixes #177; AI-assisted Claude Opus 4.6)
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/WithinSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/WithinSpans.java
index fe507d9..bfdfefa 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/WithinSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/WithinSpans.java
@@ -204,17 +204,31 @@
                     log.trace("In the next embedded branch");
 
                 WithinSpan current = null;
+                WithinSpan candidate;
 
-                // New - fetch until theres a span in the correct doc or bigger
+                // Skip stale entries, stop at future documents
                 while (!this.spanStore2.isEmpty()) {
-                    current = spanStore2.removeFirst();
-                    if (current.doc >= this.wrapDoc)
+                    candidate = spanStore2.peekFirst();
+                    if (candidate.doc < this.wrapDoc) {
+                        spanStore2.removeFirst();
+                    }
+                    else if (candidate.doc == this.wrapDoc) {
+                        current = spanStore2.removeFirst();
                         break;
-                };
+                    }
+                    else {
+                        break;
+                    }
+                }
 
-
-                // There is nothing in the second store
                 if (current == null) {
+
+                    // Future-doc entries remain: advance wrap instead
+                    if (!this.spanStore2.isEmpty()) {
+                        this.nextSpanA();
+                        continue;
+                    }
+
                     if (DEBUG)
                         log.trace("SpanStore 2 is empty");
 
@@ -626,32 +640,49 @@
             log.trace("skipTo document {}/{} -> {}", this.embeddedDoc,
                     this.wrapDoc, target);
 
-        // Initialize spans
         if (!this.init())
             return false;
 
-        assert target > this.embeddedDoc;
+        // Already at or past target: just find next match
+        if (this.matchDoc >= target)
+            return this.next() && this.matchDoc >= target;
 
-        // Only forward embedded spans
-        if (this.more && (this.embeddedDoc < target)) {
-            if (this.embeddedSpans.skipTo(target)) {
-                this.inSameDoc = false;
-                this.embeddedStart = -1;
-                this.embeddedEnd = -1;
-                this.embeddedPayload = null;
-                this.embeddedDoc = this.embeddedSpans.doc();
-            }
+        // Fast-forward operands when both are behind target
+        if (this.embeddedDoc >= 0 && this.wrapDoc < target
+                && this.embeddedDoc < target) {
 
-            // Can't be skipped to target
-            else {
-                this.inSameDoc = false;
-                this.more = false;
+            if (!this.wrapSpans.skipTo(target))
                 return false;
-            };
-        };
+            this.wrapDoc = this.wrapSpans.doc();
+            if (this.wrapDoc == DocIdSetIterator.NO_MORE_DOCS)
+                return false;
 
-        // Move to same doc
-        return this.toSameDoc();
+            if (!this.embeddedSpans.skipTo(this.wrapDoc))
+                return false;
+            this.embeddedDoc = this.embeddedSpans.doc();
+            if (this.embeddedDoc == DocIdSetIterator.NO_MORE_DOCS)
+                return false;
+
+            // Reset internal state after skip
+            this.spanStore1.clear();
+            this.spanStore2.clear();
+            this.wrapStart = this.wrapSpans.start();
+            this.embeddedStart = this.embeddedSpans.start();
+            this.wrapEnd = -1;
+            this.embeddedEnd = -1;
+            this.embeddedPayload = null;
+            this.inSameDoc = (this.wrapDoc == this.embeddedDoc);
+            this.more = true;
+            this.tryMatch = true;
+            this.nextSpanB = true;
+        }
+
+        while (true) {
+            if (!this.next())
+                return false;
+            if (this.matchDoc >= target)
+                return true;
+        }
     };
 
 
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestWithinIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestWithinIndex.java
index b7c2416..0f18b1b 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestWithinIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestWithinIndex.java
@@ -3,27 +3,46 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.*;
 import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeSet;
+
 import static de.ids_mannheim.korap.TestSimple.*;
 
 import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.Spans;
 import org.apache.lucene.search.spans.SpanTermQuery;
+import org.apache.lucene.util.Bits;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import de.ids_mannheim.korap.Krill;
+import de.ids_mannheim.korap.KrillCollection;
 import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.collection.CollectionBuilder;
 import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.query.SpanClassQuery;
 import de.ids_mannheim.korap.query.SpanElementQuery;
+import de.ids_mannheim.korap.query.SpanFocusQuery;
 import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 import de.ids_mannheim.korap.query.SpanNextQuery;
 import de.ids_mannheim.korap.query.SpanWithinQuery;
 import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import de.ids_mannheim.korap.response.Match;
 import de.ids_mannheim.korap.response.Result;
 import de.ids_mannheim.korap.util.QueryException;
 
@@ -1169,4 +1188,890 @@
         Result kr = ki.search(sq, (short) 1);
         assertEquals(1, kr.getTotalResults());
     }
+
+
+    // Build one "tokens" FieldDocument from sentence token arrays.
+    // Each input array is one sentence, e.g. ["b","a","w2"].
+    // Example doc: [["b","a","w2"],["a","w4","w5"]].
+    private FieldDocument multiSentenceDoc (String[]... sentences) {
+        FieldDocument fd = new FieldDocument();
+
+        int total = 0;
+        for (String[] s : sentences) total += s.length;
+
+        StringBuilder surface = new StringBuilder();
+        StringBuilder tv = new StringBuilder();
+
+        int tokIdx = 0;
+        int charOff = 0;
+        int sentStart = 0;
+
+        for (int si = 0; si < sentences.length; si++) {
+            String[] sent = sentences[si];
+            int sentEnd = sentStart + sent.length;
+
+            for (int ti = 0; ti < sent.length; ti++) {
+                String tok = sent[ti];
+                int cStart = charOff;
+                int cEnd = charOff + tok.length();
+
+                surface.append(tok);
+
+                tv.append("[(").append(cStart).append("-").append(cEnd)
+                        .append(")");
+                tv.append("s:").append(tok);
+
+                if (tokIdx == 0) {
+                    int totalChars = 0;
+                    for (String[] s : sentences)
+                        for (String t : s)
+                            totalChars += t.length();
+                    tv.append("|-:t$<i>").append(total);
+                    tv.append("|<>:base/s:t$<b>64<i>0<i>")
+                            .append(totalChars).append("<i>")
+                            .append(total).append("<b>0");
+                }
+                if (ti == 0) {
+                    int sentCharEnd = cStart;
+                    for (String t : sent) sentCharEnd += t.length();
+                    tv.append("|<>:base/s:s$<b>64<i>")
+                            .append(cStart).append("<i>")
+                            .append(sentCharEnd).append("<i>")
+                            .append(sentEnd).append("<b>1");
+                }
+
+                tv.append("|_").append(tokIdx).append("$<i>")
+                        .append(cStart).append("<i>").append(cEnd);
+                tv.append("]");
+
+                charOff = cEnd;
+                tokIdx++;
+            }
+            sentStart = sentEnd;
+        }
+
+        fd.addTV("tokens", surface.toString(), tv.toString());
+        return fd;
+    }
+
+    // focus(1: contains(contains(<s>, {1: s:a}), {2: s:b}))
+    private SpanQuery nestedContainsDiffClassQuery () {
+        SpanQuery sentence = new SpanElementQuery("tokens", "base/s:s");
+        SpanQuery tokenA = new SpanClassQuery(
+                new SpanTermQuery(new Term("tokens", "s:a")), (byte) 1);
+        SpanQuery tokenB = new SpanClassQuery(
+                new SpanTermQuery(new Term("tokens", "s:b")), (byte) 2);
+        SpanQuery innerContains = new SpanWithinQuery(sentence, tokenA);
+        SpanQuery outerContains = new SpanWithinQuery(innerContains, tokenB);
+        SpanFocusQuery focus = new SpanFocusQuery(outerContains, (byte) 1);
+        focus.setSorted(false);
+        return focus;
+    }
+
+    /**
+     * Two docs in one segment where doc 1 has b in a separate sentence.
+     * The fix prevents b from leaking into doc 0's a-only sentence.
+     */
+    @Test
+    public void testNestedContainsSameSegmentCrossDocLeakage ()
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+
+        // Doc 0: S0 has b+a, S1 has a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "b", "a", "w2" },
+                new String[] { "a", "w4", "w5" }));
+
+        // Doc 1: S0 has a only, S1 has b only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2" },
+                new String[] { "b", "w4", "w5" }));
+
+        ki.commit();
+
+        Result kr = ki.search(nestedContainsDiffClassQuery(), (short) 50);
+        assertEquals("Only Doc 0 S0 has both a+b, expect 1 match",
+                1, kr.getTotalResults());
+        assertEquals(1, kr.getMatch(0).getStartPos());
+        assertEquals(2, kr.getMatch(0).getEndPos());
+        ki.close();
+    }
+
+    /**
+     * Same data as above but each doc in its own segment.
+     * Verifies no cross-doc leak with separate segments.
+     */
+    @Test
+    public void testNestedContainsSeparateSegmentsNoLeakage ()
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+
+        // Doc 0: S0 has b+a, S1 has a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "b", "a", "w2" },
+                new String[] { "a", "w4", "w5" }));
+        ki.commit();
+
+        // Doc 1: S0 has a only, S1 has b only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2" },
+                new String[] { "b", "w4", "w5" }));
+        ki.commit();
+
+        Result kr = ki.search(nestedContainsDiffClassQuery(), (short) 50);
+        assertEquals("Separate segments: expect 1 match",
+                1, kr.getTotalResults());
+        assertEquals(1, kr.getMatch(0).getStartPos());
+        assertEquals(2, kr.getMatch(0).getEndPos());
+        ki.close();
+    }
+
+    /**
+     * Multiple a-only docs then one doc with both a+b in same segment.
+     * B from last doc must not leak into earlier docs.
+     */
+    @Test
+    public void testNestedContainsManyAOnlyDocsThenBoth ()
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+
+        // Doc 0: single sentence with a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2" }));
+        // Doc 1: single sentence with a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "w0", "a", "w2" }));
+        // Doc 2: single sentence with a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2" }));
+        // Doc 3: single sentence with both a and b.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "b", "w2" }));
+
+        ki.commit();
+
+        Result kr = ki.search(nestedContainsDiffClassQuery(), (short) 50);
+        assertEquals("Only Doc 3 has both, expect 1 match",
+                1, kr.getTotalResults());
+        assertEquals(0, kr.getMatch(0).getStartPos());
+        assertEquals(1, kr.getMatch(0).getEndPos());
+        ki.close();
+    }
+
+    /**
+     * Multi-sentence a-only doc then doc with a+b in one sentence.
+     * Tests scenario from fuzz seed 125901200207375.
+     */
+    @Test
+    public void testNestedContainsMultiSentenceAOnlyThenBoth ()
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+
+        // Doc 0: two sentences, both are a only.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "w0", "w1", "a", "w3", "w4" },
+                new String[] { "w5", "a", "w7", "w8", "w9" }));
+
+        // Doc 1: one sentence with both a and b.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2", "b", "w4" }));
+
+        ki.commit();
+
+        Result kr = ki.search(nestedContainsDiffClassQuery(), (short) 50);
+        assertEquals("Only Doc 1 has both a+b, expect 1 match",
+                1, kr.getTotalResults());
+        assertEquals(0, kr.getMatch(0).getStartPos());
+        assertEquals(1, kr.getMatch(0).getEndPos());
+        ki.close();
+    }
+
+    // Regression: skipTo() must also work before first next().
+    @Test
+    public void testWithinSkipToBeforeNextInitializesSpans ()
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+
+        // One local doc with a single sentence that contains token a.
+        ki.addDoc(multiSentenceDoc(
+                new String[] { "a", "w1", "w2" }));
+        ki.commit();
+
+        SpanQuery sq = new SpanWithinQuery(
+                new SpanElementQuery("tokens", "base/s:s"),
+                new SpanTermQuery(new Term("tokens", "s:a")));
+
+        Map<Term, TermContext> termContexts = new HashMap<>();
+        for (LeafReaderContext atomic : ki.reader().leaves()) {
+            Bits bitset = atomic.reader().getLiveDocs();
+            Spans spans = sq.getSpans(atomic, bitset, termContexts);
+            assertTrue("skipTo() before next() must initialize spans",
+                    spans.skipTo(0));
+            assertEquals(0, spans.doc());
+            assertEquals(0, spans.start());
+            assertEquals(3, spans.end());
+        }
+
+        ki.close();
+    }
+
+    // ----------------------------------------------------------------------
+    // Fuzzing tests for nested contains + focus
+    //
+    // Call with:
+    // $ mvn test -Dtest="TestWithinIndex" -Dfuzz.iterations=200 -pl .
+    // ----------------------------------------------------------------------
+
+    // Read iteration count; default 0 keeps fuzz tests disabled.
+    private static int getFuzzIterations () {
+        String prop = System.getProperty("fuzz.iterations");
+        if (prop != null) return Integer.parseInt(prop);
+        return 0;
+    }
+
+    // Read optional seed; default uses current nano time.
+    private static long getFuzzBaseSeed () {
+        String prop = System.getProperty("fuzz.seed");
+        if (prop != null) return Long.parseLong(prop);
+        return System.nanoTime();
+    }
+
+    enum BiasStrategy {
+        UNIFORM,
+        HEAVY_A_RARE_B,
+        ALTERNATING,
+        CLUSTER,
+        DENSE
+    }
+
+    static class SentenceInfo {
+        final int startPos;
+        final int endPos;
+        final List<Integer> aPositions;
+        final List<Integer> bPositions;
+
+        SentenceInfo (int startPos, int endPos,
+                List<Integer> aPositions, List<Integer> bPositions) {
+            this.startPos = startPos;
+            this.endPos = endPos;
+            this.aPositions = aPositions;
+            this.bPositions = bPositions;
+        }
+
+        boolean hasA () { return !aPositions.isEmpty(); }
+        boolean hasB () { return !bPositions.isEmpty(); }
+        boolean hasBoth () { return hasA() && hasB(); }
+    }
+
+    static class DocInfo {
+        final String textSigle;
+        final String genre;
+        final List<SentenceInfo> sentences;
+
+        DocInfo (String textSigle, String genre,
+                List<SentenceInfo> sentences) {
+            this.textSigle = textSigle;
+            this.genre = genre;
+            this.sentences = sentences;
+        }
+    }
+
+    static class IndexConfig {
+        final List<DocInfo> docs;
+        final int[] commitAfterDoc;
+        final long seed;
+        final BiasStrategy strategy;
+
+        IndexConfig (List<DocInfo> docs, int[] commitAfterDoc,
+                long seed, BiasStrategy strategy) {
+            this.docs = docs;
+            this.commitAfterDoc = commitAfterDoc;
+            this.seed = seed;
+            this.strategy = strategy;
+        }
+    }
+
+    // Generate one random fuzz corpus with a random bias strategy.
+    private IndexConfig generateFuzzConfig (long seed) {
+        Random rng = new Random(seed);
+        BiasStrategy[] strategies = BiasStrategy.values();
+        BiasStrategy strategy = strategies[rng.nextInt(strategies.length)];
+        return generateFuzzConfig(seed, rng, strategy);
+    }
+
+    // Generate one random fuzz corpus using a fixed strategy.
+    private IndexConfig generateFuzzConfig (long seed, Random rng,
+            BiasStrategy strategy) {
+        int numDocs = 1 + rng.nextInt(5);
+        List<DocInfo> docs = new ArrayList<>();
+
+        for (int d = 0; d < numDocs; d++) {
+            int numSentences = 2 + rng.nextInt(14);
+            List<SentenceInfo> sentences = new ArrayList<>();
+            int docTokenPos = 0;
+
+            for (int s = 0; s < numSentences; s++) {
+                int sentLen = decideSentenceLength(rng, strategy);
+                int sentStart = docTokenPos;
+                int sentEnd = docTokenPos + sentLen;
+
+                boolean placeA = decidePlaceA(rng, strategy, s, numSentences);
+                boolean placeB = decidePlaceB(rng, strategy, s, numSentences);
+
+                int numA = placeA ? (1 + rng.nextInt(
+                        strategy == BiasStrategy.DENSE ? 3 : 2)) : 0;
+                int numB = placeB ? (1 + rng.nextInt(
+                        strategy == BiasStrategy.DENSE ? 3 : 2)) : 0;
+                numA = Math.min(numA, sentLen / 2);
+                numB = Math.min(numB, Math.max(0, sentLen - numA));
+
+                Set<Integer> usedOffsets = new HashSet<>();
+                List<Integer> aPositions = new ArrayList<>();
+                List<Integer> bPositions = new ArrayList<>();
+
+                for (int i = 0; i < numA; i++) {
+                    int off = pickUnusedOffset(rng, sentLen, usedOffsets);
+                    if (off >= 0) {
+                        usedOffsets.add(off);
+                        aPositions.add(sentStart + off);
+                    }
+                }
+                for (int i = 0; i < numB; i++) {
+                    int off = pickUnusedOffset(rng, sentLen, usedOffsets);
+                    if (off >= 0) {
+                        usedOffsets.add(off);
+                        bPositions.add(sentStart + off);
+                    }
+                }
+
+                sentences.add(new SentenceInfo(sentStart, sentEnd,
+                        aPositions, bPositions));
+                docTokenPos = sentEnd;
+            }
+
+            String genre = (d % 3 == 0) ? "science"
+                    : (d % 3 == 1) ? "fiction" : "news";
+            docs.add(new DocInfo("TST/D" + d + "/T0", genre, sentences));
+        }
+
+        int[] commitAfterDoc = decideCommitPoints(rng, numDocs);
+        return new IndexConfig(docs, commitAfterDoc, seed, strategy);
+    }
+
+    // Choose sentence length for one random sentence.
+    private int decideSentenceLength (Random rng, BiasStrategy strategy) {
+        if (strategy == BiasStrategy.DENSE) {
+            return 6 + rng.nextInt(10);
+        }
+        int r = rng.nextInt(100);
+        if (r < 5) return 2 + rng.nextInt(2);
+        if (r < 15) return 20 + rng.nextInt(11);
+        return 3 + rng.nextInt(15);
+    }
+
+    // Decide if sentence gets at least one a token.
+    private boolean decidePlaceA (Random rng, BiasStrategy strategy,
+            int sentIdx, int numSentences) {
+        switch (strategy) {
+            case HEAVY_A_RARE_B:
+                return rng.nextDouble() < 0.9;
+            case ALTERNATING:
+                return sentIdx % 2 == 0 || rng.nextDouble() < 0.15;
+            case CLUSTER:
+                return sentIdx < numSentences / 2 || rng.nextDouble() < 0.2;
+            case DENSE:
+                return true;
+            default:
+                return rng.nextDouble() < 0.6;
+        }
+    }
+
+    // Decide if sentence gets at least one b token.
+    private boolean decidePlaceB (Random rng, BiasStrategy strategy,
+            int sentIdx, int numSentences) {
+        switch (strategy) {
+            case HEAVY_A_RARE_B:
+                return rng.nextDouble() < 0.1;
+            case ALTERNATING:
+                return sentIdx % 2 == 1 || rng.nextDouble() < 0.15;
+            case CLUSTER:
+                return sentIdx >= numSentences / 2 || rng.nextDouble() < 0.2;
+            case DENSE:
+                return true;
+            default:
+                return rng.nextDouble() < 0.4;
+        }
+    }
+
+    // Pick a random token offset not used yet in sentence.
+    private int pickUnusedOffset (Random rng, int sentLen,
+            Set<Integer> used) {
+        if (used.size() >= sentLen) return -1;
+        for (int attempt = 0; attempt < 20; attempt++) {
+            int pos = rng.nextInt(sentLen);
+            if (!used.contains(pos)) return pos;
+        }
+        for (int pos = 0; pos < sentLen; pos++) {
+            if (!used.contains(pos)) return pos;
+        }
+        return -1;
+    }
+
+    // Choose where to commit so we get multiple segment layouts.
+    private int[] decideCommitPoints (Random rng, int numDocs) {
+        if (numDocs <= 1) return new int[] { 0 };
+        List<Integer> points = new ArrayList<>();
+        for (int d = 0; d < numDocs; d++) {
+            if (d == numDocs - 1 || rng.nextDouble() < 0.4) {
+                points.add(d);
+            }
+        }
+        if (!points.contains(numDocs - 1)) points.add(numDocs - 1);
+        int[] result = new int[points.size()];
+        for (int i = 0; i < result.length; i++) result[i] = points.get(i);
+        return result;
+    }
+
+    // Build a KrillIndex from generated docs and commit plan.
+    private KrillIndex buildFuzzIndex (IndexConfig config)
+            throws IOException {
+        KrillIndex ki = new KrillIndex();
+        int commitIdx = 0;
+
+        for (int d = 0; d < config.docs.size(); d++) {
+            DocInfo doc = config.docs.get(d);
+            FieldDocument fd = buildFuzzFieldDocument(doc);
+            ki.addDoc(fd);
+
+            if (commitIdx < config.commitAfterDoc.length
+                    && config.commitAfterDoc[commitIdx] == d) {
+                ki.commit();
+                commitIdx++;
+            }
+        }
+
+        if (commitIdx == 0 || config.commitAfterDoc[commitIdx - 1]
+                != config.docs.size() - 1) {
+            ki.commit();
+        }
+
+        return ki;
+    }
+
+    // Convert one generated doc into a tokens field with TV data.
+    private FieldDocument buildFuzzFieldDocument (DocInfo doc) {
+        FieldDocument fd = new FieldDocument();
+        fd.addString("textSigle", doc.textSigle);
+        fd.addString("genre", doc.genre);
+
+        Set<Integer> aPositions = new HashSet<>();
+        Set<Integer> bPositions = new HashSet<>();
+        for (SentenceInfo sent : doc.sentences) {
+            aPositions.addAll(sent.aPositions);
+            bPositions.addAll(sent.bPositions);
+        }
+
+        int totalTokens = 0;
+        for (SentenceInfo sent : doc.sentences) {
+            totalTokens += (sent.endPos - sent.startPos);
+        }
+
+        String[] allTokens = new String[totalTokens];
+        int idx = 0;
+        for (SentenceInfo sent : doc.sentences) {
+            for (int pos = sent.startPos; pos < sent.endPos; pos++) {
+                if (aPositions.contains(pos)) {
+                    allTokens[idx] = "a";
+                }
+                else if (bPositions.contains(pos)) {
+                    allTokens[idx] = "b";
+                }
+                else {
+                    allTokens[idx] = "w" + pos;
+                }
+                idx++;
+            }
+        }
+
+        int totalChars = 0;
+        for (String t : allTokens) totalChars += t.length();
+
+        StringBuilder surface = new StringBuilder();
+        StringBuilder tv = new StringBuilder();
+
+        int tokIdx = 0;
+        int charOff = 0;
+
+        for (int si = 0; si < doc.sentences.size(); si++) {
+            SentenceInfo sent = doc.sentences.get(si);
+            int sentLen = sent.endPos - sent.startPos;
+
+            int sentCharStart = charOff;
+            int sentCharEnd = sentCharStart;
+            for (int ti = 0; ti < sentLen; ti++) {
+                sentCharEnd += allTokens[tokIdx + ti].length();
+            }
+
+            for (int ti = 0; ti < sentLen; ti++) {
+                String tok = allTokens[tokIdx + ti];
+                int cStart = charOff;
+                int cEnd = charOff + tok.length();
+                surface.append(tok);
+
+                tv.append("[(").append(cStart).append("-").append(cEnd)
+                        .append(")");
+                tv.append("s:").append(tok);
+
+                if (tokIdx + ti == 0) {
+                    tv.append("|-:t$<i>").append(totalTokens);
+                    tv.append("|<>:base/s:t$<b>64<i>0<i>")
+                            .append(totalChars).append("<i>")
+                            .append(totalTokens).append("<b>0");
+                }
+
+                if (ti == 0) {
+                    tv.append("|<>:base/s:s$<b>64<i>")
+                            .append(sentCharStart).append("<i>")
+                            .append(sentCharEnd).append("<i>")
+                            .append(sent.endPos).append("<b>1");
+                }
+
+                tv.append("|_").append(tokIdx + ti).append("$<i>")
+                        .append(cStart).append("<i>").append(cEnd);
+                tv.append("]");
+
+                charOff = cEnd;
+            }
+            tokIdx += sentLen;
+        }
+
+        fd.addTV("tokens", surface.toString(), tv.toString());
+        return fd;
+    }
+
+    // focus(1: contains(contains(<s>, {1: a}), {1: b}))
+    private SpanQuery nestedContainsSameClassQuery () {
+        SpanQuery sentence = new SpanElementQuery("tokens", "base/s:s");
+        SpanQuery tokenA = new SpanClassQuery(
+                new SpanTermQuery(new Term("tokens", "s:a")), (byte) 1);
+        SpanQuery tokenB = new SpanClassQuery(
+                new SpanTermQuery(new Term("tokens", "s:b")), (byte) 1);
+        SpanQuery innerContains = new SpanWithinQuery(sentence, tokenA);
+        SpanQuery outerContains = new SpanWithinQuery(innerContains, tokenB);
+        SpanFocusQuery focus = new SpanFocusQuery(outerContains, (byte) 1);
+        focus.setSorted(false);
+        return focus;
+    }
+
+    // Collect all a positions from sentences that also contain b.
+    private Set<Integer> expectedAPositions (DocInfo doc) {
+        Set<Integer> result = new TreeSet<>();
+        for (SentenceInfo sent : doc.sentences) {
+            if (sent.hasBoth()) {
+                result.addAll(sent.aPositions);
+            }
+        }
+        return result;
+    }
+
+    // Collect all a positions in one generated document.
+    private Set<Integer> allAPositions (DocInfo doc) {
+        Set<Integer> result = new TreeSet<>();
+        for (SentenceInfo sent : doc.sentences) {
+            result.addAll(sent.aPositions);
+        }
+        return result;
+    }
+
+    // Collect all a and b positions in one generated document.
+    private Set<Integer> allABPositions (DocInfo doc) {
+        Set<Integer> result = new TreeSet<>();
+        for (SentenceInfo sent : doc.sentences) {
+            result.addAll(sent.aPositions);
+            result.addAll(sent.bPositions);
+        }
+        return result;
+    }
+
+    // Check invariants for focus(class1) over different class ids.
+    private void verifyDiffClassInvariants (Result kr,
+            IndexConfig config, String context) {
+
+        Set<Integer> anyDocExpectedA = new TreeSet<>();
+        for (DocInfo doc : config.docs) {
+            anyDocExpectedA.addAll(expectedAPositions(doc));
+        }
+
+        Set<Integer> matchedPositions = new TreeSet<>();
+        int storedMatches = kr.getMatches().size();
+
+        for (int i = 0; i < storedMatches; i++) {
+            Match m = kr.getMatch(i);
+            int mStart = m.getStartPos();
+            int mEnd = m.getEndPos();
+
+            assertTrue(context + ": Match " + i + " [" + mStart + ","
+                    + mEnd + ") must be single token (end==start+1)",
+                    mEnd == mStart + 1);
+
+            boolean validInSomeDoc = false;
+            for (DocInfo doc : config.docs) {
+                if (allAPositions(doc).contains(mStart)
+                        && expectedAPositions(doc).contains(mStart)) {
+                    validInSomeDoc = true;
+                    break;
+                }
+            }
+            assertTrue(context + ": Match " + i + " start=" + mStart
+                    + " must be a valid 'a' in a sentence with 'b'",
+                    validInSomeDoc);
+
+            matchedPositions.add(mStart);
+        }
+
+        if (config.docs.size() == 1
+                && kr.getTotalResults() == storedMatches) {
+            Set<Integer> expected = expectedAPositions(config.docs.get(0));
+            for (int pos : expected) {
+                assertTrue(context + ": Expected 'a' at position "
+                        + pos + " not found in results",
+                        matchedPositions.contains(pos));
+            }
+        }
+    }
+
+    // Check invariants for focus(class1) with shared class ids.
+    private void verifySameClassInvariants (Result kr,
+            IndexConfig config, String context) {
+
+        int storedMatches = kr.getMatches().size();
+        for (int i = 0; i < storedMatches; i++) {
+            Match m = kr.getMatch(i);
+            int mStart = m.getStartPos();
+            int mEnd = m.getEndPos();
+
+            boolean validInSomeDoc = false;
+            for (DocInfo doc : config.docs) {
+                Set<Integer> abPos = allABPositions(doc);
+
+                if (!abPos.contains(mStart)) continue;
+                if (!abPos.contains(mEnd - 1)) continue;
+
+                boolean withinSentence = false;
+                boolean sentHasBoth = false;
+                for (SentenceInfo sent : doc.sentences) {
+                    if (mStart >= sent.startPos && mEnd <= sent.endPos) {
+                        withinSentence = true;
+                        sentHasBoth = sent.hasBoth();
+                        break;
+                    }
+                }
+                if (withinSentence && sentHasBoth) {
+                    validInSomeDoc = true;
+                    break;
+                }
+            }
+
+            assertTrue(context + ": Match " + i + " [" + mStart + ","
+                    + mEnd + ") failed same-class invariants",
+                    validInSomeDoc);
+        }
+    }
+
+    // Check diff-class invariants after virtual corpus filtering.
+    private void verifyDiffClassInvariantsFiltered (Result kr,
+            IndexConfig config, Set<String> includedSigles,
+            String context) {
+
+        int storedMatches = kr.getMatches().size();
+        for (int i = 0; i < storedMatches; i++) {
+            Match m = kr.getMatch(i);
+            int mStart = m.getStartPos();
+            int mEnd = m.getEndPos();
+
+            assertTrue(context + ": Match " + i + " [" + mStart + ","
+                    + mEnd + ") must be single token",
+                    mEnd == mStart + 1);
+
+            boolean validInFilteredDoc = false;
+            for (DocInfo doc : config.docs) {
+                if (!includedSigles.contains(doc.textSigle)) continue;
+                if (expectedAPositions(doc).contains(mStart)) {
+                    validInFilteredDoc = true;
+                    break;
+                }
+            }
+            assertTrue(context + ": Match " + i + " start=" + mStart
+                    + " must be valid 'a' in filtered docs",
+                    validInFilteredDoc);
+        }
+    }
+
+    // Function type used by fuzzLoop for one seeded iteration.
+    @FunctionalInterface
+    interface FuzzAction {
+        void run (long seed) throws Exception;
+    }
+
+    // Run a fuzz action over N seeds and print reproducible failures.
+    private void fuzzLoop (String testName, FuzzAction action) {
+        int iterations = getFuzzIterations();
+        assumeTrue("Fuzz tests skipped (set -Dfuzz.iterations=N to run)",
+                iterations > 0);
+        long baseSeed = getFuzzBaseSeed();
+
+        for (int i = 0; i < iterations; i++) {
+            long seed = baseSeed + i;
+            try {
+                action.run(seed);
+            }
+            catch (AssertionError e) {
+                throw new AssertionError(
+                        "FUZZ FAILURE [" + testName + "] iteration="
+                        + i + " seed=" + seed + "\n"
+                        + "Reproduce: -Dfuzz.seed=" + seed
+                        + " -Dfuzz.iterations=1", e);
+            }
+            catch (Exception e) {
+                throw new AssertionError(
+                        "FUZZ ERROR [" + testName + "] iteration="
+                        + i + " seed=" + seed, e);
+            }
+        }
+    }
+
+    // Fuzz test: class1 focus with inner class1 and outer class2.
+    @Test
+    public void fuzzNestedContainsDiffClass () {
+        fuzzLoop("fuzzNestedContainsDiffClass", seed -> {
+            IndexConfig config = generateFuzzConfig(seed);
+            KrillIndex ki = buildFuzzIndex(config);
+            try {
+                Result kr = ki.search(
+                        nestedContainsDiffClassQuery(), (short) 500);
+                verifyDiffClassInvariants(kr, config,
+                        "seed=" + seed + " strategy=" + config.strategy);
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
+
+    // Fuzz test: class1 focus with both terms in class1.
+    @Test
+    public void fuzzNestedContainsSameClass () {
+        fuzzLoop("fuzzNestedContainsSameClass", seed -> {
+            IndexConfig config = generateFuzzConfig(seed);
+            KrillIndex ki = buildFuzzIndex(config);
+            try {
+                Result kr = ki.search(
+                        nestedContainsSameClassQuery(), (short) 500);
+                verifySameClassInvariants(kr, config,
+                        "seed=" + seed + " strategy=" + config.strategy);
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
+
+    // Fuzz test: force one commit per doc to maximize segment count.
+    @Test
+    public void fuzzNestedContainsMultiSegment () {
+        fuzzLoop("fuzzNestedContainsMultiSegment", seed -> {
+            Random rng = new Random(seed);
+            BiasStrategy strategy = BiasStrategy.values()[
+                    rng.nextInt(BiasStrategy.values().length)];
+            IndexConfig config = generateFuzzConfig(seed, rng, strategy);
+
+            int numDocs = config.docs.size();
+            int[] manyCommits = new int[numDocs];
+            for (int d = 0; d < numDocs; d++) manyCommits[d] = d;
+            IndexConfig multiSegConfig = new IndexConfig(
+                    config.docs, manyCommits, seed, strategy);
+
+            KrillIndex ki = buildFuzzIndex(multiSegConfig);
+            try {
+                Result kr = ki.search(
+                        nestedContainsDiffClassQuery(), (short) 500);
+                verifyDiffClassInvariants(kr, multiSegConfig,
+                        "seed=" + seed + " strategy=" + strategy);
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
+
+    // Fuzz test: run diff-class query on a filtered virtual corpus.
+    @Test
+    public void fuzzNestedContainsVirtualCorpus () {
+        fuzzLoop("fuzzNestedContainsVirtualCorpus", seed -> {
+            IndexConfig config = generateFuzzConfig(seed);
+            if (config.docs.size() < 2) return;
+
+            KrillIndex ki = buildFuzzIndex(config);
+            try {
+                String targetSigle = config.docs.get(0).textSigle;
+                Set<String> included = new HashSet<>();
+                included.add(targetSigle);
+
+                Krill ks = new Krill(nestedContainsDiffClassQuery());
+                ks.getMeta().setCount((short) 500);
+
+                CollectionBuilder cb = new CollectionBuilder();
+                KrillCollection kc = new KrillCollection(ki);
+                kc.fromBuilder(cb.term("textSigle", targetSigle));
+                ks.setCollection(kc);
+
+                Result kr = ks.apply(ki);
+                verifyDiffClassInvariantsFiltered(kr, config, included,
+                        "seed=" + seed + " vc_sigle=" + targetSigle);
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
+
+    // Fuzz test: heavy backtracking setup with many a and rare b.
+    @Test
+    public void fuzzNestedContainsHeavyBacktracking () {
+        fuzzLoop("fuzzNestedContainsHeavyBacktracking", seed -> {
+            Random rng = new Random(seed);
+            IndexConfig config = generateFuzzConfig(seed, rng,
+                    BiasStrategy.HEAVY_A_RARE_B);
+            KrillIndex ki = buildFuzzIndex(config);
+            try {
+                Result kr = ki.search(
+                        nestedContainsDiffClassQuery(), (short) 500);
+                verifyDiffClassInvariants(kr, config,
+                        "seed=" + seed + " strategy=HEAVY_A_RARE_B");
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
+
+    // Fuzz test: dense setup where almost every sentence has a and b.
+    @Test
+    public void fuzzNestedContainsDense () {
+        fuzzLoop("fuzzNestedContainsDense", seed -> {
+            Random rng = new Random(seed);
+            IndexConfig config = generateFuzzConfig(seed, rng,
+                    BiasStrategy.DENSE);
+            KrillIndex ki = buildFuzzIndex(config);
+            try {
+                Result kr = ki.search(
+                        nestedContainsDiffClassQuery(), (short) 500);
+                verifyDiffClassInvariants(kr, config,
+                        "seed=" + seed + " strategy=DENSE");
+            }
+            finally {
+                ki.close();
+            }
+        });
+    }
 };
