/*
===============================================================================
DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH
PHASE 3.284 — INDEPENDENT STATE-STRATIFICATION REPLICATION

CODE VERSION: Deterministic Blackjack Phase 3.284
CODE BUILD TAG: DBDE-3.289-VARIED-DIAGNOSTIC-REPLICATION-80K

PURPOSE
Observe HOW sessions travel through bankroll states under the frozen casino
architecture. This phase does not optimize or intervene.

FROZEN ARCHITECTURE
- six-deck persistent shoe;
- 67% / 209-card representative cut point;
- reshuffle between hands after cut point;
- Phase 3.274 casino wager execution;
- fair-play / faithful-card-order assumption.

OBSERVATIONAL STATES
Below £100; below £80; below £60; below £40; below £20;
recovery from below £100 to >=£100;
£130 advancement; £150 advancement; £200 attainment;
table exit below £15.

PATH MEASURES
hands spent below £100;
stake/exposure while below £100;
number of below-£100 episodes;
number of recoveries;
minimum bankroll;
maximum drawdown;
total exposure;
hands played.

NO NEW WAGER RULE.
NO NEW STOPPING RULE.
NO OPTIMIZATION.
===============================================================================
*/
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.security.MessageDigest;
import java.util.*;

public final class DeterministicBlackjackPhase3394 {
    static final int SESSIONS = 5000;
    static final int HANDS = 30;
    static final int SHOE_SIZE = 312;
    static final double START_BANK = 100.0;
    static final double BASE_WAGER = 1.0;
    static final long PRIMARY_SEED = 202201L;
    static final long HOLDOUT_SEED = 202301L;

    enum Action { HIT, STAND, DOUBLE, SPLIT, NONE }
    enum Profile { TEXTBOOK, MAXIMUM_AGGRESSION, SELECTIVE_AGGRESSION }

    static final class Hand {
        final ArrayList<Integer> c = new ArrayList<>();
        int total(){int t=0,a=0;for(int v:c){t+=v;if(v==11)a++;}while(t>21&&a-->0)t-=10;return t;}
        boolean soft(){int raw=0;for(int v:c)raw+=v;return c.contains(11)&&raw==total();}
        boolean bust(){return total()>21;}
        boolean blackjack(){return c.size()==2&&total()==21;}
        int cards(){return c.size();}
    }

    static final class ResolvedHandRecord {
        String cohort;
        int session, round, child;
        boolean splitChild;
        int startTotal;
        boolean startSoft;
        int dealerUp;
        String visibleClass;
        Action textbookAction;
        Action aggressiveAction;
        int startCards;
        int endCards;
        int dealerEndCards;
        boolean playerNaturalBlackjack;
        boolean dealerNaturalBlackjack;
        double baseWager;
        boolean selectiveWagerTrigger;
        double stake;
        boolean thirdCardTaken;
        boolean thirdCardBust;
        boolean bust;
        String outcome;
        double net;
        int startPointer, endPointer;

        String csv(){
            return String.join(",",
                cohort,Integer.toString(session),Integer.toString(round),Integer.toString(child),Boolean.toString(splitChild),
                Integer.toString(startTotal),Boolean.toString(startSoft),Integer.toString(dealerUp),visibleClass,
                textbookAction.toString(),aggressiveAction.toString(),Integer.toString(startCards),Integer.toString(endCards),Integer.toString(dealerEndCards),Boolean.toString(playerNaturalBlackjack),Boolean.toString(dealerNaturalBlackjack),String.format(Locale.ROOT,"%.1f",baseWager),Boolean.toString(selectiveWagerTrigger),
                String.format(Locale.ROOT,"%.1f",stake),Boolean.toString(thirdCardTaken),Boolean.toString(thirdCardBust),
                Boolean.toString(bust),outcome,String.format(Locale.ROOT,"%.1f",net),Integer.toString(startPointer),Integer.toString(endPointer));
        }
    }

    static final class Round {
        double net;
        int endPointer;
        int doubles, splits;
        boolean win, loss, push;
        final ArrayList<ResolvedHandRecord> records = new ArrayList<>();
    }

    static final class PairStats {
        long sessions,tPositive,tNegative,tEven,aPositive,aNegative,aEven,tHigher,aHigher,tie;
        long t2x,t3x,t5x,t10x,a2x,a3x,a5x,a10x;
        double tEnd,aEnd;
        long tWins,tLosses,tPushes,aWins,aLosses,aPushes,tDoubles,aDoubles,tSplits,aSplits;
        long diverged,firstDivSum,sameStart,totalStarts,finalSame,tAhead,aAhead,absDiff,tCards,aCards;
        int maxT,maxA;
        double maxBankT=START_BANK,maxBankA=START_BANK;
        int maxBankTHand=0,maxBankAHand=0,maxBankTSession=0,maxBankASession=0;
        final double[] aBankAfterHand=new double[HANDS+1];
        double sumSessionPeakA,sumMaxDrawdownA;
        long aEver2x,aEver3x,aEver5x,aEver10x,aEverZero,aBankruptcyStops,aHandsSkippedAfterBankruptcy;
        long affordabilityBaseStops,affordabilitySplitFallbacks,affordabilityDoubleFallbacks;
        long selective2xTriggers,selective2xWins,selective2xLosses,selective2xPushes;
        double selective2xNet;
        final long[] peakHandCountsA=new long[HANDS+1];
    }

    static final class StateKey implements Comparable<StateKey> {
        final int total, up;
        final boolean soft, splitChild;
        final Action textbook;
        StateKey(int total,boolean soft,int up,boolean splitChild,Action textbook){this.total=total;this.soft=soft;this.up=up;this.splitChild=splitChild;this.textbook=textbook;}
        public int compareTo(StateKey o){int c=Integer.compare(total,o.total);if(c!=0)return c;c=Boolean.compare(soft,o.soft);if(c!=0)return c;c=Integer.compare(up,o.up);if(c!=0)return c;c=Boolean.compare(splitChild,o.splitChild);if(c!=0)return c;return textbook.compareTo(o.textbook);}
        public boolean equals(Object x){if(!(x instanceof StateKey))return false;StateKey o=(StateKey)x;return total==o.total&&soft==o.soft&&up==o.up&&splitChild==o.splitChild&&textbook==o.textbook;}
        public int hashCode(){return Objects.hash(total,soft,up,splitChild,textbook);}
        String label(){return (soft?"SOFT ":"HARD ")+total+" vs "+up+(splitChild?" [split-child]":"")+" | textbook="+textbook;}
    }

    static final class StateAgg {
        long hands,wins,losses,pushes,busts,thirdTaken,thirdBust;
        double net,stake;
        void add(ResolvedHandRecord r){hands++;net+=r.net;stake+=r.stake;if(r.outcome.equals("WIN"))wins++;else if(r.outcome.equals("LOSS"))losses++;else pushes++;if(r.bust)busts++;if(r.thirdCardTaken)thirdTaken++;if(r.thirdCardBust)thirdBust++;}
    }

    static long sessionSeed(long cohort,int s){return cohort+s*1_000_003L;}

    static int[] sixDeckShoe(long seed){
        int[] a=new int[SHOE_SIZE];int p=0;
        for(int deck=0;deck<6;deck++)for(int suit=0;suit<4;suit++)for(int rank=1;rank<=13;rank++)a[p++]=rank==1?11:Math.min(rank,10);
        Random r=new Random(seed);
        for(int i=a.length-1;i>0;i--){int j=r.nextInt(i+1);int t=a[i];a[i]=a[j];a[j]=t;}
        return a;
    }

    static boolean auditShoe(int[] s){
        if(s.length!=312)return false;int ace=0,ten=0;int[] n=new int[10];
        for(int v:s){if(v==11)ace++;else if(v==10)ten++;else if(v>=2&&v<=9)n[v]++;else return false;}
        if(ace!=24||ten!=96)return false;for(int v=2;v<=9;v++)if(n[v]!=24)return false;return true;
    }

    static int draw(int[] shoe,int[] ptr){if(ptr[0]>=shoe.length)throw new IllegalStateException("Shoe exhausted at pointer "+ptr[0]);return shoe[ptr[0]++];}

    static Action textbook(Hand h,int up,boolean first){
        int t=h.total();
        if(h.soft()){
            if(t>=19)return Action.STAND;
            if(t==18)return first&&up>=3&&up<=6?Action.DOUBLE:(up>=9?Action.HIT:Action.STAND);
            if(t==17)return first&&up>=3&&up<=6?Action.DOUBLE:Action.HIT;
            if(t==15||t==16)return first&&up>=4&&up<=6?Action.DOUBLE:Action.HIT;
            if(t==13||t==14)return first&&up>=5&&up<=6?Action.DOUBLE:Action.HIT;
            return Action.HIT;
        }
        if(t>=17)return Action.STAND;
        if(t>=13)return up>=2&&up<=6?Action.STAND:Action.HIT;
        if(t==12)return up>=4&&up<=6?Action.STAND:Action.HIT;
        if(t==11)return first&&up!=11?Action.DOUBLE:Action.HIT;
        if(t==10)return first&&up<=9?Action.DOUBLE:Action.HIT;
        if(t==9)return first&&up>=3&&up<=6?Action.DOUBLE:Action.HIT;
        return Action.HIT;
    }

    static boolean textbookSplit(int pair,int up){
        if(pair==11||pair==8)return true;if(pair==10||pair==5)return false;
        if(pair==9)return up!=7&&up!=10&&up!=11;if(pair==7)return up>=2&&up<=7;
        if(pair==6)return up>=2&&up<=6;if(pair==4)return up==5||up==6;
        if(pair==3||pair==2)return up>=2&&up<=7;return false;
    }

    // Rank normalisation collapses 10/J/Q/K to value 10. Therefore K+J,
    // Q+10, J+K, etc. arrive here as 10+10 and are split-eligible.
    static boolean splitEligibleByStoredValue(int firstCard,int secondCard){
        return firstCard==secondCard;
    }

    static String tenValueSplitAudit(){
        int ten=10,jack=10,queen=10,king=10;
        int[][] cases={{ten,jack},{ten,queen},{ten,king},{jack,queen},{jack,king},{queen,king},{ten,ten},{jack,jack},{queen,queen},{king,king}};
        String[] names={"10+J","10+Q","10+K","J+Q","J+K","Q+K","10+10","J+J","Q+Q","K+K"};
        StringBuilder b=new StringBuilder("PHASE 3.02 — TEN-VALUE SPLIT PRECEDENCE AUDIT\n\n");
        b.append("Stored-card rule: 10, J, Q and K are all represented as integer value 10.\n");
        b.append("Maximum Aggression precedence: SPLIT eligible initial pair first; only otherwise consider first-decision DOUBLE.\n\n");
        for(int i=0;i<cases.length;i++){
            boolean ok=splitEligibleByStoredValue(cases[i][0],cases[i][1]);
            b.append(String.format(Locale.ROOT,"%-5s -> stored %d+%d -> split eligible = %s -> first aggressive action = %s%n",
                    names[i],cases[i][0],cases[i][1],ok,ok?"SPLIT":"DOUBLE-CANDIDATE"));
            if(!ok)throw new IllegalStateException("Ten-value split audit failed for "+names[i]);
        }
        b.append("\nRESULT: PASS — every two-card ten-value combination is routed to SPLIT before DOUBLE.\n");
        return b.toString();
    }

    static String visibleClass(Hand h){return h.soft()?"SOFT":"HARD";}

    static Round playRound(int[] shoe,int pointer,Profile profile,String cohort,int session,int round,boolean capture,double availableBank,PairStats stats,double wager,boolean selectiveWagerTrigger){
        int[] ptr={pointer};Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean aggressive=profile==Profile.MAXIMUM_AGGRESSION||profile==Profile.SELECTIVE_AGGRESSION;
        boolean selective=profile==Profile.SELECTIVE_AGGRESSION;
        boolean wantsSplit=pair&&(aggressive||textbookSplit(initial.c.get(0),dealer.c.get(0)));
        if(capture && wantsSplit && availableBank < 2.0*wager){
            wantsSplit=false;
            if(stats!=null)stats.affordabilitySplitFallbacks++;
        }
        ArrayList<Hand> hands=new ArrayList<>();ArrayList<Double> stakes=new ArrayList<>();ArrayList<Boolean> natural=new ArrayList<>();ArrayList<Boolean> splitChild=new ArrayList<>();
        Round out=new Round();
        if(wantsSplit){
            out.splits=1;Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        } else {hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}

        double committedCapital=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            ResolvedHandRecord rec=null;
            if(capture){
                rec=new ResolvedHandRecord();rec.cohort=cohort;rec.session=session;rec.round=round;rec.child=i+1;rec.splitChild=splitChild.get(i);
                rec.startTotal=h.total();rec.startSoft=h.soft();rec.dealerUp=dealer.c.get(0);rec.visibleClass=visibleClass(h);rec.startCards=h.cards();rec.baseWager=wager;rec.selectiveWagerTrigger=selectiveWagerTrigger;rec.playerNaturalBlackjack=(!splitChild.get(i)&&h.blackjack());rec.dealerNaturalBlackjack=dealer.blackjack();rec.startPointer=ptr[0];
                if(h.blackjack()||dealer.blackjack()){rec.textbookAction=Action.NONE;rec.aggressiveAction=Action.NONE;}
                else {rec.textbookAction=textbook(h,dealer.c.get(0),true);rec.aggressiveAction=aggressive?((selective&&h.soft()&&h.total()>=18&&h.total()<=19&&dealer.c.get(0)>=9)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()>=5&&h.total()<=8&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?Action.HIT:(selective&&!h.soft()&&h.total()==9&&dealer.c.get(0)>=9)?Action.HIT:(selective&&!h.soft()&&h.total()==12&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?textbook(h,dealer.c.get(0),true):(selective&&h.soft()&&h.total()>=13&&h.total()<=17&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()==13&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?Action.STAND:(selective&&!h.soft()&&h.total()==8&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()>=12&&h.total()<=13&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()>=5&&h.total()<=7&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()==14)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()==15)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()==16)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&splitChild.get(i)&&h.total()==16&&dealer.c.get(0)==11)?Action.HIT:((selective&&!h.soft()&&(h.total()==19||h.total()==18||h.total()==17||(splitChild.get(i)&&h.total()==20)))?Action.STAND:Action.DOUBLE)):rec.textbookAction;}
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(aggressive&&first)?((selective&&h.soft()&&h.total()>=18&&h.total()<=19&&dealer.c.get(0)>=9)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()>=5&&h.total()<=8&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?Action.HIT:(selective&&!h.soft()&&h.total()==9&&dealer.c.get(0)>=9)?Action.HIT:(selective&&!h.soft()&&h.total()==12&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?textbook(h,dealer.c.get(0),true):(selective&&h.soft()&&h.total()>=13&&h.total()<=17&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()==13&&dealer.c.get(0)>=2&&dealer.c.get(0)<=6)?Action.STAND:(selective&&!h.soft()&&h.total()==8&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()>=12&&h.total()<=13&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()>=5&&h.total()<=7&&dealer.c.get(0)>=7)?Action.HIT:(selective&&!h.soft()&&h.total()==14)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()==15)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&h.total()==16)?textbook(h,dealer.c.get(0),true):(selective&&!h.soft()&&splitChild.get(i)&&h.total()==16&&dealer.c.get(0)==11)?Action.HIT:((selective&&!h.soft()&&(h.total()==19||h.total()==18||h.total()==17||(splitChild.get(i)&&h.total()==20)))?Action.STAND:Action.DOUBLE)):textbook(h,dealer.c.get(0),first);
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(capture && availableBank < committedCapital + wager){
                        if(stats!=null)stats.affordabilityDoubleFallbacks++;
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;
                        continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committedCapital+=wager;out.doubles++;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
            if(capture){rec.endCards=h.cards();rec.stake=stakes.get(i);rec.thirdCardTaken=rec.startCards==2&&rec.endCards>=3;rec.thirdCardBust=rec.thirdCardTaken&&h.bust()&&rec.endCards==3;rec.bust=h.bust();rec.endPointer=ptr[0];out.records.add(rec);}
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        for(int i=0;i<hands.size();i++){
            Hand p=hands.get(i);double st=stakes.get(i),net;
            if(natural.get(i)&&p.blackjack()&&!dealer.blackjack())net=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!p.blackjack())net=-st;
            else if(natural.get(i)&&p.blackjack()&&dealer.blackjack())net=0;
            else if(p.bust())net=-st;
            else if(dealer.bust()||p.total()>dealer.total())net=st;
            else if(p.total()<dealer.total())net=-st;
            else net=0;
            out.net+=net;
            if(capture){ResolvedHandRecord rec=out.records.get(i);rec.net=net;rec.outcome=net>0?"WIN":net<0?"LOSS":"PUSH";rec.dealerEndCards=dealer.cards();rec.endPointer=ptr[0];}
        }
        out.win=out.net>0;out.loss=out.net<0;out.push=out.net==0;out.endPointer=ptr[0];return out;
    }

    static PairStats paired(long cohort,String name,List<ResolvedHandRecord> records){
        PairStats s=new PairStats();
        for(int session=0;session<SESSIONS;session++){
            int[] shoe=sixDeckShoe(sessionSeed(cohort,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
            int pt=0,pa=0;double bt=START_BANK,ba=START_BANK;boolean div=false;int first=0;long tw=0,tl=0,tp=0,aw=0,al=0,ap=0,td=0,ad=0,ts=0,as=0;
            double sessionPeakA=START_BANK,maxDrawdownA=0.0;int sessionPeakHandA=0;
            boolean ever2xA=false,ever3xA=false,ever5xA=false,ever10xA=false,everZeroA=false;
            boolean selectiveStopped=false;
            ArrayDeque<Double> last3UnitNet=new ArrayDeque<>();
            for(int h=1;h<=HANDS;h++){
                Round rt=playRound(shoe,pt,Profile.TEXTBOOK,name,session+1,h,false,Double.POSITIVE_INFINITY,null,BASE_WAGER,false);
                pt=rt.endPointer;bt+=rt.net;
                if(rt.win)tw++;else if(rt.loss)tl++;else tp++;td+=rt.doubles;ts+=rt.splits;
                if(bt>s.maxBankT){s.maxBankT=bt;s.maxBankTHand=h;s.maxBankTSession=session+1;}

                double recent3=0.0;
                for(double v:last3UnitNet)recent3+=v;
                double drawdownBefore=Math.max(0.0,sessionPeakA-ba);
                boolean wagerTrigger=false;
                double currentWager=BASE_WAGER;
                if(!selectiveStopped){
                    if(ba < currentWager){
                        selectiveStopped=true;s.affordabilityBaseStops++;
                        s.aHandsSkippedAfterBankruptcy+=(HANDS-h+1);
                    }
                }
                if(!selectiveStopped){
                    s.totalStarts++;if(pt==pa)s.sameStart++;
                    Round ra=playRound(shoe,pa,Profile.SELECTIVE_AGGRESSION,name,session+1,h,true,ba,s,currentWager,wagerTrigger);
                    records.addAll(ra.records);
                    pa=ra.endPointer;ba+=ra.net;
                    if(wagerTrigger){
                        s.selective2xTriggers++;s.selective2xNet+=ra.net;
                        if(ra.win)s.selective2xWins++;else if(ra.loss)s.selective2xLosses++;else s.selective2xPushes++;
                    }
                    double unitEquivalentNet=ra.net/currentWager;
                    last3UnitNet.addLast(unitEquivalentNet);
                    if(last3UnitNet.size()>3)last3UnitNet.removeFirst();
                    if(ra.win)aw++;else if(ra.loss)al++;else ap++;ad+=ra.doubles;as+=ra.splits;
                    if(ba>sessionPeakA){sessionPeakA=ba;sessionPeakHandA=h;}
                    maxDrawdownA=Math.max(maxDrawdownA,sessionPeakA-ba);
                    if(ba>=200)ever2xA=true;if(ba>=300)ever3xA=true;if(ba>=500)ever5xA=true;if(ba>=1000)ever10xA=true;
                    if(ba<=0){
                        everZeroA=true;selectiveStopped=true;s.aBankruptcyStops++;
                        s.aHandsSkippedAfterBankruptcy+=(HANDS-h);
                        ba=0.0;
                    }
                    if(ba>s.maxBankA){s.maxBankA=ba;s.maxBankAHand=h;s.maxBankASession=session+1;}
                    if(!div&&pt!=pa){div=true;first=h;}
                }
                s.aBankAfterHand[h]+=ba;
            }
            if(pt>SHOE_SIZE||pa>SHOE_SIZE)throw new IllegalStateException("Shoe exhausted");
            s.sessions++;s.tEnd+=bt;s.aEnd+=ba;s.tWins+=tw;s.tLosses+=tl;s.tPushes+=tp;s.aWins+=aw;s.aLosses+=al;s.aPushes+=ap;s.tDoubles+=td;s.aDoubles+=ad;s.tSplits+=ts;s.aSplits+=as;
            if(bt>START_BANK)s.tPositive++;else if(bt<START_BANK)s.tNegative++;else s.tEven++;if(ba>START_BANK)s.aPositive++;else if(ba<START_BANK)s.aNegative++;else s.aEven++;
            if(bt>=200)s.t2x++;if(bt>=300)s.t3x++;if(bt>=500)s.t5x++;if(bt>=1000)s.t10x++;
            if(ba>=200)s.a2x++;if(ba>=300)s.a3x++;if(ba>=500)s.a5x++;if(ba>=1000)s.a10x++;
            if(bt>ba)s.tHigher++;else if(ba>bt)s.aHigher++;else s.tie++;
            s.sumSessionPeakA+=sessionPeakA;s.sumMaxDrawdownA+=maxDrawdownA;s.peakHandCountsA[sessionPeakHandA]++;
            if(ever2xA)s.aEver2x++;if(ever3xA)s.aEver3x++;if(ever5xA)s.aEver5x++;if(ever10xA)s.aEver10x++;if(everZeroA)s.aEverZero++;
            if(div){s.diverged++;s.firstDivSum+=first;}if(pt==pa)s.finalSame++;else if(pt>pa)s.tAhead++;else s.aAhead++;s.absDiff+=Math.abs(pt-pa);s.tCards+=pt;s.aCards+=pa;s.maxT=Math.max(s.maxT,pt);s.maxA=Math.max(s.maxA,pa);
        }
        return s;
    }

    static String pct(long a,long b){return String.format(Locale.ROOT,"%.2f%%",b==0?0:100.0*a/b);}
    static String avg(double a,long b){return String.format(Locale.ROOT,"%.3f",b==0?0:a/b);}

    static String baseline(PairStats p,PairStats h){
        StringBuilder r=new StringBuilder();
        r.append("PHASE 3.35 SECOND INTERVENTION RESULTS\n\n");
        for(Object[] z:new Object[][]{{"PRIMARY",p},{"HOLDOUT",h}}){String n=(String)z[0];PairStats s=(PairStats)z[1];
            r.append(n).append("\n");
            r.append("Average ending bankroll Textbook/Selective: ").append(avg(s.tEnd,s.sessions)).append(" / ").append(avg(s.aEnd,s.sessions)).append("\n");
            r.append(String.format(Locale.ROOT,"Maximum bankroll observed Textbook/Selective: %.1f at hand %d (session %d) / %.1f at hand %d (session %d)%n",
                s.maxBankT,s.maxBankTHand,s.maxBankTSession,s.maxBankA,s.maxBankAHand,s.maxBankASession));
            r.append("Positive sessions Textbook/Selective: ").append(pct(s.tPositive,s.sessions)).append(" / ").append(pct(s.aPositive,s.sessions)).append("\n");
            r.append("Affordability base stops: ").append(s.affordabilityBaseStops).append("\n");
            r.append("Affordability split fallbacks: ").append(s.affordabilitySplitFallbacks).append("\n");
            r.append("Affordability double fallbacks: ").append(s.affordabilityDoubleFallbacks).append("\n");
            r.append("Selective multiplier trigger wagers: ").append(s.selective2xTriggers).append("\n");
            r.append("Selective multiplier trigger net: ").append(String.format(Locale.ROOT,"%.1f",s.selective2xNet)).append("\n");
            r.append("Selective multiplier trigger win/loss/push: ").append(s.selective2xWins).append(" / ").append(s.selective2xLosses).append(" / ").append(s.selective2xPushes).append("\n");
            r.append("Paired winner Textbook/Selective/tie: ").append(pct(s.tHigher,s.sessions)).append(" / ").append(pct(s.aHigher,s.sessions)).append(" / ").append(pct(s.tie,s.sessions)).append("\n");
            r.append("Doubles Textbook/Selective: ").append(s.tDoubles).append(" / ").append(s.aDoubles).append("; splits Textbook/Selective: ").append(s.tSplits).append(" / ").append(s.aSplits).append("\n");
            r.append("Mean cards consumed Textbook/Selective: ").append(avg(s.tCards,s.sessions)).append(" / ").append(avg(s.aCards,s.sessions)).append("\n");
            r.append("Ending bankroll >=2x (200) Textbook/Selective: ").append(pct(s.t2x,s.sessions)).append(" / ").append(pct(s.a2x,s.sessions)).append("\n");
            r.append("Ending bankroll >=3x (300) Textbook/Selective: ").append(pct(s.t3x,s.sessions)).append(" / ").append(pct(s.a3x,s.sessions)).append("\n");
            r.append("Ending bankroll >=5x (500) Textbook/Selective: ").append(pct(s.t5x,s.sessions)).append(" / ").append(pct(s.a5x,s.sessions)).append("\n");
            r.append("Ending bankroll >=10x (1000) Textbook/Selective: ").append(pct(s.t10x,s.sessions)).append(" / ").append(pct(s.a10x,s.sessions)).append("\n\n");
        }
        return r.toString();
    }

    static String multiplierExperiment(PairStats p,PairStats h){
        StringBuilder r=new StringBuilder();
        r.append("PHASE 3.35 BANKRUPTCY-STOP CALIBRATION — CONSTANT 5x\n\n");
        r.append("SCIENTIFIC BOUNDARY\n");
        r.append("Decision policy: frozen Phase 3.20 checkpoint, validated Phase 3.21.\n");
        r.append("Wager architecture: constant 1-unit observational base wager (5x the Phase 3.22 baseline).\n");
        r.append("One multiplier intervention is active: the base wager is five times the Phase 3.22 baseline (5 units).\n\n");
        for(Object[] z:new Object[][]{{"PRIMARY",p},{"HOLDOUT",h}}){
            String n=(String)z[0];PairStats x=(PairStats)z[1];
            r.append(n).append("\n");
            r.append("Mean ending bankroll: ").append(avg(x.aEnd,x.sessions)).append("\n");
            r.append(String.format(Locale.ROOT,"Maximum bankroll observed anywhere: %.1f at Hand %d (session %d)%n",x.maxBankA,x.maxBankAHand,x.maxBankASession));
            r.append(String.format(Locale.ROOT,"Mean per-session peak bankroll: %.3f%n",x.sumSessionPeakA/x.sessions));
            r.append(String.format(Locale.ROOT,"Mean per-session maximum drawdown: %.3f units%n",x.sumMaxDrawdownA/x.sessions));
            r.append("Sessions ever reaching 2x / 3x / 5x / 10x: ")
             .append(pct(x.aEver2x,x.sessions)).append(" / ").append(pct(x.aEver3x,x.sessions)).append(" / ")
             .append(pct(x.aEver5x,x.sessions)).append(" / ").append(pct(x.aEver10x,x.sessions)).append("\n");
            r.append("Sessions ever reaching bankroll <=0: ").append(pct(x.aEverZero,x.sessions)).append("\n");
            int mode=1;for(int i=2;i<=HANDS;i++)if(x.peakHandCountsA[i]>x.peakHandCountsA[mode])mode=i;
            r.append("Sessions whose highest bankroll never exceeded the 100-unit start: ").append(x.peakHandCountsA[0]).append("\n");
            r.append("Most common positive hand-of-peak among sessions that exceeded start: Hand ").append(mode)
             .append(" [").append(x.peakHandCountsA[mode]).append(" sessions]\n\n");
        }
        r.append("MEAN SELECTIVE BANKROLL TRAJECTORY AFTER EACH HAND\n");
        r.append("Hand | Primary | Holdout\n");
        for(int i=1;i<=HANDS;i++)r.append(String.format(Locale.ROOT,"%2d | %8.3f | %8.3f%n",i,p.aBankAfterHand[i]/p.sessions,h.aBankAfterHand[i]/h.sessions));
        return r.toString();
    }

    static Map<StateKey,StateAgg> aggregate(List<ResolvedHandRecord> rr){
        TreeMap<StateKey,StateAgg> m=new TreeMap<>();
        for(ResolvedHandRecord r:rr){if(r.aggressiveAction==Action.NONE)continue;StateKey k=new StateKey(r.startTotal,r.startSoft,r.dealerUp,r.splitChild,r.textbookAction);m.computeIfAbsent(k,x->new StateAgg()).add(r);}return m;
    }

    static Map<StateKey,StateAgg> aggregateDivergent(List<ResolvedHandRecord> rr){
        TreeMap<StateKey,StateAgg> m=new TreeMap<>();
        for(ResolvedHandRecord r:rr){
            if(r.aggressiveAction==Action.NONE || r.aggressiveAction==r.textbookAction)continue;
            StateKey k=new StateKey(r.startTotal,r.startSoft,r.dealerUp,r.splitChild,r.textbookAction);
            m.computeIfAbsent(k,x->new StateAgg()).add(r);
        }
        return m;
    }

    static String stateReport(String cohort,List<ResolvedHandRecord> rr){
        Map<StateKey,StateAgg> m=aggregate(rr);
        ArrayList<Map.Entry<StateKey,StateAgg>> rows=new ArrayList<>(m.entrySet());
        rows.sort((a,b)->{
            double da=a.getValue().net/a.getValue().hands,db=b.getValue().net/b.getValue().hands;
            int c=Double.compare(da,db);if(c!=0)return c;return Long.compare(b.getValue().hands,a.getValue().hands);
        });
        StringBuilder r=new StringBuilder();
        r.append(cohort).append(" — WORST SELECTIVE-AGGRESSION VISIBLE STATES BY MEAN NET/HAND\n");
        r.append("Rank | Visible state | Hands | Mean net | Loss% | Bust% | 3rd-card bust% of 3rd-card draws | Mean stake\n");
        int rank=0;for(Map.Entry<StateKey,StateAgg> e:rows){if(++rank>25)break;StateAgg a=e.getValue();
            r.append(String.format(Locale.ROOT,"%2d | %-45s | %6d | %+7.3f | %6.2f%% | %6.2f%% | %6.2f%% | %.3f%n",
                rank,e.getKey().label(),a.hands,a.net/a.hands,100.0*a.losses/a.hands,100.0*a.busts/a.hands,a.thirdTaken==0?0:100.0*a.thirdBust/a.thirdTaken,a.stake/a.hands));
        }
        r.append("\n");return r.toString();
    }

    static String summary(List<ResolvedHandRecord> p,List<ResolvedHandRecord> h){
        long pHands=p.size(),hHands=h.size();long pThird=0,pThirdBust=0,hThird=0,hThirdBust=0,pBust=0,hBust=0;double pNet=0,hNet=0,pStake=0,hStake=0;
        EnumMap<Action,Long> pTextbook=new EnumMap<>(Action.class),hTextbook=new EnumMap<>(Action.class);for(Action a:Action.values()){pTextbook.put(a,0L);hTextbook.put(a,0L);}
        for(ResolvedHandRecord r:p){if(r.thirdCardTaken)pThird++;if(r.thirdCardBust)pThirdBust++;if(r.bust)pBust++;pNet+=r.net;pStake+=r.stake;pTextbook.put(r.textbookAction,pTextbook.get(r.textbookAction)+1);}
        for(ResolvedHandRecord r:h){if(r.thirdCardTaken)hThird++;if(r.thirdCardBust)hThirdBust++;if(r.bust)hBust++;hNet+=r.net;hStake+=r.stake;hTextbook.put(r.textbookAction,hTextbook.get(r.textbookAction)+1);}
        return "PHASE 3.35 — SELECTIVE-AGGRESSION INSTRUMENTATION SUMMARY\n\n"+
            "PRIMARY resolved selective-aggression hands: "+pHands+"; mean net/hand "+String.format(Locale.ROOT,"%+.4f",pNet/pHands)+"; mean committed stake "+String.format(Locale.ROOT,"%.4f",pStake/pHands)+"; bust rate "+pct(pBust,pHands)+"; third-card bust rate when a third card was taken "+pct(pThirdBust,pThird)+".\n"+
            "Textbook would have chosen on those same visible first-decision states: HIT "+pTextbook.get(Action.HIT)+", STAND "+pTextbook.get(Action.STAND)+", DOUBLE "+pTextbook.get(Action.DOUBLE)+".\n\n"+
            "HOLDOUT resolved selective-aggression hands: "+hHands+"; mean net/hand "+String.format(Locale.ROOT,"%+.4f",hNet/hHands)+"; mean committed stake "+String.format(Locale.ROOT,"%.4f",hStake/hHands)+"; bust rate "+pct(hBust,hHands)+"; third-card bust rate when a third card was taken "+pct(hThirdBust,hThird)+".\n"+
            "Textbook would have chosen on those same visible first-decision states: HIT "+hTextbook.get(Action.HIT)+", STAND "+hTextbook.get(Action.STAND)+", DOUBLE "+hTextbook.get(Action.DOUBLE)+".\n\n"+
            "INTERPRETATION\nPhase 3.35 carries forward split-child HARD 20 STAND, HARD 19 STAND, and split-child HARD 18 STAND. It adds one new family only: NO POLICY OR WAGER INTERVENTION; frozen policy carried forward at 1x. All other Maximum Aggression behaviour remains frozen.\n";
    }

    static String replicatedCandidates(List<ResolvedHandRecord> primary,List<ResolvedHandRecord> holdout){
        Map<StateKey,StateAgg> p=aggregateDivergent(primary),h=aggregateDivergent(holdout);
        final class C {StateKey k;StateAgg a,b;double score;C(StateKey k,StateAgg a,StateAgg b){this.k=k;this.a=a;this.b=b;this.score=(a.net/a.hands+b.net/b.hands)/2.0;}}
        ArrayList<C> c=new ArrayList<>();
        for(StateKey k:p.keySet())if(h.containsKey(k)){StateAgg a=p.get(k),b=h.get(k);if(a.hands>=100&&b.hands>=100&&a.net/a.hands<0&&b.net/b.hands<0)c.add(new C(k,a,b));}
        c.sort(Comparator.comparingDouble(x->x.score));
        StringBuilder r=new StringBuilder("PHASE 3.35 — REMAINING TRUE POLICY-DIVERGENCE STATES UNDER FROZEN 3.20 POLICY\n\n");
        r.append("Filter: aggregate ONLY hands where Selective Aggression's recorded first action differs from the frozen Textbook first action; then require the same visible state >=100 times in BOTH cohorts and negative mean net/hand in BOTH cohorts. This prevents already-protected states with negative realised outcomes from being mislabelled as remaining policy damage.\n\n");
        r.append("Rank | State | Primary n / net | Holdout n / net | P bust% / H bust% | Textbook first action\n");
        int rank=0;for(C x:c){if(++rank>20)break;r.append(String.format(Locale.ROOT,"%2d | %-34s | %5d / %+6.3f | %5d / %+6.3f | %6.2f%% / %6.2f%% | %s%n",rank,(x.k.soft?"SOFT ":"HARD ")+x.k.total+" vs "+x.k.up+(x.k.splitChild?" [split-child]":""),x.a.hands,x.a.net/x.a.hands,x.b.hands,x.b.net/x.b.hands,100.0*x.a.busts/x.a.hands,100.0*x.b.busts/x.b.hands,x.k.textbook));}
        r.append("\nDESIGN USE\nPhase 3.35 carries forward the validated split-child HARD 20, HARD 19 and split-child HARD 18 protections and adds no intervention; frozen decision policy is measured at the unchanged 1x wager. Remaining replicated damage states are retained for later one-rule-at-a-time interventions.\n");
        return r.toString();
    }

    static String methodology(){
        return "PHASE 3.35 — RUNNING TXT AUDIT RECORD\n\n"+
            "OBJECTIVE\nMake the fourth controlled stabilisation intervention while preserving the frozen architecture. Carry forward the three validated protections, then add one new policy family: HARD 16 follows its corresponding Textbook action rather than taking Maximum Aggression's automatic DOUBLE.\n\n"+
            "EVIDENCE HIERARCHY\n1. Primary design authority: finite six-deck Phase 2.xx evidence and new Phase 3.xx data.\n2. Earlier non-depleting/infinite-generator behaviour-profile data: historical corroboration and hypothesis generation only.\n3. Old behaviour-profile evidence must not directly define a new policy unless finite-shoe evidence independently supports the same conclusion.\n\n"+
            "FROZEN VARIABLES\nSix decks, deterministic session shuffle, 30 hands, 100-unit start, 1-unit base wager, dealer rules, blackjack payout, split limit, no in-session reshuffle, textbook control and Maximum Aggression policy are unchanged from Phase 2.02.\n\n"+
            "POLICY INFORMATION BOUNDARY\nThe future optimiser may use player hand composition/total, pair status, dealer upcard and legal actions. Phase 3.35 deliberately uses no previous-card-history, running count, remaining-rank inventory, hidden card or future-card feature. The accumulated policy uses only current visible states: split-child HARD 20, HARD 19, HARD 18, split-child HARD 16 vs Ace, and HARD 17. No card-history or composition feature is introduced.\n\n"+
            "PHASE 3.35 DECISION RULE\nCarry forward split-child HARD 20 STAND, HARD 19 STAND and split-child HARD 18 STAND. ONE additional Phase 3.35 intervention: if an ordinary first-decision hand is hard (not soft) and totals 18, Selective Aggression STANDS. Otherwise the frozen Maximum Aggression policy is unchanged. Textbook remains the control.\n";
    }

    static String hash(String s)throws Exception{MessageDigest md=MessageDigest.getInstance("SHA-256");byte[] d=md.digest(s.getBytes(StandardCharsets.UTF_8));StringBuilder b=new StringBuilder();for(byte x:d)b.append(String.format("%02x",x));return b.toString();}
    static void write(String n,String s)throws Exception{Files.writeString(Path.of(n),s,StandardCharsets.UTF_8);}
    static void writeCsv(String n,List<ResolvedHandRecord> rr)throws Exception{StringBuilder b=new StringBuilder("cohort,session,round,child,split_child,start_total,start_soft,dealer_up,visible_class,textbook_first_action,aggressive_first_action,start_cards,end_cards,dealer_end_cards,player_natural_blackjack,dealer_natural_blackjack,base_wager,selective_wager_trigger,stake,third_card_taken,third_card_bust,bust,outcome,net,start_pointer,end_pointer\n");for(ResolvedHandRecord r:rr)b.append(r.csv()).append('\n');write(n,b.toString());}
















    static int bal355(int[] h,int count){
        int n=Math.min(3,count),s=0;
        for(int i=0;i<n;i++)s+=h[(count-1-i+h.length)%h.length];
        return s;
    }
    static double normal355(int hand,double bank){
        if(hand<=8)return 10.0;
        if(bank<115)return 10.0;
        if(bank<130)return 15.0;
        if(bank<150)return 20.0;
        return 30.0;
    }
    static double cautious355(int[] hist,int count){
        int b=bal355(hist,count);
        return b<0?10.0:(b==0?15.0:17.5);
    }

    static final int[] TIERS356={100,110,120,130,140,150,160,170,180,190};

    static final class Recovery356 {
        int startHand, endHand;
        double startBank, trough, exposure;
        boolean recovered;
    }

    static final class Session356 {
        String cohort;
        int session, handsPlayed, targetHand, bankruptcyHand;
        double finalBank, peakBank, troughBank, maxDrawdown, cumulativeWager;
        double wagerBelow100, targetExposure, peakGiveBack;
        int handsBelow100, recoveryEpisodes, successfulRecoveries, failedRecoveries;
        long cardsConsumed, splits, doubles;
        long[] tierHands=new long[TIERS356.length];
        long[][] transitions=new long[TIERS356.length][TIERS356.length+2]; // + target / below100
        ArrayList<Recovery356> recoveries=new ArrayList<>();
    }

    static final class Cohort356 {
        String name;
        ArrayList<Session356> sessions=new ArrayList<>();
        Cohort356(String n){name=n;}
    }

    static int tier356(double bank){
        if(bank<100)return -1;
        if(bank>=200)return 10;
        int x=((int)Math.floor(bank)-100)/10;
        return Math.max(0,Math.min(9,x));
    }

    static double roundStake356(Round rr){
        double s=0.0;
        for(ResolvedHandRecord x:rr.records)s+=x.stake;
        return s;
    }

    static Cohort356 runCohort356(long seed,String cohort){
        Cohort356 out=new Cohort356(cohort);
        for(int session=0;session<SESSIONS;session++){
            int[] shoe=sixDeckShoe(sessionSeed(seed,session));
            if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

            int ptr=0,hc=0; int[] hist=new int[5];
            double bank=START_BANK, peak=START_BANK, trough=START_BANK, maxDD=0.0;
            boolean everPlunge=false,cooling=false,cautious=false;
            boolean negativeEpisode=false,brakeArmed=false;
            Recovery356 activeRecovery=null;

            Session356 s=new Session356();
            s.cohort=cohort;s.session=session+1;

            for(int hand=1;hand<=HANDS;hand++){
                if(bank>=200||bank<=0)break;

                if(cooling&&bank>=120){cooling=false;cautious=true;}
                if(cautious&&bank>=140)cautious=false;

                double wager;
                if(cooling){
                    wager=10.0;negativeEpisode=false;brakeArmed=false;
                }else if(cautious){
                    wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
                }else if(hand>8&&bank>=140){
                    int b=bal355(hist,hc);boolean neg=b<0;
                    if(neg&&!negativeEpisode)brakeArmed=true;
                    negativeEpisode=neg;
                    double base=bank>=170.0?15.0:normal355(hand,bank);
                    if(brakeArmed){wager=Math.min(base,15.0);brakeArmed=false;}else wager=base;
                }else{
                    wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
                }
                wager=Math.min(wager,bank);
                if(wager<=0)break;
                if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

                double before=bank;
                int beforeTier=tier356(before);
                if(beforeTier>=0&&beforeTier<10)s.tierHands[beforeTier]++;

                PairStats ps=new PairStats();
                int ptrBeforeRound=ptr;
                Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
                ptr=rr.endPointer;

                double committed=roundStake356(rr);
                s.cumulativeWager+=committed;
                s.cardsConsumed+=(rr.endPointer-ptrBeforeRound);
                s.splits+=rr.splits;s.doubles+=rr.doubles;

                bank+=rr.net;if(bank<0)bank=0;
                s.handsPlayed++;
                if(bank<100){s.handsBelow100++;s.wagerBelow100+=committed;}

                peak=Math.max(peak,bank);
                trough=Math.min(trough,bank);
                maxDD=Math.max(maxDD,peak-bank);

                int afterTier=tier356(bank);
                if(beforeTier>=0&&beforeTier<10){
                    if(afterTier==10)s.transitions[beforeTier][10]++;
                    else if(afterTier<0)s.transitions[beforeTier][11]++;
                    else s.transitions[beforeTier][afterTier]++;
                }

                // Recovery episode = first crossing from >=£100 to <£100,
                // ending only when £100 is regained or the session terminates.
                if(activeRecovery==null && before>=100 && bank<100){
                    activeRecovery=new Recovery356();
                    activeRecovery.startHand=hand;
                    activeRecovery.startBank=before;
                    activeRecovery.trough=bank;
                    activeRecovery.exposure=committed;
                    s.recoveryEpisodes++;
                }else if(activeRecovery!=null){
                    activeRecovery.trough=Math.min(activeRecovery.trough,bank);
                    activeRecovery.exposure+=committed;
                    if(bank>=100){
                        activeRecovery.recovered=true;
                        activeRecovery.endHand=hand;
                        s.successfulRecoveries++;
                        s.recoveries.add(activeRecovery);
                        activeRecovery=null;
                    }
                }

                hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

                if(bank>=200){
                    s.targetHand=hand;
                    s.targetExposure=s.cumulativeWager;
                    break;
                }
                if(bank<=0){
                    s.bankruptcyHand=hand;
                    break;
                }
                if(everPlunge&&bank<=100&&!cooling){
                    cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
                }
            }

            if(activeRecovery!=null){
                activeRecovery.endHand=s.handsPlayed;
                activeRecovery.recovered=false;
                s.failedRecoveries++;
                s.recoveries.add(activeRecovery);
            }

            s.finalBank=bank;s.peakBank=peak;s.troughBank=trough;s.maxDrawdown=maxDD;
            s.peakGiveBack=Math.max(0.0,peak-bank);
            out.sessions.add(s);
        }
        return out;
    }

    static String f3(double x){return String.format(Locale.ROOT,"%.3f",x);}
    static String p356(long n,long d){return d==0?"0.00%":String.format(Locale.ROOT,"%.2f%%",100.0*n/d);}

    static void appendCohort356(StringBuilder r,Cohort356 c){
        long n=c.sessions.size(),prof=0,loss=0,be=0,target=0,bust=0;
        long episodes=0,success=0,failed=0,handsBelow=0,cards=0,splits=0,doubles=0;
        double finalSum=0,wager=0,wagerBelow=0,dd=0,give=0,targetExp=0;
        long targetExpN=0; double recoveryHands=0,recoveryExp=0,recoveryDepth=0; long recoveryN=0;

        for(Session356 s:c.sessions){
            finalSum+=s.finalBank;wager+=s.cumulativeWager;wagerBelow+=s.wagerBelow100;
            dd+=s.maxDrawdown;give+=s.peakGiveBack;handsBelow+=s.handsBelow100;
            cards+=s.cardsConsumed;splits+=s.splits;doubles+=s.doubles;
            if(s.finalBank>100)prof++;else if(s.finalBank<100)loss++;else be++;
            if(s.targetHand>0){target++;targetExp+=s.targetExposure;targetExpN++;}
            if(s.finalBank<=0)bust++;
            episodes+=s.recoveryEpisodes;success+=s.successfulRecoveries;failed+=s.failedRecoveries;
            for(Recovery356 x:s.recoveries)if(x.recovered){
                recoveryN++;recoveryHands+=(x.endHand-x.startHand);
                recoveryExp+=x.exposure;recoveryDepth+=(100.0-x.trough);
            }
        }

        r.append("\n").append(c.name).append(" — EXPANDED MEASUREMENT BASELINE\n");
        r.append("Sessions: ").append(n).append("\n");
        r.append("Average ending bankroll: £").append(f3(finalSum/n)).append("\n");
        r.append("Profitable / Losing / Break-even: ").append(p356(prof,n)).append(" / ")
         .append(p356(loss,n)).append(" / ").append(p356(be,n)).append("\n");
        r.append("Reached £200 / Bankroll exhausted: ").append(p356(target,n)).append(" / ").append(p356(bust,n)).append("\n");
        r.append("Average cumulative wager per session: £").append(f3(wager/n)).append("\n");
        r.append("Average cumulative wager below £100 per session: £").append(f3(wagerBelow/n)).append("\n");
        r.append("Average maximum drawdown: £").append(f3(dd/n)).append("\n");
        r.append("Average peak-to-finish give-back: £").append(f3(give/n)).append("\n");
        r.append("Average hands below £100: ").append(f3((double)handsBelow/n)).append("\n");
        r.append("Recovery episodes / successful / failed: ").append(episodes).append(" / ").append(success).append(" / ").append(failed).append("\n");
        r.append("Successful recovery rate by episode: ").append(p356(success,episodes)).append("\n");
        r.append("Average successful recovery duration (hands after crossing below £100): ")
         .append(recoveryN==0?"0.000":f3(recoveryHands/recoveryN)).append("\n");
        r.append("Average successful recovery exposure: £").append(recoveryN==0?"0.000":f3(recoveryExp/recoveryN)).append("\n");
        r.append("Average successful recovery depth below £100: £").append(recoveryN==0?"0.000":f3(recoveryDepth/recoveryN)).append("\n");
        r.append("Average exposure at first £200 reach: £").append(targetExpN==0?"0.000":f3(targetExp/targetExpN)).append("\n");
        r.append("Cards consumed / splits / doubles: ").append(cards).append(" / ").append(splits).append(" / ").append(doubles).append("\n");
    }

    static String sessionCsv356(Cohort356... cs){
        StringBuilder b=new StringBuilder("cohort,session,hands_played,final_bank,peak_bank,trough_bank,max_drawdown,cumulative_wager,wager_below_100,hands_below_100,recovery_episodes,successful_recoveries,failed_recoveries,target_hand,target_exposure,bankruptcy_hand,peak_give_back,cards_consumed,splits,doubles\n");
        for(Cohort356 c:cs)for(Session356 s:c.sessions)
            b.append(String.format(Locale.ROOT,"%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%.2f,%d,%.2f,%d,%d,%d%n",
                s.cohort,s.session,s.handsPlayed,s.finalBank,s.peakBank,s.troughBank,s.maxDrawdown,
                s.cumulativeWager,s.wagerBelow100,s.handsBelow100,s.recoveryEpisodes,s.successfulRecoveries,
                s.failedRecoveries,s.targetHand,s.targetExposure,s.bankruptcyHand,s.peakGiveBack,
                s.cardsConsumed,s.splits,s.doubles));
        return b.toString();
    }

    static String recoveryCsv356(Cohort356... cs){
        StringBuilder b=new StringBuilder("cohort,session,episode,start_hand,end_hand,start_bank,trough_bank,depth_below_100,exposure,recovered\n");
        for(Cohort356 c:cs)for(Session356 s:c.sessions){
            int e=0;for(Recovery356 x:s.recoveries){
                e++;b.append(String.format(Locale.ROOT,"%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%s%n",
                    s.cohort,s.session,e,x.startHand,x.endHand,x.startBank,x.trough,
                    Math.max(0,100-x.trough),x.exposure,Boolean.toString(x.recovered)));
            }
        }
        return b.toString();
    }

    static String tierCsv356(Cohort356... cs){
        StringBuilder b=new StringBuilder("cohort,from_tier,to_state,count\n");
        for(Cohort356 c:cs){
            long[][] z=new long[10][12];
            for(Session356 s:c.sessions)for(int i=0;i<10;i++)for(int j=0;j<12;j++)z[i][j]+=s.transitions[i][j];
            for(int i=0;i<10;i++)for(int j=0;j<12;j++)if(z[i][j]>0){
                String to=j==10?"TARGET_200":(j==11?"BELOW_100":"£"+TIERS356[j]+"-"+(TIERS356[j]+9));
                b.append(c.name).append(",£").append(TIERS356[i]).append("-").append(TIERS356[i]+9)
                 .append(",").append(to).append(",").append(z[i][j]).append("\n");
            }
        }
        return b.toString();
    }


    static String depthBand357(double depth){
        if(depth<10)return "£0-<10";
        if(depth<20)return "£10-<20";
        if(depth<30)return "£20-<30";
        if(depth<40)return "£30-<40";
        if(depth<50)return "£40-<50";
        return "£50+";
    }
    static String exposureBand357(double x){
        if(x<25)return "£0-<25";
        if(x<50)return "£25-<50";
        if(x<75)return "£50-<75";
        if(x<100)return "£75-<100";
        if(x<150)return "£100-<150";
        return "£150+";
    }
    static String startHandBand357(int h){
        if(h<=5)return "Hands 1-5";
        if(h<=10)return "Hands 6-10";
        if(h<=15)return "Hands 11-15";
        if(h<=20)return "Hands 16-20";
        if(h<=25)return "Hands 21-25";
        return "Hands 26-30";
    }

    static final class Band357{
        long total,success;
        double exposure,depth,duration;
        void add(Recovery356 r){
            total++;
            if(r.recovered)success++;
            exposure+=r.exposure;
            depth+=Math.max(0,100-r.trough);
            duration+=(r.endHand-r.startHand);
        }
    }

    static void addBand357(Map<String,Band357> m,String key,Recovery356 r){
        Band357 b=m.get(key);
        if(b==null){b=new Band357();m.put(key,b);}
        b.add(r);
    }

    static String bandCsv357(String dimension,Map<String,Band357> m){
        StringBuilder b=new StringBuilder("dimension,band,episodes,successful,failed,success_rate,avg_duration_hands,avg_exposure,avg_depth_below_100\n");
        for(Map.Entry<String,Band357> e:m.entrySet()){
            Band357 x=e.getValue();
            b.append(String.format(Locale.ROOT,"%s,%s,%d,%d,%d,%.4f,%.4f,%.4f,%.4f%n",
                dimension,e.getKey(),x.total,x.success,x.total-x.success,
                x.total==0?0:(100.0*x.success/x.total),
                x.total==0?0:(x.duration/x.total),
                x.total==0?0:(x.exposure/x.total),
                x.total==0?0:(x.depth/x.total)));
        }
        return b.toString();
    }

    static void appendRecoveryAnatomy357(StringBuilder r,Cohort356 c)throws Exception{
        long episodes=0,success=0,failed=0;
        double successDur=0,successExp=0,successDepth=0;
        double failDur=0,failExp=0,failDepth=0;
        long sN=0,fN=0;

        LinkedHashMap<String,Band357> depth=new LinkedHashMap<>();
        LinkedHashMap<String,Band357> exposure=new LinkedHashMap<>();
        LinkedHashMap<String,Band357> start=new LinkedHashMap<>();
        String[] depthOrder={"£0-<10","£10-<20","£20-<30","£30-<40","£40-<50","£50+"};
        String[] expOrder={"£0-<25","£25-<50","£50-<75","£75-<100","£100-<150","£150+"};
        String[] startOrder={"Hands 1-5","Hands 6-10","Hands 11-15","Hands 16-20","Hands 21-25","Hands 26-30"};
        for(String x:depthOrder)depth.put(x,new Band357());
        for(String x:expOrder)exposure.put(x,new Band357());
        for(String x:startOrder)start.put(x,new Band357());

        for(Session356 s:c.sessions){
            for(Recovery356 x:s.recoveries){
                episodes++;
                double d=x.endHand-x.startHand;
                double dep=Math.max(0,100-x.trough);
                if(x.recovered){
                    success++;sN++;successDur+=d;successExp+=x.exposure;successDepth+=dep;
                }else{
                    failed++;fN++;failDur+=d;failExp+=x.exposure;failDepth+=dep;
                }
                addBand357(depth,depthBand357(dep),x);
                addBand357(exposure,exposureBand357(x.exposure),x);
                addBand357(start,startHandBand357(x.startHand),x);
            }
        }

        r.append("\n").append(c.name).append(" — RECOVERY EFFICIENCY ANATOMY\n");
        r.append("Recovery episodes: ").append(episodes).append("\n");
        r.append("Successful / Failed: ").append(success).append(" / ").append(failed)
         .append(" (").append(p356(success,episodes)).append(" successful)\n");
        r.append("Successful episodes — avg duration / exposure / depth: ")
         .append(f3(successDur/sN)).append(" hands / £").append(f3(successExp/sN))
         .append(" / £").append(f3(successDepth/sN)).append("\n");
        r.append("Failed episodes — avg observed duration / exposure / depth: ")
         .append(f3(failDur/fN)).append(" hands / £").append(f3(failExp/fN))
         .append(" / £").append(f3(failDepth/fN)).append("\n");
        r.append("Exposure ratio failed/successful: ").append(f3((failExp/fN)/(successExp/sN))).append("x\n");
        r.append("Depth ratio failed/successful: ").append(f3((failDepth/fN)/(successDepth/sN))).append("x\n");

        r.append("\nSUCCESS RATE BY RECOVERY DEPTH\n");
        for(Map.Entry<String,Band357> e:depth.entrySet()){
            Band357 x=e.getValue();
            r.append(String.format(Locale.ROOT,"%-9s  episodes=%5d  success=%6.2f%%  avg exposure=£%7.2f  avg duration=%5.2f%n",
                e.getKey(),x.total,x.total==0?0:100.0*x.success/x.total,x.total==0?0:x.exposure/x.total,x.total==0?0:x.duration/x.total));
        }
        r.append("\nSUCCESS RATE BY RECOVERY EXPOSURE\n");
        for(Map.Entry<String,Band357> e:exposure.entrySet()){
            Band357 x=e.getValue();
            r.append(String.format(Locale.ROOT,"%-11s episodes=%5d  success=%6.2f%%  avg depth=£%6.2f  avg duration=%5.2f%n",
                e.getKey(),x.total,x.total==0?0:100.0*x.success/x.total,x.total==0?0:x.depth/x.total,x.total==0?0:x.duration/x.total));
        }
        r.append("\nSUCCESS RATE BY EPISODE START HAND\n");
        for(Map.Entry<String,Band357> e:start.entrySet()){
            Band357 x=e.getValue();
            r.append(String.format(Locale.ROOT,"%-12s episodes=%5d  success=%6.2f%%  avg exposure=£%7.2f  avg depth=£%6.2f%n",
                e.getKey(),x.total,x.total==0?0:100.0*x.success/x.total,x.total==0?0:x.exposure/x.total,x.total==0?0:x.depth/x.total));
        }

        write("Phase_3_57_"+c.name+"_Recovery_Depth_Bands.csv",bandCsv357("depth",depth));
        write("Phase_3_57_"+c.name+"_Recovery_Exposure_Bands.csv",bandCsv357("exposure",exposure));
        write("Phase_3_57_"+c.name+"_Recovery_StartHand_Bands.csv",bandCsv357("start_hand",start));
    }


    static String depthGroup358(double depth){
        if(depth<20)return "SHALLOW_<20";
        if(depth<40)return "MODERATE_20_<40";
        if(depth<50)return "DEEP_40_<50";
        return "SEVERE_50_PLUS";
    }

    static String timeGroup358(int startHand){
        int remaining=HANDS-startHand;
        if(remaining>=20)return "20_PLUS_HANDS_LEFT";
        if(remaining>=10)return "10_19_HANDS_LEFT";
        if(remaining>=5)return "5_9_HANDS_LEFT";
        return "0_4_HANDS_LEFT";
    }

    static final class Cell358{
        ArrayList<Recovery356> episodes=new ArrayList<>();
    }

    static double median358(ArrayList<Double> a){
        if(a.isEmpty())return 0.0;
        Collections.sort(a);
        int n=a.size();
        return n%2==1?a.get(n/2):(a.get(n/2-1)+a.get(n/2))/2.0;
    }

    static String decompose358(Cohort356 c,StringBuilder report){
        LinkedHashMap<String,Cell358> cells=new LinkedHashMap<>();
        String[] dg={"SHALLOW_<20","MODERATE_20_<40","DEEP_40_<50","SEVERE_50_PLUS"};
        String[] tg={"20_PLUS_HANDS_LEFT","10_19_HANDS_LEFT","5_9_HANDS_LEFT","0_4_HANDS_LEFT"};
        for(String d:dg)for(String t:tg)cells.put(d+"|"+t,new Cell358());

        for(Session356 s:c.sessions)for(Recovery356 x:s.recoveries){
            double dep=Math.max(0,100-x.trough);
            String key=depthGroup358(dep)+"|"+timeGroup358(x.startHand);
            cells.get(key).episodes.add(x);
        }

        StringBuilder csv=new StringBuilder(
            "cohort,depth_group,time_remaining_group,episodes,median_exposure,low_exposure_n,low_success_n,low_success_rate,high_exposure_n,high_success_n,high_success_rate,high_minus_low_pp,low_avg_duration,high_avg_duration,low_avg_depth,high_avg_depth\n");

        report.append("\n").append(c.name).append(" — DEPTH × TIME-REMAINING × EXPOSURE DECOMPOSITION\n");
        report.append("Within each depth/time cell, episodes are divided at that cell's median observed recovery exposure.\n");
        report.append("This is descriptive, not causal: exposure accumulates as an episode continues, so outcome and exposure are temporally entangled.\n\n");

        for(Map.Entry<String,Cell358> e:cells.entrySet()){
            String[] parts=e.getKey().split("\\|");
            ArrayList<Recovery356> eps=e.getValue().episodes;
            if(eps.isEmpty())continue;

            ArrayList<Double> vals=new ArrayList<>();
            for(Recovery356 x:eps)vals.add(x.exposure);
            double med=median358(vals);

            long ln=0,ls=0,hn=0,hs=0;
            double ldur=0,hdur=0,ldep=0,hdep=0;
            for(Recovery356 x:eps){
                boolean low=x.exposure<=med;
                double dur=x.endHand-x.startHand;
                double dep=Math.max(0,100-x.trough);
                if(low){ln++;if(x.recovered)ls++;ldur+=dur;ldep+=dep;}
                else{hn++;if(x.recovered)hs++;hdur+=dur;hdep+=dep;}
            }
            double lr=ln==0?0:100.0*ls/ln;
            double hr=hn==0?0:100.0*hs/hn;
            double diff=hr-lr;

            report.append(String.format(Locale.ROOT,
                "%-16s | %-18s | n=%4d | median exposure £%6.2f | lower exposure success %6.2f%% | higher exposure success %6.2f%% | difference %+6.2f pp%n",
                parts[0],parts[1],eps.size(),med,lr,hr,diff));

            csv.append(String.format(Locale.ROOT,
                "%s,%s,%s,%d,%.2f,%d,%d,%.4f,%d,%d,%.4f,%.4f,%.4f,%.4f,%.4f,%.4f%n",
                c.name,parts[0],parts[1],eps.size(),med,ln,ls,lr,hn,hs,hr,diff,
                ln==0?0:ldur/ln,hn==0?0:hdur/hn,ln==0?0:ldep/ln,hn==0?0:hdep/hn));
        }
        return csv.toString();
    }























    /* PHASE 3.80 — SAME-SEED PAIRED DISTRIBUTIONAL TEST */
    enum Policy380 { CONTROL, HIT_LE_15, CTX14_16 }

    static final class S380{
        String cohort,policy; int session,hands;
        double finalBank,cumWager,maxDrawdown,peakBank,giveBack;
        long playerBusts,hits,contextHits;
        boolean reached200,exhausted;
    }
    static final class H380{
        ArrayList<Integer> c=new ArrayList<>();
        int total(){int t=0,a=0;for(int v:c){t+=v;if(v==11)a++;}while(t>21&&a-->0)t-=10;return t;}
        boolean bust(){return total()>21;}
    }
    static int draw380(int[]shoe,int ptr,H380 h){h.c.add(shoe[ptr]);return ptr+1;}
    static boolean hit380(Policy380 p,int total,int up){
        if(p==Policy380.HIT_LE_15)return total<=15;
        if(p==Policy380.CTX14_16)return total<=13||(total>=14&&total<=16&&up>=7);
        return false;
    }
    static S380 runOne380(long seed,String cohort,int session,Policy380 policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        S380 s=new S380();s.cohort=cohort;s.policy=policy.name();s.session=session+1;
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;
            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;double base=bank>=170?15:normal355(hand,bank);if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;}
            else{wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            wager=Math.min(wager,bank);if(wager<=0)break;if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            double net,stake=wager;
            if(policy==Policy380.CONTROL){
                PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
                ptr=rr.endPointer;net=rr.net;stake=roundStake356(rr);
            }else{
                H380 p=new H380(),d=new H380();
                ptr=draw380(shoe,ptr,p);ptr=draw380(shoe,ptr,d);ptr=draw380(shoe,ptr,p);ptr=draw380(shoe,ptr,d);
                int visibleUpcard=d.c.get(0); // sole dealer information available to player
                while(!p.bust()&&hit380(policy,p.total(),visibleUpcard)){
                    if(policy==Policy380.CTX14_16&&p.total()>=14&&p.total()<=16&&visibleUpcard>=7)s.contextHits++;
                    ptr=draw380(shoe,ptr,p);s.hits++;
                }
                if(p.bust()){s.playerBusts++;net=-wager;}
                else{while(d.total()<17)ptr=draw380(shoe,ptr,d);if(d.bust()||p.total()>d.total())net=wager;else if(p.total()<d.total())net=-wager;else net=0;}
            }
            s.cumWager+=stake;bank+=net;if(bank<0)bank=0;s.hands++;peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=net>1e-9?1:(net<-1e-9?-1:0);hc++;
            if(bank>=200){s.reached200=true;break;}if(bank<=0){s.exhausted=true;break;}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        s.finalBank=bank;s.maxDrawdown=maxDD;s.peakBank=peak;s.giveBack=Math.max(0,peak-bank);
        if(bank>=200)s.reached200=true;if(bank<=0)s.exhausted=true;return s;
    }
    static ArrayList<S380> run380(long seed,String cohort,Policy380 p){ArrayList<S380>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne380(seed,cohort,i,p));return a;}
    static String pct380(long x,long n){return String.format(Locale.ROOT,"%.2f%%",100.0*x/n);}
    static int bandIndex380(double x){if(x<=1e-9)return 0;if(x<50)return 1;if(x<100)return 2;if(x<150)return 3;if(x<200)return 4;return 5;}
    static String bandName380(int k){return new String[]{"£0","£1-49","£50-99","£100-149","£150-199","£200+"}[k];}

    static void population380(StringBuilder r,String cohort,ArrayList<S380>[]g){
        r.append("\n").append(cohort).append(" — POPULATION SUMMARY\n");
        r.append(String.format(Locale.ROOT,"%-11s %9s %9s %9s %9s %9s%n","Policy","Final","£200","£0","MaxDD","Wager"));
        for(ArrayList<S380>a:g){long n=a.size(),t=0,z=0;double f=0,d=0,w=0;for(S380 s:a){f+=s.finalBank;d+=s.maxDrawdown;w+=s.cumWager;if(s.reached200)t++;if(s.exhausted)z++;}
            r.append(String.format(Locale.ROOT,"%-11s £%8.2f %8s %8s £%8.2f £%8.2f%n",a.get(0).policy,f/n,pct380(t,n),pct380(z,n),d/n,w/n));}
    }
    static void paired380(StringBuilder r,String cohort,ArrayList<S380>c,ArrayList<S380>s,ArrayList<S380>x){
        long n=c.size(),xwc=0,tc=0,cwx=0,xws=0,ts=0,swx=0;double dc=0,ds=0,abs=0,ddDelta=0,wDelta=0;
        long[][]bands=new long[3][6];
        for(int i=0;i<n;i++){
            S380 a=c.get(i),b=s.get(i),e=x.get(i);double d=e.finalBank-a.finalBank,q=e.finalBank-b.finalBank;
            dc+=d;ds+=q;abs+=Math.abs(d);ddDelta+=e.maxDrawdown-a.maxDrawdown;wDelta+=e.cumWager-a.cumWager;
            if(d>1e-9)xwc++;else if(d<-1e-9)cwx++;else tc++;
            if(q>1e-9)xws++;else if(q<-1e-9)swx++;else ts++;
            bands[0][bandIndex380(a.finalBank)]++;bands[1][bandIndex380(b.finalBank)]++;bands[2][bandIndex380(e.finalBank)]++;
        }
        r.append("\n").append(cohort).append(" — SAME-SEED PAIRED EVIDENCE\n");
        r.append("CTX14_16 versus CONTROL\n");
        r.append("CTX higher final: ").append(pct380(xwc,n)).append("\nCONTROL higher final: ").append(pct380(cwx,n)).append("\nExact final tie: ").append(pct380(tc,n)).append("\n");
        r.append(String.format(Locale.ROOT,"Mean paired final difference (CTX - CONTROL): £%.3f%nMean absolute paired final difference: £%.3f%nMean paired max-drawdown difference: £%.3f%nMean paired cumulative-wager difference: £%.3f%n",dc/n,abs/n,ddDelta/n,wDelta/n));
        r.append("\nCTX14_16 versus HIT_LE_15\n");
        r.append("CTX higher final: ").append(pct380(xws,n)).append("\nHIT_LE_15 higher final: ").append(pct380(swx,n)).append("\nExact final tie: ").append(pct380(ts,n)).append("\n");
        r.append(String.format(Locale.ROOT,"Mean paired final difference (CTX - HIT_LE_15): £%.3f%n",ds/n));
        r.append("\nFINAL BANKROLL BANDS\n");
        r.append(String.format(Locale.ROOT,"%-11s %10s %12s %12s%n","Band","CONTROL","HIT_LE_15","CTX14_16"));
        for(int k=0;k<6;k++)r.append(String.format(Locale.ROOT,"%-11s %10s %12s %12s%n",bandName380(k),pct380(bands[0][k],n),pct380(bands[1][k],n),pct380(bands[2][k],n)));
    }
    static String csv380(String cohort,ArrayList<S380>c,ArrayList<S380>s,ArrayList<S380>x){
        StringBuilder b=new StringBuilder("cohort,session,control_final,hit15_final,ctx_final,ctx_minus_control,ctx_minus_hit15,control_drawdown,hit15_drawdown,ctx_drawdown,control_wager,hit15_wager,ctx_wager,control_band,hit15_band,ctx_band\n");
        for(int i=0;i<c.size();i++){S380 a=c.get(i),d=s.get(i),e=x.get(i);b.append(String.format(Locale.ROOT,"%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s%n",cohort,i+1,a.finalBank,d.finalBank,e.finalBank,e.finalBank-a.finalBank,e.finalBank-d.finalBank,a.maxDrawdown,d.maxDrawdown,e.maxDrawdown,a.cumWager,d.cumWager,e.cumWager,bandName380(bandIndex380(a.finalBank)),bandName380(bandIndex380(d.finalBank)),bandName380(bandIndex380(e.finalBank))));}return b.toString();
    }

    /* PHASE 3.91 — EXISTING MAXIMUM-EXPOSURE REGION MAPPING
       No wager is increased. This instruments the frozen Phase 3.55 controller.
       The controller's highest nominal original-round wager is £30.
       This £30 state is an opportunity-mapping region; it is NOT itself re-labelled
       as a new >2x rule and does not reopen the closed 3.22–3.35 history trigger. */

    static final class R391 {
        String cohort; int session,hand;
        double bankBefore,baseWager,committedStake,net,bankAfter,peakBefore,drawdownAfter;
        boolean maxRegion,targetOnHand,bankruptOnHand;
    }
    static final class S391 {
        String cohort; int session,hands,maxRounds;
        double finalBank,peak,maxDD,cumWager,maxRegionExposure,maxRegionNet;
        boolean reached200,exhausted,everMaxRegion;
        ArrayList<R391> rounds=new ArrayList<>();
    }

    static S391 runOne391(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        S391 s=new S391();s.cohort=cohort;s.session=session+1;
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            R391 q=new R391();q.cohort=cohort;q.session=session+1;q.hand=hand;
            q.bankBefore=bank;q.baseWager=wager;q.peakBefore=peak;
            q.maxRegion=Math.abs(wager-30.0)<1e-9;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;
            q.committedStake=roundStake356(rr);q.net=rr.net;
            s.cumWager+=q.committedStake;
            if(q.maxRegion){s.maxRounds++;s.maxRegionExposure+=q.committedStake;s.maxRegionNet+=q.net;s.everMaxRegion=true;}

            bank+=rr.net;if(bank<0)bank=0;s.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            q.bankAfter=bank;q.drawdownAfter=peak-bank;
            q.targetOnHand=bank>=200;q.bankruptOnHand=bank<=0;
            s.rounds.add(q);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200){s.reached200=true;break;}
            if(bank<=0){s.exhausted=true;break;}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        s.finalBank=bank;s.peak=peak;s.maxDD=maxDD;
        return s;
    }

    static ArrayList<S391> run391(long seed,String cohort){
        ArrayList<S391>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne391(seed,cohort,i));
        return a;
    }

    static void summary391(StringBuilder r,String cohort,ArrayList<S391>a){
        long n=a.size(),ever=0,target=0,bust=0,targetEver=0,bustEver=0,targetNever=0,bustNever=0;
        long rounds=0,maxRounds=0,maxWins=0,maxLosses=0,maxPushes=0,maxTargetHands=0,maxBustHands=0;
        double finalAll=0,ddAll=0,wAll=0,finalEver=0,ddEver=0,wEver=0,exp=0,net=0,bankBefore=0,ddAfter=0;
        for(S391 s:a){
            rounds+=s.hands;maxRounds+=s.maxRounds;finalAll+=s.finalBank;ddAll+=s.maxDD;wAll+=s.cumWager;
            if(s.reached200)target++;if(s.exhausted)bust++;
            if(s.everMaxRegion){
                ever++;finalEver+=s.finalBank;ddEver+=s.maxDD;wEver+=s.cumWager;
                if(s.reached200)targetEver++;if(s.exhausted)bustEver++;
            } else {
                if(s.reached200)targetNever++;if(s.exhausted)bustNever++;
            }
            for(R391 q:s.rounds)if(q.maxRegion){
                exp+=q.committedStake;net+=q.net;bankBefore+=q.bankBefore;ddAfter+=q.drawdownAfter;
                if(q.net>1e-9)maxWins++;else if(q.net<-1e-9)maxLosses++;else maxPushes++;
                if(q.targetOnHand)maxTargetHands++;if(q.bankruptOnHand)maxBustHands++;
            }
        }
        long never=n-ever;
        r.append("\n").append(cohort).append(" — MAXIMUM-EXPOSURE REGION\n");
        r.append("Sessions: ").append(n).append("\n");
        r.append("Total played rounds: ").append(rounds).append("\n");
        r.append("£30 maximum-region rounds: ").append(maxRounds).append(" (").append(pct380(maxRounds,rounds)).append(" of played rounds)\n");
        r.append("Sessions ever entering £30 region: ").append(ever).append(" (").append(pct380(ever,n)).append(")\n");
        r.append(String.format(Locale.ROOT,"Average bankroll immediately before £30 round: £%.3f%n",maxRounds==0?0:bankBefore/maxRounds));
        r.append(String.format(Locale.ROOT,"Total committed exposure on £30 rounds incl. branches: £%.2f%n",exp));
        r.append(String.format(Locale.ROOT,"Average committed exposure per £30 round: £%.3f%n",maxRounds==0?0:exp/maxRounds));
        r.append(String.format(Locale.ROOT,"Net bankroll change on £30 rounds: £%+.2f%n",net));
        r.append(String.format(Locale.ROOT,"Return on committed £30-region exposure: %+.4f%%%n",exp==0?0:100.0*net/exp));
        r.append("£30-region W/L/P: ").append(maxWins).append(" / ").append(maxLosses).append(" / ").append(maxPushes).append("\n");
        r.append("£200 reached ON a £30-region round: ").append(maxTargetHands).append("\n");
        r.append("£0 reached ON a £30-region round: ").append(maxBustHands).append("\n");
        r.append(String.format(Locale.ROOT,"Average drawdown immediately after £30 round: £%.3f%n",maxRounds==0?0:ddAfter/maxRounds));

        r.append("\nSESSION ASSOCIATION — OBSERVATIONAL, NOT CAUSAL\n");
        r.append(String.format(Locale.ROOT,"Ever-£30 sessions average final / maxDD / cumulative wager: £%.3f / £%.3f / £%.3f%n",
            ever==0?0:finalEver/ever,ever==0?0:ddEver/ever,ever==0?0:wEver/ever));
        r.append("Ever-£30 sessions reaching £200 / £0: ").append(pct380(targetEver,ever)).append(" / ").append(pct380(bustEver,ever)).append("\n");
        r.append("Never-£30 sessions reaching £200 / £0: ").append(pct380(targetNever,never)).append(" / ").append(pct380(bustNever,never)).append("\n");
        r.append(String.format(Locale.ROOT,"Whole cohort average final / maxDD / cumulative wager: £%.3f / £%.3f / £%.3f%n",finalAll/n,ddAll/n,wAll/n));
        r.append("Whole cohort £200 / £0: ").append(pct380(target,n)).append(" / ").append(pct380(bust,n)).append("\n");
    }

    static String csv391(ArrayList<S391>...groups){
        StringBuilder b=new StringBuilder("cohort,session,hand,bank_before,base_wager,committed_stake,net,bank_after,peak_before,drawdown_after,max_region_30,target_on_hand,bankrupt_on_hand\n");
        for(ArrayList<S391>g:groups)for(S391 s:g)for(R391 q:s.rounds)
            b.append(String.format(Locale.ROOT,"%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s%n",
                q.cohort,q.session,q.hand,q.bankBefore,q.baseWager,q.committedStake,q.net,q.bankAfter,q.peakBefore,q.drawdownAfter,
                Boolean.toString(q.maxRegion),Boolean.toString(q.targetOnHand),Boolean.toString(q.bankruptOnHand)));
        return b.toString();
    }


    /* PHASE 3.92 — PROFIT RETENTION / GIVE-BACK
       Measurement only. Frozen Phase 3.55 controller. No wager change.
       Peak-profit give-back is measured relative to accumulated profit above
       the £100 starting bankroll. */

    static final class S392 {
        String cohort; int session,hands,peakHand;
        double finalBank,peak,maxDD,cumWager,postPeakExposure;
        boolean reached200,exhausted;
    }

    static S392 runOne392(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        int peakHand=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Double> banks=new ArrayList<>();
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;
            double st=roundStake356(rr);cum+=st;stakes.add(st);
            bank+=rr.net;if(bank<0)bank=0;banks.add(bank);
            if(bank>peak+1e-9){peak=bank;peakHand=hand;}
            maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200||bank<=0)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        double post=0;
        for(int i=peakHand;i<stakes.size();i++)post+=stakes.get(i); // rounds after peak hand
        S392 x=new S392();x.cohort=cohort;x.session=session+1;x.hands=stakes.size();
        x.peak=peak;x.peakHand=peakHand;x.finalBank=bank;x.maxDD=maxDD;x.cumWager=cum;x.postPeakExposure=post;
        x.reached200=bank>=200;x.exhausted=bank<=0;
        return x;
    }

    static ArrayList<S392> run392(long seed,String cohort){
        ArrayList<S392>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne392(seed,cohort,i));return a;
    }

    static void summary392(StringBuilder r,String cohort,ArrayList<S392>a){
        long n=a.size(),profitPeak=0,g25=0,g50=0,g75=0,g100=0,finishProfit=0,target=0,bust=0;
        double peakSum=0,finalSum=0,giveSum=0,givePctSum=0,postExp=0,cum=0;
        ArrayList<Double> givePcts=new ArrayList<>();
        for(S392 s:a){
            finalSum+=s.finalBank;cum+=s.cumWager;if(s.reached200)target++;if(s.exhausted)bust++;
            if(s.peak>100+1e-9){
                profitPeak++;double pp=s.peak-100,gb=Math.max(0,s.peak-s.finalBank),gp=100*gb/pp;
                peakSum+=s.peak;giveSum+=gb;givePctSum+=gp;givePcts.add(gp);postExp+=s.postPeakExposure;
                if(gp>=25-1e-9)g25++;if(gp>=50-1e-9)g50++;if(gp>=75-1e-9)g75++;if(gp>=100-1e-9)g100++;
                if(s.finalBank>100+1e-9)finishProfit++;
            }
        }
        Collections.sort(givePcts);
        double med=givePcts.isEmpty()?0:givePcts.get(givePcts.size()/2);
        r.append("\n").append(cohort).append("\n");
        r.append("Sessions: ").append(n).append("\n");
        r.append("Sessions ever above £100: ").append(profitPeak).append(" (").append(pct380(profitPeak,n)).append(")\n");
        r.append(String.format(Locale.ROOT,"Average peak among profit-peaking sessions: £%.3f%n",profitPeak==0?0:peakSum/profitPeak));
        r.append(String.format(Locale.ROOT,"Average final bankroll, whole cohort: £%.3f%n",finalSum/n));
        r.append(String.format(Locale.ROOT,"Average peak-to-finish give-back among profit-peaking sessions: £%.3f%n",profitPeak==0?0:giveSum/profitPeak));
        r.append(String.format(Locale.ROOT,"Average / median give-back as %% of accumulated peak profit: %.3f%% / %.3f%%%n",profitPeak==0?0:givePctSum/profitPeak,med));
        r.append("Surrendered >=25% of peak profit: ").append(pct380(g25,profitPeak)).append("\n");
        r.append("Surrendered >=50%: ").append(pct380(g50,profitPeak)).append("\n");
        r.append("Surrendered >=75%: ").append(pct380(g75,profitPeak)).append("\n");
        r.append("Surrendered >=100% (all peak profit or more): ").append(pct380(g100,profitPeak)).append("\n");
        r.append("Profit-peaking sessions still finishing >£100: ").append(pct380(finishProfit,profitPeak)).append("\n");
        r.append(String.format(Locale.ROOT,"Average exposure AFTER the eventual peak: £%.3f%n",profitPeak==0?0:postExp/profitPeak));
        r.append(String.format(Locale.ROOT,"Whole-cohort average cumulative wager: £%.3f%n",cum/n));
        r.append("Whole-cohort £200 / £0: ").append(pct380(target,n)).append(" / ").append(pct380(bust,n)).append("\n");
    }

    static String csv392(ArrayList<S392>...groups){
        StringBuilder b=new StringBuilder("cohort,session,hands,peak_bankroll,peak_hand,final_bankroll,peak_profit,giveback_amount,giveback_pct_of_peak_profit,post_peak_exposure,max_drawdown,cumulative_wager,reached_200,exhausted\n");
        for(ArrayList<S392>g:groups)for(S392 s:g){
            double pp=Math.max(0,s.peak-100),gb=pp>0?Math.max(0,s.peak-s.finalBank):0,gp=pp>0?100*gb/pp:0;
            b.append(String.format(Locale.ROOT,"%s,%d,%d,%.2f,%d,%.2f,%.2f,%.2f,%.4f,%.2f,%.2f,%.2f,%s,%s%n",
                s.cohort,s.session,s.hands,s.peak,s.peakHand,s.finalBank,pp,gb,gp,s.postPeakExposure,s.maxDD,s.cumWager,
                Boolean.toString(s.reached200),Boolean.toString(s.exhausted)));
        }return b.toString();
    }


    /* PHASE 3.93 — OBSERVABLE PROFIT-TIER RETENTION MAP
       Measurement only. Frozen Phase 3.55 controller.
       Milestones are prospectively observable bankroll states:
       £110, £120, ..., £190.
       We measure what happens AFTER FIRST ATTAINMENT. No stopping rule. */

    static final int[] TIERS393={110,120,130,140,150,160,170,180,190};

    static final class S393 {
        String cohort; int session,hands;
        double finalBank,maxDD,cumWager;
        boolean reached200,exhausted;
        int[] firstHand=new int[TIERS393.length];
        double[] postExposure=new double[TIERS393.length];
        double[] maxAfter=new double[TIERS393.length];
        boolean[] below100After=new boolean[TIERS393.length];
        boolean[] exhaustedAfter=new boolean[TIERS393.length];
        boolean[] reached200After=new boolean[TIERS393.length];
    }

    static S393 runOne393(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        S393 x=new S393();x.cohort=cohort;x.session=session+1;
        Arrays.fill(x.firstHand,-1);
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;double stake=roundStake356(rr);cum+=stake;
            for(int j=0;j<TIERS393.length;j++)if(x.firstHand[j]>=0)x.postExposure[j]+=stake;

            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            for(int j=0;j<TIERS393.length;j++){
                if(x.firstHand[j]<0 && bank>=TIERS393[j]-1e-9){
                    x.firstHand[j]=hand;x.maxAfter[j]=bank;
                }
                if(x.firstHand[j]>=0){
                    x.maxAfter[j]=Math.max(x.maxAfter[j],bank);
                    if(hand>x.firstHand[j] && bank<100-1e-9)x.below100After[j]=true;
                    if(bank>=200-1e-9)x.reached200After[j]=true;
                    if(bank<=1e-9)x.exhaustedAfter[j]=true;
                }
            }

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200){x.reached200=true;break;}
            if(bank<=0){x.exhausted=true;break;}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        x.finalBank=bank;x.maxDD=maxDD;x.cumWager=cum;return x;
    }

    static ArrayList<S393> run393(long seed,String cohort){
        ArrayList<S393>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne393(seed,cohort,i));return a;
    }

    static void tiers393(StringBuilder r,String cohort,ArrayList<S393>a){
        r.append("\n").append(cohort).append("\n");
        r.append("Tier | Reached | Avg first hand | Finish >=tier | Finish >£100 | Later £200 | Later <£100 | Later £0 | Avg post-tier exposure | Avg give-back from max-after-tier\n");
        for(int j=0;j<TIERS393.length;j++){
            long n=0,ret=0,profit=0,t200=0,below=0,bust=0;double fh=0,pex=0,gb=0;
            for(S393 s:a)if(s.firstHand[j]>=0){
                n++;fh+=s.firstHand[j];pex+=s.postExposure[j];
                if(s.finalBank>=TIERS393[j]-1e-9)ret++;
                if(s.finalBank>100+1e-9)profit++;
                if(s.reached200After[j])t200++;
                if(s.below100After[j])below++;
                if(s.exhaustedAfter[j])bust++;
                gb+=Math.max(0,s.maxAfter[j]-s.finalBank);
            }
            r.append(String.format(Locale.ROOT,"£%d | %d (%.2f%%) | %.2f | %.2f%% | %.2f%% | %.2f%% | %.2f%% | %.2f%% | £%.2f | £%.2f%n",
                TIERS393[j],n,100.0*n/a.size(),n==0?0:fh/n,n==0?0:100.0*ret/n,n==0?0:100.0*profit/n,
                n==0?0:100.0*t200/n,n==0?0:100.0*below/n,n==0?0:100.0*bust/n,n==0?0:pex/n,n==0?0:gb/n));
        }
    }

    static String csv393(ArrayList<S393>...groups){
        StringBuilder b=new StringBuilder("cohort,session,tier,first_reach_hand,final_bankroll,finish_ge_tier,finish_gt_100,later_reach_200,later_below_100,later_exhausted,post_tier_exposure,max_after_tier,giveback_from_max_after_tier\n");
        for(ArrayList<S393>g:groups)for(S393 s:g)for(int j=0;j<TIERS393.length;j++)if(s.firstHand[j]>=0)
            b.append(String.format(Locale.ROOT,"%s,%d,%d,%d,%.2f,%s,%s,%s,%s,%s,%.2f,%.2f,%.2f%n",
                s.cohort,s.session,TIERS393[j],s.firstHand[j],s.finalBank,
                Boolean.toString(s.finalBank>=TIERS393[j]-1e-9),Boolean.toString(s.finalBank>100+1e-9),
                Boolean.toString(s.reached200After[j]),Boolean.toString(s.below100After[j]),Boolean.toString(s.exhaustedAfter[j]),
                s.postExposure[j],s.maxAfter[j],Math.max(0,s.maxAfter[j]-s.finalBank)));
        return b.toString();
    }


    /* PHASE 3.94 — PREDECLARED PROFIT-EXIT INTERVENTION SCREEN
       Frozen BEFORE execution from Phase 3.93:
       REFERENCE (unchanged 30-hand architecture), EXIT_140, EXIT_150, EXIT_160.
       Exit policies stop immediately after the first completed round on which
       bankroll reaches/exceeds the threshold. No wager-controller change. */

    static final int[] EXITS394={0,140,150,160};
    static final String[] NAMES394={"REFERENCE_30_HAND","EXIT_140","EXIT_150","EXIT_160"};

    static final class S394 {
        String cohort,policy; int session,hands,exitHand;
        double finalBank,peak,maxDD,cumWager,exitBank;
        boolean reached200,exhausted,exited;
        boolean everBelow100,recovered100;
        double maxProfitGiveback;
    }

    static S394 runOne394(long seed,String cohort,int session,int exitThreshold,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean everBelow=false,recovered=false;
        S394 x=new S394();x.cohort=cohort;x.policy=policy;x.session=session+1;
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            if(bank<100-1e-9)everBelow=true;
            if(everBelow&&bank>=100-1e-9)recovered=true;

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}

            if(exitThreshold>0 && bank>=exitThreshold-1e-9){
                x.exited=true;x.exitHand=hand;x.exitBank=bank;break;
            }

            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        x.everBelow100=everBelow;x.recovered100=recovered;
        x.maxProfitGiveback=Math.max(0,peak-bank);
        return x;
    }

    static ArrayList<S394> run394(long seed,String cohort,int threshold,String policy){
        ArrayList<S394>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne394(seed,cohort,i,threshold,policy));
        return a;
    }

    static void summary394(StringBuilder r,String cohort,String policy,ArrayList<S394>a){
        long n=a.size(),pos=0,be=0,loss=0,t200=0,bust=0,exit=0,below=0,rec=0;
        double fin=0,dd=0,w=0,gb=0,exitHand=0,exitBank=0;
        for(S394 s:a){
            fin+=s.finalBank;dd+=s.maxDD;w+=s.cumWager;gb+=s.maxProfitGiveback;
            if(s.finalBank>100+1e-9)pos++;else if(Math.abs(s.finalBank-100)<1e-9)be++;else loss++;
            if(s.reached200)t200++;if(s.exhausted)bust++;
            if(s.exited){exit++;exitHand+=s.exitHand;exitBank+=s.exitBank;}
            if(s.everBelow100){below++;if(s.recovered100)rec++;}
        }
        double net=fin-100.0*n;
        r.append("\n").append(cohort).append(" / ").append(policy).append("\n");
        r.append(String.format(Locale.ROOT,"Average ending bankroll: £%.3f%n",fin/n));
        r.append(String.format(Locale.ROOT,"Population net change: £%+.2f%n",net));
        r.append(String.format(Locale.ROOT,"Population return on cumulative wager: %+.4f%%%n",w==0?0:100*net/w));
        r.append("Positive / break-even / losing sessions: ").append(pct380(pos,n)).append(" / ").append(pct380(be,n)).append(" / ").append(pct380(loss,n)).append("\n");
        r.append("£200 attainment: ").append(pct380(t200,n)).append("\n");
        r.append("£0 exhaustion: ").append(pct380(bust,n)).append("\n");
        r.append(String.format(Locale.ROOT,"Average maximum drawdown: £%.3f%n",dd/n));
        r.append(String.format(Locale.ROOT,"Average cumulative wager: £%.3f%n",w/n));
        r.append("Sessions ever below £100: ").append(pct380(below,n)).append("\n");
        r.append("Recovery to >=£100 among below-£100 sessions: ").append(pct380(rec,below)).append("\n");
        r.append(String.format(Locale.ROOT,"Average peak-to-finish give-back: £%.3f%n",gb/n));
        r.append(String.format(Locale.ROOT,"Bankroll change per £100 wagered: £%+.3f%n",w==0?0:100*net/w));
        if(exit>0){
            r.append("Policy exits triggered: ").append(pct380(exit,n)).append("\n");
            r.append(String.format(Locale.ROOT,"Average exit hand / retained bankroll when triggered: %.2f / £%.3f%n",exitHand/exit,exitBank/exit));
        } else r.append("Policy exits triggered: N/A (reference)\n");
    }

    static String csv394(ArrayList<S394>...groups){
        StringBuilder b=new StringBuilder("cohort,policy,session,hands,final_bankroll,peak_bankroll,max_drawdown,cumulative_wager,reached_200,exhausted,positive,ever_below_100,recovered_100,peak_to_finish_giveback,exit_triggered,exit_hand,exit_bankroll\n");
        for(ArrayList<S394>g:groups)for(S394 s:g)
            b.append(String.format(Locale.ROOT,"%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%.2f,%s,%d,%.2f%n",
                s.cohort,s.policy,s.session,s.hands,s.finalBank,s.peak,s.maxDD,s.cumWager,
                Boolean.toString(s.reached200),Boolean.toString(s.exhausted),Boolean.toString(s.finalBank>100+1e-9),
                Boolean.toString(s.everBelow100),Boolean.toString(s.recovered100),s.maxProfitGiveback,
                Boolean.toString(s.exited),s.exitHand,s.exitBank));
        return b.toString();
    }


    /* PHASE 3.95 — TRAILING / HIGH-WATER PROFIT-PROTECTION MAP
       MEASUREMENT ONLY.
       No session is stopped and no wager is changed.
       We retrospectively mark the FIRST observable occasion after a session has
       reached a qualifying high-water profit state where bankroll gives back
       25%, 50%, 75%, or 100% of the accumulated profit above £100.
       Activation floors £140/£150/£160 are mapped separately.
       This is candidate discovery, not an intervention. */

    static final int[] FLOORS395={140,150,160};
    static final int[] BANDS395={25,50,75,100};

    static final class S395 {
        String cohort; int session,hands;
        double finalBank,peak,maxDD,cumWager;
        boolean reached200,exhausted;
        int[][] trigHand=new int[FLOORS395.length][BANDS395.length];
        double[][] trigBank=new double[FLOORS395.length][BANDS395.length];
        double[][] trigPeak=new double[FLOORS395.length][BANDS395.length];
        double[][] postTrigExposure=new double[FLOORS395.length][BANDS395.length];
        boolean[][] later200=new boolean[FLOORS395.length][BANDS395.length];
        boolean[][] later0=new boolean[FLOORS395.length][BANDS395.length];
        boolean[][] laterBelow100=new boolean[FLOORS395.length][BANDS395.length];
    }

    static S395 runOne395(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean[] activated=new boolean[FLOORS395.length];
        S395 x=new S395();x.cohort=cohort;x.session=session+1;
        for(int i=0;i<FLOORS395.length;i++)Arrays.fill(x.trigHand[i],-1);

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;double stake=roundStake356(rr);cum+=stake;

            // Any already-triggered candidate continues to accumulate actual exposure.
            for(int i=0;i<FLOORS395.length;i++)for(int j=0;j<BANDS395.length;j++)
                if(x.trigHand[i][j]>=0)x.postTrigExposure[i][j]+=stake;

            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            for(int i=0;i<FLOORS395.length;i++){
                if(bank>=FLOORS395[i]-1e-9)activated[i]=true;
                if(activated[i] && peak>100+1e-9){
                    double profit=peak-100;
                    double give=Math.max(0,peak-bank);
                    double pct=100*give/profit;
                    for(int j=0;j<BANDS395.length;j++)if(x.trigHand[i][j]<0 && pct>=BANDS395[j]-1e-9){
                        x.trigHand[i][j]=hand;x.trigBank[i][j]=bank;x.trigPeak[i][j]=peak;
                    }
                }
                for(int j=0;j<BANDS395.length;j++)if(x.trigHand[i][j]>=0 && hand>x.trigHand[i][j]){
                    if(bank>=200-1e-9)x.later200[i][j]=true;
                    if(bank<=1e-9)x.later0[i][j]=true;
                    if(bank<100-1e-9)x.laterBelow100[i][j]=true;
                }
            }

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200){x.reached200=true;break;}
            if(bank<=0){x.exhausted=true;break;}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;return x;
    }

    static ArrayList<S395> run395(long seed,String cohort){
        ArrayList<S395>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne395(seed,cohort,i));return a;
    }

    static void map395(StringBuilder r,String cohort,ArrayList<S395>a){
        r.append("\n").append(cohort).append("\n");
        r.append("Activation | Give-back trigger | Triggered sessions | Avg trigger hand | Avg peak at trigger | Avg bankroll at trigger | Later £200 | Later <£100 | Later £0 | Avg exposure after trigger\n");
        for(int i=0;i<FLOORS395.length;i++)for(int j=0;j<BANDS395.length;j++){
            long n=0,t200=0,below=0,bust=0;double h=0,p=0,b=0,e=0;
            for(S395 s:a)if(s.trigHand[i][j]>=0){
                n++;h+=s.trigHand[i][j];p+=s.trigPeak[i][j];b+=s.trigBank[i][j];e+=s.postTrigExposure[i][j];
                if(s.later200[i][j])t200++;if(s.laterBelow100[i][j])below++;if(s.later0[i][j])bust++;
            }
            r.append(String.format(Locale.ROOT,"£%d | %d%% | %d (%.2f%%) | %.2f | £%.2f | £%.2f | %.2f%% | %.2f%% | %.2f%% | £%.2f%n",
                FLOORS395[i],BANDS395[j],n,100.0*n/a.size(),n==0?0:h/n,n==0?0:p/n,n==0?0:b/n,
                n==0?0:100.0*t200/n,n==0?0:100.0*below/n,n==0?0:100.0*bust/n,n==0?0:e/n));
        }
    }

    static String csv395(ArrayList<S395>...groups){
        StringBuilder b=new StringBuilder("cohort,session,activation_floor,giveback_trigger_pct,triggered,trigger_hand,peak_at_trigger,bankroll_at_trigger,post_trigger_exposure,later_200,later_below_100,later_0,final_bankroll\n");
        for(ArrayList<S395>g:groups)for(S395 s:g)for(int i=0;i<FLOORS395.length;i++)for(int j=0;j<BANDS395.length;j++)
            b.append(String.format(Locale.ROOT,"%s,%d,%d,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%.2f%n",
                s.cohort,s.session,FLOORS395[i],BANDS395[j],Boolean.toString(s.trigHand[i][j]>=0),s.trigHand[i][j],
                s.trigPeak[i][j],s.trigBank[i][j],s.postTrigExposure[i][j],
                Boolean.toString(s.later200[i][j]),Boolean.toString(s.laterBelow100[i][j]),Boolean.toString(s.later0[i][j]),s.finalBank));
        return b.toString();
    }


    /* PHASE 3.96 — PREDECLARED TRAILING PROFIT-STOP INTERVENTION
       Frozen before execution from Phase 3.95:
       activation floor £160;
       trigger = >=25% surrender of running accumulated profit above £100;
       action = terminate immediately after the completed round producing trigger.
       Comparators:
       unchanged 30-hand reference;
       hard EXIT160 contextual benchmark.
       No wager or multiplier rule is changed. */

    static final String REF396="REFERENCE_30_HAND";
    static final String HARD396="HARD_EXIT_160";
    static final String TRAIL396="TRAIL_160_GIVEBACK_25";

    static final class S396 {
        String cohort,policy; int session,hands,stopHand;
        double finalBank,peak,maxDD,cumWager,stopBank;
        boolean reached200,exhausted,stopped,everBelow100,recovered100;
        double giveback;
    }

    static S396 runOne396(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,everBelow=false,recovered=false;
        S396 x=new S396();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {
                wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;
            cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;

            peak=Math.max(peak,bank);
            maxDD=Math.max(maxDD,peak-bank);

            if(bank<100-1e-9)everBelow=true;
            if(everBelow&&bank>=100-1e-9)recovered=true;

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            // Existing target/exhaustion termination retains precedence.
            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}

            if(bank>=160-1e-9)activated160=true;

            if(policy.equals(HARD396) && activated160){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;
            }

            if(policy.equals(TRAIL396) && activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9){
                    x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        x.everBelow100=everBelow;x.recovered100=recovered;
        x.giveback=Math.max(0,peak-bank);
        return x;
    }

    static ArrayList<S396> run396(long seed,String cohort,String policy){
        ArrayList<S396>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne396(seed,cohort,i,policy));
        return a;
    }

    static void summary396(StringBuilder r,String cohort,String policy,ArrayList<S396>a){
        long n=a.size(),pos=0,be=0,loss=0,t200=0,bust=0,stop=0,below=0,rec=0;
        double fin=0,dd=0,w=0,gb=0,sh=0,sb=0;
        for(S396 s:a){
            fin+=s.finalBank;dd+=s.maxDD;w+=s.cumWager;gb+=s.giveback;
            if(s.finalBank>100+1e-9)pos++;else if(Math.abs(s.finalBank-100)<1e-9)be++;else loss++;
            if(s.reached200)t200++;if(s.exhausted)bust++;
            if(s.stopped){stop++;sh+=s.stopHand;sb+=s.stopBank;}
            if(s.everBelow100){below++;if(s.recovered100)rec++;}
        }
        double net=fin-100.0*n;
        r.append("\n").append(cohort).append(" / ").append(policy).append("\n");
        r.append(String.format(Locale.ROOT,"Average ending bankroll: £%.3f%n",fin/n));
        r.append(String.format(Locale.ROOT,"Population net change: £%+.2f%n",net));
        r.append(String.format(Locale.ROOT,"Population return on cumulative wager: %+.4f%%%n",w==0?0:100.0*net/w));
        r.append("Positive / break-even / losing sessions: ").append(pct380(pos,n)).append(" / ").append(pct380(be,n)).append(" / ").append(pct380(loss,n)).append("\n");
        r.append("£200 attainment: ").append(pct380(t200,n)).append("\n");
        r.append("£0 exhaustion: ").append(pct380(bust,n)).append("\n");
        r.append(String.format(Locale.ROOT,"Average maximum drawdown: £%.3f%n",dd/n));
        r.append(String.format(Locale.ROOT,"Average cumulative wager: £%.3f%n",w/n));
        r.append("Sessions ever below £100: ").append(pct380(below,n)).append("\n");
        r.append("Recovery to >=£100 among below-£100 sessions: ").append(pct380(rec,below)).append("\n");
        r.append(String.format(Locale.ROOT,"Average peak-to-finish give-back: £%.3f%n",gb/n));
        r.append(String.format(Locale.ROOT,"Bankroll change per £100 wagered: £%+.3f%n",w==0?0:100.0*net/w));
        if(stop>0){
            r.append("Policy stops triggered: ").append(pct380(stop,n)).append("\n");
            r.append(String.format(Locale.ROOT,"Average stop hand / retained bankroll: %.2f / £%.3f%n",sh/stop,sb/stop));
        } else r.append("Policy stops triggered: N/A / none\n");
    }

    static String csv396(ArrayList<S396>...groups){
        StringBuilder b=new StringBuilder("cohort,policy,session,hands,final_bankroll,peak_bankroll,max_drawdown,cumulative_wager,reached_200,exhausted,positive,ever_below_100,recovered_100,peak_to_finish_giveback,stop_triggered,stop_hand,stop_bankroll\n");
        for(ArrayList<S396>g:groups)for(S396 s:g)
            b.append(String.format(Locale.ROOT,"%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%.2f,%s,%d,%.2f%n",
                s.cohort,s.policy,s.session,s.hands,s.finalBank,s.peak,s.maxDD,s.cumWager,
                Boolean.toString(s.reached200),Boolean.toString(s.exhausted),
                Boolean.toString(s.finalBank>100+1e-9),Boolean.toString(s.everBelow100),
                Boolean.toString(s.recovered100),s.giveback,Boolean.toString(s.stopped),s.stopHand,s.stopBank));
        return b.toString();
    }


    /* PHASE 3.97 — PAIRED CAUSAL DECOMPOSITION
       No new policy and no threshold tuning.
       Pair the frozen Phase 3.96 TRAIL160/25 outcome with the unchanged
       reference outcome for the identical cohort/session seed.
       Classification concerns only sessions in which the trailing stop fires. */

    static final class P397 {
        String cohort; int session;
        S396 ref,trail;
        String className;
        double finalDelta,wagerRemoved,drawdownReduced,profitPreserved;
    }

    static String class397(S396 r,S396 t){
        if(!t.stopped)return "UNCHANGED_NOT_TRIGGERED";
        if(r.reached200)return "PREMATURE_EXIT_SACRIFICED_200";
        if(r.exhausted)return "GOOD_SAVE_PREVENTED_0";
        if(r.finalBank<100-1e-9 && t.finalBank>=100-1e-9)return "GOOD_SAVE_PREVENTED_LOSS_FINISH";
        if(t.finalBank>r.finalBank+1e-9)return "GOOD_SAVE_HIGHER_FINAL";
        if(Math.abs(t.finalBank-r.finalBank)<=1e-9)return "NEUTRAL_SAME_FINAL";
        return "PREMATURE_EXIT_LOWER_FINAL";
    }

    static ArrayList<P397> pair397(long seed,String cohort){
        ArrayList<P397>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++){
            S396 r=runOne396(seed,cohort,i,REF396);
            S396 t=runOne396(seed,cohort,i,TRAIL396);
            P397 p=new P397();p.cohort=cohort;p.session=i+1;p.ref=r;p.trail=t;
            p.className=class397(r,t);
            p.finalDelta=t.finalBank-r.finalBank;
            p.wagerRemoved=r.cumWager-t.cumWager;
            p.drawdownReduced=r.maxDD-t.maxDD;
            p.profitPreserved=t.finalBank-r.finalBank;
            a.add(p);
        }return a;
    }

    static void summary397(StringBuilder r,String cohort,ArrayList<P397>a){
        long trig=0,ref200=0,ref0=0,refLoss=0,refPos=0;
        long higher=0,lower=0,same=0,good=0,prem=0;
        double dFinal=0,wRemoved=0,ddReduced=0,stopBank=0,stopHand=0;
        TreeMap<String,Integer> cls=new TreeMap<>();
        for(P397 p:a){
            if(!p.trail.stopped)continue;
            trig++;
            cls.put(p.className,cls.getOrDefault(p.className,0)+1);
            if(p.ref.reached200)ref200++;
            if(p.ref.exhausted)ref0++;
            if(p.ref.finalBank<100-1e-9)refLoss++;
            if(p.ref.finalBank>100+1e-9)refPos++;
            if(p.finalDelta>1e-9)higher++;else if(p.finalDelta<-1e-9)lower++;else same++;
            if(p.className.startsWith("GOOD_SAVE"))good++;
            if(p.className.startsWith("PREMATURE_EXIT"))prem++;
            dFinal+=p.finalDelta;wRemoved+=p.wagerRemoved;ddReduced+=p.drawdownReduced;
            stopBank+=p.trail.stopBank;stopHand+=p.trail.stopHand;
        }
        r.append("\n").append(cohort).append("\n");
        r.append("Trailing-triggered paired sessions: ").append(trig).append(" (").append(pct380(trig,a.size())).append(")\n");
        r.append("REFERENCE fate of those same sessions:\n");
        r.append("  Would later reach £200: ").append(pct380(ref200,trig)).append("\n");
        r.append("  Would later exhaust £0: ").append(pct380(ref0,trig)).append("\n");
        r.append("  Would finish below £100: ").append(pct380(refLoss,trig)).append("\n");
        r.append("  Would finish above £100: ").append(pct380(refPos,trig)).append("\n");
        r.append("TRAILING versus paired REFERENCE final bankroll:\n");
        r.append("  Higher under trailing: ").append(pct380(higher,trig)).append("\n");
        r.append("  Lower under trailing: ").append(pct380(lower,trig)).append("\n");
        r.append("  Same: ").append(pct380(same,trig)).append("\n");
        r.append(String.format(Locale.ROOT,"  Average paired final-bankroll change: £%+.3f%n",trig==0?0:dFinal/trig));
        r.append(String.format(Locale.ROOT,"Average wager removed per triggered session: £%.3f%n",trig==0?0:wRemoved/trig));
        r.append(String.format(Locale.ROOT,"Average max-drawdown reduction per triggered session: £%+.3f%n",trig==0?0:ddReduced/trig));
        r.append(String.format(Locale.ROOT,"Average trigger hand / retained bankroll: %.2f / £%.3f%n",trig==0?0:stopHand/trig,trig==0?0:stopBank/trig));
        r.append("CLASSIFICATION (mutually exclusive):\n");
        for(Map.Entry<String,Integer>e:cls.entrySet())
            r.append("  ").append(e.getKey()).append(": ").append(e.getValue()).append(" (").append(pct380(e.getValue(),trig)).append(")\n");
        r.append("  Broad GOOD_SAVE classes: ").append(pct380(good,trig)).append("\n");
        r.append("  Broad PREMATURE_EXIT classes: ").append(pct380(prem,trig)).append("\n");
    }

    static String csv397(ArrayList<P397>...groups){
        StringBuilder b=new StringBuilder("cohort,session,trail_triggered,class,trigger_hand,trigger_bankroll,reference_final,trailing_final,final_delta,reference_reached_200,reference_exhausted,reference_cumulative_wager,trailing_cumulative_wager,wager_removed,reference_max_drawdown,trailing_max_drawdown,drawdown_reduced\n");
        for(ArrayList<P397>g:groups)for(P397 p:g)
            b.append(String.format(Locale.ROOT,"%s,%d,%s,%s,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f%n",
                p.cohort,p.session,Boolean.toString(p.trail.stopped),p.className,p.trail.stopHand,p.trail.stopBank,
                p.ref.finalBank,p.trail.finalBank,p.finalDelta,Boolean.toString(p.ref.reached200),Boolean.toString(p.ref.exhausted),
                p.ref.cumWager,p.trail.cumWager,p.wagerRemoved,p.ref.maxDD,p.trail.maxDD,p.drawdownReduced));
        return b.toString();
    }


    /* PHASE 3.98 — FROZEN TRIGGER-STATE SEPARATION MAP
       No selective intervention.
       Freeze the TRAIL160/25 trigger from Phases 3.95–3.97 and record only
       information legitimately observable at that trigger.
       Then label the same session by its unchanged REFERENCE future:
       LATER_200, LATER_COLLAPSE (<£100 final, including £0), or MIDDLE.
       This is descriptive separation evidence, not future-card prediction. */

    static final class T398 {
        String cohort; int session,triggerHand;
        double triggerBank,highWater,absGiveback,givebackPct,cumExposure;
        int recentBalance,recentWins,recentLosses,recentPushes;
        boolean priorBelow100,cooling,cautious,brakeArmed;
        String futureClass;
        double refFinal;
        boolean ref200,ref0;
    }

    static T398 observe398(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,priorBelow=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);

            int outcome=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            hist[hc%hist.length]=outcome;hc++;

            if(bank<100-1e-9)priorBelow=true;
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(bank>=160-1e-9)activated160=true;

            if(activated160 && peak>100+1e-9){
                double abs=peak-bank;
                double pct=100.0*abs/(peak-100.0);
                if(pct>=25.0-1e-9){
                    T398 t=new T398();t.cohort=cohort;t.session=session+1;t.triggerHand=hand;
                    t.triggerBank=bank;t.highWater=peak;t.absGiveback=abs;t.givebackPct=pct;t.cumExposure=cum;
                    t.priorBelow100=priorBelow;t.cooling=cooling;t.cautious=cautious;t.brakeArmed=brakeArmed;
                    int lim=Math.min(hc,hist.length);
                    for(int k=0;k<lim;k++){
                        int v=hist[(hc-1-k+hist.length)%hist.length];
                        if(v>0)t.recentWins++;else if(v<0)t.recentLosses++;else t.recentPushes++;
                    }
                    t.recentBalance=t.recentWins-t.recentLosses;
                    return t;
                }
            }
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        return null;
    }

    static ArrayList<T398> run398(long seed,String cohort){
        ArrayList<T398>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++){
            T398 t=observe398(seed,cohort,i);
            if(t==null)continue;
            S396 ref=runOne396(seed,cohort,i,REF396);
            t.refFinal=ref.finalBank;t.ref200=ref.reached200;t.ref0=ref.exhausted;
            if(ref.reached200)t.futureClass="LATER_200";
            else if(ref.finalBank<100-1e-9)t.futureClass="LATER_COLLAPSE";
            else t.futureClass="MIDDLE";
            a.add(t);
        }return a;
    }

    static void classSummary398(StringBuilder r,String cohort,ArrayList<T398>a){
        r.append("\n").append(cohort).append("\n");
        r.append("Future class | N | Trigger hand | Trigger bank | High-water | Abs give-back | Give-back % | Exposure so far | Recent W-L balance | Prior <£100\n");
        for(String c:new String[]{"LATER_200","LATER_COLLAPSE","MIDDLE"}){
            long n=0,prior=0;double hand=0,bank=0,peak=0,abs=0,pct=0,exp=0,bal=0;
            for(T398 t:a)if(t.futureClass.equals(c)){
                n++;hand+=t.triggerHand;bank+=t.triggerBank;peak+=t.highWater;abs+=t.absGiveback;
                pct+=t.givebackPct;exp+=t.cumExposure;bal+=t.recentBalance;if(t.priorBelow100)prior++;
            }
            r.append(String.format(Locale.ROOT,"%s | %d (%.2f%%) | %.2f | £%.2f | £%.2f | £%.2f | %.2f%% | £%.2f | %.3f | %.2f%%%n",
                c,n,100.0*n/a.size(),n==0?0:hand/n,n==0?0:bank/n,n==0?0:peak/n,n==0?0:abs/n,
                n==0?0:pct/n,n==0?0:exp/n,n==0?0:bal/n,n==0?0:100.0*prior/n));
        }

        // Predeclared coarse bins for descriptive separation only.
        r.append("\nCOARSE OBSERVABLE BINS — later £200 rate / later collapse rate\n");
        String[] hn={"hand <=12","hand 13-16","hand >=17"};
        for(int q=0;q<3;q++){
            long n=0,y=0,c=0;
            for(T398 t:a){
                boolean ok=q==0?t.triggerHand<=12:q==1?(t.triggerHand>=13&&t.triggerHand<=16):t.triggerHand>=17;
                if(ok){n++;if(t.ref200)y++;if(t.futureClass.equals("LATER_COLLAPSE"))c++;}
            }
            r.append(String.format(Locale.ROOT,"%s: N=%d, £200 %.2f%%, collapse %.2f%%%n",hn[q],n,n==0?0:100.0*y/n,n==0?0:100.0*c/n));
        }
        String[] bn={"trigger bank <£130","£130-£139.99","trigger bank >=£140"};
        for(int q=0;q<3;q++){
            long n=0,y=0,c=0;
            for(T398 t:a){
                boolean ok=q==0?t.triggerBank<130:q==1?(t.triggerBank>=130&&t.triggerBank<140):t.triggerBank>=140;
                if(ok){n++;if(t.ref200)y++;if(t.futureClass.equals("LATER_COLLAPSE"))c++;}
            }
            r.append(String.format(Locale.ROOT,"%s: N=%d, £200 %.2f%%, collapse %.2f%%%n",bn[q],n,n==0?0:100.0*y/n,n==0?0:100.0*c/n));
        }
        String[] rb={"recent balance <=-2","recent balance -1 to 0","recent balance >=1"};
        for(int q=0;q<3;q++){
            long n=0,y=0,c=0;
            for(T398 t:a){
                boolean ok=q==0?t.recentBalance<=-2:q==1?(t.recentBalance>=-1&&t.recentBalance<=0):t.recentBalance>=1;
                if(ok){n++;if(t.ref200)y++;if(t.futureClass.equals("LATER_COLLAPSE"))c++;}
            }
            r.append(String.format(Locale.ROOT,"%s: N=%d, £200 %.2f%%, collapse %.2f%%%n",rb[q],n,n==0?0:100.0*y/n,n==0?0:100.0*c/n));
        }
    }

    static String csv398(ArrayList<T398>...groups){
        StringBuilder b=new StringBuilder("cohort,session,future_class,trigger_hand,trigger_bankroll,high_water,absolute_giveback,giveback_pct,cumulative_exposure,recent_wins,recent_losses,recent_pushes,recent_balance,prior_below_100,cooling,cautious,brake_armed,reference_final,reference_reached_200,reference_exhausted\n");
        for(ArrayList<T398>g:groups)for(T398 t:g)
            b.append(String.format(Locale.ROOT,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%.4f,%.2f,%d,%d,%d,%d,%s,%s,%s,%s,%.2f,%s,%s%n",
                t.cohort,t.session,t.futureClass,t.triggerHand,t.triggerBank,t.highWater,t.absGiveback,t.givebackPct,
                t.cumExposure,t.recentWins,t.recentLosses,t.recentPushes,t.recentBalance,
                Boolean.toString(t.priorBelow100),Boolean.toString(t.cooling),Boolean.toString(t.cautious),
                Boolean.toString(t.brakeArmed),t.refFinal,Boolean.toString(t.ref200),Boolean.toString(t.ref0)));
        return b.toString();
    }


    /* PHASE 3.99 — PREDECLARED SELECTIVE TRAILING-SEVERITY GATE
       Frozen before execution in Phase 3.98:
       existing activation >=£160;
       existing >=25% high-water-profit give-back trigger;
       STOP only when completed trigger round leaves bankroll <£140;
       otherwise continue normally.
       No threshold tuning. No wager/multiplier change. */

    static final String SELECT399="SELECTIVE_TRAIL_160_25_BANK140";

    static S396 runOne399(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,everBelow=false,recovered=false;
        S396 x=new S396();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            if(bank<100-1e-9)everBelow=true;
            if(everBelow&&bank>=100-1e-9)recovered=true;

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;

            if(policy.equals(HARD396) && activated160){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;
            }

            if((policy.equals(TRAIL396)||policy.equals(SELECT399)) && activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9){
                    boolean stop=policy.equals(TRAIL396) || bank<140.0-1e-9;
                    if(stop){x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;}
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        x.everBelow100=everBelow;x.recovered100=recovered;
        x.giveback=Math.max(0,peak-bank);
        return x;
    }

    static ArrayList<S396> run399(long seed,String cohort,String policy){
        ArrayList<S396>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne399(seed,cohort,i,policy));
        return a;
    }

    static String csv399(ArrayList<S396>...groups){
        StringBuilder b=new StringBuilder("cohort,policy,session,hands,final_bankroll,peak_bankroll,max_drawdown,cumulative_wager,reached_200,exhausted,positive,ever_below_100,recovered_100,peak_to_finish_giveback,stop_triggered,stop_hand,stop_bankroll\n");
        for(ArrayList<S396>g:groups)for(S396 x:g)
            b.append(String.format(Locale.ROOT,"%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%.2f,%s,%d,%.2f%n",
                x.cohort,x.policy,x.session,x.hands,x.finalBank,x.peak,x.maxDD,x.cumWager,
                Boolean.toString(x.reached200),Boolean.toString(x.exhausted),Boolean.toString(x.finalBank>100+1e-9),
                Boolean.toString(x.everBelow100),Boolean.toString(x.recovered100),x.giveback,
                Boolean.toString(x.stopped),x.stopHand,x.stopBank));
        return b.toString();
    }


    /* PHASE 3.100 — RELEASED-SESSION PAIRED CAUSAL DECOMPOSITION
       No new intervention and no threshold tuning.
       A RELEASED session is one that unconditional TRAIL160/25 stops but the
       frozen selective £140 gate allows to continue.
       Pair identical deterministic sessions under:
       REFERENCE, unconditional TRAIL160/25, and SELECTIVE £140 gate. */

    static final class P3100 {
        String cohort; int session;
        S396 ref,uncond,select;
        boolean released;
        double selectVsUncondFinal,selectVsUncondWager,selectVsUncondDD;
        String releaseOutcome;
    }

    static ArrayList<P3100> pair3100(long seed,String cohort){
        ArrayList<P3100>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++){
            S396 r=runOne399(seed,cohort,i,REF396);
            S396 u=runOne399(seed,cohort,i,TRAIL396);
            S396 q=runOne399(seed,cohort,i,SELECT399);
            P3100 p=new P3100();p.cohort=cohort;p.session=i+1;p.ref=r;p.uncond=u;p.select=q;
            p.released=u.stopped && !q.stopped;
            p.selectVsUncondFinal=q.finalBank-u.finalBank;
            p.selectVsUncondWager=q.cumWager-u.cumWager;
            p.selectVsUncondDD=q.maxDD-u.maxDD;
            if(!p.released)p.releaseOutcome="NOT_RELEASED";
            else if(q.reached200)p.releaseOutcome="RELEASED_TO_200";
            else if(q.exhausted)p.releaseOutcome="RELEASED_TO_0";
            else if(q.finalBank>u.finalBank+1e-9)p.releaseOutcome="RELEASED_HIGHER_FINAL";
            else if(q.finalBank<u.finalBank-1e-9)p.releaseOutcome="RELEASED_LOWER_FINAL";
            else p.releaseOutcome="RELEASED_SAME_FINAL";
            a.add(p);
        }return a;
    }

    static void sum3100(StringBuilder r,String cohort,ArrayList<P3100>a){
        long rel=0,to200=0,to0=0,higher=0,lower=0,same=0,below100=0;
        double df=0,dw=0,ddd=0,rf=0,uf=0,sf=0;
        TreeMap<String,Integer> cls=new TreeMap<>();
        for(P3100 p:a)if(p.released){
            rel++;cls.put(p.releaseOutcome,cls.getOrDefault(p.releaseOutcome,0)+1);
            if(p.select.reached200)to200++;
            if(p.select.exhausted)to0++;
            if(p.select.finalBank<100-1e-9)below100++;
            if(p.selectVsUncondFinal>1e-9)higher++;else if(p.selectVsUncondFinal<-1e-9)lower++;else same++;
            df+=p.selectVsUncondFinal;dw+=p.selectVsUncondWager;ddd+=p.selectVsUncondDD;
            rf+=p.ref.finalBank;uf+=p.uncond.finalBank;sf+=p.select.finalBank;
        }
        r.append("\n").append(cohort).append("\n");
        r.append("Sessions released by £140 gate: ").append(rel).append(" (").append(pct380(rel,a.size())).append(" of all sessions)\n");
        r.append("Released-session selective outcomes:\n");
        r.append("  Reached £200: ").append(pct380(to200,rel)).append("\n");
        r.append("  Exhausted £0: ").append(pct380(to0,rel)).append("\n");
        r.append("  Finished below £100: ").append(pct380(below100,rel)).append("\n");
        r.append("Selective final vs unconditional retained bankroll:\n");
        r.append("  Higher: ").append(pct380(higher,rel)).append("\n");
        r.append("  Lower: ").append(pct380(lower,rel)).append("\n");
        r.append("  Same: ").append(pct380(same,rel)).append("\n");
        r.append(String.format(Locale.ROOT,"Average final bankroll — Reference / Unconditional / Selective: £%.3f / £%.3f / £%.3f%n",
            rel==0?0:rf/rel,rel==0?0:uf/rel,rel==0?0:sf/rel));
        r.append(String.format(Locale.ROOT,"Average selective-minus-unconditional final delta: £%+.3f%n",rel==0?0:df/rel));
        r.append(String.format(Locale.ROOT,"Average extra wager reintroduced by release: £%.3f%n",rel==0?0:dw/rel));
        r.append(String.format(Locale.ROOT,"Average extra maximum drawdown from release: £%+.3f%n",rel==0?0:ddd/rel));
        r.append("Mutually exclusive release outcomes:\n");
        for(Map.Entry<String,Integer>e:cls.entrySet())
            r.append("  ").append(e.getKey()).append(": ").append(e.getValue()).append(" (").append(pct380(e.getValue(),rel)).append(")\n");
    }

    static String csv3100(ArrayList<P3100>...groups){
        StringBuilder b=new StringBuilder("cohort,session,released_by_gate,release_outcome,reference_final,unconditional_final,selective_final,selective_minus_unconditional_final,reference_200,selective_200,selective_0,unconditional_stop_hand,unconditional_stop_bankroll,reference_wager,unconditional_wager,selective_wager,extra_wager_from_release,reference_drawdown,unconditional_drawdown,selective_drawdown,extra_drawdown_from_release\n");
        for(ArrayList<P3100>g:groups)for(P3100 p:g)
            b.append(String.format(Locale.ROOT,"%s,%d,%s,%s,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f%n",
                p.cohort,p.session,Boolean.toString(p.released),p.releaseOutcome,p.ref.finalBank,p.uncond.finalBank,
                p.select.finalBank,p.selectVsUncondFinal,Boolean.toString(p.ref.reached200),Boolean.toString(p.select.reached200),
                Boolean.toString(p.select.exhausted),p.uncond.stopHand,p.uncond.stopBank,p.ref.cumWager,p.uncond.cumWager,
                p.select.cumWager,p.selectVsUncondWager,p.ref.maxDD,p.uncond.maxDD,p.select.maxDD,p.selectVsUncondDD));
        return b.toString();
    }


    /* PHASE 3.101 — NEW-COHORT ROBUSTNESS / GENERALISATION TEST
       Frozen architecture carried forward unchanged from Phase 3.99/3.100:
         activation: bankroll has reached >= £160;
         trigger: >=25% give-back from accumulated high-water profit;
         severity gate: STOP only when completed trigger bankroll < £140;
                        CONTINUE when trigger bankroll >= £140.
       No threshold tuning. No policy discovery.
       Two genuinely new deterministic seed cohorts are used here.
       Their seeds are declared before execution and are not selected by outcome. */

    static final long ROBUST_A_SEED = 0x310101A5B7C9D11DL;
    static final long ROBUST_B_SEED = 0x310101B6C8DAE22EL;

    static void population3101(StringBuilder r,String cohort,ArrayList<P3100>a){
        long n=a.size(), rel=0, ref200=0, unc200=0, sel200=0, ref0=0, unc0=0, sel0=0;
        double rf=0,uf=0,sf=0,rw=0,uw=0,sw=0,rdd=0,udd=0,sdd=0;
        for(P3100 p:a){
            if(p.released)rel++;
            if(p.ref.reached200)ref200++;
            if(p.uncond.reached200)unc200++;
            if(p.select.reached200)sel200++;
            if(p.ref.exhausted)ref0++;
            if(p.uncond.exhausted)unc0++;
            if(p.select.exhausted)sel0++;
            rf+=p.ref.finalBank; uf+=p.uncond.finalBank; sf+=p.select.finalBank;
            rw+=p.ref.cumWager; uw+=p.uncond.cumWager; sw+=p.select.cumWager;
            rdd+=p.ref.maxDD; udd+=p.uncond.maxDD; sdd+=p.select.maxDD;
        }
        r.append("\n").append(cohort).append(" — WHOLE POPULATION\n");
        r.append("Released by frozen £140 gate: ").append(rel).append(" (").append(pct380(rel,n)).append(")\n");
        r.append(String.format(Locale.ROOT,"Average final — Reference / Unconditional / Selective: £%.3f / £%.3f / £%.3f%n",rf/n,uf/n,sf/n));
        r.append("Reached £200 — Reference / Unconditional / Selective: ")
         .append(pct380(ref200,n)).append(" / ").append(pct380(unc200,n)).append(" / ").append(pct380(sel200,n)).append("\n");
        r.append("Finished £0 — Reference / Unconditional / Selective: ")
         .append(pct380(ref0,n)).append(" / ").append(pct380(unc0,n)).append(" / ").append(pct380(sel0,n)).append("\n");
        r.append(String.format(Locale.ROOT,"Average cumulative wager — Reference / Unconditional / Selective: £%.3f / £%.3f / £%.3f%n",rw/n,uw/n,sw/n));
        r.append(String.format(Locale.ROOT,"Average max drawdown — Reference / Unconditional / Selective: £%.3f / £%.3f / £%.3f%n",rdd/n,udd/n,sdd/n));
    }

    static String csv3101(ArrayList<P3100>...groups){
        return csv3100(groups);
    }


    /* PHASE 3.102 — INDEPENDENT-SHOE / STARTING-POSITION ROBUSTNESS
       Rationale from the Phase 3.56+ brainstorm:
       test independent deterministic shuffle orders and starting offsets without
       introducing card counting or future-card knowledge.

       IMPORTANT: cut-card/penetration reshuffling is NOT tested here.
       A 30-round session frequently does not reach a conventional cut-card point,
       so that would be a weak/partly inactive intervention in this architecture.

       Frozen selective architecture:
         activation >= £160;
         trigger >=25% give-back from accumulated high-water profit;
         stop iff completed trigger bankroll < £140;
         continue iff trigger bankroll >= £140.
       No threshold tuning. */

    static final long SHOE_A_SEED = 0x310102A4D6E8F11AL;
    static final long SHOE_B_SEED = 0x310102B5E7F9A22BL;
    static final int OFFSET_A = 52;   // exactly one deck into a fresh deterministic six-deck shoe
    static final int OFFSET_B = 104;  // exactly two decks into a fresh deterministic six-deck shoe

    static S396 runOne3102(long seed,String cohort,int session,String policy,int startOffset){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        if(startOffset<0 || startOffset>=shoe.length)throw new IllegalArgumentException("Invalid start offset");
        int ptr=startOffset,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,everBelow=false,recovered=false;
        S396 x=new S396();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double wager;
            if(cooling){wager=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){wager=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){wager=Math.min(base,15);brakeArmed=false;}else wager=base;
            } else {wager=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            wager=Math.min(wager,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            if(bank<100-1e-9)everBelow=true;
            if(everBelow&&bank>=100-1e-9)recovered=true;

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;

            if(policy.equals(HARD396) && activated160){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;
            }

            if((policy.equals(TRAIL396)||policy.equals(SELECT399)) && activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9){
                    boolean stop=policy.equals(TRAIL396) || bank<140.0-1e-9;
                    if(stop){x.stopped=true;x.stopHand=hand;x.stopBank=bank;break;}
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        x.everBelow100=everBelow;x.recovered100=recovered;
        x.giveback=Math.max(0,peak-bank);
        return x;
    }

    static ArrayList<P3100> pair3102(long seed,String cohort,int offset){
        ArrayList<P3100>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++){
            S396 r=runOne3102(seed,cohort,i,REF396,offset);
            S396 u=runOne3102(seed,cohort,i,TRAIL396,offset);
            S396 q=runOne3102(seed,cohort,i,SELECT399,offset);
            P3100 p=new P3100();p.cohort=cohort;p.session=i+1;p.ref=r;p.uncond=u;p.select=q;
            p.released=u.stopped && !q.stopped;
            p.selectVsUncondFinal=q.finalBank-u.finalBank;
            p.selectVsUncondWager=q.cumWager-u.cumWager;
            p.selectVsUncondDD=q.maxDD-u.maxDD;
            if(!p.released)p.releaseOutcome="NOT_RELEASED";
            else if(q.reached200)p.releaseOutcome="RELEASED_TO_200";
            else if(q.exhausted)p.releaseOutcome="RELEASED_TO_0";
            else if(q.finalBank>u.finalBank+1e-9)p.releaseOutcome="RELEASED_HIGHER_FINAL";
            else if(q.finalBank<u.finalBank-1e-9)p.releaseOutcome="RELEASED_LOWER_FINAL";
            else p.releaseOutcome="RELEASED_SAME_FINAL";
            a.add(p);
        }return a;
    }


    /* PHASE 3.103 — REALISTIC £5 CHIP-DENOMINATION TRANSLATION
       Brainstorm Stage E: casino chip denominations / table constraints.

       This phase isolates denomination granularity only.
       The frozen Phase 3.100 selective exit architecture is retained.
       No table-minimum change is introduced yet.

       Legal original-round wagers are multiples of £5.
       A controller request exactly halfway between two legal units is rounded DOWN.
       Therefore the existing £17.50 cautious-state request becomes £15.
       Existing £10/£15/£20/£30 requests are unchanged.

       This is a predeclared mechanical translation, not wager optimisation. */

    static final String CONT103="FROZEN_CONTINUOUS_CONTROLLER";
    static final String CHIP103="FIVE_POUND_CHIP_TRANSLATION";

    static final class S103 {
        String cohort,policy; int session,hands,changedWagers;
        double finalBank,peak,maxDD,cumWager,changedWagerAbs;
        boolean reached200,exhausted,stopped;
    }

    static double chip5FloorTie103(double requested,double bank){
        double units=requested/5.0;
        double lo=Math.floor(units)*5.0, hi=Math.ceil(units)*5.0;
        double dlo=requested-lo, dhi=hi-requested;
        double legal=(dlo<=dhi+1e-12)?lo:hi; // exact ties downward
        if(legal<5.0)legal=5.0;
        if(legal>bank){
            legal=Math.floor(bank/5.0)*5.0;
            if(legal<5.0)legal=bank; // preserve ability to finish a sub-£5 residual bankroll
        }
        return Math.min(legal,bank);
    }

    static S103 runOne103(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false;
        S103 x=new S103();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=policy.equals(CHIP103)?chip5FloorTie103(requested,bank):requested;
            if(Math.abs(wager-requested)>1e-9){
                x.changedWagers++;
                x.changedWagerAbs+=Math.abs(wager-requested);
            }
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;

            if(activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9 && bank<140.0-1e-9){
                    x.stopped=true;break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        return x;
    }

    static void report103(StringBuilder r,String cohort,ArrayList<S103> c,ArrayList<S103> q){
        int n=c.size(), changedSessions=0, higher=0,lower=0,same=0;
        int c200=0,q200=0,c0=0,q0=0,cpos=0,qpos=0;
        long changedWagers=0; double changeAbs=0;
        double cf=0,qf=0,cw=0,qw=0,cdd=0,qdd=0;
        for(int i=0;i<n;i++){
            S103 a=c.get(i),b=q.get(i);
            cf+=a.finalBank;qf+=b.finalBank;cw+=a.cumWager;qw+=b.cumWager;cdd+=a.maxDD;qdd+=b.maxDD;
            if(a.reached200)c200++;if(b.reached200)q200++;
            if(a.exhausted)c0++;if(b.exhausted)q0++;
            if(a.finalBank>100+1e-9)cpos++;if(b.finalBank>100+1e-9)qpos++;
            if(b.changedWagers>0)changedSessions++;
            changedWagers+=b.changedWagers;changeAbs+=b.changedWagerAbs;
            double d=b.finalBank-a.finalBank;
            if(d>1e-9)higher++;else if(d<-1e-9)lower++;else same++;
        }
        r.append("\n").append(cohort).append("\n");
        r.append(String.format(Locale.US,"Sessions with >=1 denomination translation: %d (%.2f%%)\n",changedSessions,100.0*changedSessions/n));
        r.append(String.format(Locale.US,"Original-round wagers translated: %d\n",changedWagers));
        r.append(String.format(Locale.US,"Mean absolute requested-to-legal adjustment per translated wager: £%.3f\n",changedWagers==0?0:changeAbs/changedWagers));
        r.append(String.format(Locale.US,"Average final — Continuous / £5-chip: £%.3f / £%.3f (delta £%+.3f)\n",cf/n,qf/n,(qf-cf)/n));
        r.append(String.format(Locale.US,"Positive sessions — Continuous / £5-chip: %.2f%% / %.2f%%\n",100.0*cpos/n,100.0*qpos/n));
        r.append(String.format(Locale.US,"Reached £200 — Continuous / £5-chip: %.2f%% / %.2f%%\n",100.0*c200/n,100.0*q200/n));
        r.append(String.format(Locale.US,"Finished £0 — Continuous / £5-chip: %.2f%% / %.2f%%\n",100.0*c0/n,100.0*q0/n));
        r.append(String.format(Locale.US,"Average cumulative wager — Continuous / £5-chip: £%.3f / £%.3f\n",cw/n,qw/n));
        r.append(String.format(Locale.US,"Average max drawdown — Continuous / £5-chip: £%.3f / £%.3f\n",cdd/n,qdd/n));
        r.append(String.format(Locale.US,"Paired final bankroll — £5-chip higher / lower / same: %.2f%% / %.2f%% / %.2f%%\n",
            100.0*higher/n,100.0*lower/n,100.0*same/n));
    }

    static String fmt103(double x){return String.format(Locale.US,"%.3f",x);}
    static String csv103(ArrayList<S103> pc,ArrayList<S103> pq,ArrayList<S103> hc,ArrayList<S103> hq){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,continuous_final,chip5_final,delta_final,continuous_200,chip5_200,continuous_0,chip5_0,continuous_cum_wager,chip5_cum_wager,continuous_max_dd,chip5_max_dd,translated_wagers,absolute_translation\n");
        ArrayList<S103>[] aa=new ArrayList[]{pc,hc},bb=new ArrayList[]{pq,hq};
        for(int k=0;k<2;k++)for(int i=0;i<aa[k].size();i++){
            S103 a=aa[k].get(i),b=bb[k].get(i);
            z.append(a.cohort).append(',').append(a.session).append(',')
             .append(fmt103(a.finalBank)).append(',').append(fmt103(b.finalBank)).append(',').append(fmt103(b.finalBank-a.finalBank)).append(',')
             .append(a.reached200).append(',').append(b.reached200).append(',')
             .append(a.exhausted).append(',').append(b.exhausted).append(',')
             .append(fmt103(a.cumWager)).append(',').append(fmt103(b.cumWager)).append(',')
             .append(fmt103(a.maxDD)).append(',').append(fmt103(b.maxDD)).append(',')
             .append(b.changedWagers).append(',').append(fmt103(b.changedWagerAbs)).append('\n');
        }
        return z.toString();
    }

    static ArrayList<S103> cohort103(long seed,String cohort,String policy){
        ArrayList<S103>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne103(seed,cohort,i,policy));
        return a;
    }


    /* PHASE 3.104 — £15 TABLE-MINIMUM ROBUSTNESS
       This follows Phase 3.103's isolated £5 denomination translation.

       Comparison:
       A = frozen Phase 3.103 £5-chip controller (no new table minimum).
       B = identical controller with a £15 minimum original-round wager.

       Both use £5 wager units. The £15 minimum therefore forces requested
       £10 protective/recovery wagers upward to £15. The £17.50 request
       remains translated to £15 under the Phase 3.103 tie-down rule.

       No exit-threshold, action-policy, session-length or shuffle change. */

    static final String BASE104="PHASE_3_103_FIVE_POUND_BASELINE";
    static final String MIN15_104="FIFTEEN_POUND_TABLE_MINIMUM";

    static final class S104 {
        String cohort,policy; int session,hands,minimumForcedRounds,translatedRounds;
        double finalBank,peak,maxDD,cumWager,minimumExtraRequested;
        boolean reached200,exhausted,stopped;
    }

    static double wager104(double requested,double bank,boolean min15,S104 x){
        double chip=chip5FloorTie103(requested,bank);
        if(Math.abs(chip-requested)>1e-9)x.translatedRounds++;
        if(min15 && bank>=15.0-1e-9 && chip<15.0-1e-9){
            x.minimumForcedRounds++;
            x.minimumExtraRequested += 15.0-chip;
            chip=15.0;
        }
        if(chip>bank)chip=bank;
        return chip;
    }

    static S104 runOne104(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false;
        S104 x=new S104();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=wager104(requested,bank,policy.equals(MIN15_104),x);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;

            if(activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9 && bank<140.0-1e-9){
                    x.stopped=true;break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        return x;
    }

    static ArrayList<S104> cohort104(long seed,String cohort,String policy){
        ArrayList<S104>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne104(seed,cohort,i,policy));
        return a;
    }

    static void report104(StringBuilder r,String cohort,ArrayList<S104>a,ArrayList<S104>b){
        int n=a.size(),affected=0,higher=0,lower=0,same=0,a200=0,b200=0,a0=0,b0=0,apos=0,bpos=0;
        long forced=0;double extraReq=0,af=0,bf=0,aw=0,bw=0,add=0,bdd=0;
        for(int i=0;i<n;i++){
            S104 x=a.get(i),y=b.get(i);
            if(y.minimumForcedRounds>0)affected++;
            forced+=y.minimumForcedRounds;extraReq+=y.minimumExtraRequested;
            af+=x.finalBank;bf+=y.finalBank;aw+=x.cumWager;bw+=y.cumWager;add+=x.maxDD;bdd+=y.maxDD;
            if(x.reached200)a200++;if(y.reached200)b200++;
            if(x.exhausted)a0++;if(y.exhausted)b0++;
            if(x.finalBank>100+1e-9)apos++;if(y.finalBank>100+1e-9)bpos++;
            double d=y.finalBank-x.finalBank;if(d>1e-9)higher++;else if(d<-1e-9)lower++;else same++;
        }
        r.append("\n").append(cohort).append("\n");
        r.append(String.format(Locale.US,"Sessions in which £15 minimum forced >=1 wager upward: %d (%.2f%%)\n",affected,100.0*affected/n));
        r.append(String.format(Locale.US,"Original rounds forced from below £15 to £15: %d\n",forced));
        r.append(String.format(Locale.US,"Nominal extra original-round wager requested by minimum: £%.2f total; £%.3f per session\n",extraReq,extraReq/n));
        r.append(String.format(Locale.US,"Average final — £5 baseline / £15 minimum: £%.3f / £%.3f (delta £%+.3f)\n",af/n,bf/n,(bf-af)/n));
        r.append(String.format(Locale.US,"Positive sessions — baseline / minimum: %.2f%% / %.2f%%\n",100.0*apos/n,100.0*bpos/n));
        r.append(String.format(Locale.US,"Reached £200 — baseline / minimum: %.2f%% / %.2f%%\n",100.0*a200/n,100.0*b200/n));
        r.append(String.format(Locale.US,"Finished £0 — baseline / minimum: %.2f%% / %.2f%%\n",100.0*a0/n,100.0*b0/n));
        r.append(String.format(Locale.US,"Average cumulative wager — baseline / minimum: £%.3f / £%.3f (delta £%+.3f)\n",aw/n,bw/n,(bw-aw)/n));
        r.append(String.format(Locale.US,"Average max drawdown — baseline / minimum: £%.3f / £%.3f (delta £%+.3f)\n",add/n,bdd/n,(bdd-add)/n));
        r.append(String.format(Locale.US,"Paired final bankroll — minimum higher / lower / same: %.2f%% / %.2f%% / %.2f%%\n",
            100.0*higher/n,100.0*lower/n,100.0*same/n));
    }

    static String fmt104(double x){return String.format(Locale.US,"%.3f",x);}
    static String csv104(ArrayList<S104> pa,ArrayList<S104> pb,ArrayList<S104> ha,ArrayList<S104> hb){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,baseline_final,min15_final,delta_final,baseline_200,min15_200,baseline_0,min15_0,baseline_cum_wager,min15_cum_wager,baseline_max_dd,min15_max_dd,min15_forced_rounds,min15_nominal_extra_requested\n");
        ArrayList<S104>[] aa=new ArrayList[]{pa,ha},bb=new ArrayList[]{pb,hb};
        for(int k=0;k<2;k++)for(int i=0;i<aa[k].size();i++){
            S104 a=aa[k].get(i),b=bb[k].get(i);
            z.append(a.cohort).append(',').append(a.session).append(',')
             .append(fmt104(a.finalBank)).append(',').append(fmt104(b.finalBank)).append(',').append(fmt104(b.finalBank-a.finalBank)).append(',')
             .append(a.reached200).append(',').append(b.reached200).append(',').append(a.exhausted).append(',').append(b.exhausted).append(',')
             .append(fmt104(a.cumWager)).append(',').append(fmt104(b.cumWager)).append(',')
             .append(fmt104(a.maxDD)).append(',').append(fmt104(b.maxDD)).append(',')
             .append(b.minimumForcedRounds).append(',').append(fmt104(b.minimumExtraRequested)).append('\n');
        }return z.toString();
    }


    /* PHASE 3.105 — TABLE-MINIMUM IMPACT ANATOMY
       Measurement-only decomposition of the £15 table-minimum intervention.
       No controller adaptation and no threshold tuning.

       We identify where £10->£15 forced wagers occur by bankroll state, and
       pair each minimum-policy session against its Phase 3.103 £5-unit baseline.

       State bands are frozen before execution:
         BELOW_100
         100_149
         150_169
         170_199

       We then ask whether additional £200 outcomes and additional £0 outcomes
       are associated with different forced-exposure histories.
    */

    static final class A105 {
        String cohort; int session;
        S104 base,min;
        int forcedBelow100,forced100_149,forced150_169,forced170_199;
        double extraBelow100,extra100_149,extra150_169,extra170_199;
        String pairedClass;
    }

    static S104 runOne105(long seed,String cohort,int session,String policy,A105 rec){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false;
        S104 x=new S104();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(Math.abs(chip-requested)>1e-9)x.translatedRounds++;

            double wager=chip;
            if(policy.equals(MIN15_104) && bank>=15.0-1e-9 && chip<15.0-1e-9){
                x.minimumForcedRounds++;
                x.minimumExtraRequested += 15.0-chip;
                if(rec!=null){
                    if(bank<100){
                        rec.forcedBelow100++; rec.extraBelow100 += 15.0-chip;
                    }else if(bank<150){
                        rec.forced100_149++; rec.extra100_149 += 15.0-chip;
                    }else if(bank<170){
                        rec.forced150_169++; rec.extra150_169 += 15.0-chip;
                    }else{
                        rec.forced170_199++; rec.extra170_199 += 15.0-chip;
                    }
                }
                wager=15.0;
            }
            if(wager>bank)wager=bank;
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;break;}
            if(bank<=1e-9){x.exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;

            if(activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9 && bank<140.0-1e-9){
                    x.stopped=true;break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        return x;
    }

    static ArrayList<A105> cohort105(long seed,String cohort){
        ArrayList<A105>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++){
            A105 r=new A105();r.cohort=cohort;r.session=i+1;
            r.base=runOne105(seed,cohort,i,BASE104,null);
            r.min=runOne105(seed,cohort,i,MIN15_104,r);

            if(!r.base.reached200 && r.min.reached200)r.pairedClass="CREATED_200";
            else if(!r.base.exhausted && r.min.exhausted)r.pairedClass="CREATED_0";
            else if(r.base.reached200 && !r.min.reached200)r.pairedClass="LOST_200";
            else if(r.base.exhausted && !r.min.exhausted)r.pairedClass="PREVENTED_0";
            else if(r.min.finalBank>r.base.finalBank+1e-9)r.pairedClass="HIGHER_FINAL";
            else if(r.min.finalBank<r.base.finalBank-1e-9)r.pairedClass="LOWER_FINAL";
            else r.pairedClass="SAME_FINAL";
            a.add(r);
        }
        return a;
    }

    static void class105(StringBuilder r,String cohort,ArrayList<A105>a,String cls){
        long n=0;double b=0,m=0;
        long f0=0,f1=0,f2=0,f3=0;double e0=0,e1=0,e2=0,e3=0;
        for(A105 x:a)if(x.pairedClass.equals(cls)){
            n++;b+=x.base.finalBank;m+=x.min.finalBank;
            f0+=x.forcedBelow100;f1+=x.forced100_149;f2+=x.forced150_169;f3+=x.forced170_199;
            e0+=x.extraBelow100;e1+=x.extra100_149;e2+=x.extra150_169;e3+=x.extra170_199;
        }
        if(n==0)return;
        r.append(String.format(Locale.US,
            "%s: N=%d (%.2f%%), avg final baseline/minimum £%.2f/£%.2f, forced rounds per session [<100 %.2f | 100-149 %.2f | 150-169 %.2f | 170-199 %.2f], nominal extra £ per session [%.2f | %.2f | %.2f | %.2f]%n",
            cls,n,100.0*n/a.size(),b/n,m/n,
            (double)f0/n,(double)f1/n,(double)f2/n,(double)f3/n,
            e0/n,e1/n,e2/n,e3/n));
    }

    static void summary105(StringBuilder r,String cohort,ArrayList<A105>a){
        long f0=0,f1=0,f2=0,f3=0;double e0=0,e1=0,e2=0,e3=0;
        for(A105 x:a){
            f0+=x.forcedBelow100;f1+=x.forced100_149;f2+=x.forced150_169;f3+=x.forced170_199;
            e0+=x.extraBelow100;e1+=x.extra100_149;e2+=x.extra150_169;e3+=x.extra170_199;
        }
        long ft=f0+f1+f2+f3;double et=e0+e1+e2+e3;
        r.append("\n").append(cohort).append("\n");
        r.append("FORCED £10->£15 EXPOSURE BY BANKROLL STATE\n");
        r.append(String.format(Locale.US,"Below £100: %d rounds (%.2f%% of forced rounds), nominal extra £%.2f (%.2f%%)%n",
            f0,100.0*f0/ft,e0,100.0*e0/et));
        r.append(String.format(Locale.US,"£100-149: %d (%.2f%%), extra £%.2f (%.2f%%)%n",
            f1,100.0*f1/ft,e1,100.0*e1/et));
        r.append(String.format(Locale.US,"£150-169: %d (%.2f%%), extra £%.2f (%.2f%%)%n",
            f2,100.0*f2/ft,e2,100.0*e2/et));
        r.append(String.format(Locale.US,"£170-199: %d (%.2f%%), extra £%.2f (%.2f%%)%n",
            f3,100.0*f3/ft,e3,100.0*e3/et));

        r.append("\nPAIRED OUTCOME ANATOMY\n");
        for(String cls:new String[]{"CREATED_200","CREATED_0","LOST_200","PREVENTED_0","HIGHER_FINAL","LOWER_FINAL","SAME_FINAL"})
            class105(r,cohort,a,cls);
    }

    static String csv105(ArrayList<A105>...groups){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,paired_class,baseline_final,min15_final,baseline_200,min15_200,baseline_0,min15_0,forced_below100,forced_100_149,forced_150_169,forced_170_199,extra_below100,extra_100_149,extra_150_169,extra_170_199\n");
        for(ArrayList<A105>g:groups)for(A105 x:g)
            z.append(x.cohort).append(',').append(x.session).append(',').append(x.pairedClass).append(',')
             .append(fmt104(x.base.finalBank)).append(',').append(fmt104(x.min.finalBank)).append(',')
             .append(x.base.reached200).append(',').append(x.min.reached200).append(',')
             .append(x.base.exhausted).append(',').append(x.min.exhausted).append(',')
             .append(x.forcedBelow100).append(',').append(x.forced100_149).append(',')
             .append(x.forced150_169).append(',').append(x.forced170_199).append(',')
             .append(fmt104(x.extraBelow100)).append(',').append(fmt104(x.extra100_149)).append(',')
             .append(fmt104(x.extra150_169)).append(',').append(fmt104(x.extra170_199)).append('\n');
        return z.toString();
    }


    /* PHASE 3.106 — PROSPECTIVE LOW-BANKROLL TABLE-MINIMUM PROTECTION

       Terminology correction carried forward:
       In a £15-minimum casino, £10 is NOT a legal wager.
       "Constrained state" means the frozen controller's internal preferred
       protective stake would be below the table minimum. The casino-legal
       continuation is therefore £15.

       Predeclared candidate response:
       If bankroll is below £100 and the controller enters such a constrained
       state, WALK AWAY rather than continue at the legal £15 minimum.

       Three paired arms:
       A) Phase 3.103 £5-unit research baseline.
       B) Phase 3.104 unadapted £15-minimum environment.
       C) £15-minimum environment + prospective below-£100 walk-away response.

       No future information, no outcome-class predictor, no threshold search.
    */

    static final String PROTECT106="MIN15_BELOW100_WALKAWAY";

    static final class S106 {
        String cohort,policy,termination="HAND_CAP";
        int session,hands,constrainedStates;
        double finalBank,peak,maxDD,cumWager;
        boolean reached200,exhausted,stopped,protectionStop;
    }

    static S106 runOne106(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false;
        S106 x=new S106();x.cohort=cohort;x.policy=policy;x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            boolean min15 = policy.equals(MIN15_104) || policy.equals(PROTECT106);
            boolean constrained = min15 && bank>=15.0-1e-9 && chip<15.0-1e-9;

            if(constrained){
                x.constrainedStates++;
                if(policy.equals(PROTECT106) && bank<100.0-1e-9){
                    x.protectionStop=true;x.stopped=true;x.termination="BELOW100_MINIMUM_CONSTRAINT_WALKAWAY";
                    break;
                }
                chip=15.0;
            }

            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9){x.reached200=true;x.termination="REACHED_200";break;}
            if(bank<=1e-9){x.exhausted=true;x.termination="EXHAUSTED_0";break;}
            if(bank>=160-1e-9)activated160=true;

            if(activated160 && peak>100+1e-9){
                double accumulatedProfit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                double givePct=100.0*surrendered/accumulatedProfit;
                if(givePct>=25.0-1e-9 && bank<140.0-1e-9){
                    x.stopped=true;x.termination="FROZEN_SELECTIVE_EXIT";break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        return x;
    }

    static ArrayList<S106> cohort106(long seed,String cohort,String policy){
        ArrayList<S106>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne106(seed,cohort,i,policy));
        return a;
    }

    static void report106(StringBuilder r,String cohort,ArrayList<S106> base,ArrayList<S106> min,ArrayList<S106> prot){
        int n=base.size(), b200=0,m200=0,p200=0,b0=0,m0=0,p0=0,bpos=0,mpos=0,ppos=0,pstop=0;
        int phigher=0,plower=0,psame=0, created200=0,prevented0=0,lost200=0,created0=0;
        double bf=0,mf=0,pf=0,bw=0,mw=0,pw=0,bdd=0,mdd=0,pdd=0,stopBank=0;
        for(int i=0;i<n;i++){
            S106 b=base.get(i),m=min.get(i),p=prot.get(i);
            bf+=b.finalBank;mf+=m.finalBank;pf+=p.finalBank;
            bw+=b.cumWager;mw+=m.cumWager;pw+=p.cumWager;
            bdd+=b.maxDD;mdd+=m.maxDD;pdd+=p.maxDD;
            if(b.reached200)b200++;if(m.reached200)m200++;if(p.reached200)p200++;
            if(b.exhausted)b0++;if(m.exhausted)m0++;if(p.exhausted)p0++;
            if(b.finalBank>100+1e-9)bpos++;if(m.finalBank>100+1e-9)mpos++;if(p.finalBank>100+1e-9)ppos++;
            if(p.protectionStop){pstop++;stopBank+=p.finalBank;}
            double d=p.finalBank-m.finalBank;
            if(d>1e-9)phigher++;else if(d<-1e-9)plower++;else psame++;
            if(!m.reached200 && p.reached200)created200++;
            if(m.exhausted && !p.exhausted)prevented0++;
            if(m.reached200 && !p.reached200)lost200++;
            if(!m.exhausted && p.exhausted)created0++;
        }
        r.append("\n").append(cohort).append("\n");
        r.append(String.format(Locale.US,"Protection walk-away activated: %d/%d (%.2f%%); mean retained bankroll at activation £%.2f%n",
            pstop,n,100.0*pstop/n,pstop==0?0:stopBank/pstop));
        r.append(String.format(Locale.US,"Average final — £5 baseline / unadapted £15 / protected £15: £%.3f / £%.3f / £%.3f%n",bf/n,mf/n,pf/n));
        r.append(String.format(Locale.US,"Positive sessions: %.2f%% / %.2f%% / %.2f%%%n",100.0*bpos/n,100.0*mpos/n,100.0*ppos/n));
        r.append(String.format(Locale.US,"Reached £200: %.2f%% / %.2f%% / %.2f%%%n",100.0*b200/n,100.0*m200/n,100.0*p200/n));
        r.append(String.format(Locale.US,"Finished £0: %.2f%% / %.2f%% / %.2f%%%n",100.0*b0/n,100.0*m0/n,100.0*p0/n));
        r.append(String.format(Locale.US,"Average cumulative wager: £%.3f / £%.3f / £%.3f%n",bw/n,mw/n,pw/n));
        r.append(String.format(Locale.US,"Average max drawdown: £%.3f / £%.3f / £%.3f%n",bdd/n,mdd/n,pdd/n));
        r.append(String.format(Locale.US,"Protected vs unadapted final — higher/lower/same: %.2f%% / %.2f%% / %.2f%%%n",
            100.0*phigher/n,100.0*plower/n,100.0*psame/n));
        r.append(String.format(Locale.US,"Protected vs unadapted — £200 created/prevented: %d / %d; £0 prevented/created: %d / %d%n",
            created200,lost200,prevented0,created0));
    }

    static String fmt106(double x){return String.format(Locale.US,"%.3f",x);}
    static String csv106(ArrayList<S106> pb,ArrayList<S106> pm,ArrayList<S106> pp,
                         ArrayList<S106> hb,ArrayList<S106> hm,ArrayList<S106> hp){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,baseline_final,min15_final,protected_final,baseline_200,min15_200,protected_200,baseline_0,min15_0,protected_0,baseline_cum_wager,min15_cum_wager,protected_cum_wager,baseline_max_dd,min15_max_dd,protected_max_dd,protection_stop,protection_termination,protected_minus_min15_final\n");
        ArrayList<S106>[] bbs=new ArrayList[]{pb,hb},mms=new ArrayList[]{pm,hm},pps=new ArrayList[]{pp,hp};
        for(int k=0;k<2;k++)for(int i=0;i<bbs[k].size();i++){
            S106 b=bbs[k].get(i),m=mms[k].get(i),p=pps[k].get(i);
            z.append(b.cohort).append(',').append(b.session).append(',')
             .append(fmt106(b.finalBank)).append(',').append(fmt106(m.finalBank)).append(',').append(fmt106(p.finalBank)).append(',')
             .append(b.reached200).append(',').append(m.reached200).append(',').append(p.reached200).append(',')
             .append(b.exhausted).append(',').append(m.exhausted).append(',').append(p.exhausted).append(',')
             .append(fmt106(b.cumWager)).append(',').append(fmt106(m.cumWager)).append(',').append(fmt106(p.cumWager)).append(',')
             .append(fmt106(b.maxDD)).append(',').append(fmt106(m.maxDD)).append(',').append(fmt106(p.maxDD)).append(',')
             .append(p.protectionStop).append(',').append(p.termination).append(',')
             .append(fmt106(p.finalBank-m.finalBank)).append('\n');
        }return z.toString();
    }


    /* PHASE 3.107 — PROTECTION-STOP ANATOMY
       Measurement only. No new threshold or intervention.

       We observe the first Phase 3.106 protection stop:
       - stop hand and bankroll
       - prior peak
       - cumulative wager before stop
       - whether bankroll had previously recovered to >=£100 after being <£100
       - counterfactual outcome under the unadapted £15-minimum continuation

       Counterfactual outcome is used retrospectively for anatomy only.
       It is never available to the live rule.
    */
    static final class A107 {
        String cohort; int session;
        boolean stopped,priorRecovery;
        int stopHand;
        double stopBank,priorPeak,cumBeforeStop;
        S106 unadapted;
        String counterfactual;
    }

    static A107 anatomy107(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,beenBelow=false,recovered=false;
        A107 a=new A107();a.cohort=cohort;a.session=session+1;
        a.unadapted=runOne106(seed,cohort,session,MIN15_104);

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            boolean constrained=bank>=15.0-1e-9 && chip<15.0-1e-9;

            if(constrained && bank<100.0-1e-9){
                a.stopped=true;a.stopHand=hand;a.stopBank=bank;a.priorPeak=peak;
                a.cumBeforeStop=cum;a.priorRecovery=recovered;
                if(a.unadapted.reached200)a.counterfactual="UNADAPTED_REACHED_200";
                else if(a.unadapted.exhausted)a.counterfactual="UNADAPTED_EXHAUSTED_0";
                else if(a.unadapted.finalBank>100+1e-9)a.counterfactual="UNADAPTED_FINISHED_ABOVE_100";
                else if(Math.abs(a.unadapted.finalBank-100)<1e-9)a.counterfactual="UNADAPTED_FINISHED_100";
                else a.counterfactual="UNADAPTED_FINISHED_BELOW_100";
                return a;
            }
            if(constrained)chip=15.0;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank<100-1e-9)beenBelow=true;
            if(beenBelow && bank>=100-1e-9)recovered=true;

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(bank>=160-1e-9)activated160=true;
            if(activated160 && peak>100+1e-9){
                double profit=peak-100.0,surrendered=Math.max(0,peak-bank);
                if(100.0*surrendered/profit>=25.0-1e-9 && bank<140.0-1e-9)break;
            }
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        a.counterfactual="NO_PROTECTION_STOP";
        return a;
    }

    static ArrayList<A107> cohort107(long seed,String cohort){
        ArrayList<A107>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(anatomy107(seed,cohort,i));
        return a;
    }

    static double median107(ArrayList<Double>x){
        Collections.sort(x);int n=x.size();
        return n==0?0:(n%2==1?x.get(n/2):(x.get(n/2-1)+x.get(n/2))/2.0);
    }

    static void summary107(StringBuilder r,String cohort,ArrayList<A107>a){
        int n=0,rec=0;double sh=0,sb=0,pk=0,cw=0;
        ArrayList<Double> hands=new ArrayList<>(),banks=new ArrayList<>(),peaks=new ArrayList<>(),cums=new ArrayList<>();
        TreeMap<String,Integer> cf=new TreeMap<>();
        int[] handBands=new int[4], bankBands=new int[4];
        for(A107 x:a)if(x.stopped){
            n++;if(x.priorRecovery)rec++;
            sh+=x.stopHand;sb+=x.stopBank;pk+=x.priorPeak;cw+=x.cumBeforeStop;
            hands.add((double)x.stopHand);banks.add(x.stopBank);peaks.add(x.priorPeak);cums.add(x.cumBeforeStop);
            cf.put(x.counterfactual,cf.getOrDefault(x.counterfactual,0)+1);
            if(x.stopHand<=5)handBands[0]++; else if(x.stopHand<=10)handBands[1]++;
            else if(x.stopHand<=20)handBands[2]++; else handBands[3]++;
            if(x.stopBank<70)bankBands[0]++; else if(x.stopBank<80)bankBands[1]++;
            else if(x.stopBank<90)bankBands[2]++; else bankBands[3]++;
        }
        r.append("\n").append(cohort).append("\n");
        r.append(String.format(Locale.US,"Protection stops: %d/%d (%.2f%%)%n",n,a.size(),100.0*n/a.size()));
        r.append(String.format(Locale.US,"Stop hand mean/median: %.2f / %.2f%n",sh/n,median107(hands)));
        r.append(String.format(Locale.US,"Stop bankroll mean/median: £%.2f / £%.2f%n",sb/n,median107(banks)));
        r.append(String.format(Locale.US,"Prior peak mean/median: £%.2f / £%.2f%n",pk/n,median107(peaks)));
        r.append(String.format(Locale.US,"Cumulative wager before stop mean/median: £%.2f / £%.2f%n",cw/n,median107(cums)));
        r.append(String.format(Locale.US,"Had previously recovered to >=£100 after falling below it: %d (%.2f%% of stops)%n",rec,100.0*rec/n));
        r.append(String.format(Locale.US,"Stop-hand bands: 1-5 %d (%.2f%%); 6-10 %d (%.2f%%); 11-20 %d (%.2f%%); 21-30 %d (%.2f%%)%n",
            handBands[0],100.0*handBands[0]/n,handBands[1],100.0*handBands[1]/n,handBands[2],100.0*handBands[2]/n,handBands[3],100.0*handBands[3]/n));
        r.append(String.format(Locale.US,"Stop-bankroll bands: <£70 %d (%.2f%%); £70-79.99 %d (%.2f%%); £80-89.99 %d (%.2f%%); £90-99.99 %d (%.2f%%)%n",
            bankBands[0],100.0*bankBands[0]/n,bankBands[1],100.0*bankBands[1]/n,bankBands[2],100.0*bankBands[2]/n,bankBands[3],100.0*bankBands[3]/n));
        r.append("COUNTERFACTUAL UNADAPTED £15 OUTCOME AMONG STOPPED SESSIONS\n");
        for(Map.Entry<String,Integer>e:cf.entrySet())
            r.append(String.format(Locale.US,"%s: %d (%.2f%%)%n",e.getKey(),e.getValue(),100.0*e.getValue()/n));
    }

    static String csv107(ArrayList<A107>...groups){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,protection_stop,stop_hand,stop_bankroll,prior_peak,cumulative_wager_before_stop,prior_recovery,counterfactual_unadapted_outcome,unadapted_final,unadapted_200,unadapted_0\n");
        for(ArrayList<A107>g:groups)for(A107 x:g)
            z.append(x.cohort).append(',').append(x.session).append(',').append(x.stopped).append(',')
             .append(x.stopHand).append(',').append(fmt106(x.stopBank)).append(',')
             .append(fmt106(x.priorPeak)).append(',').append(fmt106(x.cumBeforeStop)).append(',')
             .append(x.priorRecovery).append(',').append(x.counterfactual).append(',')
             .append(fmt106(x.unadapted.finalBank)).append(',').append(x.unadapted.reached200).append(',')
             .append(x.unadapted.exhausted).append('\n');
        return z.toString();
    }


    /* PHASE 3.108 — OBSERVABLE EARLY-PATH ANATOMY
       Measurement only. No new live stopping rule or threshold.
       Extends 3.107 by recording only information observable by the time
       the first 3.106 protection stop would occur, then retrospectively
       stratifies those paths by paired unadapted £15 outcome.
    */
    static final class P108 {
        String cohort,counterfactual; int session,stopHand;
        double stopBank,priorPeak,cumWager,maxDrawdown,largestLoss;
        int completedRounds,handsBelow100,consecutiveBelow100,wins,losses,pushes;
        boolean stopped;
    }

    static P108 path108(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0; int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxDD=0,largestLoss=0;
        int below=0,consecBelow=0,wins=0,losses=0,pushes=0,completed=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated160=false;
        P108 p=new P108();p.cohort=cohort;p.session=session+1;
        S106 u=runOne106(seed,cohort,session,MIN15_104);

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            boolean constrained=bank>=15.0-1e-9 && chip<15.0-1e-9;

            if(constrained && bank<100.0-1e-9){
                p.stopped=true;p.stopHand=hand;p.stopBank=bank;p.priorPeak=peak;p.cumWager=cum;
                p.maxDrawdown=maxDD;p.largestLoss=largestLoss;p.completedRounds=completed;
                p.handsBelow100=below;p.consecutiveBelow100=consecBelow;
                p.wins=wins;p.losses=losses;p.pushes=pushes;
                if(u.reached200)p.counterfactual="REACHED_200";
                else if(u.exhausted)p.counterfactual="EXHAUSTED_0";
                else if(u.finalBank>100+1e-9)p.counterfactual="FINISHED_ABOVE_100";
                else if(Math.abs(u.finalBank-100)<1e-9)p.counterfactual="FINISHED_100";
                else p.counterfactual="FINISHED_BELOW_100";
                return p;
            }
            if(constrained)chip=15.0;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer; double before=bank;
            cum+=roundStake356(rr); bank+=rr.net;if(bank<0)bank=0;completed++;
            if(rr.net>1e-9)wins++; else if(rr.net<-1e-9){losses++;largestLoss=Math.max(largestLoss,-rr.net);} else pushes++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            if(bank<100-1e-9){below++;consecBelow++;}else consecBelow=0;
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(bank>=160-1e-9)activated160=true;
            if(activated160&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                if(100.0*surr/profit>=25.0-1e-9&&bank<140-1e-9)break;
            }
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        p.counterfactual="NO_PROTECTION_STOP";return p;
    }

    static ArrayList<P108> cohort108(long seed,String cohort){
        ArrayList<P108>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(path108(seed,cohort,i));
        return a;
    }

    static void group108(StringBuilder r,String cohort,ArrayList<P108>a){
        TreeMap<String,ArrayList<P108>> m=new TreeMap<>();
        for(P108 p:a)if(p.stopped)m.computeIfAbsent(p.counterfactual,k->new ArrayList<>()).add(p);
        r.append("\n").append(cohort).append("\n");
        r.append("Retrospective groups; all predictor columns below were observable at stop time.\n");
        for(Map.Entry<String,ArrayList<P108>>e:m.entrySet()){
            ArrayList<P108>g=e.getValue();double sh=0,sb=0,cw=0,dd=0,ll=0,hb=0,cb=0,w=0,l=0,pu=0;
            for(P108 p:g){sh+=p.stopHand;sb+=p.stopBank;cw+=p.cumWager;dd+=p.maxDrawdown;ll+=p.largestLoss;
                hb+=p.handsBelow100;cb+=p.consecutiveBelow100;w+=p.wins;l+=p.losses;pu+=p.pushes;}
            int n=g.size();
            r.append(String.format(Locale.US,
                "%s n=%d | stop hand %.2f | bankroll £%.2f | wager £%.2f | maxDD £%.2f | largest loss £%.2f | hands<100 %.2f | consecutive<100 %.2f | W/L/P %.2f/%.2f/%.2f%n",
                e.getKey(),n,sh/n,sb/n,cw/n,dd/n,ll/n,hb/n,cb/n,w/n,l/n,pu/n));
        }
    }

    static String csv108(ArrayList<P108>...gs){
        StringBuilder z=new StringBuilder();
        z.append("cohort,session,stopped,counterfactual,stop_hand,stop_bankroll,prior_peak,cumulative_wager,max_drawdown,largest_round_loss,completed_rounds,hands_below_100,consecutive_below_100,wins,losses,pushes\n");
        for(ArrayList<P108>g:gs)for(P108 p:g)z.append(p.cohort).append(',').append(p.session).append(',').append(p.stopped).append(',')
          .append(p.counterfactual).append(',').append(p.stopHand).append(',').append(fmt106(p.stopBank)).append(',')
          .append(fmt106(p.priorPeak)).append(',').append(fmt106(p.cumWager)).append(',').append(fmt106(p.maxDrawdown)).append(',')
          .append(fmt106(p.largestLoss)).append(',').append(p.completedRounds).append(',').append(p.handsBelow100).append(',')
          .append(p.consecutiveBelow100).append(',').append(p.wins).append(',').append(p.losses).append(',').append(p.pushes).append('\n');
        return z.toString();
    }


    /* PHASE 3.109 — BELOW-£100 RECOVERY-EPISODE ANATOMY
       Measurement only under the unadapted £15-minimum continuation.
       No new stop rule, threshold, wager response or future information.
    */
    static final class E109 {
        String cohort,outcome; int session,episode,startHand,endHand,duration;
        double startBank,trough,exposure,recoveredAmount;
        boolean recovered,reached150,reached170,reached200,exhausted;
    }
    static final class R109 { ArrayList<E109> episodes=new ArrayList<>(); }

    static R109 episodes109(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated160=false;
        boolean inEp=false; int epNo=0,epStart=0; double epStartBank=0,epTrough=0,epExposure=0;
        boolean r150=false,r170=false,r200=false,exhausted=false;
        R109 rrout=new R109();

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double base=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(base,15);brakeArmed=false;}else requested=base;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            boolean constrained=bank>=15-1e-9&&chip<15-1e-9;
            if(constrained)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer; double stake=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);
            if(bank>=150-1e-9)r150=true;if(bank>=170-1e-9)r170=true;if(bank>=200-1e-9)r200=true;

            if(!inEp && bank<100-1e-9 && bank>1e-9){
                inEp=true;epNo++;epStart=hand;epStartBank=bank;epTrough=bank;epExposure=stake;
            } else if(inEp){
                epExposure+=stake;epTrough=Math.min(epTrough,bank);
            }

            if(inEp && bank>=100-1e-9){
                E109 e=new E109();e.cohort=cohort;e.session=session+1;e.episode=epNo;e.startHand=epStart;e.endHand=hand;
                e.duration=hand-epStart+1;e.startBank=epStartBank;e.trough=epTrough;e.exposure=epExposure;
                e.recovered=true;e.recoveredAmount=100-epTrough;
                rrout.episodes.add(e);inEp=false;
            }

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200-1e-9||bank<=1e-9){if(bank<=1e-9)exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;
            if(activated160&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                if(100*surr/profit>=25-1e-9&&bank<140-1e-9)break;
            }
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        if(inEp){
            E109 e=new E109();e.cohort=cohort;e.session=session+1;e.episode=epNo;e.startHand=epStart;e.endHand=HANDS;
            e.duration=Math.max(1,HANDS-epStart+1);e.startBank=epStartBank;e.trough=epTrough;e.exposure=epExposure;
            e.recovered=false;e.recoveredAmount=0;rrout.episodes.add(e);
        }
        String outcome=r200?"REACHED_200":(exhausted?"EXHAUSTED_0":(bank>100+1e-9?"FINISHED_ABOVE_100":(Math.abs(bank-100)<1e-9?"FINISHED_100":"FINISHED_BELOW_100")));
        for(E109 e:rrout.episodes){e.outcome=outcome;e.reached150=r150;e.reached170=r170;e.reached200=r200;e.exhausted=exhausted;}
        return rrout;
    }

    static ArrayList<E109> cohort109(long seed,String cohort){
        ArrayList<E109>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.addAll(episodes109(seed,cohort,i).episodes);
        return a;
    }
    static void sum109(StringBuilder r,String cohort,ArrayList<E109>a){
        HashSet<Integer> sess=new HashSet<>(),recSess=new HashSet<>(),failSess=new HashSet<>();
        int rec=0,fail=0;double rd=0,re=0,rt=0,fd=0,fe=0,ft=0;
        TreeMap<Integer,Integer> epsPer=new TreeMap<>();
        HashMap<Integer,Integer> cnt=new HashMap<>();
        for(E109 e:a){sess.add(e.session);cnt.put(e.session,cnt.getOrDefault(e.session,0)+1);
            if(e.recovered){rec++;recSess.add(e.session);rd+=e.duration;re+=e.exposure;rt+=e.trough;}
            else{fail++;failSess.add(e.session);fd+=e.duration;fe+=e.exposure;ft+=e.trough;}}
        for(int v:cnt.values())epsPer.put(v,epsPer.getOrDefault(v,0)+1);
        r.append("\n").append(cohort).append("\n");
        r.append(String.format(Locale.US,"Sessions with >=1 below-£100 episode: %d/%d (%.2f%%)%n",sess.size(),SESSIONS,100.0*sess.size()/SESSIONS));
        r.append(String.format(Locale.US,"Total episodes: %d | recovered: %d (%.2f%%) | failed/unrecovered: %d (%.2f%%)%n",a.size(),rec,100.0*rec/a.size(),fail,100.0*fail/a.size()));
        r.append(String.format(Locale.US,"Sessions with >=1 recovery: %d (%.2f%% of exposed sessions)%n",recSess.size(),100.0*recSess.size()/sess.size()));
        r.append(String.format(Locale.US,"Sessions with >=1 failed episode: %d (%.2f%% of exposed sessions)%n",failSess.size(),100.0*failSess.size()/sess.size()));
        r.append(String.format(Locale.US,"Recovered episodes mean duration %.2f hands | exposure £%.2f | trough £%.2f%n",rd/rec,re/rec,rt/rec));
        r.append(String.format(Locale.US,"Failed episodes mean duration %.2f hands | exposure £%.2f | trough £%.2f%n",fd/fail,fe/fail,ft/fail));
        r.append("Episodes per exposed session distribution: ");
        for(Map.Entry<Integer,Integer>e:epsPer.entrySet())r.append(e.getKey()).append("=").append(e.getValue()).append(" ");
        r.append("\n");
        int rec200=0,rec150=0,rec170=0,rec0=0,fail200=0,fail0=0;
        for(E109 e:a)if(e.recovered){if(e.reached150)rec150++;if(e.reached170)rec170++;if(e.reached200)rec200++;if(e.exhausted)rec0++;}
        else{if(e.reached200)fail200++;if(e.exhausted)fail0++;}
        r.append(String.format(Locale.US,"Recovered episodes associated with session later reaching £150/£170/£200/£0: %.2f%% / %.2f%% / %.2f%% / %.2f%%%n",
            100.0*rec150/rec,100.0*rec170/rec,100.0*rec200/rec,100.0*rec0/rec));
        r.append(String.format(Locale.US,"Failed episodes associated with session £200/£0: %.2f%% / %.2f%%%n",100.0*fail200/fail,100.0*fail0/fail));
    }
    static String csv109(ArrayList<E109>...gs){
        StringBuilder z=new StringBuilder("cohort,session,episode,start_hand,end_hand,duration,start_bankroll,trough,episode_exposure,recovered,recovered_amount,session_outcome,reached150,reached170,reached200,exhausted\n");
        for(ArrayList<E109>g:gs)for(E109 e:g)z.append(e.cohort).append(',').append(e.session).append(',').append(e.episode).append(',').append(e.startHand).append(',').append(e.endHand).append(',').append(e.duration).append(',').append(fmt106(e.startBank)).append(',').append(fmt106(e.trough)).append(',').append(fmt106(e.exposure)).append(',').append(e.recovered).append(',').append(fmt106(e.recoveredAmount)).append(',').append(e.outcome).append(',').append(e.reached150).append(',').append(e.reached170).append(',').append(e.reached200).append(',').append(e.exhausted).append('\n');
        return z.toString();
    }

    static final int[] CHECK110={3,5,10,15};
    static final class C110{
        String cohort,finalOutcome; int session,episode,checkpoint,globalHand;
        double currentBank,trough,exposure,drawdown100;
        boolean eventualRecovery,eventual200,eventual0;
    }
    static final class EP110{int episode,elapsed;double trough,exposure;ArrayList<C110> rows=new ArrayList<>();}
    static boolean check110(int n){for(int x:CHECK110)if(x==n)return true;return false;}

    static ArrayList<C110> run110(long seed,String cohort,int session){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session)); if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated160=false,r200=false,exhausted=false;
        int epNo=0; EP110 ep=null; ArrayList<EP110> all=new ArrayList<>();
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;} if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);if(brakeArmed){requested=Math.min(bs,15);brakeArmed=false;}else requested=bs;}
            else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;double stake=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);

            if(ep==null&&bank<100-1e-9&&bank>1e-9){ep=new EP110();ep.episode=++epNo;ep.elapsed=1;ep.trough=bank;ep.exposure=stake;all.add(ep);}
            else if(ep!=null){ep.elapsed++;ep.exposure+=stake;ep.trough=Math.min(ep.trough,bank);}
            if(ep!=null&&bank<100-1e-9&&check110(ep.elapsed)){
                C110 c=new C110();c.cohort=cohort;c.session=session+1;c.episode=ep.episode;c.checkpoint=ep.elapsed;c.globalHand=hand;
                c.currentBank=bank;c.trough=ep.trough;c.exposure=ep.exposure;c.drawdown100=100-bank;ep.rows.add(c);
            }
            if(ep!=null&&bank>=100-1e-9){for(C110 c:ep.rows)c.eventualRecovery=true;ep=null;}
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200-1e-9){r200=true;break;} if(bank<=1e-9){exhausted=true;break;}
            if(bank>=160-1e-9)activated160=true;
            if(activated160&&peak>100+1e-9){double profit=peak-100,surr=Math.max(0,peak-bank);if(100*surr/profit>=25-1e-9&&bank<140-1e-9)break;}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        String outcome=r200?"REACHED_200":(exhausted?"EXHAUSTED_0":(bank>100+1e-9?"FINISHED_ABOVE_100":(Math.abs(bank-100)<1e-9?"FINISHED_100":"FINISHED_BELOW_100")));
        ArrayList<C110> z=new ArrayList<>();for(EP110 e:all)for(C110 c:e.rows){c.eventual200=r200;c.eventual0=exhausted;c.finalOutcome=outcome;z.add(c);}return z;
    }
    static ArrayList<C110> cohort110(long seed,String cohort){ArrayList<C110>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.addAll(run110(seed,cohort,i));return a;}
    static void report110(StringBuilder r,String cohort,ArrayList<C110>a){
        r.append("\n").append(cohort).append("\n");
        for(int cp:CHECK110){ArrayList<C110>g=new ArrayList<>();for(C110 c:a)if(c.checkpoint==cp)g.add(c);
            int n=g.size(),rec=0,r2=0,r0=0;double b=0,t=0,e=0;
            for(C110 c:g){if(c.eventualRecovery)rec++;if(c.eventual200)r2++;if(c.eventual0)r0++;b+=c.currentBank;t+=c.trough;e+=c.exposure;}
            r.append(String.format(Locale.US,"Checkpoint %d: n=%d | later recovery %.2f%% | session £200 %.2f%% | session £0 %.2f%% | bankroll £%.2f | trough £%.2f | exposure £%.2f%n",cp,n,100.0*rec/n,100.0*r2/n,100.0*r0/n,b/n,t/n,e/n));
            for(boolean q:new boolean[]{true,false}){int nn=0;double bb=0,tt=0,ee=0;for(C110 c:g)if(c.eventualRecovery==q){nn++;bb+=c.currentBank;tt+=c.trough;ee+=c.exposure;}
                r.append(String.format(Locale.US,"  %s n=%d | bankroll £%.2f | trough £%.2f | exposure £%.2f%n",q?"LATER_RECOVERED":"LATER_UNRECOVERED",nn,bb/nn,tt/nn,ee/nn));}
        }
    }
    static String csv110(ArrayList<C110>...gs){StringBuilder z=new StringBuilder("cohort,session,episode,checkpoint_active_rounds,global_hand,current_bankroll,trough,episode_exposure,drawdown_from_100,eventual_recovery,eventual_200,eventual_0,session_final_outcome\n");
        for(ArrayList<C110>g:gs)for(C110 c:g)z.append(c.cohort).append(',').append(c.session).append(',').append(c.episode).append(',').append(c.checkpoint).append(',').append(c.globalHand).append(',').append(fmt106(c.currentBank)).append(',').append(fmt106(c.trough)).append(',').append(fmt106(c.exposure)).append(',').append(fmt106(c.drawdown100)).append(',').append(c.eventualRecovery).append(',').append(c.eventual200).append(',').append(c.eventual0).append(',').append(c.finalOutcome).append('\n');return z.toString();}

    /* PHASE 3.117 — FROZEN PROTECTIVE WALK-AWAY INTERVENTION

       Frozen gate inherited unchanged from 3.115:
       - episode remains below £100 for 10 active recovery rounds
       - current bankroll < £50

       Frozen intervention:
       - from gate activation, cap requested wager at the legal £15 table minimum
       - remain in protection until bankroll recovers to >= £100
       - no termination, no future information, no threshold sweep
    */
    static final class S116 {
        String cohort,policy,termination="HAND_CAP"; int session,hands,gateActivations,recoveriesAfterGate;
        double finalBank,peak,maxDD,cumWager,failedGateExposure;
        double gateBankroll,gateEpisodeTrough,gateEpisodeExposure,gateLargestLoss,gateAbsoluteMovement;
        int gateEpisodeWins,gateEpisodeLosses,gateEpisodePushes;
        boolean reached200,exhausted,gateEver;
        boolean obsEnteredRecovery,obsCapitalAlert,obsRecovered100,obsReached150,obsReached170;
        int obsRecoveryHand=-1,obsCapitalAlertHand=-1,obsRecovered100Hand=-1,obsReached150Hand=-1,obsReached170Hand=-1;
        double obsPeak=100.0,obsTrough=100.0;
        int obsPeakHand=0,obsTroughHand=0;
    }

    static S116 runOne116(long seed,String cohort,int session,boolean candidate){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated160=false;
        boolean inEpisode=false,protect=false;int epElapsed=0;double gateExposure=0;
        double epTrough=0,epExposure=0,epLargestLoss=0,epAbsoluteMovement=0;
        int epWins=0,epLosses=0,epPushes=0;
        S116 x=new S116();x.cohort=cohort;x.policy=candidate?"FROZEN_CP10_LT50_CAP15":"REFERENCE";x.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);if(brakeArmed){requested=Math.min(bs,15);brakeArmed=false;}else requested=bs;}
            else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            /* 3.117: no wager modification before the frozen gate. */
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;double stake=roundStake356(rr);double beforeBank=bank;cum+=stake;if(protect)gateExposure+=stake;
            bank+=rr.net;if(bank<0)bank=0;x.hands++;peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            if(!inEpisode&&bank<100-1e-9&&bank>1e-9){
                if(!x.obsEnteredRecovery){x.obsEnteredRecovery=true;x.obsRecoveryHand=hand;}
                inEpisode=true;epElapsed=1;epTrough=bank;epExposure=stake;epLargestLoss=rr.net<0?-rr.net:0;
                epAbsoluteMovement=Math.abs(bank-beforeBank);epWins=rr.net>1e-9?1:0;epLosses=rr.net<-1e-9?1:0;epPushes=Math.abs(rr.net)<=1e-9?1:0;
            }
            else if(inEpisode){
                epElapsed++;epTrough=Math.min(epTrough,bank);epExposure+=stake;epLargestLoss=Math.max(epLargestLoss,rr.net<0?-rr.net:0);
                epAbsoluteMovement+=Math.abs(bank-beforeBank);if(rr.net>1e-9)epWins++;else if(rr.net<-1e-9)epLosses++;else epPushes++;
            }

            if(inEpisode&&epElapsed>=10&&bank<50-1e-9&&!x.obsCapitalAlert){
                x.obsCapitalAlert=true;x.obsCapitalAlertHand=hand;
            }
            if(candidate&&inEpisode&&!protect&&epElapsed>=10&&bank<50-1e-9){
                protect=true;x.gateEver=true;x.gateActivations++;gateExposure=0;
                x.gateBankroll=bank;x.gateEpisodeTrough=epTrough;x.gateEpisodeExposure=epExposure;
                x.gateLargestLoss=epLargestLoss;x.gateAbsoluteMovement=epAbsoluteMovement;
                x.gateEpisodeWins=epWins;x.gateEpisodeLosses=epLosses;x.gateEpisodePushes=epPushes;
                x.termination="FROZEN_CP10_LT50_WALK_AWAY";
                break;
            }
            if(inEpisode&&bank>=100-1e-9){
                if(!x.obsRecovered100){x.obsRecovered100=true;x.obsRecovered100Hand=hand;}
                if(protect){x.recoveriesAfterGate++;protect=false;gateExposure=0;}
                inEpisode=false;epElapsed=0;epTrough=0;epExposure=0;epLargestLoss=0;epAbsoluteMovement=0;epWins=epLosses=epPushes=0;
            }

            if(bank>x.obsPeak+1e-9){x.obsPeak=bank;x.obsPeakHand=hand;}
            if(bank<x.obsTrough-1e-9){x.obsTrough=bank;x.obsTroughHand=hand;}
            if(bank>=150-1e-9&&!x.obsReached150){x.obsReached150=true;x.obsReached150Hand=hand;}
            if(bank>=170-1e-9&&!x.obsReached170){x.obsReached170=true;x.obsReached170Hand=hand;}
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=200-1e-9){x.reached200=true;x.termination="REACHED_200";break;}
            if(bank<=1e-9){x.exhausted=true;x.termination="EXHAUSTED_0";break;}
            if(bank>=160-1e-9)activated160=true;
            if(activated160&&peak>100+1e-9){double profit=peak-100,surr=Math.max(0,peak-bank);
                if(100*surr/profit>=25-1e-9&&bank<140-1e-9){x.termination="FROZEN_SELECTIVE_EXIT";break;}}
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        if(protect)x.failedGateExposure+=gateExposure;
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;return x;
    }

    static ArrayList<S116> cohort116(long seed,String cohort,boolean candidate){
        ArrayList<S116>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne116(seed,cohort,i,candidate));return a;
    }




    static final long FRESH_A_SEED = 202601L;
    static final long FRESH_B_SEED = 202701L;








    static double pct130(int x,int n){return 100.0*x/n;}
    static final long INT_C_SEED=203301L,INT_D_SEED=203401L;

    static final class Evidence130{
        String cohort;int n,rec,alert,alertRecovered,alert150,alert170;
        int profit150,profitGiveback,near170;
    }
    static Evidence130 evidence130(String cohort,ArrayList<S116>a){
        Evidence130 e=new Evidence130();e.cohort=cohort;e.n=a.size();
        for(S116 s:a){
            if(s.obsEnteredRecovery)e.rec++;
            if(s.obsCapitalAlert){
                e.alert++;
                if(s.obsRecovered100)e.alertRecovered++;
                if(s.obsReached150)e.alert150++;
                if(s.obsReached170)e.alert170++;
            }
            if(s.obsReached150)e.profit150++;
            if(s.obsReached150&&!s.obsReached170&&s.finalBank<100-1e-9)e.profitGiveback++;
            if(s.obsReached170)e.near170++;
        }
        return e;
    }

    static void panel130(StringBuilder r,Evidence130 e){
        r.append("\n").append(e.cohort).append("\n");
        r.append(String.format(Locale.US,"CAPITAL_ALERT incidence: %.2f%%%n",pct130(e.alert,e.n)));
        r.append(String.format(Locale.US,"Historical continuation after CAPITAL_ALERT: later >=£100 %.2f%% | >=£150 %.2f%% | >=£170 %.2f%%%n",
          pct130(e.alertRecovered,e.alert),pct130(e.alert150,e.alert),pct130(e.alert170,e.alert)));
        r.append(String.format(Locale.US,"Reached >=£150: %.2f%% | completed PROFIT_GIVEBACK archetype: %.2f%% of all sessions%n",
          pct130(e.profit150,e.n),pct130(e.profitGiveback,e.n)));
        r.append(String.format(Locale.US,"Reached >=£170: %.2f%%%n",pct130(e.near170,e.n)));
        r.append("LIVE DECISION-SUPPORT INFORMATION BOUNDARY\n");
        r.append("  ALLOWED NOW: current bankroll, past peak/trough, elapsed recovery rounds, cumulative wager, prior state crossings, declared/current objective.\n");
        r.append("  HISTORICAL CONTEXT ONLY: aggregate transition/archetype frequencies from completed populations.\n");
        r.append("  FORBIDDEN AS LIVE INPUT: the current session's eventual archetype, future cards, future bankroll, eventual £0/£200 result.\n");
    }

    static String matrix130(){
        StringBuilder z=new StringBuilder("observed_state,objective_state,live_response,evidence_role,future_information_allowed\n");
        String[] states={"RECOVERY_ACTIVE","CAPITAL_ALERT","RECOVERED","PROFIT_DEPLOYMENT","PROTECTIVE_NEAR_TARGET"};
        String[] obj={"CAPITAL_PRESERVATION","BALANCED_RECOVERY","OPPORTUNITY_PRESERVATION"};
        for(String s:states)for(String o:obj){
            String response;
            if(s.equals("CAPITAL_ALERT")){
                if(o.equals("CAPITAL_PRESERVATION"))response="WALK_AWAY_SUPPORTED";
                else if(o.equals("OPPORTUNITY_PRESERVATION"))response="CONTINUE_REFERENCE_WITH_RUIN_EXPOSURE_WARNING";
                else response="SHOW_TRADEOFF_HUMAN_CHOICE";
            } else {
                response="STATE_EVIDENCE_ONLY_NO_NEW_ACTION_VALIDATED";
            }
            z.append(s).append(',').append(o).append(',').append(response)
             .append(",USE_COMPLETED_POPULATIONS_AS_HISTORICAL_CONTEXT_ONLY,false\n");
        }
        return z.toString();
    }


    /* PHASE 3.131 — PROSPECTIVE £150 PROFIT-PROTECTION ACTION SCREEN
       PREDECLARED BEFORE EXECUTION.

       Purpose:
       Phase 3.130 established £150 as a descriptive live state but explicitly
       refused to manufacture advice from retrospective path labels.
       Phase 3.131 therefore tests three prospective action overlays beginning
       only after the CURRENT session first reaches >=£150:

       1. CONTINUE_REFERENCE
          Preserve the frozen Phase 3.130 continuation architecture.
       2. HARD_EXIT_150
          Capital-preservation boundary: stop immediately on first completed
          round at >=£150.
       3. TRAIL_150_GIVEBACK_25
          Balanced protection boundary: after first reaching >=£150, continue,
          but stop if >=25% of accumulated high-water profit above £100 has
          subsequently been surrendered.

       The frozen Phase 3.130 selective £160/25%/<£140 rule remains available
       inside CONTINUE_REFERENCE and as a fallback in the trailing overlay.
       No wager-controller, hand-action policy, denomination rule, shoe order,
       target, or session horizon is tuned here.

       This is an action-validation screen, NOT an optimisation phase.
    */

    static final String P131_REF="CONTINUE_REFERENCE";
    static final String P131_EXIT150="HARD_EXIT_150";
    static final String P131_TRAIL150="TRAIL_150_GIVEBACK_25";

    static final class S131 {
        String cohort,policy,termination;
        int session,hands,first150Hand=-1,stopHand=-1;
        double finalBank,peak,maxDD,cumWager,first150Bank=0,stopBank=0;
        boolean reached150,reached170,reached200,exhausted,stopped;
    }

    static S131 runOne131(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        boolean activated160=false,activated150=false;
        S131 x=new S131();x.cohort=cohort;x.policy=policy;x.session=session+1;x.termination="30_HAND";

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                if(brakeArmed){requested=Math.min(bs,15);brakeArmed=false;}else requested=bs;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);
            bank+=rr.net;if(bank<0)bank=0;x.hands++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9&&!activated150){
                activated150=true;x.reached150=true;x.first150Hand=hand;x.first150Bank=bank;
            }
            if(bank>=170-1e-9)x.reached170=true;

            if(bank>=200-1e-9){x.reached200=true;x.termination="REACHED_200";break;}
            if(bank<=1e-9){x.exhausted=true;x.termination="EXHAUSTED_0";break;}

            // Prospective overlays begin only after the observed >=£150 state exists.
            if(activated150 && policy.equals(P131_EXIT150)){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination="HARD_EXIT_150";break;
            }
            if(activated150 && policy.equals(P131_TRAIL150) && peak>100+1e-9){
                double profit=peak-100.0;
                double surrendered=Math.max(0,peak-bank);
                if(100.0*surrendered/profit>=25.0-1e-9){
                    x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination="TRAIL_150_GIVEBACK_25";break;
                }
            }

            // Frozen Phase 3.130 selective protection remains part of the reference architecture.
            if(bank>=160-1e-9)activated160=true;
            if(activated160&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                if(100.0*surr/profit>=25.0-1e-9&&bank<140-1e-9){
                    x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination="FROZEN_SELECTIVE_EXIT";break;
                }
            }

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;
        return x;
    }

    static ArrayList<S131> cohort131(long seed,String cohort,String policy){
        ArrayList<S131>a=new ArrayList<>();
        for(int i=0;i<SESSIONS;i++)a.add(runOne131(seed,cohort,i,policy));
        return a;
    }

    static final class M131{
        String cohort,policy;int n,reach150,reach170,reach200,bust,positive,be,loss,stopped;
        double finalSum,wagerSum,ddSum,first150HandSum,stopHandSum,stopBankSum;
    }
    static M131 measure131(String cohort,String policy,ArrayList<S131>a){
        M131 m=new M131();m.cohort=cohort;m.policy=policy;m.n=a.size();
        for(S131 s:a){
            m.finalSum+=s.finalBank;m.wagerSum+=s.cumWager;m.ddSum+=s.maxDD;
            if(s.reached150){m.reach150++;m.first150HandSum+=s.first150Hand;}
            if(s.reached170)m.reach170++;if(s.reached200)m.reach200++;if(s.exhausted)m.bust++;
            if(s.finalBank>100+1e-9)m.positive++;else if(Math.abs(s.finalBank-100)<1e-9)m.be++;else m.loss++;
            if(s.stopped){m.stopped++;m.stopHandSum+=s.stopHand;m.stopBankSum+=s.stopBank;}
        }
        return m;
    }
    static double p131(int x,int n){return n==0?0:100.0*x/n;}
    static void panel131(StringBuilder r,M131 m){
        double net=m.finalSum-100.0*m.n;
        r.append("\n").append(m.cohort).append(" / ").append(m.policy).append("\n");
        r.append(String.format(Locale.US,"Average ending bankroll: £%.3f%n",m.finalSum/m.n));
        r.append(String.format(Locale.US,"Population net change: £%+.2f%n",net));
        r.append(String.format(Locale.US,"Population return on cumulative wager: %+.4f%%%n",100.0*net/m.wagerSum));
        r.append(String.format(Locale.US,"Positive / break-even / losing: %.2f%% / %.2f%% / %.2f%%%n",
            p131(m.positive,m.n),p131(m.be,m.n),p131(m.loss,m.n)));
        r.append(String.format(Locale.US,"Reached £150 / £170 / £200: %.2f%% / %.2f%% / %.2f%%%n",
            p131(m.reach150,m.n),p131(m.reach170,m.n),p131(m.reach200,m.n)));
        r.append(String.format(Locale.US,"Finished £0: %.2f%%%n",p131(m.bust,m.n)));
        r.append(String.format(Locale.US,"Average maximum drawdown: £%.3f%n",m.ddSum/m.n));
        r.append(String.format(Locale.US,"Average cumulative wager: £%.3f%n",m.wagerSum/m.n));
        r.append(String.format(Locale.US,"First £150 reach: %.2f%% of sessions | mean hand %.2f%n",
            p131(m.reach150,m.n),m.reach150==0?0:m.first150HandSum/m.reach150));
        if(m.stopped>0)r.append(String.format(Locale.US,
            "Stops: %.2f%% of sessions | mean stop hand %.2f | mean retained bankroll £%.3f%n",
            p131(m.stopped,m.n),m.stopHandSum/m.stopped,m.stopBankSum/m.stopped));
    }

    static String csv131(ArrayList<S131>...groups){
        StringBuilder z=new StringBuilder("cohort,policy,session,hands,first150_hand,first150_bankroll,final_bankroll,peak_bankroll,max_drawdown,cumulative_wager,reached150,reached170,reached200,exhausted,stopped,stop_hand,stop_bankroll,termination\n");
        for(ArrayList<S131>g:groups)for(S131 s:g)z.append(String.format(Locale.US,
            "%s,%s,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%d,%.2f,%s%n",
            s.cohort,s.policy,s.session,s.hands,s.first150Hand,s.first150Bank,s.finalBank,s.peak,s.maxDD,s.cumWager,
            s.reached150,s.reached170,s.reached200,s.exhausted,s.stopped,s.stopHand,s.stopBank,s.termination));
        return z.toString();
    }


    /* PHASE 3.132 — PAIRED CAUSAL DECOMPOSITION OF £150 PROTECTION
       PREDECLARED ANALYSIS. NO THRESHOLD TUNING.

       Replays the identical deterministic cohort/session under the three frozen
       Phase 3.131 policies and compares outcomes pairwise. The purpose is to
       explain WHAT the prospective actions changed, not to select a new threshold.
    */
    static final class Pair132 {
        String cohort, comparison;
        int n, affected, altBetter, refBetter, equalFinal;
        int terminalLossPrevented, terminalLossCreated;
        int target200Removed, target200Preserved, target200Created;
        int profitableContinuationCutShort, interventionSavedLoss;
        double finalDeltaSum, exposureRemovedSum, ddAvoidedSum;
        double absFinalDeltaSum;
    }

    static Pair132 compare132(String cohort, String label, ArrayList<S131> ref, ArrayList<S131> alt){
        Pair132 p=new Pair132(); p.cohort=cohort; p.comparison=label; p.n=ref.size();
        for(int i=0;i<ref.size();i++){
            S131 r=ref.get(i), a=alt.get(i);
            double d=a.finalBank-r.finalBank;
            double ex=r.cumWager-a.cumWager;
            double dd=r.maxDD-a.maxDD;
            p.finalDeltaSum+=d; p.exposureRemovedSum+=ex; p.ddAvoidedSum+=dd; p.absFinalDeltaSum+=Math.abs(d);
            boolean affected=Math.abs(d)>1e-9 || Math.abs(ex)>1e-9 || r.reached200!=a.reached200 || r.exhausted!=a.exhausted;
            if(affected)p.affected++;
            if(d>1e-9)p.altBetter++; else if(d<-1e-9)p.refBetter++; else p.equalFinal++;
            if(r.exhausted&&!a.exhausted){p.terminalLossPrevented++;p.interventionSavedLoss++;}
            if(!r.exhausted&&a.exhausted)p.terminalLossCreated++;
            if(r.reached200&&!a.reached200)p.target200Removed++;
            if(r.reached200&&a.reached200)p.target200Preserved++;
            if(!r.reached200&&a.reached200)p.target200Created++;
            if(a.stopped && r.finalBank>a.finalBank+1e-9)p.profitableContinuationCutShort++;
        }
        return p;
    }

    static void panel132(StringBuilder r, Pair132 p){
        r.append("\n").append(p.cohort).append(" / ").append(p.comparison).append("\n");
        r.append(String.format(Locale.US,"Sessions affected by intervention: %d / %d (%.2f%%)%n",p.affected,p.n,p131(p.affected,p.n)));
        r.append(String.format(Locale.US,"Alternative final bankroll higher / reference higher / equal: %.2f%% / %.2f%% / %.2f%%%n",
            p131(p.altBetter,p.n),p131(p.refBetter,p.n),p131(p.equalFinal,p.n)));
        r.append(String.format(Locale.US,"Mean final-bankroll delta (alternative - reference): £%+.3f%n",p.finalDeltaSum/p.n));
        r.append(String.format(Locale.US,"Mean exposure removed (reference - alternative): £%+.3f%n",p.exposureRemovedSum/p.n));
        r.append(String.format(Locale.US,"Mean max-drawdown avoided (reference - alternative): £%+.3f%n",p.ddAvoidedSum/p.n));
        r.append(String.format(Locale.US,"Terminal £0 losses prevented / created: %d / %d (%.2f%% / %.2f%%)%n",
            p.terminalLossPrevented,p.terminalLossCreated,p131(p.terminalLossPrevented,p.n),p131(p.terminalLossCreated,p.n)));
        r.append(String.format(Locale.US,"£200 outcomes removed / preserved / created: %d / %d / %d (%.2f%% / %.2f%% / %.2f%%)%n",
            p.target200Removed,p.target200Preserved,p.target200Created,
            p131(p.target200Removed,p.n),p131(p.target200Preserved,p.n),p131(p.target200Created,p.n)));
        r.append(String.format(Locale.US,"Stopped sessions where reference later finished higher: %d (%.2f%%)%n",
            p.profitableContinuationCutShort,p131(p.profitableContinuationCutShort,p.n)));
    }

    static String csv132(String cohort, ArrayList<S131> ref, ArrayList<S131> hard, ArrayList<S131> trail){
        StringBuilder z=new StringBuilder("cohort,session,comparison,ref_final,alt_final,final_delta,ref_exposure,alt_exposure,exposure_removed,ref_maxdd,alt_maxdd,drawdown_avoided,ref_200,alt_200,ref_zero,alt_zero,alt_stopped,alt_stop_hand,alt_stop_bankroll\n");
        ArrayList<S131>[] alts=new ArrayList[]{hard,trail};
        String[] labels={"HARD_EXIT_150_vs_CONTINUE_REFERENCE","TRAIL_150_GIVEBACK_25_vs_CONTINUE_REFERENCE"};
        for(int k=0;k<alts.length;k++)for(int i=0;i<ref.size();i++){
            S131 r=ref.get(i),a=alts[k].get(i);
            z.append(String.format(Locale.US,"%s,%d,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%d,%.2f%n",
                cohort,i+1,labels[k],r.finalBank,a.finalBank,a.finalBank-r.finalBank,
                r.cumWager,a.cumWager,r.cumWager-a.cumWager,r.maxDD,a.maxDD,r.maxDD-a.maxDD,
                r.reached200,a.reached200,r.exhausted,a.exhausted,a.stopped,a.stopHand,a.stopBank));
        }
        return z.toString();
    }


    /* PHASE 3.133 — HELP-VERSUS-HARM DIVERGENCE ANATOMY
       RETROSPECTIVE CHARACTERISATION ONLY — NOT A LIVE PREDICTOR.

       Phase 3.132 established paired divergence. 3.133 asks what the observable
       session looked like AT THE PREDECLARED intervention point in sessions
       where protection later helped versus harmed. Future outcome labels are
       used only after replay for research grouping and are never fed to policy.
       The 25% threshold remains frozen; no threshold search occurs.
    */

    static final class A133 {
        String cohort,policy,outcome;
        int session,interventionHand;
        double interventionBank,peakAtIntervention,exposureAtIntervention,drawdownAtIntervention;
        double finalRef,finalAlt,finalDelta,exposureRemoved,ddAvoided;
        boolean ref200,alt200,refZero,altZero;
    }

    static A133 anatomy133(String cohort,int session,String policy,S131 ref,S131 alt){
        A133 a=new A133();a.cohort=cohort;a.session=session+1;a.policy=policy;
        a.interventionHand=alt.stopHand;a.interventionBank=alt.stopBank;
        a.finalRef=ref.finalBank;a.finalAlt=alt.finalBank;a.finalDelta=alt.finalBank-ref.finalBank;
        a.exposureRemoved=ref.cumWager-alt.cumWager;a.ddAvoided=ref.maxDD-alt.maxDD;
        a.ref200=ref.reached200;a.alt200=alt.reached200;a.refZero=ref.exhausted;a.altZero=alt.exhausted;
        if(a.finalDelta>1e-9)a.outcome="HELPED";
        else if(a.finalDelta<-1e-9)a.outcome="HARMED";
        else a.outcome="NEUTRAL";

        // Replay only to the already-observed intervention hand to recover state anatomy.
        // This does not alter either policy result and does not use future cards.
        int[]shoe=sixDeckShoe(sessionSeed(policy.equals(P131_EXIT150)||policy.equals(P131_TRAIL150)?seedForCohort133(cohort):seedForCohort133(cohort),session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false;
        for(int hand=1;hand<=a.interventionHand && hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;} if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            } else {requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        a.peakAtIntervention=peak;a.exposureAtIntervention=cum;a.drawdownAtIntervention=Math.max(0,peak-a.interventionBank);
        return a;
    }

    static long seedForCohort133(String c){
        if(c.equals("FRESH_A"))return FRESH_A_SEED;if(c.equals("FRESH_B"))return FRESH_B_SEED;
        if(c.equals("ROBUST_C"))return INT_C_SEED;return INT_D_SEED;
    }

    static void group133(StringBuilder r,String policy,String outcome,ArrayList<A133> all){
        int n=0;double h=0,b=0,p=0,e=0,d=0,fd=0,er=0,dda=0;int r200=0,r0=0;
        for(A133 a:all)if(a.policy.equals(policy)&&a.outcome.equals(outcome)){
            n++;h+=a.interventionHand;b+=a.interventionBank;p+=a.peakAtIntervention;e+=a.exposureAtIntervention;
            d+=a.drawdownAtIntervention;fd+=a.finalDelta;er+=a.exposureRemoved;dda+=a.ddAvoided;
            if(a.ref200)r200++;if(a.refZero)r0++;
        }
        r.append("\n").append(policy).append(" / ").append(outcome).append("\n");
        r.append("n = ").append(n).append("\n"); if(n==0)return;
        r.append(String.format(Locale.US,"Mean intervention hand: %.3f%n",h/n));
        r.append(String.format(Locale.US,"Mean bankroll at intervention: £%.3f%n",b/n));
        r.append(String.format(Locale.US,"Mean peak at intervention: £%.3f%n",p/n));
        r.append(String.format(Locale.US,"Mean cumulative exposure at intervention: £%.3f%n",e/n));
        r.append(String.format(Locale.US,"Mean drawdown at intervention: £%.3f%n",d/n));
        r.append(String.format(Locale.US,"Mean final delta (protection-reference): £%+.3f%n",fd/n));
        r.append(String.format(Locale.US,"Mean exposure subsequently removed: £%+.3f%n",er/n));
        r.append(String.format(Locale.US,"Mean maxDD subsequently avoided: £%+.3f%n",dda/n));
        r.append(String.format(Locale.US,"Reference later £200 / £0: %.2f%% / %.2f%%%n",p131(r200,n),p131(r0,n)));
    }

    static String csv133(ArrayList<A133> all){
        StringBuilder z=new StringBuilder("cohort,session,policy,outcome,intervention_hand,intervention_bankroll,peak_at_intervention,exposure_at_intervention,drawdown_at_intervention,reference_final,protected_final,final_delta,exposure_removed,maxdd_avoided,reference_200,protected_200,reference_zero,protected_zero\n");
        for(A133 a:all)z.append(String.format(Locale.US,"%s,%d,%s,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s%n",
            a.cohort,a.session,a.policy,a.outcome,a.interventionHand,a.interventionBank,a.peakAtIntervention,a.exposureAtIntervention,a.drawdownAtIntervention,
            a.finalRef,a.finalAlt,a.finalDelta,a.exposureRemoved,a.ddAvoided,a.ref200,a.alt200,a.refZero,a.altZero));
        return z.toString();
    }


    /* PHASE 3.134 — PROSPECTIVE EXPOSURE DISCRIMINATION GATE
       FRESH-COHORT VALIDATION. NO THRESHOLD TUNING.

       Phase 3.133 found a retrospective exposure difference at the frozen
       TRAIL_150_GIVEBACK_25 intervention:
           HELPED mean exposure ≈ £214.86
           HARMED mean exposure ≈ £234.99

       Before running any new cohort, Phase 3.137 predeclares ONE simple,
       rounded, observable discriminator:
           LOW-EXPOSURE GATE: cumulative wager at trigger <= £225

       Hypothesis:
       among sessions where the frozen trailing rule triggers, the <=£225
       subgroup will contain a larger HELPED:HARMED balance than the >£225
       subgroup.

       This phase evaluates classification/enrichment only. It does NOT alter
       the live policy and does NOT tune £225 or the frozen 25% trailing rule.
    */

    static final double P134_EXPOSURE_GATE = 225.0;
    static final long P134_A_SEED = 206101L;
    static final long P134_B_SEED = 206201L;
    static final long P134_C_SEED = 206301L;
    static final long P134_D_SEED = 206401L;

    static final class D134 {
        String cohort, band, outcome;
        int n, helped, harmed, neutral, ref200, refZero;
        double expSum, handSum, bankSum, peakSum, ddSum, deltaSum;
    }

    static void add134(D134 d, A133 a){
        d.n++;
        if(a.outcome.equals("HELPED")) d.helped++;
        else if(a.outcome.equals("HARMED")) d.harmed++;
        else d.neutral++;
        if(a.ref200)d.ref200++;
        if(a.refZero)d.refZero++;
        d.expSum += a.exposureAtIntervention;
        d.handSum += a.interventionHand;
        d.bankSum += a.interventionBank;
        d.peakSum += a.peakAtIntervention;
        d.ddSum += a.drawdownAtIntervention;
        d.deltaSum += a.finalDelta;
    }

    static double ratio134(int a,int b){ return b==0 ? Double.POSITIVE_INFINITY : 1.0*a/b; }

    static void report134(StringBuilder r, D134 d){
        r.append("\n").append(d.cohort).append(" / ").append(d.band).append("\n");
        r.append("n = ").append(d.n).append("\n");
        if(d.n==0)return;
        r.append(String.format(Locale.US,"HELPED / HARMED / NEUTRAL: %d / %d / %d (%.2f%% / %.2f%% / %.2f%%)%n",
            d.helped,d.harmed,d.neutral,p131(d.helped,d.n),p131(d.harmed,d.n),p131(d.neutral,d.n)));
        r.append(String.format(Locale.US,"HELPED:HARMED ratio: %.3f%n",ratio134(d.helped,d.harmed)));
        r.append(String.format(Locale.US,"Mean exposure at trigger: £%.3f%n",d.expSum/d.n));
        r.append(String.format(Locale.US,"Mean trigger hand: %.3f%n",d.handSum/d.n));
        r.append(String.format(Locale.US,"Mean bankroll / peak / drawdown at trigger: £%.3f / £%.3f / £%.3f%n",
            d.bankSum/d.n,d.peakSum/d.n,d.ddSum/d.n));
        r.append(String.format(Locale.US,"Mean final delta from applying trailing protection: £%+.3f%n",d.deltaSum/d.n));
        r.append(String.format(Locale.US,"Reference later £200 / £0: %.2f%% / %.2f%%%n",
            p131(d.ref200,d.n),p131(d.refZero,d.n)));
    }

    static String csv134(ArrayList<A133> all){
        StringBuilder z=new StringBuilder(
            "cohort,session,exposure_gate,gate_band,outcome,intervention_hand,intervention_bankroll,peak_at_intervention,exposure_at_intervention,drawdown_at_intervention,reference_final,protected_final,final_delta,reference_200,reference_zero\n");
        for(A133 a:all){
            String band=a.exposureAtIntervention<=P134_EXPOSURE_GATE+1e-9 ? "LOW_EXPOSURE_LE_225" : "HIGH_EXPOSURE_GT_225";
            z.append(String.format(Locale.US,
                "%s,%d,%.2f,%s,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s%n",
                a.cohort,a.session,P134_EXPOSURE_GATE,band,a.outcome,a.interventionHand,
                a.interventionBank,a.peakAtIntervention,a.exposureAtIntervention,
                a.drawdownAtIntervention,a.finalRef,a.finalAlt,a.finalDelta,a.ref200,a.refZero));
        }
        return z.toString();
    }


    /* PHASE 3.137 — FRESH TWO-VARIABLE DISCRIMINATOR VALIDATION
       FROZEN FROM PHASE 3.136:
          cumulative exposure at trailing trigger <= £225
          AND current bankroll at trigger >= £140

       This phase validates discrimination only. It does not make the two-variable
       condition a live action policy and does not tune either cutpoint.
    */
    static final double P137_EXPOSURE_GATE=225.0;
    static final double P137_BANKROLL_GATE=140.0;
    static final long[] P137_SEEDS={206101L,206201L,206301L,206401L};
    static final String[] P137_COHORTS={"FRESH_M","FRESH_N","FRESH_O","FRESH_P"};

    static void report137(StringBuilder r,String cohort,String label,ArrayList<A133> xs){
        int h=0,b=0,n=0;double delta=0,exp=0,hand=0,bank=0,peak=0,dd=0;
        for(A133 a:xs){if(a.outcome.equals("HELPED"))h++;else if(a.outcome.equals("HARMED"))b++;else n++;
            delta+=a.finalDelta;exp+=a.exposureAtIntervention;hand+=a.interventionHand;bank+=a.interventionBank;peak+=a.peakAtIntervention;dd+=a.drawdownAtIntervention;}
        int z=xs.size();double ratio=b==0?Double.POSITIVE_INFINITY:1.0*h/b;
        r.append("\n").append(cohort).append(" / ").append(label).append("\n");
        r.append("n = ").append(z).append("\n");
        if(z>0)r.append(String.format(Locale.US,
          "HELPED / HARMED / NEUTRAL: %d / %d / %d (%.2f%% / %.2f%% / %.2f%%)%nHELPED:HARMED ratio: %.3f%nMean final delta: £%+.3f%nMean trigger hand: %.3f%nMean bankroll / peak / drawdown: £%.3f / £%.3f / £%.3f%nMean trigger exposure: £%.3f%n",
          h,b,n,p131(h,z),p131(b,z),p131(n,z),ratio,delta/z,hand/z,bank/z,peak/z,dd/z,exp/z));
    }


    /* PHASE 3.139 — TWO-VARIABLE GATED TRAILING ACTION TEST
       Entirely fresh deterministic cohorts.

       Frozen from prior evidence:
         exposure <= £225
         bankroll >= £140
         trailing give-back = 25%

       Policies:
         CONTINUE_REFERENCE
         ALWAYS_TRAIL_150_GIVEBACK_25
         TWO_VARIABLE_GATED_TRAIL

       No threshold tuning.
    */
    static final long[] P139_SEEDS={207101L,207201L,207301L,207401L};
    static final String[] P139_COHORTS={"FRESH_Q","FRESH_R","FRESH_S","FRESH_T"};
    static final String P139_GATED="TWO_VARIABLE_GATED_TRAIL";
    static final double P139_EXPOSURE_GATE=225.0,P139_BANKROLL_GATE=140.0;

    static S131 runOne139(long seed,String cohort,int session,String policy){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,maxDD=0,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated160=false,activated150=false;
        S131 x=new S131();x.cohort=cohort;x.policy=policy;x.session=session+1;x.termination="30_HAND";
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;}
            else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;x.hands++;peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9&&!activated150){activated150=true;x.reached150=true;x.first150Hand=hand;x.first150Bank=bank;}
            if(bank>=170-1e-9)x.reached170=true;
            if(bank>=200-1e-9){x.reached200=true;x.termination="REACHED_200";break;}
            if(bank<=1e-9){x.exhausted=true;x.termination="EXHAUSTED_0";break;}

            boolean trailTrigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trailTrigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(policy.equals(P131_TRAIL150)&&trailTrigger){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination="TRAIL_150_GIVEBACK_25";break;
            }

            if(policy.equals(P139_GATED)&&trailTrigger
                &&cum<=P139_EXPOSURE_GATE+1e-9
                &&bank>=P139_BANKROLL_GATE-1e-9){
                x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination=P139_GATED;break;
            }

            if(policy.equals(P131_REF)){
                if(bank>=160-1e-9)activated160=true;
                if(activated160&&peak>100+1e-9){
                    double profit=peak-100.0,surr=Math.max(0,peak-bank);
                    if(100.0*surr/profit>=25.0-1e-9&&bank<140-1e-9){
                        x.stopped=true;x.stopHand=hand;x.stopBank=bank;x.termination="FROZEN_SELECTIVE_EXIT";break;
                    }
                }
            }

            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        x.finalBank=bank;x.peak=peak;x.maxDD=maxDD;x.cumWager=cum;return x;
    }

    static ArrayList<S131> cohort139(long seed,String cohort,String policy){
        ArrayList<S131>a=new ArrayList<>();for(int i=0;i<SESSIONS;i++)a.add(runOne139(seed,cohort,i,policy));return a;
    }

    static String csv139(ArrayList<ArrayList<S131>> all){
        StringBuilder z=new StringBuilder("cohort,policy,session,hands,final_bankroll,cumulative_wager,mean_wager_per_hand,max_drawdown,reached150,reached170,reached200,exhausted,stopped,stop_hand,stop_bankroll,termination\n");
        for(ArrayList<S131>g:all)for(S131 s:g)z.append(String.format(Locale.US,
            "%s,%s,%d,%d,%.2f,%.2f,%.4f,%.2f,%s,%s,%s,%s,%s,%d,%.2f,%s%n",
            s.cohort,s.policy,s.session,s.hands,s.finalBank,s.cumWager,s.hands>0?s.cumWager/s.hands:0,s.maxDD,
            s.reached150,s.reached170,s.reached200,s.exhausted,s.stopped,s.stopHand,s.stopBank,s.termination));
        return z.toString();
    }

    static void total139(StringBuilder r,String policy,ArrayList<ArrayList<S131>> all,int policyIndex){
        int n=0,pos=0,r150=0,r170=0,r200=0,bust=0,stops=0,hands=0;
        double finalSum=0,wager=0,dd=0;
        for(int c=0;c<4;c++)for(S131 s:all.get(c*3+policyIndex)){
            n++;finalSum+=s.finalBank;wager+=s.cumWager;dd+=s.maxDD;hands+=s.hands;
            if(s.finalBank>100+1e-9)pos++;if(s.reached150)r150++;if(s.reached170)r170++;if(s.reached200)r200++;if(s.exhausted)bust++;if(s.stopped)stops++;
        }
        double net=finalSum-100.0*n;
        r.append(String.format(Locale.US,
          "%s | n %d | avg final £%.3f | return %.4f%% | positive %.2f%% | £150 %.2f%% | £170 %.2f%% | £200 %.2f%% | £0 %.2f%% | maxDD £%.3f | exposure £%.3f | mean wager/hand £%.3f | stops %d (%.2f%%)%n",
          policy,n,finalSum/n,100.0*net/wager,p131(pos,n),p131(r150,n),p131(r170,n),p131(r200,n),p131(bust,n),dd/n,wager/n,hands>0?wager/hands:0,stops,p131(stops,n)));
    }


    /* PHASE 3.140 — POLICY-INDUCED STATE DRIFT AUDIT
       Diagnostic only. All thresholds remain frozen:
         exposure <= £225
         bankroll >= £140
         trailing give-back = 25%

       This phase records what happens when the gated policy encounters a 25%
       trailing trigger and either ACCEPTS it or DECLINES it.
    */
    static final long[] P140_SEEDS={207101L,207201L,207301L,207401L};
    static final String[] P140_COHORTS={"FRESH_Q","FRESH_R","FRESH_S","FRESH_T"};

    static class D140{
        String cohort;int session;
        int firstTriggerHand,acceptedHand,laterTriggerCount;
        double firstTriggerBank,firstTriggerExposure,firstTriggerPeak,firstTriggerDD;
        boolean accepted,declined,laterQualified;
        double finalGate,finalRef,finalAlways,extraExposureAfterFirst;
        int extraHandsAfterFirst;
    }

    static D140 auditOne140(long seed,String cohort,int session){
        S131 ref=runOne139(seed,cohort,session,P131_REF);
        S131 always=runOne139(seed,cohort,session,P131_TRAIL150);

        int[]shoe=sixDeckShoe(sessionSeed(seed,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        D140 d=new D140();d.cohort=cohort;d.session=session+1;d.finalRef=ref.finalBank;d.finalAlways=always.finalBank;
        int first=-1;double expAtFirst=0;
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;}
            else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            PairStats ps=new PairStats();Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;
            if(bank>=200-1e-9||bank<=1e-9)break;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    first=hand;expAtFirst=cum;d.firstTriggerHand=hand;d.firstTriggerBank=bank;d.firstTriggerExposure=cum;
                    d.firstTriggerPeak=peak;d.firstTriggerDD=Math.max(0,peak-bank);
                    if(qualifies){d.accepted=true;d.acceptedHand=hand;break;}
                    else d.declined=true;
                }else{
                    d.laterTriggerCount++;
                    if(qualifies){d.laterQualified=true;d.accepted=true;d.acceptedHand=hand;break;}
                }
            }
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        d.finalGate=bank;
        if(first>0){d.extraHandsAfterFirst=Math.max(0,(d.accepted?d.acceptedHand:Math.min(HANDS,hc))-first);d.extraExposureAfterFirst=Math.max(0,cum-expAtFirst);}
        return d;
    }


    /* PHASE 3.141 — POST-DECLINE PATHWAY STRATIFICATION
       Diagnostic only. No new action rule and no threshold tuning.

       Starting population:
       Phase 3.140 sessions in which the first frozen 25% trailing trigger was
       DECLINED by the two-variable gate.

       The post-decline path is instrumented into mutually exclusive outcome classes:
       TARGET_PROGRESS      -> reaches £200 after the decline
       CAPITAL_PRESERVED    -> does not reach £200, finishes >=£100
       MID_LOSS             -> finishes £70-£99.99
       SEVERE_LOSS          -> finishes £0.01-£69.99
       TERMINAL_ZERO        -> finishes £0

       Additional descriptive dimensions:
       later trigger count, re-qualification, extra hands, extra exposure,
       post-decline peak, post-decline trough, time below £100 and first
       crossings of £100/£70/£50/£0.
    */

    static final class P141 {
        String cohort,pathClass;
        int session,firstTriggerHand,laterTriggerCount,extraHands,handsBelow100;
        int first100=-1,first70=-1,first50=-1,first0=-1;
        boolean laterQualified,reached200;
        double firstBank,firstExposure,extraExposure,postPeak,postTrough,finalBank,finalRef,finalAlways;
    }

    static P141 runOne141(long seed,String cohort,int session){
        S131 ref=runOne139(seed,cohort,session,P131_REF);
        S131 always=runOne139(seed,cohort,session,P131_TRAIL150);

        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;double expAtFirst=0,postPeak=-1,postTrough=Double.POSITIVE_INFINITY;
        P141 p=new P141();p.cohort=cohort;p.session=session+1;p.finalRef=ref.finalBank;p.finalAlways=always.finalBank;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies){
                        // Not part of the declined-first population.
                        p.pathClass="NOT_DECLINED_FIRST";
                        p.finalBank=bank;return p;
                    }
                    first=hand;expAtFirst=cum;p.firstTriggerHand=hand;p.firstBank=bank;p.firstExposure=cum;
                    postPeak=bank;postTrough=bank;
                }else{
                    p.laterTriggerCount++;
                    if(qualifies){
                        p.laterQualified=true;
                        // Under the gated policy, this later qualification stops the session.
                        break;
                    }
                }
            }

            if(first>0){
                postPeak=Math.max(postPeak,bank);postTrough=Math.min(postTrough,bank);
                if(bank<100-1e-9){p.handsBelow100++;if(p.first100<0)p.first100=hand;}
                if(bank<70-1e-9&&p.first70<0)p.first70=hand;
                if(bank<50-1e-9&&p.first50<0)p.first50=hand;
                if(bank<=1e-9&&p.first0<0)p.first0=hand;
                if(bank>=200-1e-9){p.reached200=true;break;}
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        if(first<0){p.pathClass="NO_TRIGGER";p.finalBank=bank;return p;}

        p.extraHands=Math.max(0,hc-first);
        p.extraExposure=Math.max(0,cum-expAtFirst);
        p.postPeak=postPeak<0?bank:postPeak;
        p.postTrough=Double.isInfinite(postTrough)?bank:postTrough;
        p.finalBank=bank;

        if(p.reached200||bank>=200-1e-9)p.pathClass="TARGET_PROGRESS";
        else if(bank>=100-1e-9)p.pathClass="CAPITAL_PRESERVED";
        else if(bank>=70-1e-9)p.pathClass="MID_LOSS";
        else if(bank>1e-9)p.pathClass="SEVERE_LOSS";
        else p.pathClass="TERMINAL_ZERO";
        return p;
    }

    static void panel141(StringBuilder r,String cls,ArrayList<P141> xs){
        int n=0,lq=0,tr=0,hb=0;double eb=0,ee=0,pk=0,trough=0,fin=0,ref=0,alw=0;
        for(P141 p:xs)if(cls.equals(p.pathClass)){
            n++;if(p.laterQualified)lq++;tr+=p.laterTriggerCount;hb+=p.handsBelow100;
            eb+=p.extraHands;ee+=p.extraExposure;pk+=p.postPeak;trough+=p.postTrough;fin+=p.finalBank;ref+=p.finalRef;alw+=p.finalAlways;
        }
        r.append("\n").append(cls).append("\n");
        r.append("n = ").append(n).append("\n");if(n==0)return;
        r.append(String.format(Locale.US,"Share of declined-first population: %.2f%%%n",100.0*n/countDeclined141(xs)));
        r.append(String.format(Locale.US,"Mean extra hands / exposure: %.3f / £%.3f%n",eb/n,ee/n));
        r.append(String.format(Locale.US,"Mean post-decline peak / trough: £%.3f / £%.3f%n",pk/n,trough/n));
        r.append(String.format(Locale.US,"Mean hands below £100: %.3f%n",1.0*hb/n));
        r.append(String.format(Locale.US,"Mean later trigger events: %.3f | later qualifying %.2f%%%n",1.0*tr/n,p131(lq,n)));
        r.append(String.format(Locale.US,"Final mean — gated / reference / always-trail: £%.3f / £%.3f / £%.3f%n",fin/n,ref/n,alw/n));
    }

    static int countDeclined141(ArrayList<P141> xs){int n=0;for(P141 p:xs)if(!p.pathClass.equals("NO_TRIGGER")&&!p.pathClass.equals("NOT_DECLINED_FIRST"))n++;return n;}


    /* PHASE 3.143 — INSTRUMENTED +3/+5 POST-DECLINE CHECKPOINT REPLAY
       AND SIGNAL-SEPARATION DATA GENERATION

       This phase executes the checkpoint collection designed in 3.142.
       No policy or threshold is changed.

       Population:
       sessions whose first frozen 25% trailing trigger is DECLINED by the
       exposure<=£225 AND bankroll>=£140 gate.

       Predeclared checkpoint offsets:
       +3 and +5 completed hands after first decline.

       Observable checkpoint fields:
       current bankroll, incremental exposure, hands below £100,
       repeated trigger count, regain of first-trigger bankroll,
       post-decline peak and trough.

       Final path labels are retrospective and are written only after the
       session completes:
       GOOD = TARGET_PROGRESS or CAPITAL_PRESERVED
       LOSS = MID_LOSS, SEVERE_LOSS or TERMINAL_ZERO
    */

    static final class C143 {
        String cohort,finalClass,label;
        int session,offset,handsBelow100,laterTriggers;
        double bank,extraExposure,peak,trough,firstBank,firstExposure;
        boolean regained;
    }

    static ArrayList<C143> collect143(long seed,String cohort,int session){
        ArrayList<C143> out=new ArrayList<>();

        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;

        int first=-1,hb=0,later=0;
        double firstBank=0,firstExp=0,postPeak=0,postTrough=Double.POSITIVE_INFINITY;
        C143 c3=null,c5=null;
        boolean reached200=false,declined=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10;negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;
            cum+=roundStake356(rr);
            bank+=rr.net;
            if(bank<0)bank=0;
            peak=Math.max(peak,bank);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            hc++;

            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0;
                double surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies){
                        // accepted-first session: outside the 3.143 population
                        return out;
                    }
                    first=hand;
                    declined=true;
                    firstBank=bank;
                    firstExp=cum;
                    postPeak=bank;
                    postTrough=bank;
                }else{
                    later++;
                    if(qualifies){
                        // gated policy would stop here
                        break;
                    }
                }
            }

            if(first>0){
                int off=hand-first;
                postPeak=Math.max(postPeak,bank);
                postTrough=Math.min(postTrough,bank);
                if(bank<100-1e-9)hb++;

                if(off==3 || off==5){
                    C143 c=new C143();
                    c.cohort=cohort;
                    c.session=session+1;
                    c.offset=off;
                    c.bank=bank;
                    c.extraExposure=cum-firstExp;
                    c.handsBelow100=hb;
                    c.laterTriggers=later;
                    c.regained=bank>=firstBank-1e-9;
                    c.peak=postPeak;
                    c.trough=postTrough;
                    c.firstBank=firstBank;
                    c.firstExposure=firstExp;
                    if(off==3)c3=c; else c5=c;
                }

                if(bank>=200-1e-9){
                    reached200=true;
                    break;
                }
            }

            if(bank>=200-1e-9||bank<=1e-9)break;

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        if(!declined)return out;

        String fc;
        if(reached200||bank>=200-1e-9)fc="TARGET_PROGRESS";
        else if(bank>=100-1e-9)fc="CAPITAL_PRESERVED";
        else if(bank>=70-1e-9)fc="MID_LOSS";
        else if(bank>1e-9)fc="SEVERE_LOSS";
        else fc="TERMINAL_ZERO";

        String label=(fc.equals("TARGET_PROGRESS")||fc.equals("CAPITAL_PRESERVED"))?"GOOD":"LOSS";

        if(c3!=null){c3.finalClass=fc;c3.label=label;out.add(c3);}
        if(c5!=null){c5.finalClass=fc;c5.label=label;out.add(c5);}
        return out;
    }

    static void panel143(StringBuilder r,int off,String lab,ArrayList<C143> all){
        int n=0,hb=0,tr=0,rg=0;
        double b=0,e=0,p=0,t=0,fb=0;
        for(C143 c:all)if(c.offset==off&&c.label.equals(lab)){
            n++;b+=c.bank;e+=c.extraExposure;hb+=c.handsBelow100;tr+=c.laterTriggers;
            if(c.regained)rg++;p+=c.peak;t+=c.trough;fb+=c.firstBank;
        }
        r.append(String.format(Locale.US,"%n+%d HANDS / %s%n",off,lab));
        r.append("n = ").append(n).append("\n");
        if(n==0)return;
        r.append(String.format(Locale.US,
            "Mean bankroll: £%.3f%nMean incremental exposure: £%.3f%nMean hands below £100: %.3f%nMean later triggers: %.3f%nRegained first-trigger bankroll: %.2f%%%nMean post-decline peak / trough: £%.3f / £%.3f%nMean first-trigger bankroll: £%.3f%n",
            b/n,e/n,1.0*hb/n,1.0*tr/n,p131(rg,n),p/n,t/n,fb/n));
    }


    /* PHASE 3.144 — FRESH CHECKPOINT RELATIONSHIP VALIDATION
       Fresh cohorts only. No threshold optimisation and no action-policy change.

       Frozen hypotheses from Phase 3.143:
       H1: GOOD sessions have higher current bankroll than LOSS at +3 and +5.
       H2: GOOD sessions regain first-trigger bankroll more often at +3 and +5.
       H3: GOOD sessions have a higher post-decline trough at +3 and +5.

       The +3/+5 checkpoint definitions and GOOD/LOSS retrospective labels are
       unchanged from Phase 3.143.
    */
    static final long[] P144_SEEDS={208101L,208201L,208301L,208401L};
    static final String[] P144_COHORTS={"FRESH_U","FRESH_V","FRESH_W","FRESH_X"};

    static final class V144{
        int off,ng,nl,rgg,rgl;
        double bg,bl,tg,tl,eg,el,hg,hl,pg,pl,trg,trl;
    }

    static V144 measure144(int off,ArrayList<C143> all){
        V144 v=new V144();v.off=off;
        for(C143 c:all)if(c.offset==off){
            if(c.label.equals("GOOD")){
                v.ng++;v.bg+=c.bank;v.tg+=c.trough;v.eg+=c.extraExposure;
                v.hg+=c.handsBelow100;v.pg+=c.peak;v.trg+=c.laterTriggers;
                if(c.regained)v.rgg++;
            }else{
                v.nl++;v.bl+=c.bank;v.tl+=c.trough;v.el+=c.extraExposure;
                v.hl+=c.handsBelow100;v.pl+=c.peak;v.trl+=c.laterTriggers;
                if(c.regained)v.rgl++;
            }
        }
        return v;
    }

    static void report144(StringBuilder r,V144 v){
        double bg=v.ng>0?v.bg/v.ng:0, bl=v.nl>0?v.bl/v.nl:0;
        double tg=v.ng>0?v.tg/v.ng:0, tl=v.nl>0?v.tl/v.nl:0;
        double rg=v.ng>0?100.0*v.rgg/v.ng:0, rl=v.nl>0?100.0*v.rgl/v.nl:0;
        r.append(String.format(Locale.US,"%n+%d HAND VALIDATION%n",v.off));
        r.append(String.format(Locale.US,"GOOD / LOSS n: %d / %d%n",v.ng,v.nl));
        r.append(String.format(Locale.US,"Current bankroll GOOD / LOSS: £%.3f / £%.3f | difference £%+.3f | H1 %s%n",
            bg,bl,bg-bl,bg>bl?"PASS":"FAIL"));
        r.append(String.format(Locale.US,"Regained first-trigger bankroll GOOD / LOSS: %.2f%% / %.2f%% | difference %+.2f pp | H2 %s%n",
            rg,rl,rg-rl,rg>rl?"PASS":"FAIL"));
        r.append(String.format(Locale.US,"Post-decline trough GOOD / LOSS: £%.3f / £%.3f | difference £%+.3f | H3 %s%n",
            tg,tl,tg-tl,tg>tl?"PASS":"FAIL"));
        r.append(String.format(Locale.US,"Incremental exposure GOOD / LOSS: £%.3f / £%.3f%n",
            v.ng>0?v.eg/v.ng:0,v.nl>0?v.el/v.nl:0));
        r.append(String.format(Locale.US,"Hands below £100 GOOD / LOSS: %.3f / %.3f%n",
            v.ng>0?v.hg/v.ng:0,v.nl>0?v.hl/v.nl:0));
        r.append(String.format(Locale.US,"Post-decline peak GOOD / LOSS: £%.3f / £%.3f%n",
            v.ng>0?v.pg/v.ng:0,v.nl>0?v.pl/v.nl:0));
        r.append(String.format(Locale.US,"Later triggers GOOD / LOSS: %.3f / %.3f%n",
            v.ng>0?v.trg/v.ng:0,v.nl>0?v.trl/v.nl:0));
    }


    /* PHASE 3.147 — FRESH THREE-STATE ARCHITECTURE VALIDATION

       Frozen from Phase 3.146:
       OPPORTUNITY = current bankroll >= £140 AND first-trigger bankroll regained.
       CAPITAL_RISK = current bankroll < £100 AND first-trigger bankroll NOT regained.
       MIDDLE/UNRESOLVED = all other checkpoint states.

       Predeclared expectations:
       A. OPPORTUNITY remains >=75% GOOD and target progression materially exceeds
          severe+terminal deterioration.
       B. CAPITAL_RISK remains <35% GOOD and severe+terminal deterioration materially
          exceeds target progression.
       C. MIDDLE remains substantially more mixed than either extreme.

       Fresh cohorts only. No stop/continue action is executed.
    */
    static final long[] P147_SEEDS={209101L,209201L,209301L,209401L};
    static final String[] P147_COHORTS={"FRESH_Y","FRESH_Z","FRESH_AA","FRESH_AB"};

    static String state147(C143 c){
        if(c.bank>=140-1e-9 && c.regained)return "OPPORTUNITY_HIGH_REGAINED";
        if(c.bank<100-1e-9 && !c.regained)return "CAPITAL_RISK_LOW_NOT_REGAINED";
        return "MIDDLE_UNRESOLVED";
    }

    static void panel147(StringBuilder r,int off,String state,ArrayList<C143> all){
        int n=0,good=0,target=0,cap=0,mid=0,severe=0,zero=0;
        double bank=0,exp=0,hb=0,trough=0;
        for(C143 c:all)if(c.offset==off && state147(c).equals(state)){
            n++;bank+=c.bank;exp+=c.extraExposure;hb+=c.handsBelow100;trough+=c.trough;
            if(c.label.equals("GOOD"))good++;
            if(c.finalClass.equals("TARGET_PROGRESS"))target++;
            else if(c.finalClass.equals("CAPITAL_PRESERVED"))cap++;
            else if(c.finalClass.equals("MID_LOSS"))mid++;
            else if(c.finalClass.equals("SEVERE_LOSS"))severe++;
            else if(c.finalClass.equals("TERMINAL_ZERO"))zero++;
        }
        r.append(String.format(Locale.US,"%n+%d / %s%n",off,state));
        r.append("n = ").append(n).append("\n"); if(n==0)return;
        r.append(String.format(Locale.US,"GOOD: %.2f%%%n",p131(good,n)));
        r.append(String.format(Locale.US,"TARGET_PROGRESS: %.2f%%%n",p131(target,n)));
        r.append(String.format(Locale.US,"CAPITAL_PRESERVED: %.2f%%%n",p131(cap,n)));
        r.append(String.format(Locale.US,"MID_LOSS: %.2f%%%n",p131(mid,n)));
        r.append(String.format(Locale.US,"SEVERE_LOSS: %.2f%%%n",p131(severe,n)));
        r.append(String.format(Locale.US,"TERMINAL_ZERO: %.2f%%%n",p131(zero,n)));
        r.append(String.format(Locale.US,"SEVERE+TERMINAL: %.2f%%%n",p131(severe+zero,n)));
        r.append(String.format(Locale.US,"Mean bankroll / extra exposure / hands below £100 / trough: £%.3f / £%.3f / %.3f / £%.3f%n",
            bank/n,exp/n,hb/n,trough/n));
    }

    static int[] metrics147(int off,String state,ArrayList<C143> all){
        int n=0,g=0,t=0,s=0,z=0;
        for(C143 c:all)if(c.offset==off&&state147(c).equals(state)){
            n++;if(c.label.equals("GOOD"))g++;if(c.finalClass.equals("TARGET_PROGRESS"))t++;
            if(c.finalClass.equals("SEVERE_LOSS"))s++;if(c.finalClass.equals("TERMINAL_ZERO"))z++;
        }
        return new int[]{n,g,t,s,z};
    }


    /* PHASE 3.148 — STATE-ENTRY COUNTERFACTUAL VALUE MAP

       Purpose:
       quantify the theoretical value/cost of freezing bankroll at a validated
       checkpoint state versus allowing the existing post-decline policy path to
       continue.

       Frozen states from Phase 3.147:
       OPPORTUNITY = bankroll >= £140 AND regained first-trigger bankroll.
       CAPITAL_RISK = bankroll < £100 AND NOT regained.
       MIDDLE = all other checkpoint states.

       No live intervention is executed. "FREEZE NOW" is a counterfactual accounting
       benchmark only.

       For each +3 and +5 checkpoint:
       - freeze bankroll = bankroll observable at checkpoint;
       - continue outcome = final bankroll reached by the unchanged existing path;
       - delta = continue outcome - freeze bankroll;
       - target progression / severe deterioration / terminal zero retained.
    */

    static final class V148 {
        String cohort,state,finalClass;
        int session,offset;
        double checkpointBank,finalBank,delta,extraExposureAfterCheckpoint;
        int extraHandsAfterCheckpoint;
        boolean reached200,terminalZero;
    }

    static ArrayList<V148> collect148(long seed,String cohort,int session){
        ArrayList<V148> out=new ArrayList<>();

        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;

        int first=-1;
        double firstBank=0;
        V148 v3=null,v5=null;
        double expAt3=0,expAt5=0;
        int hand3=-1,hand5=-1;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10;negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;
            cum+=roundStake356(rr);
            bank+=rr.net;
            if(bank<0)bank=0;
            peak=Math.max(peak,bank);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            hc++;

            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0;
                double surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies)return out; // accepted-first outside population
                    first=hand;
                    firstBank=bank;
                }else if(qualifies){
                    // Existing gated policy would stop here.
                    break;
                }
            }

            if(first>0){
                int off=hand-first;
                if(off==3 || off==5){
                    boolean regained=bank>=firstBank-1e-9;
                    String state;
                    if(bank>=140-1e-9 && regained)state="OPPORTUNITY_HIGH_REGAINED";
                    else if(bank<100-1e-9 && !regained)state="CAPITAL_RISK_LOW_NOT_REGAINED";
                    else state="MIDDLE_UNRESOLVED";

                    V148 v=new V148();
                    v.cohort=cohort;v.session=session+1;v.offset=off;v.state=state;
                    v.checkpointBank=bank;
                    if(off==3){v3=v;expAt3=cum;hand3=hand;}
                    else {v5=v;expAt5=cum;hand5=hand;}
                }
                if(bank>=200-1e-9){reached200=true;break;}
            }

            if(bank>=200-1e-9||bank<=1e-9)break;

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        String fc;
        if(reached200||bank>=200-1e-9)fc="TARGET_PROGRESS";
        else if(bank>=100-1e-9)fc="CAPITAL_PRESERVED";
        else if(bank>=70-1e-9)fc="MID_LOSS";
        else if(bank>1e-9)fc="SEVERE_LOSS";
        else fc="TERMINAL_ZERO";

        if(v3!=null){
            v3.finalClass=fc;v3.finalBank=bank;v3.delta=bank-v3.checkpointBank;
            v3.extraExposureAfterCheckpoint=Math.max(0,cum-expAt3);
            v3.extraHandsAfterCheckpoint=Math.max(0,hc-hand3);
            v3.reached200=fc.equals("TARGET_PROGRESS");v3.terminalZero=fc.equals("TERMINAL_ZERO");
            out.add(v3);
        }
        if(v5!=null){
            v5.finalClass=fc;v5.finalBank=bank;v5.delta=bank-v5.checkpointBank;
            v5.extraExposureAfterCheckpoint=Math.max(0,cum-expAt5);
            v5.extraHandsAfterCheckpoint=Math.max(0,hc-hand5);
            v5.reached200=fc.equals("TARGET_PROGRESS");v5.terminalZero=fc.equals("TERMINAL_ZERO");
            out.add(v5);
        }
        return out;
    }

    static void panel148(StringBuilder r,int off,String state,ArrayList<V148> all){
        int n=0,better=0,worse=0,equal=0,target=0,zero=0;
        double cb=0,fb=0,delta=0,exp=0,hands=0,gain=0,loss=0;
        for(V148 v:all)if(v.offset==off&&v.state.equals(state)){
            n++;cb+=v.checkpointBank;fb+=v.finalBank;delta+=v.delta;exp+=v.extraExposureAfterCheckpoint;hands+=v.extraHandsAfterCheckpoint;
            if(v.delta>1e-9){better++;gain+=v.delta;}else if(v.delta<-1e-9){worse++;loss+=v.delta;}else equal++;
            if(v.reached200)target++;if(v.terminalZero)zero++;
        }
        r.append(String.format(Locale.US,"%n+%d / %s%n",off,state));
        r.append("n = ").append(n).append("\n");if(n==0)return;
        r.append(String.format(Locale.US,"Checkpoint freeze bankroll mean: £%.3f%n",cb/n));
        r.append(String.format(Locale.US,"Continued-path final bankroll mean: £%.3f%n",fb/n));
        r.append(String.format(Locale.US,"Mean continue-minus-freeze delta: £%+.3f%n",delta/n));
        r.append(String.format(Locale.US,"Continue higher / freeze higher / equal: %.2f%% / %.2f%% / %.2f%%%n",
            p131(better,n),p131(worse,n),p131(equal,n)));
        r.append(String.format(Locale.US,"Aggregate positive continuation contribution: £%+.2f%n",gain));
        r.append(String.format(Locale.US,"Aggregate negative continuation contribution: £%+.2f%n",loss));
        r.append(String.format(Locale.US,"Reached £200 under continuation: %.2f%%%n",p131(target,n)));
        r.append(String.format(Locale.US,"Terminal £0 under continuation: %.2f%%%n",p131(zero,n)));
        r.append(String.format(Locale.US,"Mean extra hands / exposure after checkpoint: %.3f / £%.3f%n",hands/n,exp/n));
    }


    /* PHASE 3.151 — FRESH FROZEN INTERVENTION EXECUTION
       Contract frozen in Phase 3.150.

       Fresh cohorts AC/AD/AE/AF only.
       Primary action checkpoint +5; secondary replication +3.

       Arms:
       CONTINUE_REFERENCE
       ALWAYS_TRAIL_150_GIVEBACK_25
       CAPITAL_PRESERVATION_STATE_POLICY
       BALANCED_THREE_STATE_POLICY

       No wager-policy or card-play-policy changes.
    */
    static final long[] P151_SEEDS={210101L,210201L,210301L,210401L};
    static final String[] P151_COHORTS={"FRESH_AC","FRESH_AD","FRESH_AE","FRESH_AF"};

    enum Arm151 {CONTINUE_REFERENCE,ALWAYS_TRAIL_150_GIVEBACK_25,CAPITAL_PRESERVATION_STATE_POLICY,BALANCED_THREE_STATE_POLICY,REFINED_60,REFINED_70}

    static final class R151{
        String cohort,arm,stopReason;
        int session,checkpoint,hand;
        double finalBank,exposure,maxDD,checkpointBank=Double.NaN,firstTriggerBank=Double.NaN;
        boolean reached200,terminalZero,positive,checkpointObserved=false,checkpointRegained=false;
    }

    static R151 run151(long seed,String cohort,int session,Arm151 arm,int checkpoint){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;double firstBank=0;
        String stopReason="NATURAL_END";
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(trigger){
                if(arm==Arm151.ALWAYS_TRAIL_150_GIVEBACK_25){
                    stopReason="ALWAYS_TRAIL_TRIGGER";break;
                }

                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies){
                        // Existing accepted first-trigger gate remains part of reference architecture.
                        stopReason="EXISTING_ACCEPTED_FIRST_TRIGGER";break;
                    }
                    first=hand;firstBank=bank;
                }else if(qualifies){
                    stopReason="EXISTING_LATER_GATE";break;
                }
            }

            if(first>0 && hand-first==checkpoint){
                // Phase 3.156 validation capture: observable checkpoint state only.
                // This is recorded for every arm and does not change execution.
                // The run result receives these values below through local holders.
            }

            if(first>0 && hand-first==checkpoint &&
               (arm==Arm151.CAPITAL_PRESERVATION_STATE_POLICY||arm==Arm151.BALANCED_THREE_STATE_POLICY)){
                boolean regained=bank>=firstBank-1e-9;
                boolean capitalRisk=bank<100-1e-9&&!regained;
                // Balanced also explicitly CONTINUES Opportunity and OBSERVES Middle;
                // only Capital Risk changes execution relative to reference.
                if(capitalRisk){
                    stopReason="FROZEN_CAPITAL_RISK_FREEZE";break;
                }
            }

            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        if(bank>=200-1e-9)reached200=true;
        R151 r=new R151();r.cohort=cohort;r.arm=arm.name();r.session=session+1;r.checkpoint=checkpoint;
        r.hand=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;r.stopReason=stopReason;return r;
    }

    static R151 run156(long seed,String cohort,int session,Arm151 arm,int checkpoint){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;double firstBank=0;
        double observedCheckpointBank=Double.NaN,observedFirstBank=Double.NaN;
        boolean observedCheckpoint=false,observedRegained=false;
        String stopReason="NATURAL_END";
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            PairStats ps=new PairStats();
            Round rr=playRound(shoe,ptr,Profile.SELECTIVE_AGGRESSION,cohort,session+1,hand,true,bank,ps,wager,false);
            ptr=rr.endPointer;cum+=roundStake356(rr);bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }

            if(trigger){
                if(arm==Arm151.ALWAYS_TRAIL_150_GIVEBACK_25){
                    stopReason="ALWAYS_TRAIL_TRIGGER";break;
                }

                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies){
                        // Existing accepted first-trigger gate remains part of reference architecture.
                        stopReason="EXISTING_ACCEPTED_FIRST_TRIGGER";break;
                    }
                    first=hand;firstBank=bank;
                }else if(qualifies){
                    stopReason="EXISTING_LATER_GATE";break;
                }
            }

            if(first>0 && hand-first==checkpoint && !observedCheckpoint){
                observedCheckpoint=true;
                observedCheckpointBank=bank;
                observedFirstBank=firstBank;
                observedRegained=bank>=firstBank-1e-9;
            }

            if(first>0 && hand-first==checkpoint &&
               (arm==Arm151.CAPITAL_PRESERVATION_STATE_POLICY||
                arm==Arm151.BALANCED_THREE_STATE_POLICY||
                arm==Arm151.REFINED_60||arm==Arm151.REFINED_70)){
                boolean regained=bank>=firstBank-1e-9;
                boolean capitalRisk=bank<100-1e-9&&!regained;
                boolean freeze=false;
                if(arm==Arm151.CAPITAL_PRESERVATION_STATE_POLICY||arm==Arm151.BALANCED_THREE_STATE_POLICY)
                    freeze=capitalRisk;
                else if(arm==Arm151.REFINED_60)
                    freeze=capitalRisk&&bank<=60+1e-9;
                else if(arm==Arm151.REFINED_70)
                    freeze=capitalRisk&&bank<=70+1e-9;
                if(freeze){
                    if(arm==Arm151.REFINED_60)stopReason="REFINED_60_FREEZE";
                    else if(arm==Arm151.REFINED_70)stopReason="REFINED_70_FREEZE";
                    else stopReason="FROZEN_CAPITAL_RISK_FREEZE";
                    break;
                }
            }

            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        if(bank>=200-1e-9)reached200=true;
        R151 r=new R151();r.cohort=cohort;r.arm=arm.name();r.session=session+1;r.checkpoint=checkpoint;
        r.hand=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;r.stopReason=stopReason;
        r.checkpointObserved=observedCheckpoint;r.checkpointBank=observedCheckpointBank;
        r.firstTriggerBank=observedFirstBank;r.checkpointRegained=observedRegained;
        return r;
    }

    static void report151(StringBuilder sb,String arm,int cp,ArrayList<R151> all){
        int n=0,target=0,zero=0,pos=0,freeze=0;double bank=0,exp=0,dd=0,h=0;
        for(R151 r:all)if(r.arm.equals(arm)&&r.checkpoint==cp){
            n++;bank+=r.finalBank;exp+=r.exposure;dd+=r.maxDD;h+=r.hand;
            if(r.reached200)target++;if(r.terminalZero)zero++;if(r.positive)pos++;
            if(r.stopReason.equals("FROZEN_CAPITAL_RISK_FREEZE"))freeze++;
        }
        sb.append(String.format(Locale.US,"%n%s / +%d%n",arm,cp));
        sb.append(String.format(Locale.US,"n=%d | mean final £%.3f | £200 %.2f%% | £0 %.2f%% | positive %.2f%%%n",
            n,bank/n,p131(target,n),p131(zero,n),p131(pos,n)));
        sb.append(String.format(Locale.US,"mean exposure £%.3f | mean hands %.3f | mean max drawdown £%.3f | state freezes %d (%.2f%%)%n",
            exp/n,h/n,dd/n,freeze,p131(freeze,n)));
    }


    /* PHASE 3.152 — FRESH REPLICATION + CHANGED-SESSION MECHANISM
       Frozen +5 Capital Risk intervention only. No tuning.

       Fresh cohorts AG/AH/AI/AJ.
       Compare CONTINUE_REFERENCE vs CAPITAL_PRESERVATION_STATE_POLICY at +5.

       Secondary mechanism analysis is paired and limited to sessions whose final
       outcome differs between the two arms.
    */
    static final long[] P152_SEEDS={211101L,211201L,211301L,211401L};
    static final String[] P152_COHORTS={"FRESH_AG","FRESH_AH","FRESH_AI","FRESH_AJ"};


    /* PHASE 3.156 — FROZEN SIMPLE-SEPARATOR FRESH VALIDATION
       Discovery candidates were frozen in Phase 3.155:
       A: checkpoint bankroll <= £60
       B: checkpoint bankroll <= £70

       Entirely fresh cohorts AK/AL/AM/AN.
       Validation is observational only: reference execution is unchanged.
       Outcome labels are read only after the session ends.
    */
    static final long[] P156_SEEDS={212101L,212201L,212301L,212401L};
    static final String[] P156_COHORTS={"FRESH_AK","FRESH_AL","FRESH_AM","FRESH_AN"};


    /* PHASE 3.158 — FRESH FOUR-ARM REFINEMENT EXECUTION
       Contract frozen in Phase 3.157.
       Fresh cohorts AO/AP/AQ/AR only.
       Same sessions paired across all four arms.
       +5 checkpoint. No tuning.
    */
    static final long[] P158_SEEDS={213101L,213201L,213301L,213401L};
    static final String[] P158_COHORTS={"FRESH_AO","FRESH_AP","FRESH_AQ","FRESH_AR"};

    static String armName158(Arm151 a){
        if(a==Arm151.CAPITAL_PRESERVATION_STATE_POLICY)return "ORIGINAL_CAPITAL_RISK_FREEZE";
        return a.name();
    }


    /* PHASE 3.159 — FRESH FOUR-ARM ORDERING REPLICATION
       Frozen Phase 3.157 contract, unchanged from 3.158.
       Fresh cohorts AS/AT/AU/AV only.
       Primary: replicate activation / terminal-zero prevention / £200-cost ordering.
       Secondary: cohort-level paired mechanism robustness.
       No tuning.
    */
    static final long[] P159_SEEDS={214101L,214201L,214301L,214401L};
    static final String[] P159_COHORTS={"FRESH_AS","FRESH_AT","FRESH_AU","FRESH_AV"};


    /* PHASE 3.162 — PROSPECTIVE BOUNDARY-INSTRUMENTATION REPLICATION

       Contract:
       Four-arm +5 intervention architecture frozen in Phase 3.157.
       Thresholds remain £60 / £70.
       No wager/card-play/trigger/gate tuning.

       New instrumentation:
       checkpoint bankroll, first-trigger bankroll, regained status and
       CAPITAL_RISK membership are exported BEFORE any intervention action.

       Fresh cohorts AW/AX/AY/AZ only.

       Objectives:
       1. replicate policy ordering again;
       2. directly audit 55–60 / 60–65 / 65–70 / 70–75 prospective
          boundary neighbourhoods;
       3. close the export gap documented in Phase 3.161.
    */
    static final long[] P162_SEEDS={215101L,215201L,215301L,215401L};
    static final String[] P162_COHORTS={"FRESH_AW","FRESH_AX","FRESH_AY","FRESH_AZ"};


    /* PHASE 3.164 — FINAL INDEPENDENT HOLDOUT / BRANCH-CLOSURE TEST

       Frozen architecture:
       CONTINUE_REFERENCE
       ORIGINAL_CAPITAL_RISK_FREEZE
       REFINED_60
       REFINED_70
       +5 checkpoint

       Fresh cohorts BA/BB/BC/BD only.

       PREDECLARED PRIMARY HOLDOUT:
       intervention ordering must reproduce:
       ORIGINAL > <=£70 > <=£60
       for activation count, £0 prevention count and £200-loss count.

       PREDECLARED SECONDARY HOLDOUT:
       <=£60 Capital-Risk region must remain more terminal-risk enriched and
       less target-loss enriched than £80-100.

       No tuning.
    */
    static final long[] P164_SEEDS={216101L,216201L,216301L,216401L};
    static final String[] P164_COHORTS={"FRESH_BA","FRESH_BB","FRESH_BC","FRESH_BD"};

    public static void main3164(String[]args)throws Exception{
        Arm151[] arms={Arm151.CONTINUE_REFERENCE,Arm151.CAPITAL_PRESERVATION_STATE_POLICY,Arm151.REFINED_60,Arm151.REFINED_70};
        ArrayList<R151>[] rr=new ArrayList[4];
        for(int a=0;a<4;a++)rr[a]=new ArrayList<>();

        for(int c=0;c<4;c++)for(int i=0;i<SESSIONS;i++)
            for(int a=0;a<4;a++)
                rr[a].add(run156(P164_SEEDS[c],P164_COHORTS[c],i,arms[a],5));

        int n=rr[0].size();

        StringBuilder session=new StringBuilder(
          "cohort,session,arm,checkpoint_observed,checkpoint_bank,first_trigger_bank,checkpoint_regained,capital_risk,final_bankroll,reached200,terminal_zero,positive,final_below70,exposure,hands,max_drawdown,stop_reason\n");
        StringBuilder paired=new StringBuilder(
          "cohort,session,arm,checkpoint_observed,checkpoint_bank,first_trigger_bank,checkpoint_regained,capital_risk,delta_bankroll,better,worse,equal,zero_prevented,zero_created,target200_lost,target200_created,severe70_prevented,severe70_created,exposure_delta,maxdd_delta\n");

        StringBuilder res=new StringBuilder();
        res.append("DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH\n");
        res.append("CODE VERSION: Deterministic Blackjack Phase 3.164\n");
        res.append("CODE BUILD TAG: DBDE-3.164-FINAL-INDEPENDENT-HOLDOUT-BRANCH-CLOSURE\n\n");
        res.append("PHASE 3.164 — FINAL INDEPENDENT HOLDOUT / BRANCH-CLOSURE TEST\n");
        res.append("Fresh cohorts BA/BB/BC/BD; 5,000 sessions each; +5 checkpoint.\n");
        res.append("Frozen four-arm contract and boundary instrumentation. No tuning.\n\n");

        int[] activation=new int[4], targetLost=new int[4], zeroPrevent=new int[4];

        for(int a=0;a<4;a++){
            ArrayList<R151> x=rr[a];
            double bank=0,exp=0,dd=0,hands=0;int t200=0,z=0,posi=0,sev=0,act=0,obs=0,cr=0;
            ArrayList<Double> finals=new ArrayList<>();
            for(R151 r:x){
                bank+=r.finalBank;exp+=r.exposure;dd+=r.maxDD;hands+=r.hand;finals.add(r.finalBank);
                if(r.reached200)t200++;if(r.terminalZero)z++;if(r.positive)posi++;if(r.finalBank<70-1e-9)sev++;
                if(r.stopReason.contains("FREEZE"))act++;
                if(r.checkpointObserved)obs++;
                boolean capitalRisk=r.checkpointObserved&&r.checkpointBank<100-1e-9&&!r.checkpointRegained;
                if(capitalRisk)cr++;
                session.append(String.format(Locale.US,
                  "%s,%d,%s,%s,%.2f,%.2f,%s,%s,%.2f,%s,%s,%s,%s,%.2f,%d,%.2f,%s%n",
                  r.cohort,r.session,armName158(arms[a]),r.checkpointObserved,r.checkpointBank,r.firstTriggerBank,
                  r.checkpointRegained,capitalRisk,r.finalBank,r.reached200,r.terminalZero,r.positive,
                  r.finalBank<70-1e-9,r.exposure,r.hand,r.maxDD,r.stopReason));
            }
            Collections.sort(finals);
            double med=(finals.get(n/2-1)+finals.get(n/2))/2.0;
            activation[a]=act;
            res.append(armName158(arms[a])+"\n");
            res.append(String.format(Locale.US,
              "mean final £%.3f | median £%.3f | £200 %.2f%% | £0 %.2f%% | positive %.2f%% | final<£70 %.2f%%%n",
              bank/n,med,p131(t200,n),p131(z,n),p131(posi,n),p131(sev,n)));
            res.append(String.format(Locale.US,
              "mean exposure £%.3f | mean maxDD £%.3f | mean hands %.3f | activation %d (%.2f%%)%n",
              exp/n,dd/n,hands/n,act,p131(act,n)));
            res.append(String.format(Locale.US,
              "checkpoint observed %d (%.2f%%) | observable CAPITAL_RISK %d (%.2f%%)%n%n",
              obs,p131(obs,n),cr,p131(cr,n)));
        }

        ArrayList<R151> ref=rr[0];
        for(int a=1;a<4;a++){
            int better=0,worse=0,equal=0,zp=0,zc=0,tl=0,tc=0,sp=0,sc=0;
            double help=0,harm=0,ed=0,ddd=0;
            for(int i=0;i<n;i++){
                R151 r=ref.get(i),x=rr[a].get(i);double d=x.finalBank-r.finalBank;
                boolean be=d>1e-9,wo=d<-1e-9,eq=Math.abs(d)<=1e-9;
                if(be){better++;help+=d;}else if(wo){worse++;harm+=d;}else equal++;
                boolean zzp=r.terminalZero&&!x.terminalZero, zzc=!r.terminalZero&&x.terminalZero;
                boolean ttl=r.reached200&&!x.reached200, ttc=!r.reached200&&x.reached200;
                boolean ssp=r.finalBank<70-1e-9&&x.finalBank>=70-1e-9;
                boolean ssc=r.finalBank>=70-1e-9&&x.finalBank<70-1e-9;
                if(zzp)zp++;if(zzc)zc++;if(ttl)tl++;if(ttc)tc++;if(ssp)sp++;if(ssc)sc++;
                ed+=x.exposure-r.exposure;ddd+=x.maxDD-r.maxDD;

                boolean capitalRisk=r.checkpointObserved&&r.checkpointBank<100-1e-9&&!r.checkpointRegained;
                paired.append(String.format(Locale.US,
                  "%s,%d,%s,%s,%.2f,%.2f,%s,%s,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%.2f,%.2f%n",
                  r.cohort,r.session,armName158(arms[a]),r.checkpointObserved,r.checkpointBank,r.firstTriggerBank,
                  r.checkpointRegained,capitalRisk,d,be,wo,eq,zzp,zzc,ttl,ttc,ssp,ssc,
                  x.exposure-r.exposure,x.maxDD-r.maxDD));
            }
            zeroPrevent[a]=zp;targetLost[a]=tl;
            res.append("PAIRED VS CONTINUE_REFERENCE — "+armName158(arms[a])+"\n");
            res.append(String.format(Locale.US,
              "better %d (%.2f%%) | worse %d (%.2f%%) | equal %d (%.2f%%)%n",
              better,p131(better,n),worse,p131(worse,n),equal,p131(equal,n)));
            res.append(String.format(Locale.US,"aggregate HELP £%+.2f | HARM £%+.2f | NET £%+.2f%n",help,harm,help+harm));
            res.append(String.format(Locale.US,
              "£0 prevented/created %d/%d | £200 lost/created %d/%d | severe<£70 prevented/created %d/%d%n",
              zp,zc,tl,tc,sp,sc));
            res.append(String.format(Locale.US,"mean exposure delta £%+.3f | mean maxDD delta £%+.3f%n%n",ed/n,ddd/n));
        }

        // Primary ordering test.
        boolean actOrder=activation[1]>activation[3]&&activation[3]>activation[2];
        boolean zpOrder=zeroPrevent[1]>zeroPrevent[3]&&zeroPrevent[3]>zeroPrevent[2];
        boolean tlOrder=targetLost[1]>targetLost[3]&&targetLost[3]>targetLost[2];

        // Secondary regional enrichment using ORIGINAL paired evidence and reference checkpoint state.
        int lowN=0,lowZ=0,lowT=0,highN=0,highZ=0,highT=0;
        ArrayList<R151> orig=rr[1];
        for(int i=0;i<n;i++){
            R151 r=ref.get(i),x=orig.get(i);
            boolean cr=r.checkpointObserved&&r.checkpointBank<100-1e-9&&!r.checkpointRegained;
            if(!cr)continue;
            boolean zp=r.terminalZero&&!x.terminalZero;
            boolean tl=r.reached200&&!x.reached200;
            if(r.checkpointBank<=60+1e-9){lowN++;if(zp)lowZ++;if(tl)lowT++;}
            else if(r.checkpointBank>80+1e-9&&r.checkpointBank<100-1e-9){highN++;if(zp)highZ++;if(tl)highT++;}
        }
        double lowZp=p131(lowZ,lowN),lowTp=p131(lowT,lowN),highZp=p131(highZ,highN),highTp=p131(highT,highN);
        boolean enrich=(lowZp>highZp)&&(lowTp<highTp);

        res.append("PREDECLARED HOLDOUT TESTS\n");
        res.append(String.format(Locale.US,"Primary activation ordering ORIGINAL > £70 > £60: %s%n",actOrder?"PASS":"FAIL"));
        res.append(String.format(Locale.US,"Primary £0-prevention ordering ORIGINAL > £70 > £60: %s%n",zpOrder?"PASS":"FAIL"));
        res.append(String.format(Locale.US,"Primary £200-loss ordering ORIGINAL > £70 > £60: %s%n",tlOrder?"PASS":"FAIL"));
        res.append(String.format(Locale.US,
          "Secondary <=£60 vs £80-100: PZ %.2f%% vs %.2f%% | LOST200 %.2f%% vs %.2f%% | %s%n",
          lowZp,highZp,lowTp,highTp,enrich?"PASS":"FAIL"));
        res.append(String.format(Locale.US,"TOTAL PREDECLARED HOLDOUT TESTS PASSED: %d / 4%n",
          (actOrder?1:0)+(zpOrder?1:0)+(tlOrder?1:0)+(enrich?1:0)));

        String fp=hash(res.toString()+session.toString()+paired.toString());
        write("Phase_3_164_Results.txt",res.toString());
        write("Phase_3_164_Session_Evidence.csv",session.toString());
        write("Phase_3_164_Paired_Evidence.csv",paired.toString());
        write("Phase_3_164_Replay_Verification.txt",
          "Fresh BA/BB/BC/BD final holdout. Frozen four-arm contract and checkpoint instrumentation. No tuning. SHA-256: "+fp+"\n");
        System.out.print(res+"\nSHA-256: "+fp+"\n");
    }

    /*
      PHASE 3.166 — HAND-DECISION LANDSCAPE / POLICY-SENSITIVITY MAPPING

      INSTRUMENTATION-ONLY BRANCH OPENING.

      Purpose:
      Map visible first-decision hand states under the frozen current engine before
      any alternative hit/stand/double/split policy is proposed.

      This phase deliberately DOES NOT change card-play policy.
      It records the decision landscape and identifies sufficiently frequent
      hand-state families for later controlled ablation.

      Guardrail:
      Frequency and historical outcome are descriptive evidence only.
      They do not establish that an alternative action would be better.
    */

    static String decisionFamily166(int total, boolean soft, boolean pair, int dealer){
        if(pair) return "PAIR";
        return soft ? "SOFT" : "HARD";
    }

    static String mappedAction166(int total, boolean soft, boolean pair, int dealer){
        // Phase 3.166 does not alter policy. This is a descriptive action label
        // for the frozen textbook decision surface used for candidate mapping.
        if(pair){
            if(total==4 || total==6 || total==14 || total==16 || total==18) return "SPLIT_CANDIDATE";
            if(total==20) return "STAND";
        }
        if(soft){
            if(total>=19) return "STAND";
            if(total<=17) return "HIT_OR_DOUBLE";
            return dealer>=9 || dealer==1 ? "HIT" : "STAND_OR_DOUBLE";
        }
        if(total>=17) return "STAND";
        if(total<=8) return "HIT";
        if(total==9) return (dealer>=3 && dealer<=6) ? "DOUBLE_CANDIDATE" : "HIT";
        if(total==10) return (dealer>=2 && dealer<=9) ? "DOUBLE_CANDIDATE" : "HIT";
        if(total==11) return dealer==1 ? "HIT_OR_DOUBLE" : "DOUBLE_CANDIDATE";
        if(total==12) return (dealer>=4 && dealer<=6) ? "STAND" : "HIT";
        if(total>=13 && total<=16) return (dealer>=2 && dealer<=6) ? "STAND" : "HIT";
        return "OTHER";
    }

    public static void main3166(String[]args)throws Exception{
        // The frozen 3.164 prospective engine is retained intact in this source.
        // 3.166 is intentionally a mapping phase: use deterministic exhaustive
        // visible two-card state enumeration to define the decision landscape.
        StringBuilder csv=new StringBuilder(
          "family,player_total,soft,pair,dealer_upcard,mapped_frozen_action,state_key\n");
        StringBuilder summary=new StringBuilder();
        summary.append("DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH\n");
        summary.append("CODE VERSION: Deterministic Blackjack Phase 3.166\n");
        summary.append("CODE BUILD TAG: DBDE-3.166-HAND-DECISION-LANDSCAPE-MAPPING\n\n");
        summary.append("PHASE 3.166 — HAND-DECISION LANDSCAPE / POLICY-SENSITIVITY MAPPING\n");
        summary.append("Instrumentation/mapping only. No card-play policy change.\n\n");

        int hard=0,soft=0,pair=0;
        java.util.LinkedHashMap<String,Integer> actionCounts=new java.util.LinkedHashMap<>();
        java.util.ArrayList<String> candidates=new java.util.ArrayList<>();

        // Enumerate canonical visible first-decision states.
        for(int dealer=1;dealer<=10;dealer++){
            for(int total=5;total<=20;total++){
                boolean isSoft=false, isPair=false;
                String fam=decisionFamily166(total,isSoft,isPair,dealer);
                String act=mappedAction166(total,isSoft,isPair,dealer);
                String key=fam+"_"+total+"_vs_"+dealer;
                csv.append(String.format(java.util.Locale.US,"%s,%d,%s,%s,%d,%s,%s%n",
                    fam,total,isSoft,isPair,dealer,act,key));
                hard++; actionCounts.put(act,actionCounts.getOrDefault(act,0)+1);
                if(total>=9 && total<=16) candidates.add(key+" -> "+act);
            }
            for(int total=13;total<=20;total++){
                boolean isSoft=true, isPair=false;
                String fam=decisionFamily166(total,isSoft,isPair,dealer);
                String act=mappedAction166(total,isSoft,isPair,dealer);
                String key=fam+"_"+total+"_vs_"+dealer;
                csv.append(String.format(java.util.Locale.US,"%s,%d,%s,%s,%d,%s,%s%n",
                    fam,total,isSoft,isPair,dealer,act,key));
                soft++; actionCounts.put(act,actionCounts.getOrDefault(act,0)+1);
                candidates.add(key+" -> "+act);
            }
            int[] pairTotals={4,6,8,10,12,14,16,18,20,22};
            for(int total:pairTotals){
                boolean isSoft=(total==22), isPair=true;
                String fam=decisionFamily166(total,isSoft,isPair,dealer);
                String act=mappedAction166(total,isSoft,isPair,dealer);
                String key=fam+"_"+total+"_vs_"+dealer;
                csv.append(String.format(java.util.Locale.US,"%s,%d,%s,%s,%d,%s,%s%n",
                    fam,total,isSoft,isPair,dealer,act,key));
                pair++; actionCounts.put(act,actionCounts.getOrDefault(act,0)+1);
                candidates.add(key+" -> "+act);
            }
        }

        summary.append("VISIBLE DECISION-STATE MAP\n");
        summary.append("Hard-total states mapped: "+hard+"\n");
        summary.append("Soft-total states mapped: "+soft+"\n");
        summary.append("Pair states mapped: "+pair+"\n");
        summary.append("Total canonical visible states: "+(hard+soft+pair)+"\n\n");
        summary.append("FROZEN ACTION-SURFACE LABEL COUNTS\n");
        for(java.util.Map.Entry<String,Integer> e:actionCounts.entrySet())
            summary.append(e.getKey()+": "+e.getValue()+"\n");

        summary.append("\nCANDIDATE-SENSITIVITY PRINCIPLE\n");
        summary.append("Later phases may test one visible state/action family at a time.\n");
        summary.append("Phase 3.166 itself makes no claim that any alternate action is superior.\n");
        summary.append("Priority must be determined from actual occurrence, stake exposure, bankroll context,\n");
        summary.append("outcome anatomy and sufficient sample size under the frozen engine.\n\n");

        summary.append("NEXT DESIGN — PHASE 3.167\n");
        summary.append("Instrument fresh frozen-policy sessions at first decision and record:\n");
        summary.append("- player total / soft-hard-pair family;\n");
        summary.append("- dealer upcard;\n");
        summary.append("- frozen selected action;\n");
        summary.append("- bankroll/state at decision;\n");
        summary.append("- original and total stake exposure;\n");
        summary.append("- resolved hand outcome and bankroll delta;\n");
        summary.append("- split/double involvement;\n");
        summary.append("- frequency by visible state.\n");
        summary.append("Then rank states by evidence sufficiency and consequence magnitude only.\n");
        summary.append("No alternate policy in 3.167.\n");

        write("Phase_3_166_Decision_State_Map.csv",csv.toString());
        write("Phase_3_166_Results.txt",summary.toString());
        write("Phase_3_166_Replay_Verification.txt",
          "Phase 3.166 is an instrumentation/mapping phase. Frozen 3.164 engine retained. "
         +"No hit/stand/double/split rule was changed. Canonical visible state map only.\n");
        System.out.print(summary.toString());
    }


    // =====================================================================
    // PHASE 3.167 — PROSPECTIVE HAND-DECISION OCCURRENCE / CONSEQUENCE MAP
    // =====================================================================

    static final class Decision167 {
        String cohort, controllerState, bankrollBand, family, action, outcome;
        int session, hand, decisionIndex, playerTotal, dealerUp, startCards, endCards, dealerEndCards;
        boolean soft, pair, splitChild, affordabilityFallback, bust, playerBust, dealerBust;
        double bankBefore, baseWager, totalStake, net;
        String key(){
            String type=pair?"PAIR":(soft?"SOFT":"HARD");
            return type+"_"+playerTotal+"_vs_"+dealerUp;
        }
        String csv(){
            return String.format(Locale.US,
                "%s,%d,%d,%d,%s,%s,%.2f,%s,%d,%s,%s,%d,%d,%s,%s,%s,%s,%.2f,%.2f,%s,%s,%s,%s,%d,%d,%s%n",
                cohort,session,hand,decisionIndex,controllerState,bankrollBand,bankBefore,
                family,playerTotal,soft,pair,dealerUp,startCards,splitChild,action,key(),
                affordabilityFallback,baseWager,totalStake,outcome,playerBust,dealerBust,bust,
                endCards,dealerEndCards,net);
        }
    }

    static String controllerState167(boolean cooling,boolean cautious){
        return cooling?"COOLING":(cautious?"CAUTIOUS":"NORMAL");
    }
    static String bankrollBand167(double b){
        if(b<60)return "LT60";
        if(b<70)return "60_69";
        if(b<80)return "70_79";
        if(b<100)return "80_99";
        if(b<140)return "100_139";
        if(b<170)return "140_169";
        if(b<200)return "170_199";
        return "GE200";
    }

    static Action selectiveFirst167(Hand h,int up,boolean splitChild){
        if(h.soft()&&h.total()>=18&&h.total()<=19&&up>=9)return textbook(h,up,true);
        if(!h.soft()&&h.total()>=5&&h.total()<=8&&up>=2&&up<=6)return Action.HIT;
        if(!h.soft()&&h.total()==9&&up>=9)return Action.HIT;
        if(!h.soft()&&h.total()==12&&up>=2&&up<=6)return textbook(h,up,true);
        if(h.soft()&&h.total()>=13&&h.total()<=17&&up>=7)return Action.HIT;
        if(!h.soft()&&h.total()==13&&up>=2&&up<=6)return Action.STAND;
        if(!h.soft()&&h.total()==8&&up>=7)return Action.HIT;
        if(!h.soft()&&h.total()>=12&&h.total()<=13&&up>=7)return Action.HIT;
        if(!h.soft()&&h.total()>=5&&h.total()<=7&&up>=7)return Action.HIT;
        if(!h.soft()&&h.total()==14)return textbook(h,up,true);
        if(!h.soft()&&h.total()==15)return textbook(h,up,true);
        if(!h.soft()&&h.total()==16)return textbook(h,up,true);
        if(!h.soft()&&splitChild&&h.total()==16&&up==11)return Action.HIT;
        if(!h.soft()&&(h.total()==19||h.total()==18||h.total()==17||(splitChild&&h.total()==20)))return Action.STAND;
        return Action.DOUBLE;
    }

    static final class Round167 {
        double net;
        int endPointer,doubles,splits;
        boolean win,loss,push;
        final ArrayList<Decision167> decisions=new ArrayList<>();
    }

    static Round167 playRound167(int[] shoe,int pointer,String cohort,int session,int round,
                                 double availableBank,double wager,String controllerState,
                                 String bankrollBand){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean wantsSplit=pair; // SELECTIVE_AGGRESSION is aggressive for pair precedence.
        boolean splitAffordabilityFallback=false;
        if(wantsSplit&&availableBank<2.0*wager){
            wantsSplit=false;splitAffordabilityFallback=true;
        }

        Round167 out=new Round167();

        // Original visible first decision before any split cards are drawn.
        Decision167 root=new Decision167();
        root.cohort=cohort;root.session=session;root.hand=round;root.decisionIndex=1;
        root.controllerState=controllerState;root.bankrollBand=bankrollBand;root.bankBefore=availableBank;
        root.playerTotal=initial.total();root.soft=initial.soft();root.pair=pair;root.splitChild=false;
        root.family=pair?"PAIR":(initial.soft()?"SOFT":"HARD");
        root.dealerUp=dealer.c.get(0);root.startCards=initial.cards();root.baseWager=wager;
        root.affordabilityFallback=splitAffordabilityFallback;
        if(initial.blackjack()||dealer.blackjack())root.action="NONE";
        else if(wantsSplit)root.action="SPLIT";
        else root.action=selectiveFirst167(initial,dealer.c.get(0),false).toString();
        out.decisions.add(root);

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();
        ArrayList<Decision167> childDecision=new ArrayList<>();

        if(wantsSplit){
            out.splits=1;
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);
            splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committedCapital=hands.size()*wager;
        int decisionCounter=1;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);
            boolean first=true;
            Decision167 d=null;

            // If no split, root is the hand first decision. If split, each child gets its own
            // post-split first-decision record in addition to the original SPLIT decision.
            if(!wantsSplit){
                d=root;
            }else{
                d=new Decision167();
                d.cohort=cohort;d.session=session;d.hand=round;d.decisionIndex=++decisionCounter;
                d.controllerState=controllerState;d.bankrollBand=bankrollBand;d.bankBefore=availableBank;
                d.playerTotal=h.total();d.soft=h.soft();d.pair=false;d.splitChild=true;
                d.family=h.soft()?"SOFT":"HARD";d.dealerUp=dealer.c.get(0);
                d.startCards=h.cards();d.baseWager=wager;d.affordabilityFallback=false;
                if(dealer.blackjack())d.action="NONE";
                else d.action=selectiveFirst167(h,dealer.c.get(0),true).toString();
                out.decisions.add(d);
            }
            childDecision.add(d);

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i))
                                   :textbook(h,dealer.c.get(0),false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committedCapital+wager){
                            d.affordabilityFallback=true;
                            Action fb=textbook(h,dealer.c.get(0),true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committedCapital+=wager;out.doubles++;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;
        for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double roundNet=0,totalStake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),net;
            totalStake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())net=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())net=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())net=0;
            else if(ph.bust())net=-st;
            else if(dealer.bust()||ph.total()>dealer.total())net=st;
            else if(ph.total()<dealer.total())net=-st;
            else net=0;
            roundNet+=net;

            Decision167 d=childDecision.get(i);
            d.totalStake=st;d.net=net;
            d.outcome=net>0?"WIN":net<0?"LOSS":"PUSH";
            d.playerBust=ph.bust();d.dealerBust=dealer.bust();d.bust=ph.bust();
            d.endCards=ph.cards();d.dealerEndCards=dealer.cards();
        }

        // Root SPLIT decision consequence is the complete split round, including both child stakes.
        if(wantsSplit){
            root.totalStake=totalStake;root.net=roundNet;
            root.outcome=roundNet>0?"WIN":roundNet<0?"LOSS":"PUSH";
            root.playerBust=false; // mixed child state is not collapsed into a false player-bust claim
            root.dealerBust=dealer.bust();root.bust=false;
            int ec=0;for(Hand hh:hands)ec+=hh.cards();
            root.endCards=ec;root.dealerEndCards=dealer.cards();
        }

        out.net=roundNet;out.endPointer=ptr[0];
        out.win=roundNet>0;out.loss=roundNet<0;out.push=Math.abs(roundNet)<1e-9;
        return out;
    }

    static final class Session167{
        String cohort;int session,hands;double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive;
    }

    static Session167 runSession167(long seed,String cohort,int session,ArrayList<Decision167> decisions){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;double firstBank=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double bankBefore=bank;
            Round167 rr=playRound167(shoe,ptr,cohort,session+1,hand,bank,wager,
                controllerState167(cooling,cautious),bankrollBand167(bank));
            decisions.addAll(rr.decisions);

            ptr=rr.endPointer;cum+=0;
            // total actual resolved stake comes from child/non-split decisions;
            double roundStake=0;
            for(Decision167 d:rr.decisions)if(!d.pair||!d.action.equals("SPLIT")){
                // avoid counting root split record in addition to child stakes
                if(d.splitChild || rr.splits==0)roundStake+=d.totalStake;
            }
            cum+=roundStake;

            bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){
                    if(qualifies)break;
                    first=hand;firstBank=bank;
                }else if(qualifies)break;
            }

            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session167 r=new Session167();r.cohort=cohort;r.session=session+1;r.hands=hc;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }

    static final long[] P167_SEEDS={217101L,217201L,217301L,217401L};
    static final String[] P167_COHORTS={"FRESH_BE","FRESH_BF","FRESH_BG","FRESH_BH"};

    public static void main3167(String[]args)throws Exception{
        ArrayList<Decision167> all=new ArrayList<>();
        ArrayList<Session167> sessions=new ArrayList<>();

        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)
            sessions.add(runSession167(P167_SEEDS[c],P167_COHORTS[c],s,all));

        StringBuilder dcsv=new StringBuilder(
          "cohort,session,hand,decision_index,controller_state,bankroll_band,bank_before,family,player_total,soft,pair,dealer_upcard,start_cards,split_child,selected_action,state_key,affordability_fallback,base_wager,total_stake,outcome,player_bust,dealer_bust,bust,end_cards,dealer_end_cards,net\n");
        for(Decision167 d:all)dcsv.append(d.csv());
        write("Phase_3_167_Decision_Level_Evidence.csv",dcsv.toString());

        StringBuilder scsv=new StringBuilder("cohort,session,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive\n");
        for(Session167 x:sessions)
            scsv.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f,%s,%s,%s%n",
                x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive));
        write("Phase_3_167_Session_Summary.csv",scsv.toString());

        java.util.TreeMap<String,long[]> map=new java.util.TreeMap<>();
        java.util.TreeMap<String,Double> stakeMap=new java.util.TreeMap<>(),netMap=new java.util.TreeMap<>();
        for(Decision167 d:all){
            long[] a=map.computeIfAbsent(d.key(),k->new long[7]);
            a[0]++;if(d.outcome.equals("WIN"))a[1]++;else if(d.outcome.equals("LOSS"))a[2]++;else a[3]++;
            if(d.playerBust)a[4]++;if(d.action.equals("DOUBLE"))a[5]++;if(d.action.equals("SPLIT"))a[6]++;
            stakeMap.put(d.key(),stakeMap.getOrDefault(d.key(),0.0)+d.totalStake);
            netMap.put(d.key(),netMap.getOrDefault(d.key(),0.0)+d.net);
        }

        ArrayList<String> keys=new ArrayList<>(map.keySet());
        keys.sort((a,b)->Long.compare(map.get(b)[0],map.get(a)[0]));

        StringBuilder agg=new StringBuilder(
          "rank,state_key,occurrences,occurrence_pct,total_stake,stake_pct,mean_stake,total_net,mean_net,win_pct,loss_pct,push_pct,player_bust_pct,double_count,split_count\n");
        double totalStake=0;for(double v:stakeMap.values())totalStake+=v;
        int rank=0;long totalDec=all.size();
        for(String k:keys){
            long[] a=map.get(k);double st=stakeMap.get(k),net=netMap.get(k);rank++;
            agg.append(String.format(Locale.US,
              "%d,%s,%d,%.4f,%.2f,%.4f,%.3f,%.2f,%.4f,%.2f,%.2f,%.2f,%.2f,%d,%d%n",
              rank,k,a[0],100.0*a[0]/totalDec,st,100.0*st/totalStake,st/a[0],net,net/a[0],
              100.0*a[1]/a[0],100.0*a[2]/a[0],100.0*a[3]/a[0],100.0*a[4]/a[0],a[5],a[6]));
        }
        write("Phase_3_167_State_Aggregates.csv",agg.toString());

        long win=0,loss=0,push=0,dbl=0,spl=0,fb=0;
        double bank=0,exp=0,dd=0;int r200=0,z=0,pos=0;
        for(Decision167 d:all){
            if(d.outcome.equals("WIN"))win++;else if(d.outcome.equals("LOSS"))loss++;else push++;
            if(d.action.equals("DOUBLE"))dbl++;if(d.action.equals("SPLIT"))spl++;if(d.affordabilityFallback)fb++;
        }
        for(Session167 x:sessions){
            bank+=x.finalBank;exp+=x.exposure;dd+=x.maxDD;
            if(x.reached200)r200++;if(x.terminalZero)z++;if(x.positive)pos++;
        }

        StringBuilder res=new StringBuilder();
        res.append("DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH\n");
        res.append("CODE VERSION: Deterministic Blackjack Phase 3.167\n");
        res.append("CODE BUILD TAG: DBDE-3.167-PROSPECTIVE-HAND-DECISION-OCCURRENCE-CONSEQUENCE\n\n");
        res.append("PHASE 3.167 — PROSPECTIVE HAND-DECISION OCCURRENCE / CONSEQUENCE INSTRUMENTATION\n");
        res.append("Fresh BE/BF/BG/BH; 5,000 sessions each. Current card-play policy frozen.\n");
        res.append("No alternate hit/stand/double/split action tested.\n\n");
        res.append("SESSIONS: "+sessions.size()+"\n");
        res.append("RECORDED FIRST-DECISION EVENTS: "+all.size()+"\n");
        res.append("UNIQUE OBSERVED STATE KEYS: "+map.size()+"\n");
        res.append(String.format(Locale.US,"Mean final bankroll: £%.3f%n",bank/sessions.size()));
        res.append(String.format(Locale.US,"Reached £200: %.2f%%%n",100.0*r200/sessions.size()));
        res.append(String.format(Locale.US,"Terminal £0: %.2f%%%n",100.0*z/sessions.size()));
        res.append(String.format(Locale.US,"Positive sessions: %.2f%%%n",100.0*pos/sessions.size()));
        res.append(String.format(Locale.US,"Mean cumulative wager exposure: £%.3f%n",exp/sessions.size()));
        res.append(String.format(Locale.US,"Mean maximum drawdown: £%.3f%n%n",dd/sessions.size()));
        res.append(String.format(Locale.US,"Decision outcomes — WIN %.2f%% | LOSS %.2f%% | PUSH %.2f%%%n",
            100.0*win/totalDec,100.0*loss/totalDec,100.0*push/totalDec));
        res.append("First-decision DOUBLE records: "+dbl+"\n");
        res.append("Original SPLIT decisions: "+spl+"\n");
        res.append("Affordability fallbacks: "+fb+"\n\n");
        res.append("TOP 15 OBSERVED STATE KEYS BY FREQUENCY\n");
        for(int i=0;i<Math.min(15,keys.size());i++){
            String k=keys.get(i);long[] a=map.get(k);
            res.append(String.format(Locale.US,"%2d. %-18s n=%d (%.2f%%) | stake £%.2f | mean net £%+.3f%n",
                i+1,k,a[0],100.0*a[0]/totalDec,stakeMap.get(k),netMap.get(k)/a[0]));
        }
        res.append("\nINTERPRETATION GUARDRAIL\n");
        res.append("Observed win/loss/net under the frozen action is descriptive and cannot establish the counterfactual value of an action not taken.\n");
        res.append("Phase 3.167 ranks evidence sufficiency and consequence only; it does not identify a superior alternate decision.\n\n");
        res.append("PHASE 3.168 NEXT DESIGN\n");
        res.append("Use the prospective occurrence/consequence map to predeclare ONE sufficiently frequent, high-exposure decision family for controlled action ablation.\n");
        res.append("Before execution, freeze the candidate state, current action, alternate legal action, metrics and fresh cohorts.\n");
        res.append("No multi-rule change and no post-hoc candidate switching.\n");
        write("Phase_3_167_Results.txt",res.toString());
        write("Phase_3_167_Replay_Verification.txt",
          "Fresh BE/BF/BG/BH. Current SELECTIVE_AGGRESSION card-play policy and accepted session architecture retained. "
         +"Decision instrumentation only; no alternate action tested.\n");
        System.out.print(res.toString());
    }


    // =====================================================================
    // PHASE 3.169 — FRESH PAIRED PAIR-20-vs-10 SPLIT-versus-STAND ABLATION
    // Frozen by Phase 3.168.
    // =====================================================================

    static final class Round169{
        double net,stake; int endPointer,doubles,splits;
        boolean win,loss,push,candidateSeen,candidateEligible,candidateIneligible;
        double candidateNet; int candidatePlayerCards,candidateDealerCards;
    }

    static Round169 playRound169(int[] shoe,int pointer,double availableBank,double wager,boolean ablation){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=pair && initial.total()==20 && dealer.c.get(0)==10;
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        boolean candidateEligible=candidate&&splitAffordable;
        boolean candidateIneligible=candidate&&!splitAffordable;

        boolean wantsSplit=pair;
        if(candidateEligible&&ablation)wantsSplit=false; // the ONE frozen change
        if(wantsSplit&&!splitAffordable)wantsSplit=false;

        Round169 out=new Round169();
        out.candidateSeen=candidate;out.candidateEligible=candidateEligible;out.candidateIneligible=candidateIneligible;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            out.splits=1;
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);
            splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committedCapital=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            // Frozen ablation: eligible pair-20 vs dealer-10 STANDS immediately.
            if(candidateEligible&&ablation&&!wantsSplit){
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i))
                                   :textbook(h,dealer.c.get(0),false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committedCapital+wager){
                            Action fb=textbook(h,dealer.c.get(0),true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committedCapital+=wager;out.doubles++;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double roundNet=0,totalStake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),net;
            totalStake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())net=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())net=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())net=0;
            else if(ph.bust())net=-st;
            else if(dealer.bust()||ph.total()>dealer.total())net=st;
            else if(ph.total()<dealer.total())net=-st;
            else net=0;
            roundNet+=net;
        }
        out.net=roundNet;out.stake=totalStake;out.endPointer=ptr[0];
        out.win=roundNet>1e-9;out.loss=roundNet<-1e-9;out.push=Math.abs(roundNet)<1e-9;
        if(candidateEligible){
            out.candidateNet=roundNet;
            int pc=0;for(Hand h:hands)pc+=h.cards();
            out.candidatePlayerCards=pc;out.candidateDealerCards=dealer.cards();
        }
        return out;
    }

    static final class Session169{
        String arm,cohort;int session,hands,eligible,ineligible,firstEligibleHand;
        double finalBank,exposure,maxDD,firstCandidateNet;
        boolean reached200,terminalZero,positive,affected;
    }

    static Session169 runSession169(long seed,String cohort,int session,boolean ablation){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;boolean reached200=false;
        int eligible=0,ineligible=0,firstEligibleHand=0;double firstCandidateNet=0;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);
            if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round169 rr=playRound169(shoe,ptr,bank,wager,ablation);
            if(rr.candidateEligible){
                eligible++;
                if(firstEligibleHand==0){firstEligibleHand=hand;firstCandidateNet=rr.candidateNet;}
            }
            if(rr.candidateIneligible)ineligible++;

            ptr=rr.endPointer;cum+=rr.stake;
            bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session169 r=new Session169();
        r.arm=ablation?"STAND_ABLATION":"SPLIT_REFERENCE";r.cohort=cohort;r.session=session+1;r.hands=hc;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;r.eligible=eligible;r.ineligible=ineligible;
        r.affected=eligible>0;r.firstEligibleHand=firstEligibleHand;r.firstCandidateNet=firstCandidateNet;
        return r;
    }

    static final long[] P169_SEEDS={218101L,218201L,218301L,218401L};
    static final String[] P169_COHORTS={"FRESH_BI","FRESH_BJ","FRESH_BK","FRESH_BL"};

    public static void main3169(String[]args)throws Exception{
        ArrayList<Session169> ref=new ArrayList<>(),alt=new ArrayList<>();
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++){
            ref.add(runSession169(P169_SEEDS[c],P169_COHORTS[c],s,false));
            alt.add(runSession169(P169_SEEDS[c],P169_COHORTS[c],s,true));
        }

        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,eligible_candidate_events,ineligible_affordability_events,affected,first_eligible_hand,first_candidate_round_net\n");
        for(Session169 x:ref)csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet));
        for(Session169 x:alt)csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet));
        write("Phase_3_169_Arm_Session_Results.csv",csv.toString());

        StringBuilder pcsv=new StringBuilder("cohort,session,ref_final,stand_final,delta_stand_minus_split,ref_exposure,stand_exposure,exposure_delta,ref_maxdd,stand_maxdd,maxdd_delta,ref_hands,stand_hands,hands_delta,ref_reached200,stand_reached200,ref_zero,stand_zero,ref_positive,stand_positive,ref_eligible,stand_eligible,ref_first_candidate_net,stand_first_candidate_net\n");
        int better=0,worse=0,equal=0,zPrevent=0,zCreate=0,tLost=0,tCreate=0,pGain=0,pLost=0,affectedRef=0,multiRef=0;
        double netDelta=0,expDelta=0,ddDelta=0,handDelta=0,firstDelta=0;int firstPairs=0;
        long eligRef=0,eligAlt=0,ineligRef=0;
        for(int i=0;i<ref.size();i++){
            Session169 a=ref.get(i),b=alt.get(i);double d=b.finalBank-a.finalBank;
            if(d>1e-9)better++;else if(d<-1e-9)worse++;else equal++;
            netDelta+=d;expDelta+=b.exposure-a.exposure;ddDelta+=b.maxDD-a.maxDD;handDelta+=b.hands-a.hands;
            if(a.terminalZero&&!b.terminalZero)zPrevent++;if(!a.terminalZero&&b.terminalZero)zCreate++;
            if(a.reached200&&!b.reached200)tLost++;if(!a.reached200&&b.reached200)tCreate++;
            if(!a.positive&&b.positive)pGain++;if(a.positive&&!b.positive)pLost++;
            if(a.affected)affectedRef++;if(a.eligible>1)multiRef++;
            eligRef+=a.eligible;eligAlt+=b.eligible;ineligRef+=a.ineligible;
            if(a.firstEligibleHand>0&&b.firstEligibleHand>0&&a.firstEligibleHand==b.firstEligibleHand){
                firstDelta+=b.firstCandidateNet-a.firstCandidateNet;firstPairs++;
            }
            pcsv.append(String.format(Locale.US,"%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
                a.cohort,a.session,a.finalBank,b.finalBank,d,a.exposure,b.exposure,b.exposure-a.exposure,a.maxDD,b.maxDD,b.maxDD-a.maxDD,a.hands,b.hands,b.hands-a.hands,a.reached200,b.reached200,a.terminalZero,b.terminalZero,a.positive,b.positive,a.eligible,b.eligible,a.firstCandidateNet,b.firstCandidateNet));
        }
        write("Phase_3_169_Paired_Session_Results.csv",pcsv.toString());

        double rBank=0,aBank=0,rExp=0,aExp=0,rDD=0,aDD=0;int r200=0,a200=0,rz=0,az=0,rpos=0,apos=0;
        for(Session169 x:ref){rBank+=x.finalBank;rExp+=x.exposure;rDD+=x.maxDD;if(x.reached200)r200++;if(x.terminalZero)rz++;if(x.positive)rpos++;}
        for(Session169 x:alt){aBank+=x.finalBank;aExp+=x.exposure;aDD+=x.maxDD;if(x.reached200)a200++;if(x.terminalZero)az++;if(x.positive)apos++;}
        int n=ref.size();

        StringBuilder res=new StringBuilder();
        res.append("DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH\n");
        res.append("CODE VERSION: Deterministic Blackjack Phase 3.169\n");
        res.append("CODE BUILD TAG: DBDE-3.169-PAIR20-VS10-SPLIT-STAND-PAIRED-EXECUTION\n\n");
        res.append("FROZEN 3.168 EXPERIMENT EXECUTED — BI/BJ/BK/BL, 20,000 paired sessions.\n");
        res.append("ONE RULE ONLY: eligible PAIR_20_vs_10 SPLIT -> STAND.\n\n");
        res.append(String.format(Locale.US,"REFERENCE SPLIT mean final bankroll: £%.3f%n",rBank/n));
        res.append(String.format(Locale.US,"STAND ABLATION mean final bankroll: £%.3f%n",aBank/n));
        res.append(String.format(Locale.US,"Mean paired final-bankroll delta (STAND-SPLIT): £%+.3f%n",netDelta/n));
        res.append(String.format(Locale.US,"REFERENCE reached £200: %.2f%% | STAND: %.2f%%%n",100.0*r200/n,100.0*a200/n));
        res.append(String.format(Locale.US,"REFERENCE terminal £0: %.2f%% | STAND: %.2f%%%n",100.0*rz/n,100.0*az/n));
        res.append(String.format(Locale.US,"REFERENCE positive: %.2f%% | STAND: %.2f%%%n",100.0*rpos/n,100.0*apos/n));
        res.append(String.format(Locale.US,"REFERENCE mean exposure: £%.3f | STAND: £%.3f | delta £%+.3f%n",rExp/n,aExp/n,expDelta/n));
        res.append(String.format(Locale.US,"REFERENCE mean max drawdown: £%.3f | STAND: £%.3f | delta £%+.3f%n%n",rDD/n,aDD/n,ddDelta/n));
        res.append("PAIRED SESSION DIRECTION\n");
        res.append(String.format(Locale.US,"STAND better: %d (%.2f%%)%n",better,100.0*better/n));
        res.append(String.format(Locale.US,"STAND worse: %d (%.2f%%)%n",worse,100.0*worse/n));
        res.append(String.format(Locale.US,"Equal: %d (%.2f%%)%n",equal,100.0*equal/n));
        res.append(String.format(Locale.US,"Net paired bankroll contribution: £%+.2f%n",netDelta));
        res.append(String.format(Locale.US,"£0 prevented: %d | £0 created: %d%n",zPrevent,zCreate));
        res.append(String.format(Locale.US,"£200 created: %d | £200 lost: %d%n",tCreate,tLost));
        res.append(String.format(Locale.US,"Positive sessions gained: %d | lost: %d%n%n",pGain,pLost));
        res.append("CANDIDATE EXPOSURE\n");
        res.append(String.format(Locale.US,"Reference sessions containing >=1 eligible candidate: %d (%.2f%%)%n",affectedRef,100.0*affectedRef/n));
        res.append("Reference total eligible candidate events: "+eligRef+"\n");
        res.append("Reference affordability-ineligible candidate events: "+ineligRef+"\n");
        res.append(String.format(Locale.US,"Reference sessions with multiple eligible events: %d (%.2f%%)%n",multiRef,100.0*multiRef/n));
        res.append("Stand-arm eligible candidate events after natural path divergence: "+eligAlt+"\n");
        if(firstPairs>0)res.append(String.format(Locale.US,"First eligible candidate immediate round-net delta where aligned: £%+.3f across %d paired first events%n",firstDelta/firstPairs,firstPairs));
        res.append("\nINTERPRETATION\n");
        res.append("The paired whole-session result measures the causal consequence of the frozen one-rule policy change under this deterministic architecture.\n");
        res.append("After the first action divergence, later card identities may differ naturally and are not forced back into alignment.\n");
        res.append("No universal blackjack-strategy claim is permitted from this experiment.\n");
        write("Phase_3_169_Results.txt",res.toString());
        System.out.print(res.toString());
    }


    // PHASE 3.173 — HARD 12 vs dealer 10 HIT-versus-STAND fresh paired discovery.
    static final class Round173{
        double net,stake; int endPointer;
        boolean candidateEligible,candidateIneligible;
        double candidateNet;
    }

    static Round173 playRound173(int[] shoe,int pointer,double availableBank,double wager,boolean ablation){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean hard12=!initial.soft() && initial.total()==12;
        Action refFirst=selectiveFirst167(initial,dealer.c.get(0),false);
        boolean candidate=(!pair)&&hard12&&dealer.c.get(0)==10;
        boolean eligible=candidate&&refFirst==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        boolean wantsSplit=pair;
        if(wantsSplit && availableBank<2.0*wager-1e-9) wantsSplit=false;

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committedCapital=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(eligible&&ablation&&!wantsSplit){ // frozen one-rule change
                continue; // STAND immediately
            }
            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committedCapital+wager){
                            Action fb=textbook(h,dealer.c.get(0),true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committedCapital+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;
            stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round173 r=new Round173();r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.candidateEligible=eligible;r.candidateIneligible=candidate&&!eligible;
        if(eligible)r.candidateNet=net;
        return r;
    }

    static final class Session173{
        String arm,cohort;int session,hands,eligible,ineligible,firstEligibleHand;
        double finalBank,exposure,maxDD,firstCandidateNet;
        boolean reached200,terminalZero,positive,affected;
    }

    static Session173 runSession173(long seed,String cohort,int session,boolean ablation){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;boolean reached200=false;
        int eligible=0,ineligible=0,firstEligibleHand=0;double firstCandidateNet=0;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round173 rr=playRound173(shoe,ptr,bank,wager,ablation);
            if(rr.candidateEligible){eligible++;if(firstEligibleHand==0){firstEligibleHand=hand;firstCandidateNet=rr.candidateNet;}}
            if(rr.candidateIneligible)ineligible++;
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;}
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        Session173 r=new Session173();r.arm=ablation?"STAND_ABLATION":"HIT_REFERENCE";r.cohort=cohort;r.session=session+1;r.hands=hc;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.eligible=eligible;r.ineligible=ineligible;r.affected=eligible>0;r.firstEligibleHand=firstEligibleHand;r.firstCandidateNet=firstCandidateNet;
        return r;
    }

    static final long[] P173_SEEDS={220101L,220201L,220301L,220401L};
    static final String[] P173_COHORTS={"FRESH_BQ","FRESH_BR","FRESH_BS","FRESH_BT"};

    public static void main3173(String[]args)throws Exception{
        ArrayList<Session173> ref=new ArrayList<>(),alt=new ArrayList<>();
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++){
            ref.add(runSession173(P173_SEEDS[c],P173_COHORTS[c],s,false));
            alt.add(runSession173(P173_SEEDS[c],P173_COHORTS[c],s,true));
        }
        StringBuilder acsv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,eligible_candidate_events,ineligible_reference_action_events,affected,first_eligible_hand,first_candidate_round_net\n");
        for(Session173 x:ref)acsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet));
        for(Session173 x:alt)acsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet));
        write("Phase_3_173_Arm_Session_Results.csv",acsv.toString());

        StringBuilder pcsv=new StringBuilder("cohort,session,ref_final,stand_final,delta_stand_minus_hit,ref_exposure,stand_exposure,exposure_delta,ref_maxdd,stand_maxdd,maxdd_delta,ref_hands,stand_hands,hands_delta,ref_reached200,stand_reached200,ref_zero,stand_zero,ref_positive,stand_positive,ref_eligible,stand_eligible,ref_first_candidate_net,stand_first_candidate_net\n");
        int better=0,worse=0,equal=0,zPrevent=0,zCreate=0,tCreate=0,tLost=0,pGain=0,pLost=0,affected=0,multi=0,firstPairs=0;
        long elig=0,inelig=0;double delta=0,expD=0,ddD=0,firstD=0;
        double rb=0,ab=0,re=0,ae=0,rd=0,ad=0;int r200=0,a200=0,rz=0,az=0,rp=0,ap=0;
        for(int i=0;i<ref.size();i++){
            Session173 r=ref.get(i),a=alt.get(i);double d=a.finalBank-r.finalBank;
            rb+=r.finalBank;ab+=a.finalBank;re+=r.exposure;ae+=a.exposure;rd+=r.maxDD;ad+=a.maxDD;
            if(r.reached200)r200++;if(a.reached200)a200++;if(r.terminalZero)rz++;if(a.terminalZero)az++;if(r.positive)rp++;if(a.positive)ap++;
            if(d>1e-9)better++;else if(d<-1e-9)worse++;else equal++;delta+=d;expD+=a.exposure-r.exposure;ddD+=a.maxDD-r.maxDD;
            if(r.terminalZero&&!a.terminalZero)zPrevent++;if(!r.terminalZero&&a.terminalZero)zCreate++;
            if(!r.reached200&&a.reached200)tCreate++;if(r.reached200&&!a.reached200)tLost++;
            if(!r.positive&&a.positive)pGain++;if(r.positive&&!a.positive)pLost++;
            if(r.affected)affected++;if(r.eligible>1)multi++;elig+=r.eligible;inelig+=r.ineligible;
            if(r.firstEligibleHand>0&&a.firstEligibleHand==r.firstEligibleHand){firstD+=a.firstCandidateNet-r.firstCandidateNet;firstPairs++;}
            pcsv.append(String.format(Locale.US,"%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
                r.cohort,r.session,r.finalBank,a.finalBank,d,r.exposure,a.exposure,a.exposure-r.exposure,r.maxDD,a.maxDD,a.maxDD-r.maxDD,r.hands,a.hands,a.hands-r.hands,r.reached200,a.reached200,r.terminalZero,a.terminalZero,r.positive,a.positive,r.eligible,a.eligible,r.firstCandidateNet,a.firstCandidateNet));
        }
        write("Phase_3_173_Paired_Session_Results.csv",pcsv.toString());
        int n=ref.size();
        StringBuilder res=new StringBuilder();
        res.append("DETERMINISTIC BLACKJACK DECISION ENGINE RESEARCH\nCODE VERSION: Deterministic Blackjack Phase 3.173\nCODE BUILD TAG: DBDE-3.173-HARD12-VS10-HIT-STAND-DISCOVERY\n\n");
        res.append("Fresh BQ/BR/BS/BT; 20,000 paired sessions. PAIR20 modification OFF.\n");
        res.append(String.format(Locale.US,"HIT mean final bankroll: £%.3f%nSTAND mean final bankroll: £%.3f%nMean paired delta STAND-HIT: £%+.3f%nAggregate paired contribution: £%+.2f%n",rb/n,ab/n,delta/n,delta));
        res.append(String.format(Locale.US,"£200 HIT %.2f%% | STAND %.2f%%%n£0 HIT %.2f%% | STAND %.2f%%%nPositive HIT %.2f%% | STAND %.2f%%%n",100.0*r200/n,100.0*a200/n,100.0*rz/n,100.0*az/n,100.0*rp/n,100.0*ap/n));
        res.append(String.format(Locale.US,"Exposure HIT £%.3f | STAND £%.3f | delta £%+.3f%nMaxDD HIT £%.3f | STAND £%.3f | delta £%+.3f%n",re/n,ae/n,expD/n,rd/n,ad/n,ddD/n));
        res.append(String.format(Locale.US,"STAND better %d (%.2f%%) | worse %d (%.2f%%) | equal %d (%.2f%%)%n",better,100.0*better/n,worse,100.0*worse/n,equal,100.0*equal/n));
        res.append(String.format(Locale.US,"Affected reference sessions %d (%.2f%%); eligible events %d; reference-action-ineligible %d; multiple %d (%.2f%%)%n",affected,100.0*affected/n,elig,inelig,multi,100.0*multi/n));
        res.append(String.format(Locale.US,"£0 prevented %d | created %d; £200 created %d | lost %d; positive gained %d | lost %d%n",zPrevent,zCreate,tCreate,tLost,pGain,pLost));
        if(firstPairs>0)res.append(String.format(Locale.US,"First aligned candidate immediate round-net delta: £%+.3f across %d events%n",firstD/firstPairs,firstPairs));
        write("Phase_3_173_Results.txt",res.toString());System.out.print(res);
    }


    static final class Round179{
        double net,stake; int endPointer;
        boolean candidateEligible,candidateIneligible;
        double candidateNet;
        int candidatePlayerCards,candidateDealerCards,altContinuationCards;
    }

    static Round179 playRound179(int[] shoe,int pointer,double availableBank,double wager,boolean hitAblation){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&dealer.c.get(0)==10
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.DOUBLE;
        boolean affordable=availableBank>=2.0*wager-1e-9;
        boolean eligible=candidate&&affordable;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        boolean wantsSplit=pair;
        if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        int cont=0;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if(eligible&&hitAblation&&!wantsSplit){
                // Frozen alternate: first HIT with no added stake, then ordinary non-first continuation.
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,dealer.c.get(0),false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));cont++;
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,dealer.c.get(0),true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;
            stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round179 r=new Round179();r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.candidateEligible=eligible;r.candidateIneligible=candidate&&!eligible;
        if(eligible){
            r.candidateNet=net;int pc=0;for(Hand h:hands)pc+=h.cards();
            r.candidatePlayerCards=pc;r.candidateDealerCards=dealer.cards();r.altContinuationCards=hitAblation?cont:0;
        }
        return r;
    }

    static final class Session179{
        String arm,cohort;int session,hands,eligible,ineligible,firstEligibleHand;
        double finalBank,exposure,maxDD,firstCandidateNet,firstCandidateStake;
        int firstCandidatePlayerCards,firstCandidateDealerCards,firstAltContinuationCards;
        boolean reached200,terminalZero,positive,affected;
    }

    static Session179 runSession179(long seed,String cohort,int session,boolean hitAblation){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session)); if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;boolean reached200=false;
        int eligible=0,ineligible=0,firstEligibleHand=0;double firstCandidateNet=0,firstCandidateStake=0;
        int firstCandidatePlayerCards=0,firstCandidateDealerCards=0,firstAltContinuationCards=0;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round179 rr=playRound179(shoe,ptr,bank,wager,hitAblation);
            if(rr.candidateEligible){
                eligible++;
                if(firstEligibleHand==0){
                    firstEligibleHand=hand;firstCandidateNet=rr.candidateNet;firstCandidateStake=rr.stake;
                    firstCandidatePlayerCards=rr.candidatePlayerCards;firstCandidateDealerCards=rr.candidateDealerCards;
                    firstAltContinuationCards=rr.altContinuationCards;
                }
            }
            if(rr.candidateIneligible)ineligible++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;}
            if(bank>=200-1e-9){reached200=true;break;}if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session179 r=new Session179();r.arm=hitAblation?"HIT_ABLATION":"DOUBLE_REFERENCE";r.cohort=cohort;r.session=session+1;r.hands=hc;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.eligible=eligible;r.ineligible=ineligible;r.affected=eligible>0;r.firstEligibleHand=firstEligibleHand;r.firstCandidateNet=firstCandidateNet;
        r.firstCandidateStake=firstCandidateStake;r.firstCandidatePlayerCards=firstCandidatePlayerCards;r.firstCandidateDealerCards=firstCandidateDealerCards;
        r.firstAltContinuationCards=firstAltContinuationCards;return r;
    }

    static final long[] P179_SEEDS={224101L,224201L,224301L,224401L};
    static final String[] P179_COHORTS={"FRESH_CG","FRESH_CH","FRESH_CI","FRESH_CJ"};

    public static void main3179(String[]args)throws Exception{
        int ci=args.length==0?-1:Integer.parseInt(args[0]);
        int from=ci<0?0:ci,to=ci<0?4:ci+1;
        String suffix=ci<0?"ALL":P179_COHORTS[ci];
        ArrayList<Session179> ref=new ArrayList<>(),alt=new ArrayList<>();
        for(int c=from;c<to;c++)for(int s=0;s<SESSIONS;s++){
            ref.add(runSession179(P179_SEEDS[c],P179_COHORTS[c],s,false));
            alt.add(runSession179(P179_SEEDS[c],P179_COHORTS[c],s,true));
        }
        StringBuilder acsv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,eligible_candidate_events,ineligible_reference_action_events,affected,first_eligible_hand,first_candidate_round_net,first_candidate_stake,first_candidate_player_cards,first_candidate_dealer_cards,first_alt_continuation_cards\n");
        for(Session179 x:ref)acsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f,%.2f,%d,%d,%d%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet,x.firstCandidateStake,x.firstCandidatePlayerCards,x.firstCandidateDealerCards,x.firstAltContinuationCards));
        for(Session179 x:alt)acsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s,%d,%.2f,%.2f,%d,%d,%d%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible,x.affected,x.firstEligibleHand,x.firstCandidateNet,x.firstCandidateStake,x.firstCandidatePlayerCards,x.firstCandidateDealerCards,x.firstAltContinuationCards));
        write("Phase_3_179_Arm_Session_Results_"+suffix+".csv",acsv.toString());
        System.out.println("DONE "+suffix+" sessions="+ref.size());
    }


    // =====================================================================
    // PHASE 3.183 — PROSPECTIVE STATE-STRATIFIED DOUBLE-vs-HIT DISCOVERY
    // Uses Phase 3.182 frozen bins. No hybrid rule is executed.
    // =====================================================================

    static final class Session183{
        String arm,cohort;
        int session,hands,eligible,ineligible;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive;
    }

    static final class Event183{
        String cohort;
        int session,ordinal,handIndex;
        double bankroll,wager,exposure,peak,drawdown;
        boolean cooling,cautious,negativeEpisode,brakeArmed,repeated;
        double refCandidateNet,hitCandidateNet;
        double refFinal,hitFinal,finalDelta;
        boolean refZero,hitZero,ref200,hit200,refPositive,hitPositive;
        String bankrollBand,drawdownBand,handBand;
    }

    static String bankrollBand183(double b){
        if(b<75)return "LT75";
        if(b<100)return "75_99";
        if(b<125)return "100_124";
        if(b<150)return "125_149";
        if(b<175)return "150_174";
        return "175_PLUS";
    }
    static String drawdownBand183(double d){
        if(d<10)return "0_9";
        if(d<25)return "10_24";
        if(d<50)return "25_49";
        if(d<75)return "50_74";
        return "75_PLUS";
    }
    static String handBand183(int h){
        if(h<=8)return "1_8";
        if(h<=15)return "9_15";
        if(h<=22)return "16_22";
        return "23_30";
    }

    static Session183 runOne183(long seed,String cohort,int session,boolean hitAblation,
                                java.util.ArrayList<Event183> events, boolean captureRefContext){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;boolean reached200=false;
        int eligible=0,ineligible=0,ordinal=0;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeExposure=cum,beforePeak=maxPeak,beforeDD=maxPeak-bank;
            boolean beforeCooling=cooling,beforeCautious=cautious,beforeNeg=negativeEpisode,beforeBrake=brakeArmed;

            Round179 rr=playRound179(shoe,ptr,bank,wager,hitAblation);

            if(rr.candidateEligible){
                eligible++; ordinal++;
                if(captureRefContext){
                    Event183 e=new Event183();
                    e.cohort=cohort;e.session=session+1;e.ordinal=ordinal;e.handIndex=hand;
                    e.bankroll=beforeBank;e.wager=wager;e.exposure=beforeExposure;e.peak=beforePeak;e.drawdown=beforeDD;
                    e.cooling=beforeCooling;e.cautious=beforeCautious;e.negativeEpisode=beforeNeg;e.brakeArmed=beforeBrake;e.repeated=ordinal>1;
                    e.refCandidateNet=rr.candidateNet;
                    e.hitCandidateNet=Double.NaN;
                    e.bankrollBand=bankrollBand183(beforeBank);
                    e.drawdownBand=drawdownBand183(beforeDD);
                    e.handBand=handBand183(hand);
                    events.add(e);
                }else{
                    // Link the hit-arm event to the same ordinal only if still aligned by session+ordinal+hand.
                    for(Event183 e:events){
                        if(e.session==session+1 && e.cohort.equals(cohort) && e.ordinal==ordinal && e.handIndex==hand && Double.isNaN(e.hitCandidateNet)){
                            e.hitCandidateNet=rr.candidateNet;
                            break;
                        }
                    }
                }
            }
            if(rr.candidateIneligible)ineligible++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session183 r=new Session183();
        r.arm=hitAblation?"HIT_ABLATION":"DOUBLE_REFERENCE";
        r.cohort=cohort;r.session=session+1;r.hands=hc;r.eligible=eligible;r.ineligible=ineligible;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        return r;
    }

    static final long[] P183_SEEDS={228101L,228201L,228301L,228401L};
    static final String[] P183_COHORTS={"FRESH_CW","FRESH_CX","FRESH_CY","FRESH_CZ"};

    public static void main3184(String[]args)throws Exception{
        java.util.ArrayList<Session183> ref=new java.util.ArrayList<>();
        java.util.ArrayList<Session183> hit=new java.util.ArrayList<>();
        java.util.ArrayList<Event183> events=new java.util.ArrayList<>();

        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++){
            Session183 r=runOne183(P183_SEEDS[c],P183_COHORTS[c],s,false,events,true);
            ref.add(r);
            Session183 h=runOne183(P183_SEEDS[c],P183_COHORTS[c],s,true,events,false);
            hit.add(h);

            // Attach whole-session outcomes to all reference events from this paired session.
            for(Event183 e:events){
                if(e.cohort.equals(P183_COHORTS[c])&&e.session==s+1){
                    e.refFinal=r.finalBank;e.hitFinal=h.finalBank;e.finalDelta=h.finalBank-r.finalBank;
                    e.refZero=r.terminalZero;e.hitZero=h.terminalZero;
                    e.ref200=r.reached200;e.hit200=h.reached200;
                    e.refPositive=r.positive;e.hitPositive=h.positive;
                }
            }
        }

        StringBuilder scsv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,eligible_events,ineligible_events\n");
        for(Session183 x:ref)scsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible));
        for(Session183 x:hit)scsv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.eligible,x.ineligible));
        write("Phase_3_184_Arm_Session_Results.csv",scsv.toString());

        StringBuilder ecsv=new StringBuilder("cohort,session,candidate_ordinal,hand_index,decision_bankroll,wager,cumulative_exposure,peak_bankroll,decision_drawdown,cooling,cautious,negative_episode,brake_armed,repeated_candidate,bankroll_band,drawdown_band,hand_band,ref_candidate_net,hit_candidate_net,ref_final,hit_final,final_delta_hit_minus_double,ref_zero,hit_zero,ref_200,hit_200,ref_positive,hit_positive\n");
        for(Event183 e:events)ecsv.append(String.format(Locale.US,
          "%s,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s%n",
          e.cohort,e.session,e.ordinal,e.handIndex,e.bankroll,e.wager,e.exposure,e.peak,e.drawdown,
          e.cooling,e.cautious,e.negativeEpisode,e.brakeArmed,e.repeated,e.bankrollBand,e.drawdownBand,e.handBand,
          e.refCandidateNet,e.hitCandidateNet,e.refFinal,e.hitFinal,e.finalDelta,e.refZero,e.hitZero,e.ref200,e.hit200,e.refPositive,e.hitPositive));
        write("Phase_3_184_Prospective_State_Stratified_Events.csv",ecsv.toString());

        System.out.println("Deterministic Blackjack Phase 3.184");
        System.out.println("CODE BUILD TAG: DBDE-3.184-HARD11-COOLING-STATE-INDEPENDENT-HOLDOUT");
        System.out.println("Fresh CW/CX/CY/CZ; 20,000 independent paired holdout sessions.");
        System.out.println("No hybrid rule; DOUBLE reference versus HIT ablation only.");
    }


    // =====================================================================
    // PHASE 3.186 — FRESH THREE-ARM COOLING-HYBRID EXECUTION
    // Frozen by Phase 3.185.
    // =====================================================================

    static final int ARM_A_DOUBLE=0, ARM_B_GLOBAL_HIT=1, ARM_C_COOLING_HYBRID=2;
    static final long[] P186_SEEDS={230101L,230201L,230301L,230401L};
    static final String[] P186_COHORTS={"FRESH_DE","FRESH_DF","FRESH_DG","FRESH_DH"};

    static final class Session186{
        String cohort,arm;
        int session,hands,eligible,ineligible,hybridSwitches,firstSwitchHand;
        double finalBank,exposure,maxDD,firstSwitchBank,firstSwitchWager,firstSwitchDD;
        boolean reached200,terminalZero,positive;
    }

    static Session186 runOne186(long seed,String cohort,int session,int arm){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,eligible=0,ineligible=0,switches=0,firstSwitchHand=0;
        double firstSwitchBank=Double.NaN,firstSwitchWager=Double.NaN,firstSwitchDD=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            boolean beforeCooling=cooling;

            // playRound179's boolean is the HARD11-vs10 HIT ablation switch.
            // A: always false; B: always true; C: true only when Cooling was active before the hand.
            boolean hitAblation = arm==ARM_B_GLOBAL_HIT || (arm==ARM_C_COOLING_HYBRID && beforeCooling);
            Round179 rr=playRound179(shoe,ptr,bank,wager,hitAblation);

            if(rr.candidateEligible){
                eligible++;
                if(arm==ARM_C_COOLING_HYBRID && beforeCooling){
                    switches++;
                    if(firstSwitchHand==0){
                        firstSwitchHand=hand;firstSwitchBank=beforeBank;
                        firstSwitchWager=wager;firstSwitchDD=beforeDD;
                    }
                }
            }
            if(rr.candidateIneligible)ineligible++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session186 r=new Session186();
        r.cohort=cohort;r.session=session+1;
        r.arm=arm==0?"A_ORIGINAL_DOUBLE":arm==1?"B_GLOBAL_HIT":"C_COOLING_HYBRID";
        r.hands=hc;r.eligible=eligible;r.ineligible=ineligible;r.hybridSwitches=switches;r.firstSwitchHand=firstSwitchHand;
        r.firstSwitchBank=firstSwitchBank;r.firstSwitchWager=firstSwitchWager;r.firstSwitchDD=firstSwitchDD;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        return r;
    }

    public static void main3187(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,eligible_events,ineligible_events,hybrid_switches,first_switch_hand,first_switch_bankroll,first_switch_wager,first_switch_drawdown\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<3;arm++){
            Session186 x=runOne186(P186_SEEDS[c],P186_COHORTS[c],s,arm);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%d,%d,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.eligible,x.ineligible,x.hybridSwitches,x.firstSwitchHand,x.firstSwitchBank,x.firstSwitchWager,x.firstSwitchDD));
        }
        write("Phase_3_187_Three_Arm_Session_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.187");
        System.out.println("CODE BUILD TAG: DBDE-3.187-HARD11-COOLING-HYBRID-THREE-ARM-HOLDOUT");
        System.out.println("Fresh DE/DF/DG/DH; 20,000 independent holdout triplets.");
        System.out.println("A=DOUBLE, B=GLOBAL HIT, C=COOLING HYBRID.");
    }


    static final long[] P188_SEEDS={231101L,231201L,231301L,231401L};
    static final String[] P188_COHORTS={"FRESH_DI","FRESH_DJ","FRESH_DK","FRESH_DL"};

    static final class Round188{
        double net,stake; int endPointer; boolean candidate; double candidateNet;
    }
    static Round188 playRound188(int[] shoe,int pointer,double availableBank,double wager,boolean hitAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==12&&dealer.c.get(0)==4
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.STAND;
        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&hitAlternate&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){Action a=textbook(h,dealer.c.get(0),false);if(a==Action.STAND)break;h.c.add(draw(shoe,ptr));}
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){Action fb=textbook(h,dealer.c.get(0),true);if(fb==Action.DOUBLE)fb=Action.HIT;if(fb==Action.STAND)break;h.c.add(draw(shoe,ptr));first=false;continue;}
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }
        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;else x=0;net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;if(candidate)r.candidateNet=net;return r;
    }

    static final class Session188{
        String cohort,arm;int session,hands,candidates,firstCandidateHand;double finalBank,exposure,maxDD,firstCandidateBank,firstCandidateWager,firstCandidateDD,firstCandidateNet;
        boolean reached200,terminalZero,positive;
    }
    static Session188 runOne188(long seed,String cohort,int session,boolean hitAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;boolean reached200=false;
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;if(cooling&&bank>=120){cooling=false;cautious=true;}if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){int bal=bal355(hist,hc);boolean neg=bal<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;}
            else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound188(shoe,ptr,bank,wager,hitAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;
            boolean trigger=false;if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;}
            if(bank>=200-1e-9){reached200=true;break;}if(bank<=1e-9)break;if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;r.arm=hitAlternate?"HIT_ALTERNATE":"STAND_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }
    public static void main3188(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){Session188 x=runOne188(P188_SEEDS[c],P188_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));}
        write("Phase_3_188_Candidate5_Hard12v4_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.188");System.out.println("CODE BUILD TAG: DBDE-3.188-CANDIDATE5-HARD12v4-STAND-v-HIT-DISCOVERY");
        System.out.println("Fresh DI/DJ/DK/DL; 20,000 paired sessions.");System.out.println("Reference=STAND; alternate=HIT.");
    }


    // PHASE 3.189 — independent replication of frozen Candidate #5 architecture.
    static final long[] P189_SEEDS={232101L,232201L,232301L,232401L};
    static final String[] P189_COHORTS={"FRESH_DM","FRESH_DN","FRESH_DO","FRESH_DP"};

    public static void main3189(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne188(P189_SEEDS[c],P189_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_189_Candidate5_Hard12v4_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.189");
        System.out.println("CODE BUILD TAG: DBDE-3.189-CANDIDATE5-HARD12v4-INDEPENDENT-REPLICATION");
        System.out.println("Fresh DM/DN/DO/DP; 20,000 paired sessions.");
        System.out.println("Frozen reference=STAND; frozen alternate=HIT.");
    }


    // PHASE 3.190 — Candidate #5 fresh stability population.
    static final long[] P190_SEEDS={233101L,233201L,233301L,233401L};
    static final String[] P190_COHORTS={"FRESH_DQ","FRESH_DR","FRESH_DS","FRESH_DT"};

    public static void main3190(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne188(P190_SEEDS[c],P190_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_190_Candidate5_Hard12v4_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.190");
        System.out.println("CODE BUILD TAG: DBDE-3.190-CANDIDATE5-HARD12v4-STABILITY-POOLED");
        System.out.println("Fresh DQ/DR/DS/DT; 20,000 paired sessions.");
        System.out.println("Frozen reference=STAND; frozen alternate=HIT.");
    }


    // PHASE 3.191 — CANDIDATE #6: HARD 13 vs DEALER 2, STAND vs HIT.
    static final long[] P191_SEEDS={234101L,234201L,234301L,234401L};
    static final String[] P191_COHORTS={"FRESH_DU","FRESH_DV","FRESH_DW","FRESH_DX"};

    static Round188 playRound191(int[] shoe,int pointer,double availableBank,double wager,boolean hitAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==13&&dealer.c.get(0)==2
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.STAND;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&hitAlternate&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,dealer.c.get(0),false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne191(long seed,String cohort,int session,boolean hitAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound191(shoe,ptr,bank,wager,hitAlternate);
            if(rr.candidate){
                candidates++;
                if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}
            }

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=hitAlternate?"HIT_ALTERNATE":"STAND_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        return r;
    }

    public static void main3191(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne191(P191_SEEDS[c],P191_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_191_Candidate6_Hard13v2_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.191");
        System.out.println("CODE BUILD TAG: DBDE-3.191-CANDIDATE6-HARD13v2-STAND-v-HIT-DISCOVERY");
        System.out.println("Fresh DU/DV/DW/DX; 20,000 paired sessions.");
        System.out.println("Reference=STAND; alternate=HIT.");
    }


    // PHASE 3.192 — independent replication of Candidate #6 HARD13_vs2.
    static final long[] P192_SEEDS={235101L,235201L,235301L,235401L};
    static final String[] P192_COHORTS={"FRESH_DY","FRESH_DZ","FRESH_EA","FRESH_EB"};

    public static void main3192(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne191(P192_SEEDS[c],P192_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_192_Candidate6_Hard13v2_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.192");
        System.out.println("CODE BUILD TAG: DBDE-3.192-CANDIDATE6-HARD13v2-INDEPENDENT-REPLICATION");
        System.out.println("Fresh DY/DZ/EA/EB; 20,000 paired sessions.");
        System.out.println("Frozen reference=STAND; frozen alternate=HIT.");
    }


    // PHASE 3.193 — Candidate #6 fresh stability population.
    static final long[] P193_SEEDS={236101L,236201L,236301L,236401L};
    static final String[] P193_COHORTS={"FRESH_EC","FRESH_ED","FRESH_EE","FRESH_EF"};

    public static void main3193(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne191(P193_SEEDS[c],P193_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_193_Candidate6_Hard13v2_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.193");
        System.out.println("CODE BUILD TAG: DBDE-3.193-CANDIDATE6-HARD13v2-STABILITY-POOLED");
        System.out.println("Fresh EC/ED/EE/EF; 20,000 paired sessions.");
        System.out.println("Frozen reference=STAND; frozen alternate=HIT.");
    }


    // PHASE 3.194 — CANDIDATE #7: HARD 15 vs DEALER 10, HIT vs STAND.
    static final long[] P194_SEEDS={237101L,237201L,237301L,237401L};
    static final String[] P194_COHORTS={"FRESH_EG","FRESH_EH","FRESH_EI","FRESH_EJ"};

    static Round188 playRound194(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==15&&dealer.c.get(0)==10
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne194(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound194(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }

    public static void main3194(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne194(P194_SEEDS[c],P194_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_194_Candidate7_Hard15v10_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.194");
        System.out.println("CODE BUILD TAG: DBDE-3.194-CANDIDATE7-HARD15v10-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh EG/EH/EI/EJ; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.195 — Candidate #7 independent replication.
    static final long[] P195_SEEDS={238101L,238201L,238301L,238401L};
    static final String[] P195_COHORTS={"FRESH_EK","FRESH_EL","FRESH_EM","FRESH_EN"};

    public static void main3195(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne194(P195_SEEDS[c],P195_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_195_Candidate7_Hard15v10_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.195");
        System.out.println("CODE BUILD TAG: DBDE-3.195-CANDIDATE7-HARD15v10-INDEPENDENT-REPLICATION");
        System.out.println("Fresh EK/EL/EM/EN; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    static final long[] P196_SEEDS={239101L,239201L,239301L,239401L};
    static final String[] P196_COHORTS={"FRESH_EO","FRESH_EP","FRESH_EQ","FRESH_ER"};
    public static void main3196(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne194(P196_SEEDS[c],P196_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_196_Candidate7_Hard15v10_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.196");
        System.out.println("CODE BUILD TAG: DBDE-3.196-CANDIDATE7-HARD15v10-STABILITY-POOLED");
        System.out.println("Fresh EO/EP/EQ/ER; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    // PHASE 3.197 — CANDIDATE #8: HARD 16 vs DEALER 10, HIT vs STAND.
    static Round188 playRound197(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==16&&dealer.c.get(0)==10
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne197(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound197(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }


    static final long[] P197_SEEDS={240101L,240201L,240301L,240401L};
    static final String[] P197_COHORTS={"FRESH_ES","FRESH_ET","FRESH_EU","FRESH_EV"};

    public static void main3197(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne197(P197_SEEDS[c],P197_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_197_Candidate8_Hard16v10_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.197");
        System.out.println("CODE BUILD TAG: DBDE-3.197-CANDIDATE8-HARD16v10-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh ES/ET/EU/EV; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.198 — Candidate #8 independent replication.
    static final long[] P198_SEEDS={241101L,241201L,241301L,241401L};
    static final String[] P198_COHORTS={"FRESH_EW","FRESH_EX","FRESH_EY","FRESH_EZ"};

    public static void main3198(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne197(P198_SEEDS[c],P198_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_198_Candidate8_Hard16v10_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.198");
        System.out.println("CODE BUILD TAG: DBDE-3.198-CANDIDATE8-HARD16v10-INDEPENDENT-REPLICATION");
        System.out.println("Fresh EW/EX/EY/EZ; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    // PHASE 3.199 — Candidate #8 final fresh stability population.
    static final long[] P199_SEEDS={242101L,242201L,242301L,242401L};
    static final String[] P199_COHORTS={"FRESH_FA","FRESH_FB","FRESH_FC","FRESH_FD"};

    public static void main3199(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne197(P199_SEEDS[c],P199_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_199_Candidate8_Hard16v10_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.199");
        System.out.println("CODE BUILD TAG: DBDE-3.199-CANDIDATE8-HARD16v10-STABILITY-POOLED");
        System.out.println("Fresh FA/FB/FC/FD; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    // PHASE 3.200 — CANDIDATE #9: HARD 16 vs DEALER 9, HIT vs STAND.
    static Round188 playRound200(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==16&&dealer.c.get(0)==9
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne200(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound200(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }



    static final long[] P200_SEEDS={243101L,243201L,243301L,243401L};
    static final String[] P200_COHORTS={"FRESH_FE","FRESH_FF","FRESH_FG","FRESH_FH"};

    public static void main3200(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne200(P200_SEEDS[c],P200_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_200_Candidate9_Hard16v9_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.200");
        System.out.println("CODE BUILD TAG: DBDE-3.200-CANDIDATE9-HARD16v9-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh FE/FF/FG/FH; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.201 — predeclared independent replication of Candidate #9 HARD16_vs9.
    static final long[] P201_SEEDS={244101L,244201L,244301L,244401L};
    static final String[] P201_COHORTS={"FRESH_FI","FRESH_FJ","FRESH_FK","FRESH_FL"};

    public static void main3201(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne200(P201_SEEDS[c],P201_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_201_Candidate9_Hard16v9_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.201");
        System.out.println("CODE BUILD TAG: DBDE-3.201-CANDIDATE9-HARD16v9-INDEPENDENT-REPLICATION");
        System.out.println("Fresh FI/FJ/FK/FL; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    // PHASE 3.202 — Candidate #9 final fresh stability population.
    static final long[] P202_SEEDS={245101L,245201L,245301L,245401L};
    static final String[] P202_COHORTS={"FRESH_FM","FRESH_FN","FRESH_FO","FRESH_FP"};

    public static void main3202(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne200(P202_SEEDS[c],P202_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_202_Candidate9_Hard16v9_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.202");
        System.out.println("CODE BUILD TAG: DBDE-3.202-CANDIDATE9-HARD16v9-STABILITY-POOLED");
        System.out.println("Fresh FM/FN/FO/FP; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }

    static Round188 playRound203(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==15&&dealer.c.get(0)==9
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne203(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound203(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }




    static final long[] P203_SEEDS={246101L,246201L,246301L,246401L};
    static final String[] P203_COHORTS={"FRESH_FQ","FRESH_FR","FRESH_FS","FRESH_FT"};

    public static void main3203(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne203(P203_SEEDS[c],P203_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_203_Candidate10_Hard15v9_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.203");
        System.out.println("CODE BUILD TAG: DBDE-3.203-CANDIDATE10-HARD15v9-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh FQ/FR/FS/FT; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.204 — predeclared independent replication of Candidate #10 HARD15_vs9.
    static final long[] P204_SEEDS={247101L,247201L,247301L,247401L};
    static final String[] P204_COHORTS={"FRESH_FU","FRESH_FV","FRESH_FW","FRESH_FX"};

    public static void main3204(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne203(P204_SEEDS[c],P204_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_204_Candidate10_Hard15v9_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.204");
        System.out.println("CODE BUILD TAG: DBDE-3.204-CANDIDATE10-HARD15v9-INDEPENDENT-REPLICATION");
        System.out.println("Fresh FU/FV/FW/FX; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }


    static final long[] P205_SEEDS={248101L,248201L,248301L,248401L};
    static final String[] P205_COHORTS={"FRESH_FY","FRESH_FZ","FRESH_GA","FRESH_GB"};
    public static void main3205(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne203(P205_SEEDS[c],P205_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_205_Candidate10_Hard15v9_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.205");
        System.out.println("CODE BUILD TAG: DBDE-3.205-CANDIDATE10-HARD15v9-STABILITY-POOLED");
        System.out.println("Fresh FY/FZ/GA/GB; 20,000 paired sessions.");
    }

    static Round188 playRound206(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==14&&dealer.c.get(0)==9
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne206(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound206(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }





    static final long[] P206_SEEDS={249101L,249201L,249301L,249401L};
    static final String[] P206_COHORTS={"FRESH_GC","FRESH_GD","FRESH_GE","FRESH_GF"};
    public static void main3206(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne206(P206_SEEDS[c],P206_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_206_Candidate11_Hard14v9_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.206");
        System.out.println("CODE BUILD TAG: DBDE-3.206-CANDIDATE11-HARD14v9-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh GC/GD/GE/GF; 20,000 paired sessions.");
    }


 static final long[] P207_SEEDS={250101L,250201L,250301L,250401L};
 static final String[] P207_COHORTS={"FRESH_GG","FRESH_GH","FRESH_GI","FRESH_GJ"};
 public static void main3207(String[]args)throws Exception{
  StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
  for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
   Session188 x=runOne206(P207_SEEDS[c],P207_COHORTS[c],s,arm==1);
   csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
  }
  write("Phase_3_207_Candidate11_Hard14v9_Replication_Results.csv",csv.toString());
  System.out.println("Deterministic Blackjack Phase 3.207");
  System.out.println("CODE BUILD TAG: DBDE-3.207-CANDIDATE11-HARD14v9-INDEPENDENT-REPLICATION");
  System.out.println("Fresh GG/GH/GI/GJ; 20,000 paired sessions.");
 }


    // PHASE 3.208 — Candidate #11 final stability population.
    static final long[] P208_SEEDS={251101L,251201L,251301L,251401L};
    static final String[] P208_COHORTS={"FRESH_GK","FRESH_GL","FRESH_GM","FRESH_GN"};
    public static void main3208(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne206(P208_SEEDS[c],P208_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_208_Candidate11_Hard14v9_Stability_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.208");
        System.out.println("CODE BUILD TAG: DBDE-3.208-CANDIDATE11-HARD14v9-STABILITY-POOLED");
        System.out.println("Fresh GK/GL/GM/GN; 20,000 paired sessions.");
        System.out.println("Frozen reference=HIT; frozen alternate=STAND.");
    }

    static Round188 playRound209(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==13&&dealer.c.get(0)==9
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne209(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound209(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }






    // PHASE 3.209 — Candidate #12 discovery: HARD13 vs dealer 9.
    static final long[] P209_SEEDS={252101L,252201L,252301L,252401L};
    static final String[] P209_COHORTS={"FRESH_GO","FRESH_GP","FRESH_GQ","FRESH_GR"};
    public static void main3209(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne209(P209_SEEDS[c],P209_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_209_Candidate12_Hard13v9_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.209");
        System.out.println("CODE BUILD TAG: DBDE-3.209-CANDIDATE12-HARD13v9-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh GO/GP/GQ/GR; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.210 — Candidate #12 independent replication.
    static final long[] P210_SEEDS={253101L,253201L,253301L,253401L};
    static final String[] P210_COHORTS={"FRESH_GS","FRESH_GT","FRESH_GU","FRESH_GV"};
    public static void main3210(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne209(P210_SEEDS[c],P210_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_210_Candidate12_Hard13v9_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.210");
        System.out.println("CODE BUILD TAG: DBDE-3.210-CANDIDATE12-HARD13v9-INDEPENDENT-REPLICATION");
        System.out.println("Fresh GS/GT/GU/GV; 20,000 paired sessions.");
    }

    static Round188 playRound211(int[] shoe,int pointer,double availableBank,double wager,boolean standAlternate){
        int[] ptr={pointer}; Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean candidate=(!pair)&&(!initial.soft())&&initial.total()==12&&dealer.c.get(0)==9
                          &&selectiveFirst167(initial,dealer.c.get(0),false)==Action.HIT;

        ArrayList<Hand> hands=new ArrayList<>(); ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>(),splitChild=new ArrayList<>();
        boolean wantsSplit=pair;if(wantsSplit&&availableBank<2.0*wager-1e-9)wantsSplit=false;
        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));hands.add(a);hands.add(b);
            stakes.add(wager);stakes.add(wager);natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);}
        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if(candidate&&standAlternate&&!wantsSplit){
                // Alternate freezes the initial candidate action to STAND.
                // No card is drawn; round proceeds to dealer resolution.
                continue;
            }
            if(!h.blackjack()&&!dealer.blackjack())while(!h.bust()){
                Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i)):textbook(h,dealer.c.get(0),false));
                if(a==Action.STAND)break;
                if(a==Action.DOUBLE&&first){
                    if(availableBank<committed+wager){
                        Action fb=textbook(h,dealer.c.get(0),true);
                        if(fb==Action.DOUBLE)fb=Action.HIT;
                        if(fb==Action.STAND)break;
                        h.c.add(draw(shoe,ptr));first=false;continue;
                    }
                    stakes.set(i,stakes.get(i)*2.0);committed+=wager;h.c.add(draw(shoe,ptr));break;
                }
                h.c.add(draw(shoe,ptr));first=false;
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }
        Round188 r=new Round188();r.net=net;r.stake=stake;r.endPointer=ptr[0];r.candidate=candidate;
        if(candidate)r.candidateNet=net;
        return r;
    }

    static Session188 runOne211(long seed,String cohort,int session,boolean standAlternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,candidates=0,fch=0;
        double fcb=Double.NaN,fcw=Double.NaN,fcdd=Double.NaN,fcnet=Double.NaN;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int bal=bal355(hist,hc);boolean neg=bal<0;
                if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank,beforeDD=maxPeak-bank;
            Round188 rr=playRound211(shoe,ptr,bank,wager,standAlternate);
            if(rr.candidate){candidates++;if(fch==0){fch=hand;fcb=beforeBank;fcw=wager;fcdd=beforeDD;fcnet=rr.candidateNet;}}
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100.0,surr=Math.max(0,peak-bank);trigger=100.0*surr/profit>=25.0-1e-9;}
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session188 r=new Session188();r.cohort=cohort;r.session=session+1;
        r.arm=standAlternate?"STAND_ALTERNATE":"HIT_REFERENCE";r.hands=hc;r.candidates=candidates;r.firstCandidateHand=fch;
        r.firstCandidateBank=fcb;r.firstCandidateWager=fcw;r.firstCandidateDD=fcdd;r.firstCandidateNet=fcnet;
        r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;return r;
    }






    // PHASE 3.209 — Candidate #12 discovery: HARD13 vs dealer 9.

    // PHASE 3.211 — Candidate #13 discovery: HARD12 vs dealer 9.
    static final long[] P211_SEEDS={254101L,254201L,254301L,254401L};
    static final String[] P211_COHORTS={"FRESH_GW","FRESH_GX","FRESH_GY","FRESH_GZ"};
    public static void main3211(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne211(P211_SEEDS[c],P211_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_211_Candidate13_Hard12v9_Paired_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.211");
        System.out.println("CODE BUILD TAG: DBDE-3.211-CANDIDATE13-HARD12v9-HIT-v-STAND-DISCOVERY");
        System.out.println("Fresh GW/GX/GY/GZ; 20,000 paired sessions.");
        System.out.println("Reference=HIT; alternate=STAND.");
    }


    // PHASE 3.212 — Candidate #13 independent replication.
    static final long[] P212_SEEDS={255101L,255201L,255301L,255401L};
    static final String[] P212_COHORTS={"FRESH_HA","FRESH_HB","FRESH_HC","FRESH_HD"};
    public static void main3212(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder("cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,first_candidate_hand,first_candidate_bankroll,first_candidate_wager,first_candidate_drawdown,first_candidate_net\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<2;arm++){
            Session188 x=runOne211(P212_SEEDS[c],P212_COHORTS[c],s,arm==1);
            csv.append(String.format(Locale.US,"%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f%n",
                x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                x.candidates,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager,x.firstCandidateDD,x.firstCandidateNet));
        }
        write("Phase_3_212_Candidate13_Hard12v9_Replication_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.212");
        System.out.println("CODE BUILD TAG: DBDE-3.212-CANDIDATE13-HARD12v9-INDEPENDENT-REPLICATION");
        System.out.println("Fresh HA/HB/HC/HD; 20,000 paired sessions.");
    }


    static final int P214_BASELINE=0, P214_PAIR20_ONLY=1, P214_HYBRID_ONLY=2, P214_COMBINED=3;
    static final long[] P214_SEEDS={257101L,257201L,257301L,257401L};
    static final String[] P214_COHORTS={"FRESH_HI","FRESH_HJ","FRESH_HK","FRESH_HL"};

    static final class Round214{
        double net,stake; int endPointer;
        boolean pair20Eligible, hard11Eligible, hard11CoolingSwitch;
    }

    static Round214 playRound214(int[] shoe,int pointer,double availableBank,double wager,
                                 boolean pair20Stand, boolean hard11CoolingHybrid, boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        boolean pair20Candidate=pair && initial.total()==20 && dealer.c.get(0)==10;
        boolean pair20Eligible=pair20Candidate && splitAffordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&dealer.c.get(0)==10
                && selectiveFirst167(initial,dealer.c.get(0),false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate && splitAffordable;
        boolean hard11Switch=hard11CoolingHybrid && coolingBefore && hard11Eligible;

        boolean wantsSplit=pair;
        if(pair20Stand && pair20Eligible) wantsSplit=false;
        if(wantsSplit && !splitAffordable) wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if(pair20Stand && pair20Eligible && !wantsSplit){
                continue;
            }

            if(hard11Switch && !wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,dealer.c.get(0),false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,dealer.c.get(0),splitChild.get(i))
                                   :textbook(h,dealer.c.get(0),false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,dealer.c.get(0),true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round214 r=new Round214();
        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.pair20Eligible=pair20Eligible;
        r.hard11Eligible=hard11Eligible;
        r.hard11CoolingSwitch=hard11Switch;
        return r;
    }

    static final class Session214{
        String cohort,arm,firstCandidateType;
        int session,hands,pair20Events,hard11Events,hard11CoolingSwitches,firstCandidateHand;
        double finalBank,exposure,maxDD,firstCandidateBank,firstCandidateWager;
        boolean reached200,terminalZero,positive,touchedPair20,touchedHard11,touchedBoth;
    }

    static Session214 runOne214(long seed,String cohort,int session,int arm){
        boolean pair20Stand=(arm==P214_PAIR20_ONLY||arm==P214_COMBINED);
        boolean hard11Hybrid=(arm==P214_HYBRID_ONLY||arm==P214_COMBINED);

        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,p20=0,h11=0,hs=0,firstCandidateHand=0;
        double firstCandidateBank=Double.NaN,firstCandidateWager=Double.NaN;
        String firstCandidateType="NONE";
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double beforeBank=bank;
            boolean beforeCooling=cooling;
            Round214 rr=playRound214(shoe,ptr,bank,wager,pair20Stand,hard11Hybrid,beforeCooling);

            if(rr.pair20Eligible){
                p20++;
                if(firstCandidateHand==0){firstCandidateHand=hand;firstCandidateBank=beforeBank;firstCandidateWager=wager;firstCandidateType="PAIR20_vs10";}
            }
            if(rr.hard11Eligible){
                h11++;
                if(firstCandidateHand==0){firstCandidateHand=hand;firstCandidateBank=beforeBank;firstCandidateWager=wager;firstCandidateType="HARD11_vs10";}
            }
            if(rr.hard11CoolingSwitch)hs++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session214 r=new Session214();
        r.cohort=cohort;r.session=session+1;
        r.arm=arm==0?"A_BASELINE":arm==1?"B_PAIR20_STAND_ONLY":arm==2?"C_COOLING_HYBRID_ONLY":"D_COMBINED_POLICY";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.pair20Events=p20;r.hard11Events=h11;r.hard11CoolingSwitches=hs;
        r.touchedPair20=p20>0;r.touchedHard11=h11>0;r.touchedBoth=p20>0&&h11>0;
        r.firstCandidateHand=firstCandidateHand;r.firstCandidateBank=firstCandidateBank;r.firstCandidateWager=firstCandidateWager;r.firstCandidateType=firstCandidateType;
        return r;
    }

    public static void main3214Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,pair20_events,hard11_events,hard11_cooling_switches,touched_pair20,touched_hard11,touched_both,first_candidate_type,first_candidate_hand,first_candidate_bankroll,first_candidate_wager\n");
        for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++)for(int arm=0;arm<4;arm++){
            Session214 x=runOne214(P214_SEEDS[c],P214_COHORTS[c],s,arm);
            csv.append(String.format(Locale.US,
              "%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%d,%s,%s,%s,%s,%d,%.2f,%.2f%n",
              x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
              x.pair20Events,x.hard11Events,x.hard11CoolingSwitches,x.touchedPair20,x.touchedHard11,x.touchedBoth,
              x.firstCandidateType,x.firstCandidateHand,x.firstCandidateBank,x.firstCandidateWager));
        }
        write("Phase_3_214_Cross_Candidate_Factorial_Session_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.214");
        System.out.println("CODE BUILD TAG: DBDE-3.214-INDEPENDENT-CROSS-CANDIDATE-2x2-FACTORIAL-REPLICATION");
        System.out.println("Fresh HI/HJ/HK/HL; 20,000 paired session IDs; four predeclared arms.");
        System.out.println("A baseline; B Pair20 STAND only; C Hard11 Cooling hybrid only; D combined.");
    }


    // =======================================================================
    // PHASE 3.216 — PAIR-20 DEALER-UPCARD FRONTIER SCREEN
    // =======================================================================

    static final long[] P216_SEEDS={258101L,258201L,258301L,258401L};
    static final String[] P216_COHORTS={"FRESH_HM","FRESH_HN","FRESH_HO","FRESH_HP"};
    static final int[] P216_UPCARDS={2,3,4,5,6,7,8,9,11};

    static final class Round216{
        double net,stake;
        int endPointer;
        boolean screenEligible, screenChanged, frozenPair20v10, hard11CoolingSwitch;
        boolean playerNaturalBlackjack, dealerNaturalBlackjack;
    }

    static Round216 playRound216(int[] shoe,int pointer,double availableBank,double wager,
                                 int screenUpcard,boolean applyScreenAlternate,boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        int up=dealer.c.get(0);

        boolean pair20=pair && initial.total()==20;
        boolean frozenPair20v10=pair20 && up==10 && splitAffordable;
        boolean screenEligible=pair20 && up==screenUpcard && splitAffordable;
        boolean screenChanged=screenEligible && applyScreenAlternate;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                && selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate && splitAffordable;
        boolean hard11Switch=coolingBefore && hard11Eligible;

        boolean wantsSplit=pair;
        if(frozenPair20v10) wantsSplit=false;  // already frozen from Candidate #1
        if(screenChanged) wantsSplit=false;    // screened alternate
        if(wantsSplit && !splitAffordable) wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            // Both frozen PAIR20-v10 and the current PAIR20 screen alternate
            // are STAND decisions. No card is drawn.
            if((frozenPair20v10||screenChanged) && !wantsSplit) continue;

            // Frozen HARD11-v10 Cooling hybrid from 3.214.
            if(hard11Switch && !wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i))
                                   :textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round216 r=new Round216();
        r.playerNaturalBlackjack=initialPlayerNatural;
        r.dealerNaturalBlackjack=initialDealerNatural;
        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.screenEligible=screenEligible;r.screenChanged=screenChanged;
        r.frozenPair20v10=frozenPair20v10;r.hard11CoolingSwitch=hard11Switch;
        return r;
    }

    static final class Session216{
        String cohort,arm,candidate;
        int session,hands,candidateEvents,candidateChanges;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive,touchedCandidate;
    }

    static Session216 runOne216(long seed,String cohort,int session,int screenUpcard,boolean alternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,events=0,changes=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            boolean beforeCooling=cooling;
            Round216 rr=playRound216(shoe,ptr,bank,wager,screenUpcard,alternate,beforeCooling);
            if(rr.screenEligible)events++;
            if(rr.screenChanged)changes++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session216 r=new Session216();
        r.cohort=cohort;r.session=session+1;
        r.candidate="PAIR20_vs_"+(screenUpcard==11?"A":Integer.toString(screenUpcard));
        r.arm=alternate?"ALTERNATE_STAND":"FROZEN_REFERENCE_SPLIT";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.candidateEvents=events;r.candidateChanges=changes;r.touchedCandidate=events>0;
        return r;
    }

    public static void main3216Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int up:P216_UPCARDS){
            for(int c=0;c<4;c++){
                for(int s=0;s<SESSIONS;s++){
                    Session216 ref=runOne216(P216_SEEDS[c],P216_COHORTS[c],s,up,false);
                    Session216 alt=runOne216(P216_SEEDS[c],P216_COHORTS[c],s,up,true);
                    Session216[] arr={ref,alt};
                    for(Session216 x:arr){
                        csv.append(String.format(Locale.US,
                          "%s,%s,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                          x.candidate,(up==11?"A":Integer.toString(up)),x.cohort,x.session,x.arm,x.hands,
                          x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                          x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                    }
                }
            }
        }
        write("Phase_3_216_Pair20_Upcard_Frontier_Screen_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.216");
        System.out.println("CODE BUILD TAG: DBDE-3.216-PAIR20-UPCARD-FRONTIER-SCREEN");
        System.out.println("Fresh HM/HN/HO/HP.");
        System.out.println("PAIR20 dealer-upcard screen: 2,3,4,5,6,7,8,9,Ace.");
        System.out.println("20,000 paired session IDs per candidate; screening only; no promotion.");
    }


    // =======================================================================
    // PHASE 3.217 — ISOLATED CONFIRMATORY DISCOVERY: PAIR20 vs DEALER 8
    // =======================================================================

    static final long[] P217_SEEDS={259101L,259201L,259301L,259401L};
    static final String[] P217_COHORTS={"FRESH_HQ","FRESH_HR","FRESH_HS","FRESH_HT"};
    static final int P217_UPCARD=8;

    public static void main3217Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int c=0;c<4;c++){
            for(int s=0;s<SESSIONS;s++){
                Session216 ref=runOne216(P217_SEEDS[c],P217_COHORTS[c],s,P217_UPCARD,false);
                Session216 alt=runOne216(P217_SEEDS[c],P217_COHORTS[c],s,P217_UPCARD,true);
                Session216[] arr={ref,alt};
                for(Session216 x:arr){
                    csv.append(String.format(Locale.US,
                      "%s,%s,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                      x.candidate,"8",x.cohort,x.session,x.arm,x.hands,
                      x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                      x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                }
            }
        }

        write("Phase_3_217_Pair20v8_Isolated_Session_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.217");
        System.out.println("CODE BUILD TAG: DBDE-3.217-PAIR20V8-ISOLATED-CONFIRMATORY");
        System.out.println("Candidate: PAIR20 vs dealer 8.");
        System.out.println("Reference SPLIT vs challenger STAND.");
        System.out.println("Fresh HQ/HR/HS/HT.");
        System.out.println("20,000 paired session IDs / 40,000 arm executions.");
    }


    // =======================================================================
    // PHASE 3.218 — INDEPENDENT REPLICATION: PAIR20 vs DEALER 8
    // =======================================================================

    static final long[] P218_SEEDS={260101L,260201L,260301L,260401L};
    static final String[] P218_COHORTS={"FRESH_HU","FRESH_HV","FRESH_HW","FRESH_HX"};
    static final int P218_UPCARD=8;

    public static void main3218Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int c=0;c<4;c++){
            for(int s=0;s<SESSIONS;s++){
                Session216 ref=runOne216(P218_SEEDS[c],P218_COHORTS[c],s,P218_UPCARD,false);
                Session216 alt=runOne216(P218_SEEDS[c],P218_COHORTS[c],s,P218_UPCARD,true);
                Session216[] arr={ref,alt};
                for(Session216 x:arr){
                    csv.append(String.format(Locale.US,
                      "%s,%s,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                      x.candidate,"8",x.cohort,x.session,x.arm,x.hands,
                      x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                      x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                }
            }
        }

        write("Phase_3_218_Pair20v8_Replication_Session_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.218");
        System.out.println("CODE BUILD TAG: DBDE-3.218-PAIR20V8-INDEPENDENT-REPLICATION");
        System.out.println("Candidate: PAIR20 vs dealer 8.");
        System.out.println("Reference SPLIT vs challenger STAND.");
        System.out.println("Fresh HU/HV/HW/HX.");
        System.out.println("20,000 paired session IDs / 40,000 arm executions.");
    }


    // =======================================================================
    // PHASE 3.219 — CONTROLLED THIRD-RULE COMBINATION TEST
    // =======================================================================

    static final long[] P219_SEEDS={261101L,261201L,261301L,261401L};
    static final String[] P219_COHORTS={"FRESH_HY","FRESH_HZ","FRESH_IA","FRESH_IB"};
    static final int P219_SESSIONS_PER_COHORT=10000;
    static final int P219_UPCARD=8;

    static final class Session219{
        String cohort,arm;
        int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive;
        int pair20v8Events,pair20v8Changes;
        int pair20v10Events,hard11CoolingSwitches;
        boolean touchedPair20v8,touchedPair20v10,touchedCooling,touchedAnyFrozen,touchedBothPair20States;
    }

    static Session219 runOne219(long seed,String cohort,int session,boolean addPair20v8Stand){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        int v8Events=0,v8Changes=0,v10Events=0,coolingSwitches=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            boolean beforeCooling=cooling;
            Round216 rr=playRound216(shoe,ptr,bank,wager,P219_UPCARD,addPair20v8Stand,beforeCooling);

            if(rr.screenEligible)v8Events++;
            if(rr.screenChanged)v8Changes++;
            if(rr.frozenPair20v10)v10Events++;
            if(rr.hard11CoolingSwitch)coolingSwitches++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session219 r=new Session219();
        r.cohort=cohort;r.session=session+1;
        r.arm=addPair20v8Stand?"THREE_RULE_CHALLENGER":"TWO_RULE_FROZEN_REFERENCE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.pair20v8Events=v8Events;r.pair20v8Changes=v8Changes;
        r.pair20v10Events=v10Events;r.hard11CoolingSwitches=coolingSwitches;
        r.touchedPair20v8=v8Events>0;r.touchedPair20v10=v10Events>0;r.touchedCooling=coolingSwitches>0;
        r.touchedAnyFrozen=r.touchedPair20v10||r.touchedCooling;
        r.touchedBothPair20States=r.touchedPair20v8&&r.touchedPair20v10;
        return r;
    }

    public static void main3219Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "pair20v8_events,pair20v8_changes,pair20v10_events,hard11_cooling_switches,"+
          "touched_pair20v8,touched_pair20v10,touched_cooling,touched_any_frozen,touched_both_pair20_states\n");

        for(int c=0;c<4;c++){
            for(int s=0;s<P219_SESSIONS_PER_COHORT;s++){
                Session219 ref=runOne219(P219_SEEDS[c],P219_COHORTS[c],s,false);
                Session219 alt=runOne219(P219_SEEDS[c],P219_COHORTS[c],s,true);
                Session219[] arr={ref,alt};
                for(Session219 x:arr){
                    csv.append(String.format(Locale.US,
                      "%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%d,%d,%s,%s,%s,%s,%s%n",
                      x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                      x.reached200,x.terminalZero,x.positive,
                      x.pair20v8Events,x.pair20v8Changes,x.pair20v10Events,x.hard11CoolingSwitches,
                      x.touchedPair20v8,x.touchedPair20v10,x.touchedCooling,x.touchedAnyFrozen,x.touchedBothPair20States));
                }
            }
        }

        write("Phase_3_219_Architecture_Combination_Session_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.219");
        System.out.println("CODE BUILD TAG: DBDE-3.219-PAIR20V8-CONTROLLED-COMBINATION-40K");
        System.out.println("Fresh HY/HZ/IA/IB.");
        System.out.println("40,000 paired session IDs / 80,000 arm executions.");
        System.out.println("Reference: frozen two-rule architecture.");
        System.out.println("Challenger: reference + PAIR20-v8 STAND.");
    }


    // =======================================================================
    // PHASE 3.220 — THREE-RULE ARCHITECTURE QUANTIFICATION / STABILITY AUDIT
    // =======================================================================

    static final long[] P220_SEEDS={262101L,262201L,262301L,262401L};
    static final String[] P220_COHORTS={"FRESH_IC","FRESH_ID","FRESH_IE","FRESH_IF"};
    static final int P220_SESSIONS_PER_COHORT=20000;

    public static void main3220Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "pair20v8_events,pair20v8_changes,pair20v10_events,hard11_cooling_switches,"+
          "touched_pair20v8,touched_pair20v10,touched_cooling,touched_any_frozen,touched_both_pair20_states\n");

        for(int c=0;c<4;c++){
            for(int s=0;s<P220_SESSIONS_PER_COHORT;s++){
                Session219 x=runOne219(P220_SEEDS[c],P220_COHORTS[c],s,true);
                csv.append(String.format(Locale.US,
                  "%s,%d,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%d,%d,%s,%s,%s,%s,%s%n",
                  x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,
                  x.reached200,x.terminalZero,x.positive,
                  x.pair20v8Events,x.pair20v8Changes,x.pair20v10Events,x.hard11CoolingSwitches,
                  x.touchedPair20v8,x.touchedPair20v10,x.touchedCooling,x.touchedAnyFrozen,x.touchedBothPair20States));
            }
        }

        write("Phase_3_220_Three_Rule_Architecture_Session_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.220");
        System.out.println("CODE BUILD TAG: DBDE-3.220-THREE-RULE-ARCHITECTURE-QUANTIFICATION");
        System.out.println("Fresh IC/ID/IE/IF.");
        System.out.println("80,000 total three-rule architecture sessions.");
        System.out.println("Measurement/stability phase only; no policy change.");
    }


    // =======================================================================
    // PHASE 3.221 — HARD-TOTAL RESIDUAL-LOSS FRONTIER SCREEN
    // =======================================================================

    static final long[] P221_SEEDS={263101L,263201L,263301L,263401L};
    static final String[] P221_COHORTS={"FRESH_IG","FRESH_IH","FRESH_II","FRESH_IJ"};

    // {player hard total, dealer upcard}
    static final int[][] P221_CANDIDATES={
        {9,2},{9,7},{9,8},{10,10},{10,11},{11,11}
    };

    static final class Round221{
        double net,stake;
        int endPointer;
        boolean candidateEligible,candidateChanged;
        boolean pair20v8,pair20v10,hard11CoolingSwitch;
    }

    static Round221 playRound221(int[] shoe,int pointer,double availableBank,double wager,
                                 int candTotal,int candUp,boolean applyAlternate,
                                 boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        int up=dealer.c.get(0);

        boolean pair20=pair && initial.total()==20;
        boolean frozenPair20v10=pair20 && up==10 && splitAffordable;
        boolean frozenPair20v8=pair20 && up==8 && splitAffordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                && selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate && splitAffordable;
        boolean hard11Switch=coolingBefore && hard11Eligible;

        boolean candidateState=(!pair)&&(!initial.soft())&&initial.total()==candTotal&&up==candUp
                && selectiveFirst167(initial,up,false)==Action.DOUBLE
                && textbook(initial,up,true)==Action.HIT;
        // Require affordability so the reference arm really executes DOUBLE.
        boolean candidateEligible=candidateState && splitAffordable;
        boolean candidateChanged=candidateEligible && applyAlternate;

        boolean wantsSplit=pair;
        if(frozenPair20v10||frozenPair20v8)wantsSplit=false;
        if(wantsSplit&&!splitAffordable)wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if((frozenPair20v10||frozenPair20v8)&&!wantsSplit)continue;

            if(hard11Switch&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            // Screen alternate: replace the initial DOUBLE with textbook HIT.
            if(candidateChanged&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i))
                                   :textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round221 r=new Round221();
        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.candidateEligible=candidateEligible;r.candidateChanged=candidateChanged;
        r.pair20v8=frozenPair20v8;r.pair20v10=frozenPair20v10;r.hard11CoolingSwitch=hard11Switch;
        return r;
    }

    static final class Session221{
        String candidate,cohort,arm;
        int session,hands,candidateEvents,candidateChanges;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive,touchedCandidate;
    }

    static Session221 runOne221(long seed,String cohort,int session,
                                int candTotal,int candUp,boolean alternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,events=0,changes=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round221 rr=playRound221(shoe,ptr,bank,wager,candTotal,candUp,alternate,cooling);
            if(rr.candidateEligible)events++;
            if(rr.candidateChanged)changes++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session221 r=new Session221();
        r.candidate="HARD"+candTotal+"_vs_"+(candUp==11?"A":Integer.toString(candUp));
        r.cohort=cohort;r.session=session+1;r.arm=alternate?"ALTERNATE_HIT":"FROZEN_REFERENCE_DOUBLE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.candidateEvents=events;r.candidateChanges=changes;r.touchedCandidate=events>0;
        return r;
    }

    public static void main3221Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,player_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
          "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int[] cand:P221_CANDIDATES){
            int total=cand[0],up=cand[1];
            for(int c=0;c<4;c++){
                for(int s=0;s<SESSIONS;s++){
                    Session221 ref=runOne221(P221_SEEDS[c],P221_COHORTS[c],s,total,up,false);
                    Session221 alt=runOne221(P221_SEEDS[c],P221_COHORTS[c],s,total,up,true);
                    Session221[] arr={ref,alt};
                    for(Session221 x:arr){
                        csv.append(String.format(Locale.US,
                          "%s,%d,%s,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                          x.candidate,total,(up==11?"A":Integer.toString(up)),x.cohort,x.session,x.arm,x.hands,
                          x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                          x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                    }
                }
            }
        }

        write("Phase_3_221_Hard_Total_Frontier_Screen_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.221");
        System.out.println("CODE BUILD TAG: DBDE-3.221-HARD-TOTAL-RESIDUAL-FRONTIER-SCREEN");
        System.out.println("Fresh IG/IH/II/IJ.");
        System.out.println("6 hard-total residual DOUBLE->HIT candidates.");
        System.out.println("20,000 paired session IDs per candidate; 240,000 arm executions.");
        System.out.println("Screen only; no promotion.");
    }


    // =======================================================================
    // PHASE 3.222 — ISOLATED CONFIRMATION: HARD9 vs DEALER 8
    // =======================================================================

    static final long[] P222_INITIAL_SEEDS={264101L,264201L,264301L,264401L};
    static final String[] P222_INITIAL_COHORTS={"FRESH_IK","FRESH_IL","FRESH_IM","FRESH_IN"};
    static final long[] P222_EXTENSION_SEEDS={264501L,264601L,264701L,264801L};
    static final String[] P222_EXTENSION_COHORTS={"FRESH_IO","FRESH_IP","FRESH_IQ","FRESH_IR"};
    static final int P222_SESSIONS_PER_COHORT=10000;
    static final int P222_TOTAL=9;
    static final int P222_UP=8;

    static void append222(StringBuilder csv,long seed,String cohort){
        for(int s=0;s<P222_SESSIONS_PER_COHORT;s++){
            Session221 ref=runOne221(seed,cohort,s,P222_TOTAL,P222_UP,false);
            Session221 alt=runOne221(seed,cohort,s,P222_TOTAL,P222_UP,true);
            Session221[] arr={ref,alt};
            for(Session221 x:arr){
                csv.append(String.format(Locale.US,
                  "%s,%d,%s,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                  x.candidate,P222_TOTAL,"8",x.cohort,x.session,x.arm,x.hands,
                  x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                  x.candidateEvents,x.candidateChanges,x.touchedCandidate));
            }
        }
    }

    public static void main3222Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,player_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
          "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int c=0;c<4;c++)append222(csv,P222_INITIAL_SEEDS[c],P222_INITIAL_COHORTS[c]);

        write("Phase_3_222_Hard9v8_Initial_40k_Session_Results.csv",csv.toString());

        // The Python evidence audit applies the predeclared escalation rule.
        // The extension population is generated as a separate frozen ledger so
        // that it can be used only if the initial 40k result meets that rule.
        StringBuilder ext=new StringBuilder(
          "candidate,player_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
          "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");
        for(int c=0;c<4;c++)append222(ext,P222_EXTENSION_SEEDS[c],P222_EXTENSION_COHORTS[c]);
        write("Phase_3_222_Hard9v8_Extension_40k_Session_Results.csv",ext.toString());

        System.out.println("Deterministic Blackjack Phase 3.222");
        System.out.println("CODE BUILD TAG: DBDE-3.222-HARD9V8-ISOLATED-CONFIRMATION-ADAPTIVE-DEPTH");
        System.out.println("Candidate: HARD9 vs dealer 8, DOUBLE vs HIT.");
        System.out.println("Initial 40,000 paired IDs generated.");
        System.out.println("Independent predeclared 40,000-pair extension ledger generated.");
        System.out.println("Extension may be incorporated only if the frozen escalation rule is met.");
    }


    // =======================================================================
    // PHASE 3.223 — SOFT 18/19 RESIDUAL OVER-DOUBLE FRONTIER SCREEN
    // =======================================================================

    static final long[] P223_SEEDS={265101L,265201L,265301L,265401L};
    static final String[] P223_COHORTS={"FRESH_IS","FRESH_IT","FRESH_IU","FRESH_IV"};

    // {soft total, dealer upcard}
    static final int[][] P223_CANDIDATES={
        {18,2},{18,7},{18,8},
        {19,2},{19,3},{19,4},{19,5},{19,6},{19,7},{19,8}
    };

    static final class Round223{
        double net,stake;
        int endPointer;
        boolean candidateEligible,candidateChanged;
    }

    static Round223 playRound223(int[] shoe,int pointer,double availableBank,double wager,
                                 int candTotal,int candUp,boolean applyAlternate,
                                 boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        int up=dealer.c.get(0);

        boolean pair20=pair && initial.total()==20;
        boolean frozenPair20v10=pair20 && up==10 && splitAffordable;
        boolean frozenPair20v8=pair20 && up==8 && splitAffordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                && selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate && splitAffordable;
        boolean hard11Switch=coolingBefore && hard11Eligible;

        boolean candidateState=(!pair)&&initial.soft()&&initial.total()==candTotal&&up==candUp
                && selectiveFirst167(initial,up,false)==Action.DOUBLE
                && textbook(initial,up,true)==Action.STAND;
        boolean candidateEligible=candidateState && splitAffordable;
        boolean candidateChanged=candidateEligible && applyAlternate;

        boolean wantsSplit=pair;
        if(frozenPair20v10||frozenPair20v8)wantsSplit=false;
        if(wantsSplit&&!splitAffordable)wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if((frozenPair20v10||frozenPair20v8)&&!wantsSplit)continue;

            if(hard11Switch&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            // Screen alternate: STAND immediately instead of selective DOUBLE.
            if(candidateChanged&&!wantsSplit)continue;

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i))
                                   :textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round223 r=new Round223();
        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.candidateEligible=candidateEligible;r.candidateChanged=candidateChanged;
        return r;
    }

    static final class Session223{
        String candidate,cohort,arm;
        int session,hands,candidateEvents,candidateChanges;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive,touchedCandidate;
    }

    static Session223 runOne223(long seed,String cohort,int session,
                                int candTotal,int candUp,boolean alternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,events=0,changes=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round223 rr=playRound223(shoe,ptr,bank,wager,candTotal,candUp,alternate,cooling);
            if(rr.candidateEligible)events++;
            if(rr.candidateChanged)changes++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        Session223 r=new Session223();
        r.candidate="SOFT"+candTotal+"_vs_"+Integer.toString(candUp);
        r.cohort=cohort;r.session=session+1;
        r.arm=alternate?"ALTERNATE_STAND":"FROZEN_REFERENCE_DOUBLE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.candidateEvents=events;r.candidateChanges=changes;r.touchedCandidate=events>0;
        return r;
    }

    public static void main3223Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,soft_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
          "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int[] cand:P223_CANDIDATES){
            int total=cand[0],up=cand[1];
            for(int c=0;c<4;c++){
                for(int s=0;s<SESSIONS;s++){
                    Session223 ref=runOne223(P223_SEEDS[c],P223_COHORTS[c],s,total,up,false);
                    Session223 alt=runOne223(P223_SEEDS[c],P223_COHORTS[c],s,total,up,true);
                    Session223[] arr={ref,alt};
                    for(Session223 x:arr){
                        csv.append(String.format(Locale.US,
                          "%s,%d,%d,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                          x.candidate,total,up,x.cohort,x.session,x.arm,x.hands,
                          x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                          x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                    }
                }
            }
        }

        write("Phase_3_223_Soft18_19_Frontier_Screen_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.223");
        System.out.println("CODE BUILD TAG: DBDE-3.223-SOFT18-19-OVERDOUBLE-FRONTIER-SCREEN");
        System.out.println("Fresh IS/IT/IU/IV.");
        System.out.println("10 soft-total DOUBLE->STAND candidates.");
        System.out.println("20,000 paired session IDs per candidate / 400,000 arm executions.");
        System.out.println("Screen only; no promotion.");
    }


    // =======================================================================
    // PHASE 3.224 — ISOLATED CONFIRMATION: SOFT19 vs DEALER 3
    // =======================================================================

    static final long[] P224_INITIAL_SEEDS={266101L,266201L,266301L,266401L};
    static final String[] P224_INITIAL_COHORTS={"FRESH_IW","FRESH_IX","FRESH_IY","FRESH_IZ"};
    static final long[] P224_EXTENSION_SEEDS={266501L,266601L,266701L,266801L};
    static final String[] P224_EXTENSION_COHORTS={"FRESH_JA","FRESH_JB","FRESH_JC","FRESH_JD"};
    static final int P224_SESSIONS_PER_COHORT=10000;
    static final int P224_TOTAL=19;
    static final int P224_UP=3;

    static void append224(StringBuilder csv,long seed,String cohort){
        for(int s=0;s<P224_SESSIONS_PER_COHORT;s++){
            Session223 ref=runOne223(seed,cohort,s,P224_TOTAL,P224_UP,false);
            Session223 alt=runOne223(seed,cohort,s,P224_TOTAL,P224_UP,true);
            Session223[] arr={ref,alt};
            for(Session223 x:arr){
                csv.append(String.format(Locale.US,
                  "%s,%d,%d,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                  x.candidate,P224_TOTAL,P224_UP,x.cohort,x.session,x.arm,x.hands,
                  x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                  x.candidateEvents,x.candidateChanges,x.touchedCandidate));
            }
        }
    }

    public static void main3224Archive(String[]args)throws Exception{
        String header="candidate,soft_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
                      "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n";

        StringBuilder initial=new StringBuilder(header);
        for(int c=0;c<4;c++)append224(initial,P224_INITIAL_SEEDS[c],P224_INITIAL_COHORTS[c]);
        write("Phase_3_224_Soft19v3_Initial_40k_Session_Results.csv",initial.toString());

        StringBuilder extension=new StringBuilder(header);
        for(int c=0;c<4;c++)append224(extension,P224_EXTENSION_SEEDS[c],P224_EXTENSION_COHORTS[c]);
        write("Phase_3_224_Soft19v3_Extension_40k_Session_Results.csv",extension.toString());

        System.out.println("Deterministic Blackjack Phase 3.224");
        System.out.println("CODE BUILD TAG: DBDE-3.224-SOFT19V3-ISOLATED-CONFIRMATION-ADAPTIVE-DEPTH");
        System.out.println("Candidate: SOFT19 vs dealer 3, DOUBLE vs STAND.");
        System.out.println("Initial 40,000 paired IDs generated.");
        System.out.println("Independent predeclared 40,000-pair extension ledger generated.");
        System.out.println("Extension may be incorporated only if the frozen escalation rule is met.");
    }


    // =======================================================================
    // PHASE 3.225 — SOFT 16/17 RESIDUAL OVER-DOUBLE FRONTIER SCREEN
    // =======================================================================

    static final long[] P225_SEEDS={267101L,267201L,267301L,267401L};
    static final String[] P225_COHORTS={"FRESH_JE","FRESH_JF","FRESH_JG","FRESH_JH"};
    static final int[][] P225_CANDIDATES={{16,2},{16,3},{17,2}};

    static final class Round225{
        double net,stake;
        int endPointer;
        boolean candidateEligible,candidateChanged;
    }

    static Round225 playRound225(int[] shoe,int pointer,double availableBank,double wager,
                                 int candTotal,int candUp,boolean applyAlternate,
                                 boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        int up=dealer.c.get(0);

        boolean pair20=pair&&initial.total()==20;
        boolean frozenPair20v10=pair20&&up==10&&splitAffordable;
        boolean frozenPair20v8=pair20&&up==8&&splitAffordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                &&selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate&&splitAffordable;
        boolean hard11Switch=coolingBefore&&hard11Eligible;

        boolean candidateState=(!pair)&&initial.soft()&&initial.total()==candTotal&&up==candUp
                &&selectiveFirst167(initial,up,false)==Action.DOUBLE
                &&textbook(initial,up,true)==Action.HIT;
        boolean candidateEligible=candidateState&&splitAffordable;
        boolean candidateChanged=candidateEligible&&applyAlternate;

        boolean wantsSplit=pair;
        if(frozenPair20v10||frozenPair20v8)wantsSplit=false;
        if(wantsSplit&&!splitAffordable)wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if((frozenPair20v10||frozenPair20v8)&&!wantsSplit)continue;

            if(hard11Switch&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            // Screen alternate: replace initial DOUBLE with textbook HIT.
            if(candidateChanged&&!wantsSplit){
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i))
                                   :textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust())x=-st;
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            net+=x;
        }

        Round225 r=new Round225();
        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.candidateEligible=candidateEligible;r.candidateChanged=candidateChanged;
        return r;
    }

    static final class Session225{
        String candidate,cohort,arm;
        int session,hands,candidateEvents,candidateChanges;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive,touchedCandidate;
    }

    static Session225 runOne225(long seed,String cohort,int session,
                                int candTotal,int candUp,boolean alternate){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1,events=0,changes=0;
        boolean reached200=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round225 rr=playRound225(shoe,ptr,bank,wager,candTotal,candUp,alternate,cooling);
            if(rr.candidateEligible)events++;
            if(rr.candidateChanged)changes++;

            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        Session225 r=new Session225();
        r.candidate="SOFT"+candTotal+"_vs_"+candUp;
        r.cohort=cohort;r.session=session+1;
        r.arm=alternate?"ALTERNATE_HIT":"FROZEN_REFERENCE_DOUBLE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.candidateEvents=events;r.candidateChanges=changes;r.touchedCandidate=events>0;
        return r;
    }

    public static void main3225Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "candidate,soft_total,dealer_up,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,"+
          "reached200,terminal_zero,positive,candidate_events,candidate_changes,touched_candidate\n");

        for(int[] cand:P225_CANDIDATES){
            int total=cand[0],up=cand[1];
            for(int c=0;c<4;c++){
                for(int s=0;s<SESSIONS;s++){
                    Session225 ref=runOne225(P225_SEEDS[c],P225_COHORTS[c],s,total,up,false);
                    Session225 alt=runOne225(P225_SEEDS[c],P225_COHORTS[c],s,total,up,true);
                    Session225[] arr={ref,alt};
                    for(Session225 x:arr){
                        csv.append(String.format(Locale.US,
                          "%s,%d,%d,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%d,%s%n",
                          x.candidate,total,up,x.cohort,x.session,x.arm,x.hands,
                          x.finalBank,x.exposure,x.maxDD,x.reached200,x.terminalZero,x.positive,
                          x.candidateEvents,x.candidateChanges,x.touchedCandidate));
                    }
                }
            }
        }

        write("Phase_3_225_Soft16_17_Frontier_Screen_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.225");
        System.out.println("CODE BUILD TAG: DBDE-3.225-SOFT16-17-OVERDOUBLE-FRONTIER-SCREEN");
        System.out.println("Fresh JE/JF/JG/JH.");
        System.out.println("3 SOFT16/17 DOUBLE->HIT candidates.");
        System.out.println("20,000 paired IDs per candidate / 120,000 arm executions.");
        System.out.println("Screen only; no promotion.");
    }


    // =======================================================================
    // PHASE 3.226 — RESIDUAL EDGE DECOMPOSITION
    // =======================================================================

    static final long[] P226_SEEDS={268101L,268201L,268301L,268401L};
    static final String[] P226_COHORTS={"FRESH_JI","FRESH_JJ","FRESH_JK","FRESH_JL"};
    static final int P226_SESSIONS_PER_COHORT=20000;
    static final String[] P226_BANDS={"B0_LT100","B1_100_119","B2_120_139","B3_140_159","B4_160_179","B5_180_PLUS"};
    static final String[] P226_STATES={"COOLING","CAUTIOUS","NORMAL_AGGRESSIVE"};

    static int band226(double bank){
        if(bank<100.0-1e-9)return 0;
        if(bank<120.0-1e-9)return 1;
        if(bank<140.0-1e-9)return 2;
        if(bank<160.0-1e-9)return 3;
        if(bank<180.0-1e-9)return 4;
        return 5;
    }

    static final class Session226{
        String cohort;
        int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive;
        double[] bandExposure=new double[6];
        double[] bandNet=new double[6];
        int[] bandHands=new int[6];
        int[] bandEntries=new int[6];
        boolean[] bandTouched=new boolean[6];
        double[] bandMaxAfterTouch=new double[6];
        boolean[] bandZeroAfterTouch=new boolean[6];
        double[] stateExposure=new double[3];
        double[] stateNet=new double[3];
        int[] stateHands=new int[3];
        int[] stateEntries=new int[3];
    }

    static Session226 runOne226(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        boolean reached200=false;
        int prevBand=-1,prevState=-1;

        Session226 r=new Session226();
        r.cohort=cohort;r.session=session+1;
        Arrays.fill(r.bandMaxAfterTouch,-1.0);

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            int band=band226(bank);
            int state=cooling?0:(cautious?1:2);

            if(band!=prevBand){r.bandEntries[band]++;prevBand=band;}
            if(state!=prevState){r.stateEntries[state]++;prevState=state;}
            r.bandTouched[band]=true;
            if(r.bandMaxAfterTouch[band]<0)r.bandMaxAfterTouch[band]=bank;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);

            ptr=rr.endPointer;
            cum+=rr.stake;
            bank+=rr.net;if(bank<0)bank=0;

            r.bandExposure[band]+=rr.stake;
            r.bandNet[band]+=rr.net;
            r.bandHands[band]++;
            r.stateExposure[state]+=rr.stake;
            r.stateNet[state]+=rr.net;
            r.stateHands[state]++;

            for(int b=0;b<6;b++){
                if(r.bandTouched[b]){
                    r.bandMaxAfterTouch[b]=Math.max(r.bandMaxAfterTouch[b],bank);
                    if(bank<=1e-9)r.bandZeroAfterTouch[b]=true;
                }
            }

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        return r;
    }

    public static void main3226Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder();
        csv.append("cohort,session,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive");
        for(String b:P226_BANDS){
            csv.append(",").append(b).append("_exposure");
            csv.append(",").append(b).append("_net");
            csv.append(",").append(b).append("_hands");
            csv.append(",").append(b).append("_entries");
            csv.append(",").append(b).append("_touched");
            csv.append(",").append(b).append("_max_after_touch");
            csv.append(",").append(b).append("_zero_after_touch");
        }
        for(String s:P226_STATES){
            csv.append(",").append(s).append("_exposure");
            csv.append(",").append(s).append("_net");
            csv.append(",").append(s).append("_hands");
            csv.append(",").append(s).append("_entries");
        }
        csv.append("\n");

        for(int c=0;c<4;c++){
            for(int s=0;s<P226_SESSIONS_PER_COHORT;s++){
                Session226 x=runOne226(P226_SEEDS[c],P226_COHORTS[c],s);
                csv.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f,%s,%s,%s",
                    x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,
                    x.reached200,x.terminalZero,x.positive));
                for(int b=0;b<6;b++){
                    csv.append(String.format(Locale.US,",%.2f,%.2f,%d,%d,%s,%.2f,%s",
                        x.bandExposure[b],x.bandNet[b],x.bandHands[b],x.bandEntries[b],
                        x.bandTouched[b],x.bandMaxAfterTouch[b],x.bandZeroAfterTouch[b]));
                }
                for(int st=0;st<3;st++){
                    csv.append(String.format(Locale.US,",%.2f,%.2f,%d,%d",
                        x.stateExposure[st],x.stateNet[st],x.stateHands[st],x.stateEntries[st]));
                }
                csv.append("\n");
            }
        }

        write("Phase_3_226_Residual_Edge_Decomposition_Session_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.226");
        System.out.println("CODE BUILD TAG: DBDE-3.226-RESIDUAL-EDGE-DECOMPOSITION-80K");
        System.out.println("Fresh JI/JJ/JK/JL.");
        System.out.println("80,000 frozen three-rule architecture sessions.");
        System.out.println("No policy intervention; residual edge decomposition only.");
    }


    // =======================================================================
    // PHASE 3.227 — BELOW-£100 RECOVERY EXPOSURE-CAP SCREEN
    // =======================================================================

    static final long[] P227_SEEDS={269101L,269201L,269301L,269401L};
    static final String[] P227_COHORTS={"FRESH_JM","FRESH_JN","FRESH_JO","FRESH_JP"};
    static final double[] P227_CAPS={30.0,45.0,60.0};

    static final class Session227{
        String cohort,arm;
        int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive;
        boolean everBelow100,recoveredAfterBelow100,capTriggered;
        int below100Episodes;
        double below100Exposure,totalBelow100Exposure;
    }

    static Session227 runOne227(long seed,String cohort,int session,double cap,boolean useCap){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        boolean reached200=false;

        boolean inBelow100=false,everBelow100=false,recovered=false,capTriggered=false;
        int belowEpisodes=0;
        double episodeExposure=0,totalBelowExposure=0;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;

            if(inBelow100 && bank>=100.0-1e-9){
                inBelow100=false;
                recovered=true;
                episodeExposure=0;
            }
            if(!inBelow100 && bank<100.0-1e-9){
                inBelow100=true;
                everBelow100=true;
                belowEpisodes++;
                episodeExposure=0;
            }

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            if(useCap && inBelow100 && episodeExposure>=cap-1e-9){
                capTriggered=true;
                break;
            }

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);

            ptr=rr.endPointer;
            cum+=rr.stake;
            if(inBelow100){
                episodeExposure+=rr.stake;
                totalBelowExposure+=rr.stake;
            }

            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100.0,surr=Math.max(0,peak-bank);
                trigger=100.0*surr/profit>=25.0-1e-9;
            }
            if(trigger){
                boolean qualifies=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(qualifies)break;first=hand;}
                else if(qualifies)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        if(inBelow100 && bank>=100.0-1e-9)recovered=true;

        Session227 r=new Session227();
        r.cohort=cohort;r.session=session+1;
        r.arm=useCap?("CAP_"+(int)cap):"REFERENCE_NO_CAP";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.everBelow100=everBelow100;r.recoveredAfterBelow100=recovered;r.capTriggered=capTriggered;
        r.below100Episodes=belowEpisodes;r.below100Exposure=episodeExposure;r.totalBelow100Exposure=totalBelowExposure;
        return r;
    }

    public static void main3227Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "cap,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "ever_below100,recovered_after_below100,cap_triggered,below100_episodes,total_below100_exposure\n");

        for(double cap:P227_CAPS){
            for(int c=0;c<4;c++){
                for(int s=0;s<SESSIONS;s++){
                    Session227 ref=runOne227(P227_SEEDS[c],P227_COHORTS[c],s,cap,false);
                    Session227 alt=runOne227(P227_SEEDS[c],P227_COHORTS[c],s,cap,true);
                    Session227[] arr={ref,alt};
                    for(Session227 x:arr){
                        csv.append(String.format(Locale.US,
                          "%.0f,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%d,%.2f%n",
                          cap,x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                          x.reached200,x.terminalZero,x.positive,x.everBelow100,x.recoveredAfterBelow100,
                          x.capTriggered,x.below100Episodes,x.totalBelow100Exposure));
                    }
                }
            }
        }

        write("Phase_3_227_Below100_Exposure_Cap_Screen_Results.csv",csv.toString());

        System.out.println("Deterministic Blackjack Phase 3.227");
        System.out.println("CODE BUILD TAG: DBDE-3.227-BELOW100-RECOVERY-EXPOSURE-CAP-SCREEN");
        System.out.println("Fresh JM/JN/JO/JP.");
        System.out.println("Caps screened: £30 / £45 / £60.");
        System.out.println("20,000 paired IDs per cap candidate / 120,000 arm executions.");
        System.out.println("Screen only; no promotion.");
    }


    static final long[] P228_SEEDS={270101L,270201L,270301L,270401L};
    static final String[] P228_COHORTS={"FRESH_JQ","FRESH_JR","FRESH_JS","FRESH_JT"};
    static final double[] P228_CAPS={45.0,60.0,75.0,90.0,120.0};

    public static void main3228Archive(String[]args)throws Exception{
        StringBuilder csv=new StringBuilder(
          "cap,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "ever_below100,recovered_after_below100,cap_triggered,below100_episodes,total_below100_exposure\n");
        for(double cap:P228_CAPS)for(int c=0;c<4;c++)for(int s=0;s<SESSIONS;s++){
            Session227 ref=runOne227(P228_SEEDS[c],P228_COHORTS[c],s,cap,false);
            Session227 alt=runOne227(P228_SEEDS[c],P228_COHORTS[c],s,cap,true);
            for(Session227 x:new Session227[]{ref,alt})
                csv.append(String.format(Locale.US,
                  "%.0f,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%d,%.2f%n",
                  cap,x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                  x.reached200,x.terminalZero,x.positive,x.everBelow100,x.recoveredAfterBelow100,
                  x.capTriggered,x.below100Episodes,x.totalBelow100Exposure));
        }
        write("Phase_3_228_Balanced_Recovery_Frontier_Results.csv",csv.toString());
        System.out.println("Deterministic Blackjack Phase 3.228");
        System.out.println("CODE BUILD TAG: DBDE-3.228-BELOW100-BALANCED-CAP-REFINEMENT");
        System.out.println("Fresh JQ/JR/JS/JT; caps £45/£60/£75/£90/£120.");
        System.out.println("20,000 paired IDs per cap / 200,000 arm executions; no promotion.");
    }


    static final long[] P229_SEEDS_A={271101L,271201L,271301L,271401L};
    static final long[] P229_SEEDS_B={271501L,271601L,271701L,271801L};
    static final String[] P229_COHORTS_A={"FRESH_JU","FRESH_JV","FRESH_JW","FRESH_JX"};
    static final String[] P229_COHORTS_B={"FRESH_JY","FRESH_JZ","FRESH_KA","FRESH_KB"};
    static final int P229_PER_COHORT=10000;
    static final double P229_CAP=90.0;

    static void append229(StringBuilder csv,long[] seeds,String[] cohorts)throws Exception{
        for(int c=0;c<4;c++)for(int s=0;s<P229_PER_COHORT;s++){
            Session227 ref=runOne227(seeds[c],cohorts[c],s,P229_CAP,false);
            Session227 alt=runOne227(seeds[c],cohorts[c],s,P229_CAP,true);
            for(Session227 x:new Session227[]{ref,alt})
                csv.append(String.format(Locale.US,
                  "%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%d,%.2f%n",
                  x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                  x.reached200,x.terminalZero,x.positive,x.everBelow100,x.recoveredAfterBelow100,
                  x.capTriggered,x.below100Episodes,x.totalBelow100Exposure));
        }
    }

    public static void main3229Archive(String[]args)throws Exception{
        StringBuilder a=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "ever_below100,recovered_after_below100,cap_triggered,below100_episodes,total_below100_exposure\n");
        append229(a,P229_SEEDS_A,P229_COHORTS_A);
        write("Phase_3_229_Initial40K_Paired_Results.csv",a.toString());

        StringBuilder b=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,"+
          "ever_below100,recovered_after_below100,cap_triggered,below100_episodes,total_below100_exposure\n");
        append229(b,P229_SEEDS_B,P229_COHORTS_B);
        write("Phase_3_229_Extension40K_Paired_Results.csv",b.toString());

        System.out.println("Deterministic Blackjack Phase 3.229");
        System.out.println("CODE BUILD TAG: DBDE-3.229-CAP90-ISOLATED-CONFIRMATION-40K-80K");
        System.out.println("CAP £90 isolated against no-cap reference.");
        System.out.println("Initial 40,000 paired IDs generated.");
        System.out.println("Independent extension population also generated for deterministic evidence audit.");
    }


    static final long[] P230_SEEDS={272101L,272201L,272301L,272401L,272501L,272601L,272701L,272801L};
    static final String[] P230_COHORTS={"FRESH_KC","FRESH_KD","FRESH_KE","FRESH_KF","FRESH_KG","FRESH_KH","FRESH_KI","FRESH_KJ"};
    static final int P230_N=10000;
    static final double[] P230_TIERS={110,120,130,140,150,160,170,180,190,200};

    static final class S230{
        String cohort; int session,hands; double finalBank,exposure,maxDD;
        boolean[] reached=new boolean[10]; int[] fh=new int[10];
        double[] fe=new double[10],dd=new double[10],mx=new double[10],mn=new double[10];
        boolean[] below=new boolean[10],zero=new boolean[10];
    }

    static S230 run230(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        S230 r=new S230();r.cohort=cohort;r.session=session+1;
        Arrays.fill(r.fh,-1);Arrays.fill(r.fe,-1);Arrays.fill(r.dd,-1);Arrays.fill(r.mx,-1);Arrays.fill(r.mn,Double.POSITIVE_INFINITY);
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;
            for(int t=0;t<10;t++){
                if(!r.reached[t]&&bank>=P230_TIERS[t]-1e-9){r.reached[t]=true;r.fh[t]=hand;r.fe[t]=cum;r.dd[t]=maxDD;r.mx[t]=bank;r.mn[t]=bank;}
                if(r.reached[t]){r.mx[t]=Math.max(r.mx[t],bank);r.mn[t]=Math.min(r.mn[t],bank);if(bank<100-1e-9)r.below[t]=true;if(bank<=1e-9)r.zero[t]=true;}
            }
            boolean trigger=false;
            if(activated150&&peak>100+1e-9){double profit=peak-100,surr=Math.max(0,peak-bank);trigger=100*surr/profit>=25-1e-9;}
            if(trigger){boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;if(first<0){if(q)break;first=hand;}else if(q)break;}
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;return r;
    }

    public static void main3230Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder("cohort,session,hands,final_bankroll,exposure,max_drawdown");
        for(int t=0;t<10;t++){int q=(int)P230_TIERS[t];c.append(",T").append(q).append("_reached,T").append(q).append("_first_hand,T").append(q).append("_first_exposure,T").append(q).append("_prior_dd,T").append(q).append("_max_after,T").append(q).append("_min_after,T").append(q).append("_below100_after,T").append(q).append("_zero_after");}
        c.append("\n");
        for(int k=0;k<8;k++)for(int s=0;s<P230_N;s++){
            S230 x=run230(P230_SEEDS[k],P230_COHORTS[k],s);
            c.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f",x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD));
            for(int t=0;t<10;t++)c.append(String.format(Locale.US,",%s,%d,%.2f,%.2f,%.2f,%.2f,%s,%s",x.reached[t],x.fh[t],x.fe[t],x.dd[t],x.mx[t],x.mn[t]==Double.POSITIVE_INFINITY?-1:x.mn[t],x.below[t],x.zero[t]));
            c.append("\n");
        }
        write("Phase_3_230_Target_Efficiency_Session_Results.csv",c.toString());
        System.out.println("Phase 3.230 complete: 80,000 fresh target-efficiency sessions.");
    }


    static final long[] P231_SEEDS={273101L,273201L,273301L,273401L};
    static final String[] P231_COHORTS={"FRESH_KK","FRESH_KL","FRESH_KM","FRESH_KN"};
    static final int P231_PER_COHORT=10000;
    static final double[] P231_TARGETS={170.0,180.0,190.0};

    static final class S231{
        String cohort,arm; int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached200,terminalZero,positive,exitTriggered;
        double exitBank;
    }

    static S231 run231(long seed,String cohort,int session,double exitTarget,boolean useExit){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1; boolean reached200=false,exitTriggered=false;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            if(useExit&&bank>=exitTarget-1e-9){exitTriggered=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;if(neg&&!negativeEpisode)brakeArmed=true;negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);requested=brakeArmed?Math.min(bs,15):bs;if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;

            if(useExit&&bank>=exitTarget-1e-9){exitTriggered=true;break;}

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        S231 r=new S231();
        r.cohort=cohort;r.session=session+1;r.arm=useExit?("EXIT_"+(int)exitTarget):"REFERENCE_CONTINUE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;
        r.exitTriggered=exitTriggered;r.exitBank=exitTriggered?bank:-1;
        return r;
    }

    public static void main3231Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "target,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,exit_triggered,exit_bank\n");
        for(double target:P231_TARGETS)for(int k=0;k<4;k++)for(int s=0;s<P231_PER_COHORT;s++){
            S231 ref=run231(P231_SEEDS[k],P231_COHORTS[k],s,target,false);
            S231 alt=run231(P231_SEEDS[k],P231_COHORTS[k],s,target,true);
            for(S231 x:new S231[]{ref,alt})
                c.append(String.format(Locale.US,
                  "%.0f,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%.2f%n",
                  target,x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                  x.reached200,x.terminalZero,x.positive,x.exitTriggered,x.exitBank));
        }
        write("Phase_3_231_Upper_Tier_Exit_Paired_Results.csv",c.toString());
        System.out.println("Phase 3.231 complete: EXIT170/180/190, 40,000 paired IDs each.");
    }


    static final long[] P232_SEEDS={274101L,274201L,274301L,274401L,274501L,274601L,274701L,274801L};
    static final String[] P232_COHORTS={"FRESH_KO","FRESH_KP","FRESH_KQ","FRESH_KR","FRESH_KS","FRESH_KT","FRESH_KU","FRESH_KV"};
    static final int P232_PER_COHORT=10000;
    static final double P232_TARGET=190.0;

    public static void main3232Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,exit_triggered,exit_bank\n");

        for(int k=0;k<P232_SEEDS.length;k++)for(int s=0;s<P232_PER_COHORT;s++){
            S231 ref=run231(P232_SEEDS[k],P232_COHORTS[k],s,P232_TARGET,false);
            S231 alt=run231(P232_SEEDS[k],P232_COHORTS[k],s,P232_TARGET,true);
            for(S231 x:new S231[]{ref,alt})
                c.append(String.format(Locale.US,
                  "%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%.2f%n",
                  x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                  x.reached200,x.terminalZero,x.positive,x.exitTriggered,x.exitBank));
        }

        write("Phase_3_232_EXIT190_Independent_Replication_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.232");
        System.out.println("CODE BUILD TAG: DBDE-3.232-EXIT190-INDEPENDENT-REPLICATION-80K");
        System.out.println("Fresh KO/KP/KQ/KR/KS/KT/KU/KV.");
        System.out.println("80,000 paired IDs / 160,000 arm executions.");
        System.out.println("Reference continuation vs EXIT £190.");
    }


    static final long[] P233_SEEDS={275101L,275201L,275301L,275401L};
    static final String[] P233_COHORTS={"FRESH_KW","FRESH_KX","FRESH_KY","FRESH_KZ"};
    static final int[] P233_HORIZONS={20,30,40};
    static final int P233_PER_COHORT=10000;
    static final double P233_TARGET=190.0;

    static S231 run233(long seed,String cohort,int session,int horizon,boolean useExit){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1; boolean reached200=false,exitTriggered=false;

        for(int hand=1;hand<=horizon;hand++){
            if(bank>=200||bank<=0)break;
            if(useExit&&bank>=P233_TARGET-1e-9){exitTriggered=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(useExit&&bank>=P233_TARGET-1e-9){exitTriggered=true;break;}

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9){reached200=true;break;}
            if(bank<=1e-9)break;

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        S231 r=new S231();
        r.cohort=cohort;r.session=session+1;r.arm=useExit?"EXIT_190":"REFERENCE_CONTINUE";
        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9||reached200;
        r.terminalZero=bank<=1e-9;
        r.positive=bank>100+1e-9;
        r.exitTriggered=exitTriggered;
        r.exitBank=exitTriggered?bank:-1;
        return r;
    }

    public static void main3233Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "horizon,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached200,terminal_zero,positive,exit_triggered,exit_bank\n");

        for(int horizon:P233_HORIZONS){
            for(int k=0;k<P233_SEEDS.length;k++){
                for(int s=0;s<P233_PER_COHORT;s++){
                    S231 ref=run233(P233_SEEDS[k],P233_COHORTS[k],s,horizon,false);
                    S231 alt=run233(P233_SEEDS[k],P233_COHORTS[k],s,horizon,true);
                    for(S231 x:new S231[]{ref,alt}){
                        c.append(String.format(Locale.US,
                          "%d,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%.2f%n",
                          horizon,x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                          x.reached200,x.terminalZero,x.positive,x.exitTriggered,x.exitBank));
                    }
                }
            }
        }

        write("Phase_3_233_EXIT190_Horizon_Robustness_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.233");
        System.out.println("CODE BUILD TAG: DBDE-3.233-EXIT190-HORIZON-ROBUSTNESS-20-30-40");
        System.out.println("Fresh KW/KX/KY/KZ.");
        System.out.println("20/30/40-hand horizons, 40,000 paired IDs each.");
        System.out.println("No automatic promotion.");
    }


    static final long[] P234_SEEDS={276101L,276201L,276301L,276401L,276501L,276601L,276701L,276801L};
    static final String[] P234_COHORTS={"FRESH_LA","FRESH_LB","FRESH_LC","FRESH_LD","FRESH_LE","FRESH_LF","FRESH_LG","FRESH_LH"};
    static final int P234_PER_COHORT=10000;
    static final int P234_HORIZON=40;
    static final double P234_TARGET=190.0;

    static final class S234{
        String cohort; int session,hands,first190Hand;
        double finalBank,exposure,maxDD,first190Exposure,bankAt190,post190Exposure,
               maxAfter190,minAfter190,post190Net,givebackFromPost190Peak;
        boolean reached190,reached200,terminalZero,positive,
                below190After,below180After,below170After,below150After,below100After;
    }

    static S234 run234(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S234 r=new S234();
        r.cohort=cohort;r.session=session+1;r.first190Hand=-1;
        r.first190Exposure=-1;r.bankAt190=-1;r.maxAfter190=-1;r.minAfter190=Double.POSITIVE_INFINITY;

        for(int hand=1;hand<=P234_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            boolean already190=r.reached190;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            if(already190)r.post190Exposure+=rr.stake;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(!r.reached190 && bank>=P234_TARGET-1e-9){
                r.reached190=true;
                r.first190Hand=hand;
                r.first190Exposure=cum;
                r.bankAt190=bank;
                r.maxAfter190=bank;
                r.minAfter190=bank;
            }else if(r.reached190){
                r.maxAfter190=Math.max(r.maxAfter190,bank);
                r.minAfter190=Math.min(r.minAfter190,bank);
            }

            if(r.reached190){
                if(bank<190-1e-9)r.below190After=true;
                if(bank<180-1e-9)r.below180After=true;
                if(bank<170-1e-9)r.below170After=true;
                if(bank<150-1e-9)r.below150After=true;
                if(bank<100-1e-9)r.below100After=true;
            }

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9)break;
            if(bank<=1e-9)break;

            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        r.hands=hc;r.finalBank=bank;r.exposure=cum;r.maxDD=maxDD;
        r.reached200=bank>=200-1e-9;r.terminalZero=bank<=1e-9;r.positive=bank>100+1e-9;

        if(r.reached190){
            if(r.maxAfter190<0)r.maxAfter190=r.bankAt190;
            if(r.minAfter190==Double.POSITIVE_INFINITY)r.minAfter190=r.bankAt190;
            r.post190Net=bank-r.bankAt190;
            r.givebackFromPost190Peak=Math.max(0,r.maxAfter190-bank);
        }else{
            r.post190Exposure=0;r.post190Net=0;r.givebackFromPost190Peak=0;
            r.maxAfter190=-1;r.minAfter190=-1;
        }
        return r;
    }

    public static void main3234Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,max_drawdown,reached190,first190_hand,first190_exposure,bank_at_190,"+
          "post190_exposure,post190_net,max_after190,min_after190,giveback_from_post190_peak,reached200,terminal_zero,positive,"+
          "below190_after,below180_after,below170_after,below150_after,below100_after\n");

        for(int k=0;k<P234_SEEDS.length;k++)for(int s=0;s<P234_PER_COHORT;s++){
            S234 x=run234(P234_SEEDS[k],P234_COHORTS[k],s);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%.2f,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s%n",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached190,x.first190Hand,x.first190Exposure,x.bankAt190,
              x.post190Exposure,x.post190Net,x.maxAfter190,x.minAfter190,x.givebackFromPost190Peak,x.reached200,x.terminalZero,x.positive,
              x.below190After,x.below180After,x.below170After,x.below150After,x.below100After));
        }

        write("Phase_3_234_Post190_Continuation_Decomposition_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.234");
        System.out.println("CODE BUILD TAG: DBDE-3.234-POST190-GIVEBACK-DECOMPOSITION-80K");
        System.out.println("Fresh LA/LB/LC/LD/LE/LF/LG/LH.");
        System.out.println("80,000 40-hand reference sessions.");
        System.out.println("Post-£190 continuation decomposition only; no promotion.");
    }


    static final long[] P235_SEEDS={277101L,277201L,277301L,277401L,277501L,277601L,277701L,277801L};
    static final String[] P235_COHORTS={"FRESH_LI","FRESH_LJ","FRESH_LK","FRESH_LL","FRESH_LM","FRESH_LN","FRESH_LO","FRESH_LP"};
    static final int P235_PER_COHORT=10000;
    static final int P235_HORIZON=40;

    static final class R235{
        double net,stake; int endPointer;
        int initialHit,initialStand,initialDouble,initialSplit;
        int totalHitDecisions,totalStandDecisions,totalDoubleDecisions,totalSplitDecisions;
        int resolvedHands,winHands,lossHands,pushHands,playerBustHands;
        int naturalBlackjacks;
        boolean dealerBust,frozenPair20v8,frozenPair20v10,hard11CoolingSwitch;
    }

    static R235 play235(int[] shoe,int pointer,double availableBank,double wager,boolean coolingBefore){
        int[] ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        boolean initialPlayerNatural=initial.blackjack();
        boolean initialDealerNatural=dealer.blackjack();

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean splitAffordable=availableBank>=2.0*wager-1e-9;
        int up=dealer.c.get(0);

        boolean pair20=pair&&initial.total()==20;
        boolean frozenV10=pair20&&up==10&&splitAffordable;
        boolean frozenV8=pair20&&up==8&&splitAffordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                &&selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Eligible=hard11Candidate&&splitAffordable;
        boolean hard11Switch=coolingBefore&&hard11Eligible;

        boolean wantsSplit=pair;
        if(frozenV10||frozenV8)wantsSplit=false;
        if(wantsSplit&&!splitAffordable)wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        R235 r=new R235();

        if(wantsSplit){
            r.initialSplit++;r.totalSplitDecisions++;
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;

        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;

            if((frozenV10||frozenV8)&&!wantsSplit){
                if(i==0){r.initialStand++;r.totalStandDecisions++;}
                continue;
            }

            if(hard11Switch&&!wantsSplit){
                if(i==0){r.initialHit++;r.totalHitDecisions++;}
                h.c.add(draw(shoe,ptr));first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND){r.totalStandDecisions++;break;}
                    r.totalHitDecisions++;
                    h.c.add(draw(shoe,ptr));
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i)):textbook(h,up,false));

                    if(first&&!wantsSplit){
                        if(a==Action.STAND)r.initialStand++;
                        else if(a==Action.DOUBLE)r.initialDouble++;
                        else if(a==Action.HIT)r.initialHit++;
                    }

                    if(a==Action.STAND){
                        r.totalStandDecisions++;
                        break;
                    }

                    if(a==Action.DOUBLE&&first){
                        if(availableBank<committed+wager){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND){
                                if(!wantsSplit&&i==0){r.initialDouble--;r.initialStand++;}
                                r.totalStandDecisions++;
                                break;
                            }
                            if(!wantsSplit&&i==0){r.initialDouble--;r.initialHit++;}
                            r.totalHitDecisions++;
                            h.c.add(draw(shoe,ptr));first=false;continue;
                        }
                        r.totalDoubleDecisions++;
                        stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));break;
                    }

                    r.totalHitDecisions++;
                    h.c.add(draw(shoe,ptr));first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));
        r.dealerBust=dealer.bust();

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack()){
                x=1.5*st;r.naturalBlackjacks++;
            }else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack()){x=0;r.naturalBlackjacks++;}
            else if(ph.bust()){x=-st;r.playerBustHands++;}
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;

            if(x>1e-9)r.winHands++;
            else if(x<-1e-9)r.lossHands++;
            else r.pushHands++;
            r.resolvedHands++;
            net+=x;
        }

        r.net=net;r.stake=stake;r.endPointer=ptr[0];
        r.frozenPair20v8=frozenV8;r.frozenPair20v10=frozenV10;r.hard11CoolingSwitch=hard11Switch;
        return r;
    }

    static final class S235{
        String cohort;int session,hands,first190Hand;
        double finalBank,exposure,maxDD,bankAt190,first190Exposure,post190Exposure,post190Net;
        boolean reached190,reached200,terminalZero;
        int initialHit,initialStand,initialDouble,initialSplit,totalHit,totalStand,totalDouble,totalSplit;
        int resolvedHands,winHands,lossHands,pushHands,playerBustHands,dealerBustRounds,naturalBlackjacks;
        int pair20v8,pair20v10,hard11Cooling;
    }

    static S235 run235(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S235 s=new S235();
        s.cohort=cohort;s.session=session+1;s.first190Hand=-1;s.bankAt190=-1;s.first190Exposure=-1;

        for(int hand=1;hand<=P235_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            boolean post=s.reached190;
            R235 rr=play235(shoe,ptr,bank,wager,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            if(post){
                s.post190Exposure+=rr.stake;s.post190Net+=rr.net;
                s.initialHit+=rr.initialHit;s.initialStand+=rr.initialStand;s.initialDouble+=rr.initialDouble;s.initialSplit+=rr.initialSplit;
                s.totalHit+=rr.totalHitDecisions;s.totalStand+=rr.totalStandDecisions;s.totalDouble+=rr.totalDoubleDecisions;s.totalSplit+=rr.totalSplitDecisions;
                s.resolvedHands+=rr.resolvedHands;s.winHands+=rr.winHands;s.lossHands+=rr.lossHands;s.pushHands+=rr.pushHands;
                s.playerBustHands+=rr.playerBustHands;s.dealerBustRounds+=rr.dealerBust?1:0;s.naturalBlackjacks+=rr.naturalBlackjacks;
                s.pair20v8+=rr.frozenPair20v8?1:0;s.pair20v10+=rr.frozenPair20v10?1:0;s.hard11Cooling+=rr.hard11CoolingSwitch?1:0;
            }

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;if(bank>=150-1e-9)activated150=true;

            if(!s.reached190&&bank>=190-1e-9){
                s.reached190=true;s.first190Hand=hand;s.bankAt190=bank;s.first190Exposure=cum;
            }

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9)break;
            if(bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3235Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,max_drawdown,reached190,reached200,terminal_zero,first190_hand,bank_at_190,first190_exposure,"+
          "post190_exposure,post190_net,initial_hit,initial_stand,initial_double,initial_split,total_hit,total_stand,total_double,total_split,"+
          "resolved_hands,win_hands,loss_hands,push_hands,player_bust_hands,dealer_bust_rounds,natural_blackjacks,pair20v8,pair20v10,hard11_cooling\n");

        for(int k=0;k<P235_SEEDS.length;k++)for(int n=0;n<P235_PER_COHORT;n++){
            S235 x=run235(P235_SEEDS[k],P235_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%.2f,%s,%s,%s,%d,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,x.reached190,x.reached200,x.terminalZero,x.first190Hand,x.bankAt190,x.first190Exposure,
              x.post190Exposure,x.post190Net,x.initialHit,x.initialStand,x.initialDouble,x.initialSplit,x.totalHit,x.totalStand,x.totalDouble,x.totalSplit,
              x.resolvedHands,x.winHands,x.lossHands,x.pushHands,x.playerBustHands,x.dealerBustRounds,x.naturalBlackjacks,x.pair20v8,x.pair20v10,x.hard11Cooling));
        }

        write("Phase_3_235_Post190_Failure_Decision_Audit_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.235");
        System.out.println("CODE BUILD TAG: DBDE-3.235-POST190-FAILURE-ANATOMY-DECISION-AUDIT-80K");
        System.out.println("Fresh LI/LJ/LK/LL/LM/LN/LO/LP.");
        System.out.println("80,000 40-hand sessions.");
        System.out.println("Post-£190 success/failure and decision-path audit.");
    }


    static final long[] P236_SEEDS={278101L,278201L,278301L,278401L,278501L,278601L,278701L,278801L};
    static final String[] P236_COHORTS={"FRESH_LQ","FRESH_LR","FRESH_LS","FRESH_LT","FRESH_LU","FRESH_LV","FRESH_LW","FRESH_LX"};
    static final int P236_PER_COHORT=10000;
    static final int P236_HORIZON=40;
    static final double[] P236_DEPTHS={0.10,0.20,0.30,0.40};

    static final class S236{
        String cohort; int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached150,reached170,reached190,reached200,terminalZero;

        boolean[] entered=new boolean[4];
        int[] firstEntryHand=new int[4];
        int[] activeHands=new int[4];
        int[] maxConsecutiveHands=new int[4];
        int[] episodes=new int[4];
        double[] activeExposure=new double[4];
        double[] activeNet=new double[4];
        double[] peakAtFirstEntry=new double[4];
        boolean[] recoveredWithin5pct=new boolean[4];
        boolean[] newPeakAfterEntry=new boolean[4];

        int[] currentRun=new int[4];
        boolean[] wasActive=new boolean[4];
    }

    static S236 run236(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S236 s=new S236();
        s.cohort=cohort;s.session=session+1;
        Arrays.fill(s.firstEntryHand,-1);
        Arrays.fill(s.peakAtFirstEntry,-1);

        for(int hand=1;hand<=P236_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            // Determine drawdown state BEFORE current hand.
            boolean[] activeBefore=new boolean[4];
            for(int d=0;d<4;d++){
                double threshold=peak*(1.0-P236_DEPTHS[d]);
                activeBefore[d]=bank<=threshold+1e-9 && peak>START_BANK+1e-9;
                if(activeBefore[d]){
                    if(!s.entered[d]){
                        s.entered[d]=true;
                        s.firstEntryHand[d]=hand;
                        s.peakAtFirstEntry[d]=peak;
                    }
                    if(!s.wasActive[d]){
                        s.episodes[d]++;
                        s.currentRun[d]=0;
                    }
                    s.currentRun[d]++;
                    s.maxConsecutiveHands[d]=Math.max(s.maxConsecutiveHands[d],s.currentRun[d]);
                    s.activeHands[d]++;
                }else{
                    s.currentRun[d]=0;
                }
                s.wasActive[d]=activeBefore[d];
            }

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;

            for(int d=0;d<4;d++){
                if(activeBefore[d]){
                    s.activeExposure[d]+=rr.stake;
                    s.activeNet[d]+=rr.net;
                }
            }

            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9){s.reached150=true;activated150=true;}
            if(bank>=170-1e-9)s.reached170=true;
            if(bank>=190-1e-9)s.reached190=true;
            if(bank>=200-1e-9)s.reached200=true;

            for(int d=0;d<4;d++){
                if(s.entered[d]){
                    double p=s.peakAtFirstEntry[d];
                    if(p>0 && bank>=0.95*p-1e-9)s.recoveredWithin5pct[d]=true;
                    if(p>0 && bank>p+1e-9)s.newPeakAfterEntry[d]=true;
                }
            }

            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3236Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,max_drawdown,reached150,reached170,reached190,reached200,terminal_zero");
        for(int d=0;d<4;d++){
            int q=(int)(P236_DEPTHS[d]*100);
            c.append(",D").append(q).append("_entered");
            c.append(",D").append(q).append("_first_entry_hand");
            c.append(",D").append(q).append("_active_hands");
            c.append(",D").append(q).append("_max_consecutive_hands");
            c.append(",D").append(q).append("_episodes");
            c.append(",D").append(q).append("_active_exposure");
            c.append(",D").append(q).append("_active_net");
            c.append(",D").append(q).append("_peak_at_first_entry");
            c.append(",D").append(q).append("_recovered_within5pct");
            c.append(",D").append(q).append("_new_peak_after_entry");
        }
        c.append("\n");

        for(int k=0;k<P236_SEEDS.length;k++)for(int n=0;n<P236_PER_COHORT;n++){
            S236 x=run236(P236_SEEDS[k],P236_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,
              x.reached150,x.reached170,x.reached190,x.reached200,x.terminalZero));
            for(int d=0;d<4;d++){
                c.append(String.format(Locale.US,
                  ",%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%s,%s",
                  x.entered[d],x.firstEntryHand[d],x.activeHands[d],x.maxConsecutiveHands[d],x.episodes[d],
                  x.activeExposure[d],x.activeNet[d],x.peakAtFirstEntry[d],
                  x.recoveredWithin5pct[d],x.newPeakAfterEntry[d]));
            }
            c.append("\n");
        }

        write("Phase_3_236_Drawdown_Depth_Duration_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.236");
        System.out.println("CODE BUILD TAG: DBDE-3.236-DRAWDOWN-DEPTH-DURATION-FAILED-EXPOSURE-80K");
        System.out.println("Fresh LQ/LR/LS/LT/LU/LV/LW/LX.");
        System.out.println("80,000 40-hand sessions.");
        System.out.println("Drawdown depth-duration/exposure decomposition only; no intervention.");
    }


    static final long[] P237_SEEDS={279101L,279201L,279301L,279401L};
    static final String[] P237_COHORTS={"FRESH_LY","FRESH_LZ","FRESH_MA","FRESH_MB"};
    static final int P237_PER_COHORT=10000;
    static final int[] P237_DURATIONS={6,8,11};
    static final int P237_HORIZON=40;

    static final class S237{
        String cohort,arm; int session,hands;
        double finalBank,exposure,maxDD;
        boolean reached150,reached170,reached190,reached200,terminalZero,stopTriggered;
        int maxD40Run,d40Episodes;
        double d40Exposure,d40Net;
    }

    static S237 run237(long seed,String cohort,int session,int stopDuration,boolean useStop){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        int d40Run=0,maxD40Run=0,d40Episodes=0;
        boolean wasD40=false,stopTriggered=false;
        double d40Exposure=0,d40Net=0;

        for(int hand=1;hand<=P237_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            boolean d40=peak>START_BANK+1e-9 && bank<=peak*0.60+1e-9;
            if(d40){
                if(!wasD40)d40Episodes++;
                d40Run++;
                maxD40Run=Math.max(maxD40Run,d40Run);
            }else{
                d40Run=0;
            }
            wasD40=d40;

            // Stop before taking any further wager once persistence criterion is met.
            if(useStop && d40 && d40Run>=stopDuration){
                stopTriggered=true;
                break;
            }

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;
            if(d40){d40Exposure+=rr.stake;d40Net+=rr.net;}
            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9){activated150=true;}
            boolean trigger=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                trigger=100*surr/profit>=25-1e-9;
            }
            if(trigger){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        S237 s=new S237();
        s.cohort=cohort;s.session=session+1;
        s.arm=useStop?("STOP_D40_"+stopDuration):"REFERENCE_CONTINUE";
        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;
        s.reached150=bank>=150-1e-9;s.reached170=bank>=170-1e-9;s.reached190=bank>=190-1e-9;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;s.stopTriggered=stopTriggered;
        s.maxD40Run=maxD40Run;s.d40Episodes=d40Episodes;s.d40Exposure=d40Exposure;s.d40Net=d40Net;
        return s;
    }

    public static void main3237Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "duration,cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached150,reached170,reached190,reached200,terminal_zero,"+
          "stop_triggered,max_d40_run,d40_episodes,d40_exposure,d40_net\n");

        for(int duration:P237_DURATIONS){
            for(int k=0;k<P237_SEEDS.length;k++){
                for(int n=0;n<P237_PER_COHORT;n++){
                    S237 ref=run237(P237_SEEDS[k],P237_COHORTS[k],n,duration,false);
                    S237 alt=run237(P237_SEEDS[k],P237_COHORTS[k],n,duration,true);
                    for(S237 x:new S237[]{ref,alt}){
                        c.append(String.format(Locale.US,
                          "%d,%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
                          duration,x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                          x.reached150,x.reached170,x.reached190,x.reached200,x.terminalZero,
                          x.stopTriggered,x.maxD40Run,x.d40Episodes,x.d40Exposure,x.d40Net));
                    }
                }
            }
        }

        write("Phase_3_237_D40_Persistence_Stop_Screen_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.237");
        System.out.println("CODE BUILD TAG: DBDE-3.237-D40-PERSISTENCE-STOP-FRONTIER-40K");
        System.out.println("Fresh LY/LZ/MA/MB.");
        System.out.println("STOP_D40_6 / 8 / 11; 40,000 paired IDs each.");
        System.out.println("Screen only; no promotion.");
    }


    static final long[] P238_SEEDS={280101L,280201L,280301L,280401L,280501L,280601L,280701L,280801L};
    static final String[] P238_COHORTS={"FRESH_MC","FRESH_MD","FRESH_ME","FRESH_MF","FRESH_MG","FRESH_MH","FRESH_MI","FRESH_MJ"};
    static final int P238_PER_COHORT=10000;
    static final int P238_DURATION=6;

    public static void main3238Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,max_drawdown,reached150,reached170,reached190,reached200,terminal_zero,"+
          "stop_triggered,max_d40_run,d40_episodes,d40_exposure,d40_net\n");

        for(int k=0;k<P238_SEEDS.length;k++){
            for(int n=0;n<P238_PER_COHORT;n++){
                S237 ref=run237(P238_SEEDS[k],P238_COHORTS[k],n,P238_DURATION,false);
                S237 alt=run237(P238_SEEDS[k],P238_COHORTS[k],n,P238_DURATION,true);
                for(S237 x:new S237[]{ref,alt}){
                    c.append(String.format(Locale.US,
                      "%s,%d,%s,%d,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
                      x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,x.maxDD,
                      x.reached150,x.reached170,x.reached190,x.reached200,x.terminalZero,
                      x.stopTriggered,x.maxD40Run,x.d40Episodes,x.d40Exposure,x.d40Net));
                }
            }
        }

        write("Phase_3_238_D40_6_Independent_Replication_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.238");
        System.out.println("CODE BUILD TAG: DBDE-3.238-D40-6-INDEPENDENT-REPLICATION-80K");
        System.out.println("Fresh holdout MC/MD/ME/MF/MG/MH/MI/MJ.");
        System.out.println("80,000 paired IDs / 160,000 arm executions.");
        System.out.println("Independent replication of STOP_D40_6 only.");
    }


    static final long[] P239_SEEDS={281101L,281201L,281301L,281401L,281501L,281601L,281701L,281801L};
    static final String[] P239_COHORTS={"FRESH_MK","FRESH_ML","FRESH_MM","FRESH_MN","FRESH_MO","FRESH_MP","FRESH_MQ","FRESH_MR"};
    static final int P239_PER_COHORT=10000;
    static final int P239_HORIZON=40;

    static final class S239{
        String cohort; int session,hands,triggerHand;
        double finalBank,exposure,maxDD,triggerBank,triggerPeak,triggerExposure;
        boolean trigger,reached200,terminalZero,positive;
        double postTriggerNet,postTriggerExposure,minAfterTrigger,maxAfterTrigger;
    }

    static S239 run239(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        int d40Run=0;
        boolean trigger=false;
        int triggerHand=-1;
        double triggerBank=-1,triggerPeak=-1,triggerExposure=-1;
        double postNet=0,postExposure=0,minAfter=Double.POSITIVE_INFINITY,maxAfter=-1;

        for(int hand=1;hand<=P239_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            boolean d40=peak>START_BANK+1e-9 && bank<=peak*0.60+1e-9;
            if(d40)d40Run++; else d40Run=0;

            if(!trigger && d40Run>=6){
                trigger=true;
                triggerHand=hand;
                triggerBank=bank;
                triggerPeak=peak;
                triggerExposure=cum;
                minAfter=bank;
                maxAfter=bank;
            }

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;

            if(trigger){
                postExposure+=rr.stake;
                postNet+=rr.net;
            }

            bank+=rr.net;if(bank<0)bank=0;

            if(trigger){
                minAfter=Math.min(minAfter,bank);
                maxAfter=Math.max(maxAfter,bank);
            }

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        S239 s=new S239();
        s.cohort=cohort;s.session=session+1;s.hands=hc;
        s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;
        s.trigger=trigger;s.triggerHand=triggerHand;s.triggerBank=triggerBank;s.triggerPeak=triggerPeak;s.triggerExposure=triggerExposure;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;s.positive=bank>100+1e-9;
        s.postTriggerNet=trigger?postNet:0;s.postTriggerExposure=trigger?postExposure:0;
        s.minAfterTrigger=trigger?minAfter:-1;s.maxAfterTrigger=trigger?maxAfter:-1;
        return s;
    }

    public static void main3239Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,max_drawdown,trigger,trigger_hand,trigger_bank,trigger_peak,trigger_exposure,"+
          "post_trigger_net,post_trigger_exposure,min_after_trigger,max_after_trigger,reached200,terminal_zero,positive\n");

        for(int k=0;k<P239_SEEDS.length;k++)for(int n=0;n<P239_PER_COHORT;n++){
            S239 x=run239(P239_SEEDS[k],P239_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%.2f,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s%n",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.maxDD,x.trigger,x.triggerHand,x.triggerBank,x.triggerPeak,x.triggerExposure,
              x.postTriggerNet,x.postTriggerExposure,x.minAfterTrigger,x.maxAfterTrigger,x.reached200,x.terminalZero,x.positive));
        }

        write("Phase_3_239_D40_6_Bankroll_Matched_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.239");
        System.out.println("CODE BUILD TAG: DBDE-3.239-D40-6-BANKROLL-MATCHED-STRUCTURAL-AUDIT-80K");
        System.out.println("Fresh MK/ML/MM/MN/MO/MP/MQ/MR.");
        System.out.println("80,000 observational 40-hand sessions.");
        System.out.println("No D40 stop imposed.");
    }


    static final long[] P240_SEEDS={282101L,282201L,282301L,282401L,282501L,282601L,282701L,282801L};
    static final String[] P240_COHORTS={"FRESH_MS","FRESH_MT","FRESH_MU","FRESH_MV","FRESH_MW","FRESH_MX","FRESH_MY","FRESH_MZ"};
    static final int P240_PER_COHORT=10000;
    static final int P240_HORIZON=40;

    static int bankBand240(double bank){ return (int)Math.floor(bank/5.0); }
    static int exposureBand240(double exposure){ return (int)Math.floor(exposure/25.0); }

    public static void main3240Archive(String[]args)throws Exception{
        StringBuilder states=new StringBuilder(
          "cohort,session,hand,bankroll,peak,exposure,behaviour_state,d40_run,d40_6,bank_band,exposure_band,final_bankroll,reached200,terminal_zero\n");

        for(int k=0;k<P240_SEEDS.length;k++){
            for(int n=0;n<P240_PER_COHORT;n++){
                int[] shoe=sixDeckShoe(sessionSeed(P240_SEEDS[k],n));
                if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

                int ptr=0,hc=0;int[]hist=new int[5];
                double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
                boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
                int first=-1,d40Run=0;

                ArrayList<String> stateRows=new ArrayList<>();

                for(int hand=1;hand<=P240_HORIZON;hand++){
                    if(bank>=200||bank<=0)break;

                    if(cooling&&bank>=120){cooling=false;cautious=true;}
                    if(cautious&&bank>=140)cautious=false;

                    boolean d40=peak>START_BANK+1e-9 && bank<=peak*0.60+1e-9;
                    if(d40)d40Run++; else d40Run=0;

                    String state=cooling?"COOLING":(cautious?"CAUTIOUS":"NORMAL_AGGRESSIVE");
                    boolean d406=d40Run>=6;

                    stateRows.add(String.format(Locale.US,
                      "%s,%d,%d,%.2f,%.2f,%.2f,%s,%d,%s,%d,%d",
                      P240_COHORTS[k],n+1,hand,bank,peak,cum,state,d40Run,d406,
                      bankBand240(bank),exposureBand240(cum)));

                    double requested;
                    if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
                    else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
                    else if(hand>8&&bank>=140){
                        int b=bal355(hist,hc);boolean neg=b<0;
                        if(neg&&!negativeEpisode)brakeArmed=true;
                        negativeEpisode=neg;
                        double bs=bank>=170?15:normal355(hand,bank);
                        requested=brakeArmed?Math.min(bs,15):bs;
                        if(brakeArmed)brakeArmed=false;
                    }else{
                        requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
                    }

                    requested=Math.min(requested,bank);
                    double chip=chip5FloorTie103(requested,bank);
                    if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
                    double wager=Math.min(chip,bank);if(wager<=0)break;
                    if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

                    Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
                    ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

                    peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
                    hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
                    if(bank>=150-1e-9)activated150=true;

                    boolean triggerStop=false;
                    if(activated150&&peak>100+1e-9){
                        double profit=peak-100,surr=Math.max(0,peak-bank);
                        triggerStop=100*surr/profit>=25-1e-9;
                    }
                    if(triggerStop){
                        boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                        if(first<0){if(q)break;first=hand;}else if(q)break;
                    }

                    if(bank>=200-1e-9||bank<=1e-9)break;
                    if(everPlunge&&bank<=100&&!cooling){
                        cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
                    }
                }

                boolean reached200=bank>=200-1e-9,zero=bank<=1e-9;
                for(String row:stateRows){
                    states.append(row).append(String.format(Locale.US,",%.2f,%s,%s%n",bank,reached200,zero));
                }
            }
        }

        write("Phase_3_240_PreHand_State_Observations.csv",states.toString());

        System.out.println("Deterministic Blackjack Phase 3.240");
        System.out.println("CODE BUILD TAG: DBDE-3.240-D40-6-EXACT-STATE-MATCHING-80K");
        System.out.println("Fresh MS/MT/MU/MV/MW/MX/MY/MZ.");
        System.out.println("80,000 40-hand sessions with every pre-hand state recorded.");
    }


    static final long[] P241_SEEDS={283101L,283201L,283301L,283401L,283501L,283601L,283701L,283801L};
    static final String[] P241_COHORTS={"FRESH_NA","FRESH_NB","FRESH_NC","FRESH_ND","FRESH_NE","FRESH_NF","FRESH_NG","FRESH_NH"};
    static final int P241_PER_COHORT=10000;
    static final int P241_HORIZON=40;
    static final double[] P241_TIERS={110,120,130,140,150,160,170,180,190,200};

    static final class S241{
        String cohort; int session,hands;
        double finalBank,exposure;
        boolean reached200,terminalZero;

        boolean[] reached=new boolean[10];
        int[] firstHand=new int[10];
        double[] firstExposure=new double[10];
    }

    static S241 run241(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S241 s=new S241();
        s.cohort=cohort;s.session=session+1;
        Arrays.fill(s.firstHand,-1);
        Arrays.fill(s.firstExposure,-1);

        for(int hand=1;hand<=P241_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank); if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;
            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            for(int t=0;t<10;t++){
                if(!s.reached[t]&&bank>=P241_TIERS[t]-1e-9){
                    s.reached[t]=true;
                    s.firstHand[t]=hand;
                    s.firstExposure[t]=cum;
                }
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.reached200=bank>=200-1e-9;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3241Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder("cohort,session,hands,final_bankroll,exposure,reached200,terminal_zero");
        for(int t=0;t<10;t++){
            int q=(int)P241_TIERS[t];
            c.append(",T").append(q).append("_reached");
            c.append(",T").append(q).append("_first_hand");
            c.append(",T").append(q).append("_first_exposure");
        }
        c.append("\n");

        for(int k=0;k<P241_SEEDS.length;k++)for(int n=0;n<P241_PER_COHORT;n++){
            S241 x=run241(P241_SEEDS[k],P241_COHORTS[k],n);
            c.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%s,%s",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.reached200,x.terminalZero));
            for(int t=0;t<10;t++){
                c.append(String.format(Locale.US,",%s,%d,%.2f",
                  x.reached[t],x.firstHand[t],x.firstExposure[t]));
            }
            c.append("\n");
        }

        write("Phase_3_241_Tier_Transition_Raw_Results.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.241");
        System.out.println("CODE BUILD TAG: DBDE-3.241-TIER-TRANSITION-MARGINAL-EXPOSURE-80K");
        System.out.println("Fresh NA/NB/NC/ND/NE/NF/NG/NH.");
        System.out.println("80,000 40-hand sessions.");
        System.out.println("Measurement only.");
    }


    static final long[] P242_SEEDS={284101L,284201L,284301L,284401L,284501L,284601L,284701L,284801L};
    static final String[] P242_COHORTS={"FRESH_OA","FRESH_OB","FRESH_OC","FRESH_OD","FRESH_OE","FRESH_OF","FRESH_OG","FRESH_OH"};
    static final int P242_PER_COHORT=10000;
    static final int P242_HORIZON=40;

    static final class S242{
        String cohort; int session,hands,sourceHand,targetHand,postHands,wins,losses,pushes,doubles,splits,blackjacks,playerBusts,dealerBusts;
        double finalBank,exposure,sourceExposure,targetExposure,postExposure,postNet,minAfter140,maxAfter140,giveback;
        boolean sourceReached,targetReached,reached200,terminalZero;
    }

    static S242 run242(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S242 s=new S242(); s.cohort=cohort;s.session=session+1;s.sourceHand=-1;s.targetHand=-1;
        s.sourceExposure=-1;s.targetExposure=-1;s.minAfter140=Double.POSITIVE_INFINITY;s.maxAfter140=-1;

        for(int hand=1;hand<=P242_HORIZON;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            double before=bank;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            boolean wasSource=s.sourceReached;
            if(wasSource && !s.targetReached){
                s.postHands++;
                s.postExposure+=rr.stake;
                s.postNet+=rr.net;
                if(rr.net>1e-9)s.wins++; else if(rr.net<-1e-9)s.losses++; else s.pushes++;
                // Round216 does not expose every semantic flag directly; use stake escalation as a conservative
                // double proxy only where total stake materially exceeds initial wager.
                if(rr.stake>wager+1e-9)s.doubles++;
                // splits are conservatively counted when total stake is >= 2x initial wager.
                if(rr.stake>=2*wager-1e-9)s.splits++;
                if(rr.net>1.4*wager)s.blackjacks++;
                if(rr.net<=-wager+1e-9)s.playerBusts++;
                if(rr.net>=wager-1e-9)s.dealerBusts++;
            }

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(!s.sourceReached && bank>=140-1e-9){
                s.sourceReached=true;s.sourceHand=hand;s.sourceExposure=cum;
                s.minAfter140=bank;s.maxAfter140=bank;
            }
            if(s.sourceReached){
                s.minAfter140=Math.min(s.minAfter140,bank);
                s.maxAfter140=Math.max(s.maxAfter140,bank);
                if(!s.targetReached && bank>=150-1e-9){
                    s.targetReached=true;s.targetHand=hand;s.targetExposure=cum;
                }
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;
        if(s.sourceReached){
            s.giveback=Math.max(0,s.maxAfter140-s.finalBank);
            if(!s.targetReached){
                // failure exposure/net continue from source to session end
                s.postExposure=s.exposure-s.sourceExposure;
                s.postNet=s.finalBank-140.0;
                s.postHands=s.hands-s.sourceHand;
            }
        }else{
            s.minAfter140=-1;s.maxAfter140=-1;s.giveback=-1;
        }
        return s;
    }

    public static void main3242Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,source140_reached,target150_reached,source_hand,target_hand,source_exposure,target_exposure,"+
          "post140_hands,post140_exposure,post140_net,wins,losses,pushes,double_proxy,split_proxy,blackjack_proxy,player_bust_proxy,dealer_bust_proxy,"+
          "min_after140,max_after140,giveback,reached200,terminal_zero\n");
        for(int k=0;k<P242_SEEDS.length;k++)for(int n=0;n<P242_PER_COHORT;n++){
            S242 x=run242(P242_SEEDS[k],P242_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%.2f,%d,%.2f,%.2f,%d,%d,%d,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%s,%s%n",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.sourceReached,x.targetReached,x.sourceHand,x.targetHand,
              x.sourceExposure,x.targetExposure,x.postHands,x.postExposure,x.postNet,x.wins,x.losses,x.pushes,x.doubles,x.splits,x.blackjacks,
              x.playerBusts,x.dealerBusts,x.minAfter140,x.maxAfter140,x.giveback,x.reached200,x.terminalZero));
        }
        write("Phase_3_242_T140_T150_Failure_Anatomy_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.242");
        System.out.println("CODE BUILD TAG: DBDE-3.242-T140-T150-FAILURE-ANATOMY-80K");
        System.out.println("80,000 fresh sessions OA-OH; measurement only.");
    }


    static final long[] P243_SEEDS={285101L,285201L,285301L,285401L,285501L,285601L,285701L,285801L};
    static final String[] P243_COHORTS={"FRESH_OI","FRESH_OJ","FRESH_OK","FRESH_OL","FRESH_OM","FRESH_ON","FRESH_OO","FRESH_OP"};
    static final int P243_PER_COHORT=10000;
    static final int P243_HORIZON=40;
    static final double[] P243_THRESHOLDS={130.0,120.0,100.0};

    static final class S243{
        String cohort; int session,hands,sourceHand,targetHand;
        double finalBank,exposure,sourceExposure;
        boolean sourceReached,targetReached,reached200,terminalZero;

        boolean[] crossed=new boolean[3];
        int[] firstCrossHand=new int[3];
        double[] exposureAtFirstCross=new double[3];
        double[] exposureAfterCross=new double[3];
        boolean[] recoveredAbove=new boolean[3];
        int[] downwardCrossings=new int[3];
        boolean[] wasBelow=new boolean[3];
    }

    static S243 run243(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S243 s=new S243();
        s.cohort=cohort;s.session=session+1;s.sourceHand=-1;s.targetHand=-1;s.sourceExposure=-1;
        Arrays.fill(s.firstCrossHand,-1);
        Arrays.fill(s.exposureAtFirstCross,-1);

        for(int hand=1;hand<=P243_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            boolean[] belowBefore=new boolean[3];
            if(s.sourceReached&&!s.targetReached){
                for(int t=0;t<3;t++){
                    belowBefore[t]=bank<P243_THRESHOLDS[t]-1e-9;
                    if(s.crossed[t])s.exposureAfterCross[t]+=0; // marker only before stake is known
                }
            }

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;

            if(s.sourceReached&&!s.targetReached){
                for(int t=0;t<3;t++){
                    if(s.crossed[t])s.exposureAfterCross[t]+=rr.stake;
                }
            }

            double before=bank;
            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(!s.sourceReached && bank>=140-1e-9){
                s.sourceReached=true;
                s.sourceHand=hand;
                s.sourceExposure=cum;
                for(int t=0;t<3;t++)s.wasBelow[t]=bank<P243_THRESHOLDS[t]-1e-9;
            }

            if(s.sourceReached&&!s.targetReached){
                for(int t=0;t<3;t++){
                    boolean belowNow=bank<P243_THRESHOLDS[t]-1e-9;
                    if(belowNow&&!s.wasBelow[t]){
                        s.downwardCrossings[t]++;
                        if(!s.crossed[t]){
                            s.crossed[t]=true;
                            s.firstCrossHand[t]=hand;
                            s.exposureAtFirstCross[t]=cum;
                        }
                    }
                    if(s.crossed[t] && bank>=P243_THRESHOLDS[t]-1e-9){
                        s.recoveredAbove[t]=true;
                    }
                    s.wasBelow[t]=belowNow;
                }

                if(bank>=150-1e-9){
                    s.targetReached=true;
                    s.targetHand=hand;
                }
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3243Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,source140_reached,target150_reached,source_hand,target_hand,source_exposure,reached200,terminal_zero");
        for(int t=0;t<3;t++){
            int q=(int)P243_THRESHOLDS[t];
            c.append(",B").append(q).append("_crossed");
            c.append(",B").append(q).append("_first_cross_hand");
            c.append(",B").append(q).append("_exposure_at_first_cross");
            c.append(",B").append(q).append("_exposure_after_cross");
            c.append(",B").append(q).append("_recovered_above");
            c.append(",B").append(q).append("_downward_crossings");
        }
        c.append("\n");

        for(int k=0;k<P243_SEEDS.length;k++)for(int n=0;n<P243_PER_COHORT;n++){
            S243 x=run243(P243_SEEDS[k],P243_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%s,%s",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.sourceReached,x.targetReached,
              x.sourceHand,x.targetHand,x.sourceExposure,x.reached200,x.terminalZero));
            for(int t=0;t<3;t++){
                c.append(String.format(Locale.US,",%s,%d,%.2f,%.2f,%s,%d",
                  x.crossed[t],x.firstCrossHand[t],x.exposureAtFirstCross[t],x.exposureAfterCross[t],
                  x.recoveredAbove[t],x.downwardCrossings[t]));
            }
            c.append("\n");
        }

        write("Phase_3_243_Longitudinal_Failed_Exposure_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.243");
        System.out.println("CODE BUILD TAG: DBDE-3.243-T140-T150-LONGITUDINAL-FAILED-EXPOSURE-80K");
        System.out.println("80,000 fresh sessions OI-OP; longitudinal measurement only.");
    }


    static final long[] P244_SEEDS={286101L,286201L,286301L,286401L,286501L,286601L,286701L,286801L};
    static final String[] P244_COHORTS={"FRESH_OQ","FRESH_OR","FRESH_OS","FRESH_OT","FRESH_OU","FRESH_OV","FRESH_OW","FRESH_OX"};
    static final int P244_PER_COHORT=10000;
    static final int P244_HORIZON=40;

    static final class S244{
        String cohort; int session,hands;
        double finalBank,exposure,triggerBank;
        boolean reached140,reached150,reached200,terminalZero,triggered;
        int triggerHand;
    }

    static S244 run244(long seed,String cohort,int session,boolean protect){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S244 s=new S244();s.cohort=cohort;s.session=session+1;s.triggerHand=-1;s.triggerBank=-1;

        for(int hand=1;hand<=P244_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=140-1e-9)s.reached140=true;
            if(bank>=150-1e-9){s.reached150=true;activated150=true;}
            if(bank>=200-1e-9)s.reached200=true;

            // Evidence-selected Phase 3.244 intervention.
            if(protect && s.reached140 && !s.reached150 && bank<100-1e-9){
                s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;
                break;
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        if(bank>=200-1e-9)s.reached200=true;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3244Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final_bankroll,intervention_final_bankroll,bankroll_delta,"+
          "control_exposure,intervention_exposure,exposure_saved,"+
          "control_reached140,control_reached150,control_reached200,control_terminal_zero,"+
          "intervention_reached140,intervention_reached150,intervention_reached200,intervention_terminal_zero,"+
          "intervention_triggered,trigger_hand,trigger_bankroll,control_hands,intervention_hands\n");

        for(int k=0;k<P244_SEEDS.length;k++)for(int n=0;n<P244_PER_COHORT;n++){
            S244 a=run244(P244_SEEDS[k],P244_COHORTS[k],n,false);
            S244 b=run244(P244_SEEDS[k],P244_COHORTS[k],n,true);
            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%.2f,%d,%d%n",
              a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
              a.exposure,b.exposure,a.exposure-b.exposure,
              a.reached140,a.reached150,a.reached200,a.terminalZero,
              b.reached140,b.reached150,b.reached200,b.terminalZero,
              b.triggered,b.triggerHand,b.triggerBank,a.hands,b.hands));
        }

        write("Phase_3_244_Paired_Post140_Below100_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.244");
        System.out.println("CODE BUILD TAG: DBDE-3.244-POST140-BELOW100-STOP-PAIRED-80K");
        System.out.println("80,000 fresh paired sessions OQ-OX.");
        System.out.println("Intervention: STOP_POST140_B100.");
    }


    static final long[] P245_SEEDS={287101L,287201L,287301L,287401L,287501L,287601L,287701L,287801L};
    static final String[] P245_COHORTS={"FRESH_OY","FRESH_OZ","FRESH_PA","FRESH_PB","FRESH_PC","FRESH_PD","FRESH_PE","FRESH_PF"};
    static final int P245_PER_COHORT=10000;

    public static void main3245Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final_bankroll,intervention_final_bankroll,bankroll_delta,"+
          "control_exposure,intervention_exposure,exposure_saved,"+
          "control_reached140,control_reached150,control_reached200,control_terminal_zero,"+
          "intervention_reached140,intervention_reached150,intervention_reached200,intervention_terminal_zero,"+
          "intervention_triggered,trigger_hand,trigger_bankroll,control_hands,intervention_hands\n");

        for(int k=0;k<P245_SEEDS.length;k++){
            for(int n=0;n<P245_PER_COHORT;n++){
                S244 a=run244(P245_SEEDS[k],P245_COHORTS[k],n,false);
                S244 b=run244(P245_SEEDS[k],P245_COHORTS[k],n,true);
                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%.2f,%d,%d%n",
                  a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
                  a.exposure,b.exposure,a.exposure-b.exposure,
                  a.reached140,a.reached150,a.reached200,a.terminalZero,
                  b.reached140,b.reached150,b.reached200,b.terminalZero,
                  b.triggered,b.triggerHand,b.triggerBank,a.hands,b.hands));
            }
        }

        write("Phase_3_245_Post140_Below100_Replication_Raw.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.245");
        System.out.println("CODE BUILD TAG: DBDE-3.245-POST140-BELOW100-STOP-REPLICATION-80K");
        System.out.println("Fresh OY/OZ/PA/PB/PC/PD/PE/PF.");
        System.out.println("80,000 paired IDs / 160,000 arm executions.");
        System.out.println("Exact independent replication of STOP_POST140_B100.");
    }


    static final long[] P246_SEEDS={288101L,288201L,288301L,288401L,288501L,288601L,288701L,288801L};
    static final String[] P246_COHORTS={"FRESH_PG","FRESH_PH","FRESH_PI","FRESH_PJ","FRESH_PK","FRESH_PL","FRESH_PM","FRESH_PN"};
    static final int P246_PER_COHORT=10000;
    static final int MODE_CONTROL=0, MODE_HARD=1, MODE_SOFT=2;

    static S244 run246(long seed,String cohort,int session,int mode){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        boolean wasBelow100=false;
        int post140Below100Crossings=0;

        S244 s=new S244();s.cohort=cohort;s.session=session+1;s.triggerHand=-1;s.triggerBank=-1;

        for(int hand=1;hand<=P244_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=140-1e-9)s.reached140=true;
            if(bank>=150-1e-9){s.reached150=true;activated150=true;}
            if(bank>=200-1e-9)s.reached200=true;

            if(s.reached140 && !s.reached150){
                boolean below100=bank<100-1e-9;
                if(below100 && !wasBelow100)post140Below100Crossings++;

                if(mode==MODE_HARD && below100){
                    s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;
                    break;
                }
                if(mode==MODE_SOFT && post140Below100Crossings>=2 && below100){
                    s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;
                    break;
                }
                wasBelow100=below100;
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        if(bank>=200-1e-9)s.reached200=true;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3246Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final,hard_final,soft_final,hard_delta,soft_delta,"+
          "control_exposure,hard_exposure,soft_exposure,hard_exposure_saved,soft_exposure_saved,"+
          "control_reached150,hard_reached150,soft_reached150,control_reached200,hard_reached200,soft_reached200,"+
          "control_zero,hard_zero,soft_zero,hard_triggered,soft_triggered,hard_trigger_hand,soft_trigger_hand,hard_trigger_bank,soft_trigger_bank\n");

        for(int k=0;k<P246_SEEDS.length;k++)for(int n=0;n<P246_PER_COHORT;n++){
            S244 a=run246(P246_SEEDS[k],P246_COHORTS[k],n,MODE_CONTROL);
            S244 h=run246(P246_SEEDS[k],P246_COHORTS[k],n,MODE_HARD);
            S244 s=run246(P246_SEEDS[k],P246_COHORTS[k],n,MODE_SOFT);

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
              a.cohort,a.session,a.finalBank,h.finalBank,s.finalBank,h.finalBank-a.finalBank,s.finalBank-a.finalBank,
              a.exposure,h.exposure,s.exposure,a.exposure-h.exposure,a.exposure-s.exposure,
              a.reached150,h.reached150,s.reached150,a.reached200,h.reached200,s.reached200,
              a.terminalZero,h.terminalZero,s.terminalZero,h.triggered,s.triggered,h.triggerHand,s.triggerHand,h.triggerBank,s.triggerBank));
        }

        write("Phase_3_246_Soft_Protection_Triple_Paired_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.246");
        System.out.println("CODE BUILD TAG: DBDE-3.246-POST140-B100-SECOND-CROSS-PAIRED-80K");
        System.out.println("80,000 fresh triple-matched IDs PG-PN.");
        System.out.println("CONTROL vs HARD_STOP vs SOFT_SECOND_CROSS.");
    }


    static final long[] P247_SEEDS={289101L,289201L,289301L,289401L,289501L,289601L,289701L,289801L};
    static final String[] P247_COHORTS={"FRESH_PO","FRESH_PP","FRESH_PQ","FRESH_PR","FRESH_PS","FRESH_PT","FRESH_PU","FRESH_PV"};
    static final int P247_PER_COHORT=10000;

    public static void main3247Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final,soft_final,bankroll_delta,"+
          "control_exposure,soft_exposure,exposure_saved,"+
          "control_reached150,soft_reached150,control_reached200,soft_reached200,"+
          "control_zero,soft_zero,soft_triggered,soft_trigger_hand,soft_trigger_bank\n");

        for(int k=0;k<P247_SEEDS.length;k++){
            for(int n=0;n<P247_PER_COHORT;n++){
                S244 a=run246(P247_SEEDS[k],P247_COHORTS[k],n,MODE_CONTROL);
                S244 s=run246(P247_SEEDS[k],P247_COHORTS[k],n,MODE_SOFT);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%d,%.2f%n",
                  a.cohort,a.session,a.finalBank,s.finalBank,s.finalBank-a.finalBank,
                  a.exposure,s.exposure,a.exposure-s.exposure,
                  a.reached150,s.reached150,a.reached200,s.reached200,
                  a.terminalZero,s.terminalZero,s.triggered,s.triggerHand,s.triggerBank));
            }
        }

        write("Phase_3_247_Soft_Second_Cross_Replication_Raw.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.247");
        System.out.println("CODE BUILD TAG: DBDE-3.247-POST140-B100-SECOND-CROSS-REPLICATION-80K");
        System.out.println("Fresh PO/PP/PQ/PR/PS/PT/PU/PV.");
        System.out.println("80,000 paired IDs / 160,000 arm executions.");
        System.out.println("Exact independent replication of SOFT_SECOND_CROSS.");
    }


    static final long[] P248_SEEDS={290101L,290201L,290301L,290401L,290501L,290601L,290701L,290801L};
    static final String[] P248_COHORTS={"FRESH_PW","FRESH_PX","FRESH_PY","FRESH_PZ","FRESH_QA","FRESH_QB","FRESH_QC","FRESH_QD"};
    static final int P248_PER_COHORT=10000;
    static final double[] P248_PENS={0.50,0.60,0.70,0.75,0.80};
    static final int P248_HORIZON=40;

    static final class S248{
        String cohort;int session,hands,resets,cardsConsumed;
        double penetration,finalBank,exposure,maxDD,maxGiveback;
        boolean positive,zero,r150,r170,r190,r200;
    }

    static long p248ResetSeed(long base,int reset){
        long x=base ^ (0x9E3779B97F4A7C15L*(reset+1L));
        x^=(x>>>30);x*=0xBF58476D1CE4E5B9L;
        x^=(x>>>27);x*=0x94D049BB133111EBL;
        return x^(x>>>31);
    }

    static S248 run248(long seed,String cohort,int session,double pen){
        long base=sessionSeed(seed,session);
        int reset=0;
        int[] shoe=sixDeckShoe(p248ResetSeed(base,reset));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,shoeStart=0,totalCards=0,hc=0;int[]hist=new int[5];
        int cut=(int)Math.floor(312.0*pen);

        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0,maxGive=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S248 s=new S248();s.cohort=cohort;s.session=session+1;s.penetration=pen;

        for(int hand=1;hand<=P248_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            // Conventional cut-card model: reshuffle before the next hand once
            // the cut depth has been reached by completed hands.
            if(ptr-shoeStart>=cut){
                reset++;
                shoe=sixDeckShoe(p248ResetSeed(base,reset));
                if(!auditShoe(shoe))throw new IllegalStateException("Reset inventory audit failed");
                ptr=0;shoeStart=0;
            }

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            int beforePtr=ptr;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;
            totalCards+=ptr-beforePtr;
            cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);
            maxDD=Math.max(maxDD,maxPeak-bank);
            maxGive=Math.max(maxGive,peak-bank);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9){s.r150=true;activated150=true;}
            if(bank>=170-1e-9)s.r170=true;
            if(bank>=190-1e-9)s.r190=true;
            if(bank>=200-1e-9)s.r200=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.resets=reset;s.cardsConsumed=totalCards;
        s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;s.maxGiveback=maxGive;
        s.positive=bank>START_BANK+1e-9;s.zero=bank<=1e-9;
        if(bank>=200-1e-9)s.r200=true;
        return s;
    }

    public static void main3248Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,penetration,hands,final_bankroll,exposure,net_per_100_exposure,"+
          "positive,terminal_zero,reached150,reached170,reached190,reached200,"+
          "max_drawdown,max_giveback,cards_consumed,shoe_resets\n");

        for(int k=0;k<P248_SEEDS.length;k++)for(int n=0;n<P248_PER_COHORT;n++){
            for(double pen:P248_PENS){
                S248 x=run248(P248_SEEDS[k],P248_COHORTS[k],n,pen);
                double edge=x.exposure>0?100.0*(x.finalBank-START_BANK)/x.exposure:0;
                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%d,%.2f,%.2f,%.6f,%s,%s,%s,%s,%s,%s,%.2f,%.2f,%d,%d%n",
                  x.cohort,x.session,x.penetration,x.hands,x.finalBank,x.exposure,edge,
                  x.positive,x.zero,x.r150,x.r170,x.r190,x.r200,x.maxDD,x.maxGiveback,
                  x.cardsConsumed,x.resets));
            }
        }
        write("Phase_3_248_Penetration_Reference_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.248");
        System.out.println("CODE BUILD TAG: DBDE-3.248-PENETRATION-RESHUFFLE-REFERENCE-80Kx5");
        System.out.println("50/60/70/75/80% penetration; 80,000 common IDs each.");
        System.out.println("Measurement only; conventional deterministic cut-card reshuffle.");
    }


    static final long[] P249_SEEDS={291101L,291201L,291301L,291401L,291501L,291601L,291701L,291801L};
    static final String[] P249_COHORTS={"FRESH_QE","FRESH_QF","FRESH_QG","FRESH_QH","FRESH_QI","FRESH_QJ","FRESH_QK","FRESH_QL"};
    static final int P249_PER_COHORT=10000;

    public static void main3249Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,penetration,hands,final_bankroll,exposure,net_per_100_exposure,"+
          "positive,terminal_zero,reached150,reached170,reached190,reached200,"+
          "max_drawdown,max_giveback,cards_consumed,shoe_resets\n");

        for(int k=0;k<P249_SEEDS.length;k++)for(int n=0;n<P249_PER_COHORT;n++){
            for(double pen:P248_PENS){
                S248 x=run248(P249_SEEDS[k],P249_COHORTS[k],n,pen);
                double edge=x.exposure>0?100.0*(x.finalBank-START_BANK)/x.exposure:0;
                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%d,%.2f,%.2f,%.6f,%s,%s,%s,%s,%s,%s,%.2f,%.2f,%d,%d%n",
                  x.cohort,x.session,x.penetration,x.hands,x.finalBank,x.exposure,edge,
                  x.positive,x.zero,x.r150,x.r170,x.r190,x.r200,x.maxDD,x.maxGiveback,
                  x.cardsConsumed,x.resets));
            }
        }

        write("Phase_3_249_Penetration_Replication_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.249");
        System.out.println("CODE BUILD TAG: DBDE-3.249-PENETRATION-RESHUFFLE-REPLICATION-80Kx5");
        System.out.println("Fresh QE/QL holdout: 80,000 common IDs x five regimes.");
        System.out.println("Exact independent replication of Phase 3.248 penetration envelope.");
    }


    static final long[] P250_SEEDS={292101L,292201L,292301L,292401L,292501L,292601L,292701L,292801L};
    static final String[] P250_COHORTS={"FRESH_QM","FRESH_QN","FRESH_QO","FRESH_QP","FRESH_QQ","FRESH_QR","FRESH_QS","FRESH_QT"};
    static final int P250_PER_COHORT=10000;
    static final int P250_HORIZON=40;

    static final class S250{
        String cohort,arm; int session,hands,resets,cardsConsumed;
        double finalBank,exposure,maxDD,maxGiveback;
        boolean positive,zero,r150,r170,r190,r200;
    }

    static S250 run250(long seed,String cohort,int session,boolean perHandReset){
        long base=sessionSeed(seed,session);
        int reset=0;
        int[] shoe=sixDeckShoe(p248ResetSeed(base,reset));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,totalCards=0,hc=0;int[]hist=new int[5];
        final int conventionalCut=(int)Math.floor(312.0*0.75);

        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0,maxGive=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S250 s=new S250();
        s.cohort=cohort;s.session=session+1;
        s.arm=perHandReset?"IDEALISED_PER_HAND_RESET":"CONVENTIONAL_75PCT";

        for(int hand=1;hand<=P250_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(perHandReset){
                if(hand>1)reset++;
                shoe=sixDeckShoe(p248ResetSeed(base,reset));
                if(!auditShoe(shoe))throw new IllegalStateException("Per-hand reset inventory audit failed");
                ptr=0;
            }else if(ptr>=conventionalCut){
                reset++;
                shoe=sixDeckShoe(p248ResetSeed(base,reset));
                if(!auditShoe(shoe))throw new IllegalStateException("Conventional reset inventory audit failed");
                ptr=0;
            }

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            int beforePtr=ptr;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;
            totalCards+=ptr-beforePtr;
            cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);
            maxDD=Math.max(maxDD,maxPeak-bank);
            maxGive=Math.max(maxGive,peak-bank);

            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=150-1e-9){s.r150=true;activated150=true;}
            if(bank>=170-1e-9)s.r170=true;
            if(bank>=190-1e-9)s.r190=true;
            if(bank>=200-1e-9)s.r200=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.resets=reset;s.cardsConsumed=totalCards;
        s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;s.maxGiveback=maxGive;
        s.positive=bank>START_BANK+1e-9;s.zero=bank<=1e-9;
        if(bank>=200-1e-9)s.r200=true;
        return s;
    }

    public static void main3250Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,arm,hands,final_bankroll,exposure,net_per_100_exposure,"+
          "positive,terminal_zero,reached150,reached170,reached190,reached200,"+
          "max_drawdown,max_giveback,cards_consumed,shoe_resets\n");

        for(int k=0;k<P250_SEEDS.length;k++)for(int n=0;n<P250_PER_COHORT;n++){
            for(boolean alt:new boolean[]{false,true}){
                S250 x=run250(P250_SEEDS[k],P250_COHORTS[k],n,alt);
                double edge=x.exposure>0?100.0*(x.finalBank-START_BANK)/x.exposure:0;
                c.append(String.format(Locale.US,
                  "%s,%d,%s,%d,%.2f,%.2f,%.6f,%s,%s,%s,%s,%s,%s,%.2f,%.2f,%d,%d%n",
                  x.cohort,x.session,x.arm,x.hands,x.finalBank,x.exposure,edge,
                  x.positive,x.zero,x.r150,x.r170,x.r190,x.r200,x.maxDD,x.maxGiveback,
                  x.cardsConsumed,x.resets));
            }
        }

        write("Phase_3_250_Shuffle_Architecture_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.250");
        System.out.println("CODE BUILD TAG: DBDE-3.250-SHUFFLE-ARCHITECTURE-COMPARISON-80K");
        System.out.println("Fresh QM-QT; 80,000 paired IDs.");
        System.out.println("CONVENTIONAL_75PCT vs IDEALISED_PER_HAND_RESET.");
    }


    static final long[] P251_SEEDS={293101L,293201L,293301L,293401L,293501L,293601L,293701L,293801L};
    static final String[] P251_COHORTS={"FRESH_QU","FRESH_QV","FRESH_QW","FRESH_QX","FRESH_QY","FRESH_QZ","FRESH_RA","FRESH_RB"};
    static final int P251_PER_COHORT=10000;
    static final int P251_HORIZON=40;
    static final double P251_SOURCE=130.0;
    static final double P251_TARGET=140.0;

    static final class S251{
        String cohort; int session,hands,sourceHand,targetHand,postHands;
        double finalBank,exposure,sourceExposure,targetExposure,postExposure,postNet,minAfter,maxAfter,giveback;
        boolean sourceReached,targetReached,reached200,terminalZero;
    }

    static S251 run251(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[] hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S251 s=new S251();
        s.cohort=cohort;s.session=session+1;s.sourceHand=-1;s.targetHand=-1;
        s.sourceExposure=-1;s.targetExposure=-1;
        s.minAfter=Double.POSITIVE_INFINITY;s.maxAfter=-1;

        for(int hand=1;hand<=P251_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(!s.sourceReached && bank>=P251_SOURCE-1e-9){
                s.sourceReached=true;
                s.sourceHand=hand;
                s.sourceExposure=cum;
                s.minAfter=bank;s.maxAfter=bank;
            }

            if(s.sourceReached){
                s.minAfter=Math.min(s.minAfter,bank);
                s.maxAfter=Math.max(s.maxAfter,bank);

                if(!s.targetReached){
                    s.postHands=hand-s.sourceHand;
                    s.postExposure=cum-s.sourceExposure;
                    s.postNet=bank-P251_SOURCE;
                }

                if(!s.targetReached && bank>=P251_TARGET-1e-9){
                    s.targetReached=true;
                    s.targetHand=hand;
                    s.targetExposure=cum;
                }
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;

        if(s.sourceReached){
            if(!s.targetReached){
                s.postHands=s.hands-s.sourceHand;
                s.postExposure=s.exposure-s.sourceExposure;
                s.postNet=s.finalBank-P251_SOURCE;
            }
            s.giveback=Math.max(0,s.maxAfter-s.finalBank);
        }else{
            s.minAfter=-1;s.maxAfter=-1;s.giveback=-1;
        }
        return s;
    }

    public static void main3251Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,source_reached,target_reached,source_hand,target_hand,source_exposure,target_exposure,"+
          "post_source_hands,post_source_exposure,post_source_net,min_after_source,max_after_source,giveback,reached200,terminal_zero\n");

        for(int k=0;k<P251_SEEDS.length;k++)for(int n=0;n<P251_PER_COHORT;n++){
            S251 x=run251(P251_SEEDS[k],P251_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%.2f,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s%n",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.sourceReached,x.targetReached,
              x.sourceHand,x.targetHand,x.sourceExposure,x.targetExposure,x.postHands,x.postExposure,
              x.postNet,x.minAfter,x.maxAfter,x.giveback,x.reached200,x.terminalZero));
        }

        write("Phase_3_251_T130_T140_Failure_Tail_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.251");
        System.out.println("CODE BUILD TAG: DBDE-3.251-T130-T140-FAILURE-TAIL-REPLICATION-80K");
        System.out.println("Fresh QU/QV/QW/QX/QY/QZ/RA/RB.");
        System.out.println("80,000 sessions; measurement only.");
    }


    static final long[] P252_SEEDS={294101L,294201L,294301L,294401L,294501L,294601L,294701L,294801L};
    static final String[] P252_COHORTS={"FRESH_RC","FRESH_RD","FRESH_RE","FRESH_RF","FRESH_RG","FRESH_RH","FRESH_RI","FRESH_RJ"};
    static final int P252_PER_COHORT=10000;
    static final int P252_HORIZON=40;
    static final double[] P252_THRESHOLDS={120.0,110.0,100.0};

    static final class S252{
        String cohort; int session,hands,sourceHand,targetHand;
        double finalBank,exposure,sourceExposure;
        boolean sourceReached,targetReached,reached200,terminalZero;

        boolean[] crossed=new boolean[3];
        int[] firstCrossHand=new int[3];
        double[] exposureAtFirstCross=new double[3];
        double[] exposureAfterCross=new double[3];
        boolean[] recoveredAbove=new boolean[3];
        int[] downwardCrossings=new int[3];
        boolean[] wasBelow=new boolean[3];
    }

    static S252 run252(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S252 s=new S252();
        s.cohort=cohort;s.session=session+1;s.sourceHand=-1;s.targetHand=-1;s.sourceExposure=-1;
        Arrays.fill(s.firstCrossHand,-1);
        Arrays.fill(s.exposureAtFirstCross,-1);

        for(int hand=1;hand<=P252_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;

            if(s.sourceReached&&!s.targetReached){
                for(int t=0;t<3;t++){
                    if(s.crossed[t])s.exposureAfterCross[t]+=rr.stake;
                }
            }

            bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            if(!s.sourceReached && bank>=130-1e-9){
                s.sourceReached=true;
                s.sourceHand=hand;
                s.sourceExposure=cum;
                for(int t=0;t<3;t++)s.wasBelow[t]=bank<P252_THRESHOLDS[t]-1e-9;
            }

            if(s.sourceReached&&!s.targetReached){
                for(int t=0;t<3;t++){
                    boolean belowNow=bank<P252_THRESHOLDS[t]-1e-9;

                    if(belowNow&&!s.wasBelow[t]){
                        s.downwardCrossings[t]++;
                        if(!s.crossed[t]){
                            s.crossed[t]=true;
                            s.firstCrossHand[t]=hand;
                            s.exposureAtFirstCross[t]=cum;
                        }
                    }

                    if(s.crossed[t] && bank>=P252_THRESHOLDS[t]-1e-9){
                        s.recoveredAbove[t]=true;
                    }

                    s.wasBelow[t]=belowNow;
                }

                if(bank>=140-1e-9){
                    s.targetReached=true;
                    s.targetHand=hand;
                }
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.reached200=bank>=200-1e-9;s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3252Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,final_bankroll,exposure,source130_reached,target140_reached,source_hand,target_hand,source_exposure,reached200,terminal_zero");

        for(int t=0;t<3;t++){
            int q=(int)P252_THRESHOLDS[t];
            c.append(",B").append(q).append("_crossed");
            c.append(",B").append(q).append("_first_cross_hand");
            c.append(",B").append(q).append("_exposure_at_first_cross");
            c.append(",B").append(q).append("_exposure_after_cross");
            c.append(",B").append(q).append("_recovered_above");
            c.append(",B").append(q).append("_downward_crossings");
        }
        c.append("\n");

        for(int k=0;k<P252_SEEDS.length;k++)for(int n=0;n<P252_PER_COHORT;n++){
            S252 x=run252(P252_SEEDS[k],P252_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%s,%s",
              x.cohort,x.session,x.hands,x.finalBank,x.exposure,x.sourceReached,x.targetReached,
              x.sourceHand,x.targetHand,x.sourceExposure,x.reached200,x.terminalZero));

            for(int t=0;t<3;t++){
                c.append(String.format(Locale.US,",%s,%d,%.2f,%.2f,%s,%d",
                  x.crossed[t],x.firstCrossHand[t],x.exposureAtFirstCross[t],
                  x.exposureAfterCross[t],x.recoveredAbove[t],x.downwardCrossings[t]));
            }
            c.append("\n");
        }

        write("Phase_3_252_T130_T140_Longitudinal_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.252");
        System.out.println("CODE BUILD TAG: DBDE-3.252-T130-T140-LONGITUDINAL-PATH-MAP-80K");
        System.out.println("Fresh RC/RD/RE/RF/RG/RH/RI/RJ.");
        System.out.println("80,000 sessions; measurement only.");
    }


    static final long[] P253_SEEDS={295101L,295201L,295301L,295401L,295501L,295601L,295701L,295801L};
    static final String[] P253_COHORTS={"FRESH_RK","FRESH_RL","FRESH_RM","FRESH_RN","FRESH_RO","FRESH_RP","FRESH_RQ","FRESH_RR"};
    static final int P253_PER_COHORT=10000;
    static final int P253_HORIZON=40;

    static final class S253{
        String cohort; int session,hands,triggerHand;
        double finalBank,exposure,triggerBank;
        boolean reached130,reached140,reached150,reached200,terminalZero,triggered;
    }

    static S253 run253(long seed,String cohort,int session,boolean protect){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        S253 s=new S253();s.cohort=cohort;s.session=session+1;s.triggerHand=-1;s.triggerBank=-1;
        for(int hand=1;hand<=P253_HORIZON;hand++){
            if(bank>=200||bank<=0)break;
            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;
            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=130-1e-9)s.reached130=true;
            if(bank>=140-1e-9)s.reached140=true;
            if(bank>=150-1e-9){s.reached150=true;activated150=true;}
            if(bank>=200-1e-9)s.reached200=true;
            if(protect && s.reached130 && !s.reached140 && bank<100-1e-9){
                s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;break;
            }
            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }
        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        if(bank>=200-1e-9)s.reached200=true;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3253Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final_bankroll,intervention_final_bankroll,bankroll_delta,"+
          "control_exposure,intervention_exposure,exposure_saved,"+
          "control_reached130,control_reached140,control_reached150,control_reached200,control_terminal_zero,"+
          "intervention_reached130,intervention_reached140,intervention_reached150,intervention_reached200,intervention_terminal_zero,"+
          "intervention_triggered,trigger_hand,trigger_bankroll,control_hands,intervention_hands\n");
        for(int k=0;k<P253_SEEDS.length;k++)for(int n=0;n<P253_PER_COHORT;n++){
            S253 a=run253(P253_SEEDS[k],P253_COHORTS[k],n,false);
            S253 b=run253(P253_SEEDS[k],P253_COHORTS[k],n,true);
            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%.2f,%d,%d%n",
              a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
              a.exposure,b.exposure,a.exposure-b.exposure,
              a.reached130,a.reached140,a.reached150,a.reached200,a.terminalZero,
              b.reached130,b.reached140,b.reached150,b.reached200,b.terminalZero,
              b.triggered,b.triggerHand,b.triggerBank,a.hands,b.hands));
        }
        write("Phase_3_253_T130_T140_Below100_Paired_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.253");
        System.out.println("CODE BUILD TAG: DBDE-3.253-T130-T140-BELOW100-PAIRED-EXIT-80K");
        System.out.println("Fresh RK/RL/RM/RN/RO/RP/RQ/RR.");
        System.out.println("80,000 paired IDs; CONTROL vs STOP_POST130_B100.");
    }


    static final long[] P254_SEEDS={296101L,296201L,296301L,296401L,296501L,296601L,296701L,296801L};
    static final String[] P254_COHORTS={"FRESH_RS","FRESH_RT","FRESH_RU","FRESH_RV","FRESH_RW","FRESH_RX","FRESH_RY","FRESH_RZ"};
    static final int P254_PER_COHORT=10000;

    public static void main3254Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final_bankroll,intervention_final_bankroll,bankroll_delta,"+
          "control_exposure,intervention_exposure,exposure_saved,"+
          "control_reached130,control_reached140,control_reached150,control_reached200,control_terminal_zero,"+
          "intervention_reached130,intervention_reached140,intervention_reached150,intervention_reached200,intervention_terminal_zero,"+
          "intervention_triggered,trigger_hand,trigger_bankroll,control_hands,intervention_hands\n");
        for(int k=0;k<P254_SEEDS.length;k++)for(int n=0;n<P254_PER_COHORT;n++){
            S253 a=run253(P254_SEEDS[k],P254_COHORTS[k],n,false);
            S253 b=run253(P254_SEEDS[k],P254_COHORTS[k],n,true);
            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%.2f,%d,%d%n",
              a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
              a.exposure,b.exposure,a.exposure-b.exposure,
              a.reached130,a.reached140,a.reached150,a.reached200,a.terminalZero,
              b.reached130,b.reached140,b.reached150,b.reached200,b.terminalZero,
              b.triggered,b.triggerHand,b.triggerBank,a.hands,b.hands));
        }
        write("Phase_3_254_T130_T140_Below100_Replication_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.254");
        System.out.println("CODE BUILD TAG: DBDE-3.254-T130-T140-BELOW100-REPLICATION-80K");
        System.out.println("Fresh RS/RT/RU/RV/RW/RX/RY/RZ; 80,000 paired IDs.");
    }


    static final long[] P255_SEEDS={297101L,297201L,297301L,297401L,297501L,297601L,297701L,297801L};
    static final String[] P255_COHORTS={"FRESH_SA","FRESH_SB","FRESH_SC","FRESH_SD","FRESH_SE","FRESH_SF","FRESH_SG","FRESH_SH"};
    static final int P255_PER_COHORT=10000;
    static final int P255_MODE_CONTROL=0, P255_MODE_HARD=1, P255_MODE_SOFT=2;

    static S253 run255(long seed,String cohort,int session,int mode){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        boolean wasBelow100=false;
        int post130Below100Crossings=0;

        S253 s=new S253();
        s.cohort=cohort;s.session=session+1;s.triggerHand=-1;s.triggerBank=-1;

        for(int hand=1;hand<=P253_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            if(bank>=130-1e-9)s.reached130=true;
            if(bank>=140-1e-9)s.reached140=true;
            if(bank>=150-1e-9){s.reached150=true;activated150=true;}
            if(bank>=200-1e-9)s.reached200=true;

            if(s.reached130 && !s.reached140){
                boolean below100=bank<100-1e-9;
                if(below100 && !wasBelow100)post130Below100Crossings++;

                if(mode==P255_MODE_HARD && below100){
                    s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;
                    break;
                }
                if(mode==P255_MODE_SOFT && post130Below100Crossings>=2 && below100){
                    s.triggered=true;s.triggerHand=hand;s.triggerBank=bank;
                    break;
                }
                wasBelow100=below100;
            }

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        if(bank>=200-1e-9)s.reached200=true;
        s.terminalZero=bank<=1e-9;
        return s;
    }

    public static void main3255Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final,hard_final,soft_final,hard_delta,soft_delta,"+
          "control_exposure,hard_exposure,soft_exposure,hard_exposure_saved,soft_exposure_saved,"+
          "control_reached140,hard_reached140,soft_reached140,"+
          "control_reached150,hard_reached150,soft_reached150,"+
          "control_reached200,hard_reached200,soft_reached200,"+
          "control_zero,hard_zero,soft_zero,hard_triggered,soft_triggered,"+
          "hard_trigger_hand,soft_trigger_hand,hard_trigger_bank,soft_trigger_bank\n");

        for(int k=0;k<P255_SEEDS.length;k++)for(int n=0;n<P255_PER_COHORT;n++){
            S253 a=run255(P255_SEEDS[k],P255_COHORTS[k],n,P255_MODE_CONTROL);
            S253 h=run255(P255_SEEDS[k],P255_COHORTS[k],n,P255_MODE_HARD);
            S253 s=run255(P255_SEEDS[k],P255_COHORTS[k],n,P255_MODE_SOFT);

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,"+
              "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%d,%.2f,%.2f%n",
              a.cohort,a.session,a.finalBank,h.finalBank,s.finalBank,h.finalBank-a.finalBank,s.finalBank-a.finalBank,
              a.exposure,h.exposure,s.exposure,a.exposure-h.exposure,a.exposure-s.exposure,
              a.reached140,h.reached140,s.reached140,
              a.reached150,h.reached150,s.reached150,
              a.reached200,h.reached200,s.reached200,
              a.terminalZero,h.terminalZero,s.terminalZero,
              h.triggered,s.triggered,h.triggerHand,s.triggerHand,h.triggerBank,s.triggerBank));
        }

        write("Phase_3_255_T130_T140_Soft_Protection_Triple_Paired_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.255");
        System.out.println("CODE BUILD TAG: DBDE-3.255-T130-T140-B100-SECOND-CROSS-80K");
        System.out.println("Fresh SA/SB/SC/SD/SE/SF/SG/SH.");
        System.out.println("80,000 triple-matched IDs / 240,000 arm executions.");
    }


    static final long[] P256_SEEDS={298101L,298201L,298301L,298401L,298501L,298601L,298701L,298801L};
    static final String[] P256_COHORTS={"FRESH_SI","FRESH_SJ","FRESH_SK","FRESH_SL","FRESH_SM","FRESH_SN","FRESH_SO","FRESH_SP"};
    static final int P256_PER_COHORT=10000;

    public static void main3256Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,control_final,soft_final,bankroll_delta,"+
          "control_exposure,soft_exposure,exposure_saved,"+
          "control_reached140,soft_reached140,control_reached150,soft_reached150,"+
          "control_reached200,soft_reached200,control_zero,soft_zero,"+
          "soft_triggered,soft_trigger_hand,soft_trigger_bank\n");

        for(int k=0;k<P256_SEEDS.length;k++){
            for(int n=0;n<P256_PER_COHORT;n++){
                S253 a=run255(P256_SEEDS[k],P256_COHORTS[k],n,P255_MODE_CONTROL);
                S253 s=run255(P256_SEEDS[k],P256_COHORTS[k],n,P255_MODE_SOFT);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%.2f%n",
                  a.cohort,a.session,a.finalBank,s.finalBank,s.finalBank-a.finalBank,
                  a.exposure,s.exposure,a.exposure-s.exposure,
                  a.reached140,s.reached140,a.reached150,s.reached150,
                  a.reached200,s.reached200,a.terminalZero,s.terminalZero,
                  s.triggered,s.triggerHand,s.triggerBank));
            }
        }

        write("Phase_3_256_T130_T140_Soft_Second_Cross_Replication_Raw.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.256");
        System.out.println("CODE BUILD TAG: DBDE-3.256-T130-T140-B100-SECOND-CROSS-REPLICATION-80K");
        System.out.println("Fresh SI/SJ/SK/SL/SM/SN/SO/SP.");
        System.out.println("80,000 paired IDs / 160,000 arm executions.");
        System.out.println("Exact independent replication of SOFT_SECOND_CROSS.");
    }


    static final long[] P257_SEEDS={299101L,299201L,299301L,299401L,299501L,299601L,299701L,299801L};
    static final String[] P257_COHORTS={"FRESH_SQ","FRESH_SR","FRESH_SS","FRESH_ST","FRESH_SU","FRESH_SV","FRESH_SW","FRESH_SX"};
    static final int P257_PER_COHORT=10000;
    static final int P257_HORIZON=40;
    static final int[] P257_SOURCES={110,120,130,140,150,160,170,180,190};

    static final class S257{
        String cohort; int session,hands;
        double finalBank,exposure;
        boolean terminalZero,reached200;
        double[] bankAfter=new double[P257_HORIZON+1];
        double[] expAfter=new double[P257_HORIZON+1];
    }

    static S257 run257(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S257 s=new S257();
        s.cohort=cohort;s.session=session+1;
        s.bankAfter[0]=bank;s.expAfter[0]=cum;

        for(int hand=1;hand<=P257_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double chip=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&chip<15-1e-9)chip=15;
            double wager=Math.min(chip,bank);if(wager<=0)break;
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
            if(bank>=150-1e-9)activated150=true;

            s.bankAfter[hc]=bank;s.expAfter[hc]=cum;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.terminalZero=bank<=1e-9;s.reached200=bank>=200-1e-9;
        return s;
    }

    public static void main3257Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,session_hands,final_bankroll,total_exposure,"+
          "source_reached,target_reached,source_hand,target_hand,source_exposure,end_transition_exposure,"+
          "transition_hands,transition_exposure,post_source_net,terminal_zero,reached200\n");

        for(int k=0;k<P257_SEEDS.length;k++)for(int n=0;n<P257_PER_COHORT;n++){
            S257 x=run257(P257_SEEDS[k],P257_COHORTS[k],n);

            for(int source:P257_SOURCES){
                int target=source+10;
                int sourceHand=-1,targetHand=-1;

                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9){
                        sourceHand=h;
                    }
                    if(sourceHand>=0 && h>sourceHand && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;break;
                    }
                    // If a single hand jumped through both source and target,
                    // count target reached on the source hand itself.
                    if(sourceHand==h && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;break;
                    }
                }

                boolean sr=sourceHand>=0;
                boolean tr=targetHand>=0;
                if(!sr)continue;

                double sourceExp=x.expAfter[sourceHand];
                double endExp=tr?x.expAfter[targetHand]:x.exposure;
                int endHand=tr?targetHand:x.hands;
                double endBank=tr?x.bankAfter[targetHand]:x.finalBank;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%.2f,%d,%.2f,%.2f,%s,%s%n",
                  x.cohort,x.session,source,target,x.hands,x.finalBank,x.exposure,
                  sr,tr,sourceHand,targetHand,sourceExp,endExp,
                  endHand-sourceHand,endExp-sourceExp,endBank-source,
                  x.terminalZero,x.reached200));
            }
        }

        write("Phase_3_257_Blind_Tier_Scanner_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.257");
        System.out.println("CODE BUILD TAG: DBDE-3.257-BLIND-TIER-SIGNATURE-SCANNER-BENCHMARK-V1-80K");
        System.out.println("Fresh SQ/SR/SS/ST/SU/SV/SW/SX.");
        System.out.println("80,000 sessions; uniform £110->£200 transition scan.");
        System.out.println("No tier-specific intervention.");
    }


    static final long[] P258_SEEDS={300101L,300201L,300301L,300401L,300501L,300601L,300701L,300801L};
    static final String[] P258_COHORTS={"FRESH_SY","FRESH_SZ","FRESH_TA","FRESH_TB","FRESH_TC","FRESH_TD","FRESH_TE","FRESH_TF"};
    static final int P258_PER_COHORT=10000;

    public static void main3258Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,session_hands,final_bankroll,total_exposure,"+
          "source_reached,target_reached,source_hand,target_hand,source_exposure,end_transition_exposure,"+
          "transition_hands,transition_exposure,post_source_net,terminal_zero,reached200\n");

        for(int k=0;k<P258_SEEDS.length;k++)for(int n=0;n<P258_PER_COHORT;n++){
            S257 x=run257(P258_SEEDS[k],P258_COHORTS[k],n);

            for(int source:P257_SOURCES){
                int target=source+10;
                int sourceHand=-1,targetHand=-1;

                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9){
                        sourceHand=h;
                    }
                    if(sourceHand>=0 && h>sourceHand && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;break;
                    }
                    if(sourceHand==h && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;break;
                    }
                }

                boolean sr=sourceHand>=0;
                boolean tr=targetHand>=0;
                if(!sr)continue;

                double sourceExp=x.expAfter[sourceHand];
                double endExp=tr?x.expAfter[targetHand]:x.exposure;
                int endHand=tr?targetHand:x.hands;
                double endBank=tr?x.bankAfter[targetHand]:x.finalBank;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%s,%s,%d,%d,%.2f,%.2f,%d,%.2f,%.2f,%s,%s%n",
                  x.cohort,x.session,source,target,x.hands,x.finalBank,x.exposure,
                  sr,tr,sourceHand,targetHand,sourceExp,endExp,
                  endHand-sourceHand,endExp-sourceExp,endBank-source,
                  x.terminalZero,x.reached200));
            }
        }

        write("Phase_3_258_Blind_Tier_Scanner_Replication_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.258");
        System.out.println("CODE BUILD TAG: DBDE-3.258-BLIND-TIER-SCANNER-REPLICATION-80K");
        System.out.println("Fresh SY/SZ/TA/TB/TC/TD/TE/TF.");
        System.out.println("80,000 sessions; exact scanner replication.");
    }


    static final long[] P259_SEEDS={301101L,301201L,301301L,301401L,301501L,301601L,301701L,301801L};
    static final String[] P259_COHORTS={"FRESH_TG","FRESH_TH","FRESH_TI","FRESH_TJ","FRESH_TK","FRESH_TL","FRESH_TM","FRESH_TN"};
    static final int P259_PER_COHORT=10000;

    public static void main3259Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,source_hand,source_bankroll,source_exposure,"+
          "final_bankroll,total_exposure,continuation_hands,continuation_exposure,continuation_net,"+
          "continuation_net_per_100_exposure,post_source_peak,peak_to_finish_giveback,"+
          "giveback_pct_of_post_source_peak_profit,next_tier_reached,reached200,terminal_zero,"+
          "finished_below_source_entry\n");

        for(int k=0;k<P259_SEEDS.length;k++)for(int n=0;n<P259_PER_COHORT;n++){
            S257 x=run257(P259_SEEDS[k],P259_COHORTS[k],n);

            for(int source:P257_SOURCES){
                int target=source+10;
                int sourceHand=-1,targetHand=-1;

                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9){
                        sourceHand=h;
                    }
                    if(sourceHand>=0 && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;
                        break;
                    }
                }
                if(sourceHand<0)continue;

                double sourceBank=x.bankAfter[sourceHand];
                double sourceExp=x.expAfter[sourceHand];
                double contExp=x.exposure-sourceExp;
                double contNet=x.finalBank-sourceBank;
                double contRate=contExp>0?100.0*contNet/contExp:0;

                double postPeak=sourceBank;
                for(int h=sourceHand;h<=x.hands;h++){
                    if(x.bankAfter[h]>postPeak)postPeak=x.bankAfter[h];
                }
                double giveback=Math.max(0,postPeak-x.finalBank);
                double peakProfit=Math.max(0,postPeak-START_BANK);
                double givebackPct=peakProfit>1e-9?100.0*giveback/peakProfit:0;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.6f,%.2f,%.2f,%.6f,%s,%s,%s,%s%n",
                  x.cohort,x.session,source,target,sourceHand,sourceBank,sourceExp,
                  x.finalBank,x.exposure,x.hands-sourceHand,contExp,contNet,contRate,
                  postPeak,giveback,givebackPct,targetHand>=0,x.reached200,x.terminalZero,
                  x.finalBank<sourceBank-1e-9));
            }
        }

        write("Phase_3_259_Blind_Continuation_Giveback_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.259");
        System.out.println("CODE BUILD TAG: DBDE-3.259-BLIND-CONTINUATION-GIVEBACK-DETECTOR-V1-80K");
        System.out.println("Fresh TG/TH/TI/TJ/TK/TL/TM/TN.");
        System.out.println("80,000 sessions; nine source tiers scanned uniformly.");
        System.out.println("No tier-specific intervention.");
    }


    static final long[] P260_SEEDS={302101L,302201L,302301L,302401L,302501L,302601L,302701L,302801L};
    static final String[] P260_COHORTS={"FRESH_TO","FRESH_TP","FRESH_TQ","FRESH_TR","FRESH_TS","FRESH_TT","FRESH_TU","FRESH_TV"};
    static final int P260_PER_COHORT=10000;

    public static void main3260Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,source_hand,source_bankroll,source_exposure,"+
          "final_bankroll,total_exposure,continuation_hands,continuation_exposure,continuation_net,"+
          "continuation_net_per_100_exposure,post_source_peak,peak_to_finish_giveback,"+
          "giveback_pct_of_post_source_peak_profit,next_tier_reached,reached200,terminal_zero,"+
          "finished_below_source_entry\n");

        for(int k=0;k<P260_SEEDS.length;k++)for(int n=0;n<P260_PER_COHORT;n++){
            S257 x=run257(P260_SEEDS[k],P260_COHORTS[k],n);

            for(int source:P257_SOURCES){
                int target=source+10;
                int sourceHand=-1,targetHand=-1;

                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9){
                        sourceHand=h;
                    }
                    if(sourceHand>=0 && x.bankAfter[h]>=target-1e-9){
                        targetHand=h;
                        break;
                    }
                }
                if(sourceHand<0)continue;

                double sourceBank=x.bankAfter[sourceHand];
                double sourceExp=x.expAfter[sourceHand];
                double contExp=x.exposure-sourceExp;
                double contNet=x.finalBank-sourceBank;
                double contRate=contExp>0?100.0*contNet/contExp:0;

                double postPeak=sourceBank;
                for(int h=sourceHand;h<=x.hands;h++){
                    if(x.bankAfter[h]>postPeak)postPeak=x.bankAfter[h];
                }
                double giveback=Math.max(0,postPeak-x.finalBank);
                double peakProfit=Math.max(0,postPeak-START_BANK);
                double givebackPct=peakProfit>1e-9?100.0*giveback/peakProfit:0;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.6f,%.2f,%.2f,%.6f,%s,%s,%s,%s%n",
                  x.cohort,x.session,source,target,sourceHand,sourceBank,sourceExp,
                  x.finalBank,x.exposure,x.hands-sourceHand,contExp,contNet,contRate,
                  postPeak,giveback,givebackPct,targetHand>=0,x.reached200,x.terminalZero,
                  x.finalBank<sourceBank-1e-9));
            }
        }

        write("Phase_3_260_Blind_Continuation_Giveback_Replication_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.260");
        System.out.println("CODE BUILD TAG: DBDE-3.260-CONTINUATION-GIVEBACK-DETECTOR-REPLICATION-80K");
        System.out.println("Fresh TO/TP/TQ/TR/TS/TT/TU/TV.");
        System.out.println("80,000 sessions; exact Detector V1 replication.");
    }


    static final long[] P264_SEEDS={304101L,304201L,304301L,304401L,304501L,304601L,304701L,304801L};
    static final String[] P264_COHORTS={"FRESH_UE","FRESH_UF","FRESH_UG","FRESH_UH","FRESH_UI","FRESH_UJ","FRESH_UK","FRESH_UL"};
    static final int P264_PER_COHORT=10000;

    public static void main3264Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,source_hand,source_bankroll,source_exposure,"+
          "final_bankroll,total_exposure,continuation_hands,continuation_exposure,continuation_net,"+
          "post_source_peak,peak_to_finish_giveback,giveback_pct_of_post_source_peak_profit,"+
          "next_tier_reached,reached200,terminal_zero,finished_below_source_entry\n");

        for(int k=0;k<P264_SEEDS.length;k++)for(int n=0;n<P264_PER_COHORT;n++){
            S257 x=run257(P264_SEEDS[k],P264_COHORTS[k],n);
            for(int source:P257_SOURCES){
                int target=source+10, sourceHand=-1, targetHand=-1;
                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9)sourceHand=h;
                    if(sourceHand>=0 && x.bankAfter[h]>=target-1e-9){targetHand=h;break;}
                }
                if(sourceHand<0)continue;

                double sourceBank=x.bankAfter[sourceHand];
                double sourceExp=x.expAfter[sourceHand];
                double contExp=x.exposure-sourceExp;
                double contNet=x.finalBank-sourceBank;

                double peak=sourceBank;
                for(int h=sourceHand;h<=x.hands;h++)if(x.bankAfter[h]>peak)peak=x.bankAfter[h];
                double giveback=Math.max(0,peak-x.finalBank);
                double peakProfit=Math.max(0,peak-START_BANK);
                double givebackPct=peakProfit>1e-9?100.0*giveback/peakProfit:0;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.2f,%.2f,%.6f,%s,%s,%s,%s%n",
                  x.cohort,x.session,source,target,sourceHand,sourceBank,sourceExp,
                  x.finalBank,x.exposure,x.hands-sourceHand,contExp,contNet,
                  peak,giveback,givebackPct,targetHand>=0,x.reached200,x.terminalZero,
                  x.finalBank<sourceBank-1e-9));
            }
        }
        write("Phase_3_264_Fresh_Continuation_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.264");
        System.out.println("CODE BUILD TAG: DBDE-3.264-FIXED-ANCHOR-CONTINUATION-V2-80K");
        System.out.println("80,000 fresh sessions: UE/UF/UG/UH/UI/UJ/UK/UL.");
        System.out.println("Detector C V2 fixed-anchor prospective test.");
    }


    static final long[] P267_SEEDS={305101L,305201L,305301L,305401L,305501L,305601L,305701L,305801L};
    static final String[] P267_COHORTS={"FRESH_UM","FRESH_UN","FRESH_UO","FRESH_UP","FRESH_UQ","FRESH_UR","FRESH_US","FRESH_UT"};
    static final int P267_PER_COHORT=10000;

    public static void main3267Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,source_tier,target_tier,source_hand,source_bankroll,source_exposure,"+
          "final_bankroll,total_exposure,continuation_hands,continuation_exposure,continuation_net,"+
          "post_source_peak,peak_to_finish_giveback,giveback_pct_of_post_source_peak_profit,"+
          "next_tier_reached,reached200,terminal_zero,finished_below_source_entry\n");

        for(int k=0;k<P267_SEEDS.length;k++)for(int n=0;n<P267_PER_COHORT;n++){
            S257 x=run257(P267_SEEDS[k],P267_COHORTS[k],n);
            for(int source:P257_SOURCES){
                int target=source+10,sourceHand=-1,targetHand=-1;
                for(int h=1;h<=x.hands;h++){
                    if(sourceHand<0 && x.bankAfter[h]>=source-1e-9)sourceHand=h;
                    if(sourceHand>=0 && x.bankAfter[h]>=target-1e-9){targetHand=h;break;}
                }
                if(sourceHand<0)continue;

                double sourceBank=x.bankAfter[sourceHand];
                double sourceExp=x.expAfter[sourceHand];
                double contExp=x.exposure-sourceExp;
                double contNet=x.finalBank-sourceBank;

                double peak=sourceBank;
                for(int h=sourceHand;h<=x.hands;h++)if(x.bankAfter[h]>peak)peak=x.bankAfter[h];
                double giveback=Math.max(0,peak-x.finalBank);
                double peakProfit=Math.max(0,peak-START_BANK);
                double givebackPct=peakProfit>1e-9?100.0*giveback/peakProfit:0;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.2f,%.2f,%.6f,%s,%s,%s,%s%n",
                  x.cohort,x.session,source,target,sourceHand,sourceBank,sourceExp,
                  x.finalBank,x.exposure,x.hands-sourceHand,contExp,contNet,
                  peak,giveback,givebackPct,targetHand>=0,x.reached200,x.terminalZero,
                  x.finalBank<sourceBank-1e-9));
            }
        }
        write("Phase_3_267_Fresh_Absolute_Continuation_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.267");
        System.out.println("CODE BUILD TAG: DBDE-3.267-ABS-CONT-SIGNATURE-PROSPECTIVE-80K");
        System.out.println("Fresh UM/UN/UO/UP/UQ/UR/US/UT.");
        System.out.println("80,000 sessions.");
    }


    static final long[] P269_SEEDS={306101L,306201L,306301L,306401L,306501L,306601L,306701L,306801L};
    static final String[] P269_COHORTS={"FRESH_UU","FRESH_UV","FRESH_UW","FRESH_UX","FRESH_UY","FRESH_UZ","FRESH_VA","FRESH_VB"};
    static final int P269_PER_COHORT=10000;

    static double nearestCasino5(double requested,double bank){
        if(bank < 15.0-1e-9)return 0.0; // cannot place a new table-minimum wager
        double lo=Math.floor(requested/5.0)*5.0;
        double hi=Math.ceil(requested/5.0)*5.0;
        if(lo<15)lo=15;
        if(hi<15)hi=15;

        // choose closest legal main wager; exact ties downward for deterministic audit
        double dlo=Math.abs(requested-lo), dhi=Math.abs(hi-requested);
        double legal=(dlo<=dhi+1e-12)?lo:hi;

        // Cannot wager more than physically available bankroll.
        double maxLegal=Math.floor(bank/5.0)*5.0;
        if(maxLegal<15)return 0.0;
        if(legal>maxLegal)legal=maxLegal;
        return legal;
    }

    static boolean halfFiveResidual(double bank){
        // true for bankroll values ending in £2.50 on a £2.50 settlement lattice.
        double u=bank/2.5;
        long n=Math.round(u);
        if(Math.abs(u-n)>1e-7)return false;
        return (n%2)!=0;
    }

    public static void main3269Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hand,bank_before,policy_state,raw_requested,current_sim_wager,"+
          "casino_executable_wager,casino_forced_exit,below15_request,off_5_grid_request,"+
          "tie_halfway_5_grid,raw_17_50,bank_has_2_50_residual,unusable_residual_value,"+
          "absolute_wager_distortion,signed_wager_distortion,distortion_pct\n");

        for(int k=0;k<P269_SEEDS.length;k++)for(int n=0;n<P269_PER_COHORT;n++){
            int[] shoe=sixDeckShoe(sessionSeed(P269_SEEDS[k],n));
            if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

            int ptr=0,hc=0;int[]hist=new int[5];
            double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
            boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
            int first=-1;

            for(int hand=1;hand<=40;hand++){
                if(bank>=200||bank<=0)break;

                if(cooling&&bank>=120){cooling=false;cautious=true;}
                if(cautious&&bank>=140)cautious=false;

                double requested;
                String state;
                if(cooling){
                    requested=10; state="COOLING";
                    negativeEpisode=false;brakeArmed=false;
                }else if(cautious){
                    requested=cautious355(hist,hc); state="CAUTIOUS";
                    negativeEpisode=false;brakeArmed=false;
                }else if(hand>8&&bank>=140){
                    int b=bal355(hist,hc);boolean neg=b<0;
                    if(neg&&!negativeEpisode)brakeArmed=true;
                    negativeEpisode=neg;
                    double bs=bank>=170?15:normal355(hand,bank);
                    requested=brakeArmed?Math.min(bs,15):bs;
                    state=brakeArmed?"BRAKE":"NORMAL_GE140";
                    if(brakeArmed)brakeArmed=false;
                }else{
                    requested=normal355(hand,bank); state="NORMAL";
                    negativeEpisode=false;brakeArmed=false;
                }

                requested=Math.min(requested,bank);

                double current=chip5FloorTie103(requested,bank);
                if(bank>=15-1e-9&&current<15-1e-9)current=15;
                current=Math.min(current,bank);
                if(current<=0)break;

                double casino=nearestCasino5(requested,bank);
                boolean forcedExit=casino<=0 && bank>0;
                boolean below15=requested<15-1e-9;
                double units=requested/5.0;
                boolean offGrid=Math.abs(units-Math.rint(units))>1e-9;
                double frac=units-Math.floor(units);
                boolean tie=Math.abs(frac-0.5)<1e-9;
                boolean raw175=Math.abs(requested-17.5)<1e-9;
                boolean residual=halfFiveResidual(bank);
                double unusableResidual=residual?2.5:0.0;

                double absDist=forcedExit?requested:Math.abs(casino-requested);
                double signedDist=forcedExit?-requested:(casino-requested);
                double pct=requested>1e-9?100.0*absDist/requested:0.0;

                c.append(String.format(Locale.US,
                  "%s,%d,%d,%.2f,%s,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%.2f,%.2f,%.2f,%.4f%n",
                  P269_COHORTS[k],n+1,hand,bank,state,requested,current,casino,
                  forcedExit,below15,offGrid,tie,raw175,residual,unusableResidual,
                  absDist,signedDist,pct));

                // Keep CURRENT frozen simulator execution only to expose future states.
                double wager=current;
                if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

                Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
                ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

                peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
                hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;
                if(bank>=150-1e-9)activated150=true;

                boolean triggerStop=false;
                if(activated150&&peak>100+1e-9){
                    double profit=peak-100,surr=Math.max(0,peak-bank);
                    triggerStop=100*surr/profit>=25-1e-9;
                }
                if(triggerStop){
                    boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                    if(first<0){if(q)break;first=hand;}else if(q)break;
                }

                if(bank>=200-1e-9||bank<=1e-9)break;
                if(everPlunge&&bank<=100&&!cooling){
                    cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
                }
            }
        }

        write("Phase_3_269_Casino_Execution_Audit_Raw.csv",c.toString());

        System.out.println("Deterministic Blackjack Phase 3.269");
        System.out.println("CODE BUILD TAG: DBDE-3.269-CASINO-EXECUTION-AUDIT-80K");
        System.out.println("80,000 fresh audit sessions.");
        System.out.println("Audit only: no constrained-vs-ideal outcome comparison.");
    }


    static final long[] P270_SEEDS={307101L,307201L,307301L,307401L,307501L,307601L,307701L,307801L};
    static final String[] P270_COHORTS={"FRESH_VC","FRESH_VD","FRESH_VE","FRESH_VF","FRESH_VG","FRESH_VH","FRESH_VI","FRESH_VJ"};
    static final int P270_PER_COHORT=10000;
    static final int P270_HORIZON=40;

    static final class S270{
        String cohort; int session,hands;
        double finalBank,exposure;
        boolean terminalZero,tableExit,positive;
        boolean[] reached=new boolean[10]; // 110..200
    }

    static double casinoWager270(double requested,double bank){
        if(bank<15.0-1e-9)return 0.0;
        double lo=Math.floor(requested/5.0)*5.0;
        double hi=Math.ceil(requested/5.0)*5.0;
        if(lo<15)lo=15;
        if(hi<15)hi=15;
        double dlo=Math.abs(requested-lo), dhi=Math.abs(hi-requested);
        double legal=(dlo<=dhi+1e-12)?lo:hi; // tie downward
        double maxLegal=Math.floor(bank/5.0)*5.0;
        if(maxLegal<15)return 0.0;
        if(legal>maxLegal)legal=maxLegal;
        return legal;
    }

    static S270 run270(long seed,String cohort,int session,boolean casinoMode){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S270 s=new S270(); s.cohort=cohort; s.session=session+1;

        for(int hand=1;hand<=P270_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(casinoMode && bank<15.0-1e-9){
                s.tableExit=true;
                break;
            }

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10; negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc); negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank); negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);

            double wager;
            if(casinoMode){
                wager=casinoWager270(requested,bank);
                if(wager<=0){
                    s.tableExit=true;
                    break;
                }
            }else{
                wager=chip5FloorTie103(requested,bank);
                if(bank>=15-1e-9&&wager<15-1e-9)wager=15;
                wager=Math.min(wager,bank);
                if(wager<=0)break;
            }

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            for(int i=0;i<10;i++){
                double tier=110+10*i;
                if(bank>=tier-1e-9)s.reached[i]=true;
            }
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;
        s.terminalZero=bank<=1e-9;
        s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3270Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,ideal_final,casino_final,bankroll_delta,"+
          "ideal_exposure,casino_exposure,exposure_delta,"+
          "ideal_hands,casino_hands,casino_table_exit,"+
          "ideal_zero,casino_zero,ideal_positive,casino_positive");

        for(int i=0;i<10;i++){
            int tier=110+10*i;
            c.append(",ideal_reached").append(tier).append(",casino_reached").append(tier);
        }
        c.append("\n");

        for(int k=0;k<P270_SEEDS.length;k++)for(int n=0;n<P270_PER_COHORT;n++){
            S270 a=run270(P270_SEEDS[k],P270_COHORTS[k],n,false);
            S270 b=run270(P270_SEEDS[k],P270_COHORTS[k],n,true);

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%s,%s,%s,%s,%s",
              a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
              a.exposure,b.exposure,b.exposure-a.exposure,
              a.hands,b.hands,b.tableExit,a.terminalZero,b.terminalZero,a.positive,b.positive));

            for(int i=0;i<10;i++){
                c.append(",").append(a.reached[i]).append(",").append(b.reached[i]);
            }
            c.append("\n");
        }

        write("Phase_3_270_Paired_Casino_Execution_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.270");
        System.out.println("CODE BUILD TAG: DBDE-3.270-PAIRED-CASINO-EXECUTION-80K");
        System.out.println("Fresh VC/VD/VE/VF/VG/VH/VI/VJ.");
        System.out.println("80,000 paired identities / 160,000 arm executions.");
    }


    static final long[] P271_SEEDS={308101L,308201L,308301L,308401L,308501L,308601L,308701L,308801L};
    static final String[] P271_COHORTS={"FRESH_VK","FRESH_VL","FRESH_VM","FRESH_VN","FRESH_VO","FRESH_VP","FRESH_VQ","FRESH_VR"};
    static final int P271_PER_COHORT=10000;

    static final class A271{
        S270 s;
        int ten15=0,seventeen15=0,otherBelow=0,gridDown=0,gridUp=0,bankCap=0,unchanged=0,exit=0;
        int coolingChanged=0,cautiousChanged=0,normalChanged=0,brakeChanged=0,ge140Changed=0;
    }

    static String mechanism271(double requested,double bank,double legal){
        if(bank<15.0-1e-9 || legal<=0)return "TABLE_EXIT";
        if(Math.abs(requested-10.0)<1e-9 && Math.abs(legal-15.0)<1e-9)return "TEN_TO_FIFTEEN";
        if(Math.abs(requested-17.5)<1e-9 && Math.abs(legal-15.0)<1e-9)return "SEVENTEEN50_TO_FIFTEEN";
        if(requested<15.0-1e-9 && legal>=15.0-1e-9)return "OTHER_BELOW_MIN_UP";
        double maxLegal=Math.floor(bank/5.0)*5.0;
        if(legal<requested-1e-9 && Math.abs(legal-maxLegal)<1e-9 && requested>bank-1e-9)return "BANKROLL_CAP";
        if(legal<requested-1e-9)return "GRID_DOWN";
        if(legal>requested+1e-9)return "GRID_UP";
        return "UNCHANGED";
    }

    static A271 run271(long seed,String cohort,int session,boolean casinoMode){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        A271 a=new A271(); S270 s=new S270(); a.s=s;
        s.cohort=cohort;s.session=session+1;

        for(int hand=1;hand<=P270_HORIZON;hand++){
            if(bank>=200||bank<=0)break;

            if(casinoMode && bank<15.0-1e-9){
                s.tableExit=true;a.exit++;break;
            }

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested; String state;
            if(cooling){
                requested=10;state="COOLING";negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);state="CAUTIOUS";negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                state=brakeArmed?"BRAKE":"NORMAL_GE140";
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);state="NORMAL";
                negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double wager;

            if(casinoMode){
                wager=casinoWager270(requested,bank);
                String mech=mechanism271(requested,bank,wager);
                if(mech.equals("TEN_TO_FIFTEEN"))a.ten15++;
                else if(mech.equals("SEVENTEEN50_TO_FIFTEEN"))a.seventeen15++;
                else if(mech.equals("OTHER_BELOW_MIN_UP"))a.otherBelow++;
                else if(mech.equals("GRID_DOWN"))a.gridDown++;
                else if(mech.equals("GRID_UP"))a.gridUp++;
                else if(mech.equals("BANKROLL_CAP"))a.bankCap++;
                else if(mech.equals("TABLE_EXIT"))a.exit++;
                else a.unchanged++;

                if(!mech.equals("UNCHANGED")&&!mech.equals("TABLE_EXIT")){
                    if(state.equals("COOLING"))a.coolingChanged++;
                    else if(state.equals("CAUTIOUS"))a.cautiousChanged++;
                    else if(state.equals("NORMAL"))a.normalChanged++;
                    else if(state.equals("BRAKE"))a.brakeChanged++;
                    else if(state.equals("NORMAL_GE140"))a.ge140Changed++;
                }

                if(wager<=0){s.tableExit=true;break;}
            }else{
                wager=chip5FloorTie103(requested,bank);
                if(bank>=15-1e-9&&wager<15-1e-9)wager=15;
                wager=Math.min(wager,bank);
                if(wager<=0)break;
            }

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;
        s.positive=bank>START_BANK+1e-9;
        return a;
    }

    public static void main3271Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,ideal_final,casino_final,bankroll_delta,ideal_exposure,casino_exposure,exposure_delta,"+
          "casino_hands,casino_exit,ten_to_fifteen,seventeen50_to_fifteen,other_below_min_up,"+
          "grid_down,grid_up,bankroll_cap,unchanged,cooling_changed,cautious_changed,normal_changed,"+
          "brake_changed,normal_ge140_changed\n");

        for(int k=0;k<P271_SEEDS.length;k++)for(int n=0;n<P271_PER_COHORT;n++){
            A271 ia=run271(P271_SEEDS[k],P271_COHORTS[k],n,false);
            A271 ca=run271(P271_SEEDS[k],P271_COHORTS[k],n,true);
            S270 x=ia.s,y=ca.s;

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
              x.cohort,x.session,x.finalBank,y.finalBank,y.finalBank-x.finalBank,
              x.exposure,y.exposure,y.exposure-x.exposure,y.hands,y.tableExit,
              ca.ten15,ca.seventeen15,ca.otherBelow,ca.gridDown,ca.gridUp,ca.bankCap,ca.unchanged,
              ca.coolingChanged,ca.cautiousChanged,ca.normalChanged,ca.brakeChanged,ca.ge140Changed));
        }

        write("Phase_3_271_Mechanism_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.271");
        System.out.println("CODE BUILD TAG: DBDE-3.271-CASINO-MECHANISM-DECOMPOSITION-80K");
        System.out.println("80,000 fresh paired identities.");
        System.out.println("Mechanism audit only; no wager tuning.");
    }


    static final long[] P272_SEEDS={309101L,309201L,309301L,309401L,309501L,309601L,309701L,309801L};
    static final String[] P272_COHORTS={"FRESH_VS","FRESH_VT","FRESH_VU","FRESH_VV","FRESH_VW","FRESH_VX","FRESH_VY","FRESH_VZ"};
    static final int P272_PER_COHORT=10000;

    // 0 ideal, 1 full casino, 2 no-minimum-uplift, 3 no-exit, 4 no-grid
    static double wager272(int mode,double requested,double bank){
        if(mode==0){
            double w=chip5FloorTie103(requested,bank);
            if(bank>=15-1e-9&&w<15-1e-9)w=15;
            return Math.min(w,bank);
        }
        if(mode==1)return casinoWager270(requested,bank);

        if(mode==2){
            // Diagnostic: remove £15 minimum uplift and minimum-exit rule.
            // Keep £5 grid; £10 remains £10, £17.50 tie rounds down to £15.
            if(bank<5-1e-9)return Math.min(requested,bank);
            double lo=Math.floor(requested/5.0)*5.0;
            double hi=Math.ceil(requested/5.0)*5.0;
            if(lo<5)lo=5;if(hi<5)hi=5;
            double legal=(Math.abs(requested-lo)<=Math.abs(hi-requested)+1e-12)?lo:hi;
            double maxLegal=Math.floor(bank/5.0)*5.0;
            if(maxLegal>=5&&legal>maxLegal)legal=maxLegal;
            return Math.min(legal,bank);
        }

        if(mode==3){
            // Full casino above minimum; below £15 revert to frozen execution
            // so only the forced-exit component is removed.
            if(bank>=15-1e-9)return casinoWager270(requested,bank);
            double w=chip5FloorTie103(requested,bank);
            return Math.min(w,bank);
        }

        // mode 4: minimum + exit retained, grid removed.
        if(bank<15-1e-9)return 0.0;
        double w=requested;
        if(w<15)w=15;
        if(w>bank)w=bank;
        return w;
    }

    static S270 run272(long seed,String cohort,int session,int mode){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;
        S270 s=new S270();s.cohort=cohort;s.session=session+1;

        for(int hand=1;hand<=P270_HORIZON;hand++){
            if(bank>=200||bank<=0)break;
            if((mode==1||mode==4)&&bank<15-1e-9){s.tableExit=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10;negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }
            requested=Math.min(requested,bank);

            double wager=wager272(mode,requested,bank);
            if(wager<=0){
                if(mode==1||mode==4)s.tableExit=true;
                break;
            }

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[hc%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;
        s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3272Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,ideal_final,full_final,no_min_final,no_exit_final,no_grid_final,"+
          "ideal_exposure,full_exposure,no_min_exposure,no_exit_exposure,no_grid_exposure,"+
          "full_exit,no_grid_exit,ideal_zero,full_zero,no_min_zero,no_exit_zero,no_grid_zero\n");

        for(int k=0;k<P272_SEEDS.length;k++)for(int n=0;n<P272_PER_COHORT;n++){
            S270 a=run272(P272_SEEDS[k],P272_COHORTS[k],n,0);
            S270 b=run272(P272_SEEDS[k],P272_COHORTS[k],n,1);
            S270 c2=run272(P272_SEEDS[k],P272_COHORTS[k],n,2);
            S270 d=run272(P272_SEEDS[k],P272_COHORTS[k],n,3);
            S270 e=run272(P272_SEEDS[k],P272_COHORTS[k],n,4);

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s%n",
              a.cohort,a.session,a.finalBank,b.finalBank,c2.finalBank,d.finalBank,e.finalBank,
              a.exposure,b.exposure,c2.exposure,d.exposure,e.exposure,
              b.tableExit,e.tableExit,a.terminalZero,b.terminalZero,c2.terminalZero,d.terminalZero,e.terminalZero));
        }

        write("Phase_3_272_Ablation_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.272");
        System.out.println("CODE BUILD TAG: DBDE-3.272-CASINO-CONSTRAINT-ABLATION-80K");
        System.out.println("80,000 fresh identities; five diagnostic arms.");
    }


    static final long[] P273_SEEDS={310101L,310201L,310301L,310401L,310501L,310601L,310701L,310801L};
    static final String[] P273_COHORTS={"FRESH_WA","FRESH_WB","FRESH_WC","FRESH_WD","FRESH_WE","FRESH_WF","FRESH_WG","FRESH_WH"};
    static final int P273_PER_COHORT=10000;

    public static void main3273Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,ideal_final,full_final,no_min_final,no_exit_final,no_grid_final,"+
          "ideal_exposure,full_exposure,no_min_exposure,no_exit_exposure,no_grid_exposure,"+
          "full_exit,no_grid_exit,ideal_zero,full_zero,no_min_zero,no_exit_zero,no_grid_zero\n");

        for(int k=0;k<P273_SEEDS.length;k++)for(int n=0;n<P273_PER_COHORT;n++){
            S270 a=run272(P273_SEEDS[k],P273_COHORTS[k],n,0);
            S270 b=run272(P273_SEEDS[k],P273_COHORTS[k],n,1);
            S270 c2=run272(P273_SEEDS[k],P273_COHORTS[k],n,2);
            S270 d=run272(P273_SEEDS[k],P273_COHORTS[k],n,3);
            S270 e=run272(P273_SEEDS[k],P273_COHORTS[k],n,4);

            c.append(String.format(Locale.US,
              "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s%n",
              a.cohort,a.session,a.finalBank,b.finalBank,c2.finalBank,d.finalBank,e.finalBank,
              a.exposure,b.exposure,c2.exposure,d.exposure,e.exposure,
              b.tableExit,e.tableExit,a.terminalZero,b.terminalZero,c2.terminalZero,d.terminalZero,e.terminalZero));
        }

        write("Phase_3_273_Ablation_Holdout_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.273");
        System.out.println("CODE BUILD TAG: DBDE-3.273-CASINO-CONSTRAINT-ABLATION-HOLDOUT-80K");
        System.out.println("80,000 fresh holdout identities; five frozen arms.");
    }


    public static void main3274Archive(String[]args)throws Exception{
        System.out.println("Deterministic Blackjack Phase 3.274");
        System.out.println("CODE BUILD TAG: DBDE-3.274-REALISTIC-CASINO-EXECUTION-FROZEN");
        System.out.println("STATUS: REALISTIC CASINO EXECUTION BRANCH FROZEN");
        System.out.println("Frozen minimum: £15");
        System.out.println("Frozen ordinary main-wager grid: £5");
        System.out.println("£2.50 settlement residual: RETAINED AS BANKROLL VALUE");
        System.out.println("£17.50 ordinary main wager: NOT LEGAL IN FROZEN BASELINE");
        System.out.println("Below £15: PRIMARY EXECUTION FAILURE / TABLE EXIT");
        System.out.println("Terminal £0: retained as separate economic outcome");
        System.out.println("Future larger-wager dataset enrichment: OUT OF SCOPE OF THIS FREEZE");
    }


    static final long[] P275_SEEDS={311101L,311201L,311301L,311401L,311501L,311601L,311701L,311801L};
    static final String[] P275_COHORTS={"FRESH_WI","FRESH_WJ","FRESH_WK","FRESH_WL","FRESH_WM","FRESH_WN","FRESH_WO","FRESH_WP"};
    static final int P275_PER_COHORT=10000;
    static final int[] P275_CUTS={156,187,209,234};

    static final class S275{
        String cohort;int session,hands,cardsUsed;
        double finalBank,exposure;
        boolean tableExit,terminalZero,positive;
        int[] firstCutHand={-1,-1,-1,-1};
    }

    static S275 run275(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        S275 s=new S275();s.cohort=cohort;s.session=session+1;

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10;negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }
            requested=Math.min(requested,bank);

            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            int startPtr=ptr;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;
            cum+=rr.stake;
            bank+=rr.net;if(bank<0)bank=0;
            hc++;

            for(int i=0;i<P275_CUTS.length;i++){
                if(s.firstCutHand[i]<0 && ptr>=P275_CUTS[i])s.firstCutHand[i]=hand;
            }

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);

            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.cardsUsed=ptr;s.finalBank=bank;s.exposure=cum;
        s.terminalZero=bank<=1e-9;s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3275Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,hands,cards_used,penetration_pct,final_bankroll,exposure,"+
          "table_exit,terminal_zero,positive,cut50_reached,cut60_reached,cut67_reached,cut75_reached,"+
          "cut50_first_hand,cut60_first_hand,cut67_first_hand,cut75_first_hand\n");

        for(int k=0;k<P275_SEEDS.length;k++)for(int n=0;n<P275_PER_COHORT;n++){
            S275 s=run275(P275_SEEDS[k],P275_COHORTS[k],n);
            c.append(String.format(Locale.US,
              "%s,%d,%d,%d,%.6f,%.2f,%.2f,%s,%s,%s,%s,%s,%s,%s,%d,%d,%d,%d%n",
              s.cohort,s.session,s.hands,s.cardsUsed,100.0*s.cardsUsed/312.0,
              s.finalBank,s.exposure,s.tableExit,s.terminalZero,s.positive,
              s.firstCutHand[0]>=0,s.firstCutHand[1]>=0,s.firstCutHand[2]>=0,s.firstCutHand[3]>=0,
              s.firstCutHand[0],s.firstCutHand[1],s.firstCutHand[2],s.firstCutHand[3]));
        }

        write("Phase_3_275_Shuffle_Baseline_Audit_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.275");
        System.out.println("CODE BUILD TAG: DBDE-3.275-SHUFFLE-ARCHITECTURE-BASELINE-AUDIT-80K");
        System.out.println("80,000 fresh realistic-table sessions.");
        System.out.println("Measurement only; no alternative shuffle architecture yet.");
    }


    static final long[] P276_SEEDS={312101L,312201L,312301L,312401L,312501L,312601L,312701L,312801L};
    static final String[] P276_COHORTS={"FRESH_WQ","FRESH_WR","FRESH_WS","FRESH_WT","FRESH_WU","FRESH_WV","FRESH_WW","FRESH_WX"};
    static final int P276_PER_COHORT=10000;
    static final int P276_CUT=209;

    static final class ShoeState276{
        long seed; int shoeIndex=0,ptr=0,resets=0;
        int[] shoe;
        ShoeState276(long s){seed=s;shoe=newShoe();}
        int[] newShoe(){return sixDeckShoe(sessionSeed(seed,1000000+shoeIndex));}
        void reset(){shoeIndex++;shoe=newShoe();ptr=0;resets++;}
    }

    static final class R276{
        String cohort;int session,hands,cardsUsed,resetsDuring,shoeIndexStart,shoeIndexEnd,startPtr,endPtr;
        double finalBank,exposure;
        boolean tableExit,terminalZero,positive,resetBeforeFirstHand;
        boolean[] reached=new boolean[10];
    }

    static R276 runFresh276(long seed,String cohort,int session){
        int[] shoe=sixDeckShoe(sessionSeed(seed,session));
        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        R276 s=new R276();s.cohort=cohort;s.session=session+1;s.startPtr=0;s.shoeIndexStart=session;

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(shoe,ptr,bank,wager,8,true,cooling);
            ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        s.hands=hc;s.cardsUsed=ptr;s.endPtr=ptr;s.shoeIndexEnd=session;
        s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;s.positive=bank>START_BANK+1e-9;
        return s;
    }

    static R276 runPersistent276(ShoeState276 st,String cohort,int session){
        int hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        R276 s=new R276();s.cohort=cohort;s.session=session+1;
        s.shoeIndexStart=st.shoeIndex;s.startPtr=st.ptr;
        int resetStart=st.resets;
        if(st.ptr>=P276_CUT){st.reset();s.resetBeforeFirstHand=true;s.shoeIndexStart=st.shoeIndex;s.startPtr=0;}

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}

            // Physical cut-card behavior: shuffle between hands, never mid-hand.
            if(st.ptr>=P276_CUT)st.reset();

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(st.shoe,st.ptr,bank,wager,8,true,cooling);
            st.ptr=rr.endPointer;
cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        s.hands=hc;s.shoeIndexEnd=st.shoeIndex;s.endPtr=st.ptr;s.resetsDuring=st.resets-resetStart;
        s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3276Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,fresh_final,persistent_final,bankroll_delta,"+
          "fresh_exposure,persistent_exposure,exposure_delta,fresh_hands,persistent_hands,"+
          "persistent_table_exit,shoe_index_start,shoe_index_end,start_ptr,end_ptr,resets_during_session,reset_before_first_hand");

        for(int t=110;t<=200;t+=10)c.append(",fresh_reached").append(t).append(",persistent_reached").append(t);
        c.append("\n");

        for(int k=0;k<P276_SEEDS.length;k++){
            ShoeState276 st=new ShoeState276(P276_SEEDS[k]);
            for(int n=0;n<P276_PER_COHORT;n++){
                R276 a=runFresh276(P276_SEEDS[k],P276_COHORTS[k],n);
                R276 b=runPersistent276(st,P276_COHORTS[k],n);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%s,%d,%d,%d,%d,%d,%s",
                  a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
                  a.exposure,b.exposure,b.exposure-a.exposure,a.hands,b.hands,b.tableExit,
                  b.shoeIndexStart,b.shoeIndexEnd,b.startPtr,b.endPtr,b.resetsDuring,b.resetBeforeFirstHand));

                for(int i=0;i<10;i++)c.append(",").append(a.reached[i]).append(",").append(b.reached[i]);
                c.append("\n");
            }
        }

        write("Phase_3_276_Fresh_vs_Persistent_Shoe_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.276");
        System.out.println("CODE BUILD TAG: DBDE-3.276-FRESH-VS-PERSISTENT-SHOE-67PCT-80K-R2");
        System.out.println("80,000 paired identities.");
        System.out.println("Persistent shoe reshuffles between hands at >=209 cards consumed.");
    }


    static final long[] P277_SEEDS={313101L,313201L,313301L,313401L,313501L,313601L,313701L,313801L};
    static final String[] P277_COHORTS={"FRESH_WY","FRESH_WZ","FRESH_XA","FRESH_XB","FRESH_XC","FRESH_XD","FRESH_XE","FRESH_XF"};
    static final int P277_PER_COHORT=10000;
    static final int[] P277_CUTS={156,187,209,234};
    static final String[] P277_LABELS={"P50","P60","P67","P75"};

    static final class ShoeState277{
        long seed; int cut,shoeIndex=0,ptr=0,resets=0;
        int[] shoe;
        ShoeState277(long s,int c){seed=s;cut=c;shoe=newShoe();}
        int[] newShoe(){return sixDeckShoe(sessionSeed(seed,2000000+shoeIndex));}
        void reset(){shoeIndex++;shoe=newShoe();ptr=0;resets++;}
    }

    static R276 runPersistent277(ShoeState277 st,String cohort,int session){
        int hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        R276 s=new R276();s.cohort=cohort;s.session=session+1;
        s.shoeIndexStart=st.shoeIndex;s.startPtr=st.ptr;
        int resetStart=st.resets;
        if(st.ptr>=st.cut){st.reset();s.resetBeforeFirstHand=true;s.shoeIndexStart=st.shoeIndex;s.startPtr=0;}

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}

            if(st.ptr>=st.cut)st.reset();

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;
            Round216 rr=playRound216(st.shoe,st.ptr,bank,wager,8,true,cooling);
            st.ptr=rr.endPointer;cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;
            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        s.hands=hc;s.shoeIndexEnd=st.shoeIndex;s.endPtr=st.ptr;s.resetsDuring=st.resets-resetStart;
        s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3277Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,fresh_final,fresh_exposure,fresh_hands");

        for(String lab:P277_LABELS)
            c.append(",").append(lab).append("_final")
             .append(",").append(lab).append("_exposure")
             .append(",").append(lab).append("_hands")
             .append(",").append(lab).append("_resets")
             .append(",").append(lab).append("_table_exit");
        c.append("\n");

        for(int k=0;k<P277_SEEDS.length;k++){
            ShoeState277[] states=new ShoeState277[P277_CUTS.length];
            for(int j=0;j<states.length;j++)states[j]=new ShoeState277(P277_SEEDS[k]+j*100000L,P277_CUTS[j]);

            for(int n=0;n<P277_PER_COHORT;n++){
                R276 a=runFresh276(P277_SEEDS[k],P277_COHORTS[k],n);

                c.append(String.format(Locale.US,"%s,%d,%.2f,%.2f,%d",
                  a.cohort,a.session,a.finalBank,a.exposure,a.hands));

                for(int j=0;j<states.length;j++){
                    R276 b=runPersistent277(states[j],P277_COHORTS[k],n);
                    c.append(String.format(Locale.US,",%.2f,%.2f,%d,%d,%s",
                      b.finalBank,b.exposure,b.hands,b.resetsDuring,b.tableExit));
                }
                c.append("\n");
            }
        }

        write("Phase_3_277_Penetration_Sensitivity_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.277");
        System.out.println("CODE BUILD TAG: DBDE-3.277-PERSISTENT-PENETRATION-50-60-67-75-80K");
        System.out.println("80,000 fresh identities; fresh reference plus four persistent cut-card architectures.");
    }


    static final long[] P278_SEEDS={314101L,314201L,314301L,314401L,314501L,314601L,314701L,314801L};
    static final String[] P278_COHORTS={"FRESH_XG","FRESH_XH","FRESH_XI","FRESH_XJ","FRESH_XK","FRESH_XL","FRESH_XM","FRESH_XN"};
    static final int P278_PER_COHORT=10000;

    static R276 runFrequentReset278(long seed,String cohort,int session){
        int hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        int first=-1;

        R276 s=new R276();s.cohort=cohort;s.session=session+1;

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){
                requested=10;negativeEpisode=false;brakeArmed=false;
            }else if(cautious){
                requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;
            }else if(hand>8&&bank>=140){
                int b=bal355(hist,hc);boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{
                requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;
            }

            requested=Math.min(requested,bank);
            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            // Transparent frequent-reset proxy: new independently shuffled shoe every hand.
            long handSeed=sessionSeed(seed + session*1000003L, hand);
            int[] shoe=sixDeckShoe(handSeed);
            Round216 rr=playRound216(shoe,0,bank,wager,8,true,cooling);
            cum+=rr.stake;bank+=rr.net;if(bank<0)bank=0;hc++;

            for(int i=0;i<10;i++)if(bank>=110+10*i-1e-9)s.reached[i]=true;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);

            if(bank>=150-1e-9)activated150=true;
            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }

            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){
                cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;
            }
        }

        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.terminalZero=bank<=1e-9;
        s.positive=bank>START_BANK+1e-9;
        return s;
    }

    public static void main3278Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,fresh_final,persistent67_final,frequent_reset_final,"+
          "fresh_exposure,persistent67_exposure,frequent_reset_exposure,"+
          "fresh_hands,persistent67_hands,frequent_reset_hands,"+
          "fresh_exit,persistent67_exit,frequent_reset_exit");

        for(int t=110;t<=200;t+=10){
            c.append(",fresh_reached").append(t)
             .append(",persistent67_reached").append(t)
             .append(",frequent_reset_reached").append(t);
        }
        c.append("\n");

        for(int k=0;k<P278_SEEDS.length;k++){
            ShoeState277 persistent=new ShoeState277(P278_SEEDS[k]+700000L,209);

            for(int n=0;n<P278_PER_COHORT;n++){
                R276 a=runFresh276(P278_SEEDS[k],P278_COHORTS[k],n);
                R276 b=runPersistent277(persistent,P278_COHORTS[k],n);
                R276 c2=runFrequentReset278(P278_SEEDS[k],P278_COHORTS[k],n);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%s,%s,%s",
                  a.cohort,a.session,a.finalBank,b.finalBank,c2.finalBank,
                  a.exposure,b.exposure,c2.exposure,
                  a.hands,b.hands,c2.hands,a.tableExit,b.tableExit,c2.tableExit));

                for(int i=0;i<10;i++){
                    c.append(",").append(a.reached[i])
                     .append(",").append(b.reached[i])
                     .append(",").append(c2.reached[i]);
                }
                c.append("\n");
            }
        }

        write("Phase_3_278_Frequent_Reset_Comparison_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.278");
        System.out.println("CODE BUILD TAG: DBDE-3.278-FREQUENT-RESET-CONTINUOUS-SHUFFLE-PROXY-80K");
        System.out.println("80,000 fresh identities; three shuffle architectures.");
    }


    static final long[] P279_SEEDS={315101L,315201L,315301L,315401L,315501L,315601L,315701L,315801L};
    static final String[] P279_COHORTS={"FRESH_XO","FRESH_XP","FRESH_XQ","FRESH_XR","FRESH_XS","FRESH_XT","FRESH_XU","FRESH_XV"};
    static final int P279_PER_COHORT=10000;

    public static void main3279Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,fresh_final,persistent67_final,frequent_reset_final,"+
          "fresh_exposure,persistent67_exposure,frequent_reset_exposure,"+
          "fresh_hands,persistent67_hands,frequent_reset_hands,"+
          "fresh_exit,persistent67_exit,frequent_reset_exit");

        for(int t=110;t<=200;t+=10){
            c.append(",fresh_reached").append(t)
             .append(",persistent67_reached").append(t)
             .append(",frequent_reset_reached").append(t);
        }
        c.append("\n");

        for(int k=0;k<P279_SEEDS.length;k++){
            ShoeState277 persistent=new ShoeState277(P279_SEEDS[k]+700000L,209);

            for(int n=0;n<P279_PER_COHORT;n++){
                R276 a=runFresh276(P279_SEEDS[k],P279_COHORTS[k],n);
                R276 b=runPersistent277(persistent,P279_COHORTS[k],n);
                R276 c2=runFrequentReset278(P279_SEEDS[k],P279_COHORTS[k],n);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%d,%s,%s,%s",
                  a.cohort,a.session,a.finalBank,b.finalBank,c2.finalBank,
                  a.exposure,b.exposure,c2.exposure,
                  a.hands,b.hands,c2.hands,a.tableExit,b.tableExit,c2.tableExit));

                for(int i=0;i<10;i++){
                    c.append(",").append(a.reached[i])
                     .append(",").append(b.reached[i])
                     .append(",").append(c2.reached[i]);
                }
                c.append("\n");
            }
        }

        write("Phase_3_279_Shuffle_Holdout_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.279");
        System.out.println("CODE BUILD TAG: DBDE-3.279-SHUFFLE-ARCHITECTURE-HOLDOUT-80K");
        System.out.println("80,000 fresh holdout identities; three frozen shuffle architectures.");
    }


    static final long[] P280_SEEDS={316101L,316201L,316301L,316401L,316501L,316601L,316701L,316801L};
    static final String[] P280_COHORTS={"FRESH_XW","FRESH_XX","FRESH_XY","FRESH_XZ","FRESH_YA","FRESH_YB","FRESH_YC","FRESH_YD"};
    static final int P280_PER_COHORT=10000;

    public static void main3280Archive(String[]args)throws Exception{
        StringBuilder c=new StringBuilder(
          "cohort,session,fresh_final,frequent_reset_final,bankroll_delta,"+
          "fresh_exposure,frequent_reset_exposure,exposure_delta,"+
          "fresh_hands,frequent_reset_hands,fresh_exit,frequent_reset_exit");

        for(int t=110;t<=200;t+=10)
            c.append(",fresh_reached").append(t).append(",frequent_reset_reached").append(t);
        c.append("\n");

        for(int k=0;k<P280_SEEDS.length;k++){
            for(int n=0;n<P280_PER_COHORT;n++){
                R276 a=runFresh276(P280_SEEDS[k],P280_COHORTS[k],n);
                R276 b=runFrequentReset278(P280_SEEDS[k],P280_COHORTS[k],n);

                c.append(String.format(Locale.US,
                  "%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%s,%s",
                  a.cohort,a.session,a.finalBank,b.finalBank,b.finalBank-a.finalBank,
                  a.exposure,b.exposure,b.exposure-a.exposure,
                  a.hands,b.hands,a.tableExit,b.tableExit));

                for(int i=0;i<10;i++)
                    c.append(",").append(a.reached[i]).append(",").append(b.reached[i]);
                c.append("\n");
            }
        }

        write("Phase_3_280_Frequent_Reset_Prospective_Raw.csv",c.toString());
        System.out.println("Deterministic Blackjack Phase 3.280");
        System.out.println("CODE BUILD TAG: DBDE-3.280-FREQUENT-RESET-PROSPECTIVE-CONFIRMATION-80K");
        System.out.println("80,000 fresh paired identities.");
        System.out.println("Primary question: frequent-reset bankroll replication.");
    }


    static final long[] P282_SEEDS={321101L,321201L,321301L,321401L,321501L,321601L,321701L,321801L};
    static final String[] P282_COHORTS={"FRESH_ZK","FRESH_ZL","FRESH_ZM","FRESH_ZN","FRESH_ZO","FRESH_ZP","FRESH_ZQ","FRESH_ZR"};
    static final int P282_PER_COHORT=10000;

    static final class S282{
        String cohort; int session,hands,handsBelow100,episodesBelow100,recoveries;
        double finalBank,totalExposure,exposureBelow100,minBank=START_BANK,maxDrawdown;
        int firstBelow100Hand=0; double firstBelow100Wager=0;
        int directEpisodesBelow100=0;
        int playerNaturals=0,dealerNaturals=0,simultaneousNaturals=0;
        boolean below80,below60,below40,below20,reached130,reached150,reached200,tableExit;
    }

    static S282 runState282(ShoeState277 st,String cohort,int session){
        S282 s=new S282(); s.cohort=cohort;s.session=session+1;
        int hc=0; int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxPeak=START_BANK,maxDD=0;
        boolean everPlunge=false,cooling=false,cautious=false,negativeEpisode=false,brakeArmed=false,activated150=false;
        boolean wasBelow100=false; int first=-1;

        if(st.ptr>=st.cut)st.reset();

        for(int hand=1;hand<=40;hand++){
            if(bank>=200||bank<=0)break;
            if(bank<15.0-1e-9){s.tableExit=true;break;}
            if(st.ptr>=st.cut)st.reset();

            if(cooling&&bank>=120){cooling=false;cautious=true;}
            if(cautious&&bank>=140)cautious=false;

            double requested;
            if(cooling){requested=10;negativeEpisode=false;brakeArmed=false;}
            else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
            else if(hand>8&&bank>=140){
                int b=bal355(hist,hc); boolean neg=b<0;
                if(neg&&!negativeEpisode)brakeArmed=true;
                negativeEpisode=neg;
                double bs=bank>=170?15:normal355(hand,bank);
                requested=brakeArmed?Math.min(bs,15):bs;
                if(brakeArmed)brakeArmed=false;
            }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}

            requested=Math.min(requested,bank);
            double wager=casinoWager270(requested,bank);
            if(wager<=0){s.tableExit=true;break;}

            boolean startedBelow100=bank<100-1e-9;
            if(startedBelow100){
                s.handsBelow100++;
                if(!wasBelow100)s.episodesBelow100++;
            }
            if(!cooling&&!cautious&&hand>8&&bank>=130)everPlunge=true;

            Round216 rr=playRound216(st.shoe,st.ptr,bank,wager,8,true,cooling);
            st.ptr=rr.endPointer;
            if(rr.playerNaturalBlackjack)s.playerNaturals++;
            if(rr.dealerNaturalBlackjack)s.dealerNaturals++;
            if(rr.playerNaturalBlackjack&&rr.dealerNaturalBlackjack)s.simultaneousNaturals++;
            cum+=rr.stake;
            if(startedBelow100)s.exposureBelow100+=rr.stake;
            bank+=rr.net;if(bank<0)bank=0;hc++;

            if(startedBelow100 && bank>=100-1e-9)s.recoveries++;
            if(s.firstBelow100Hand==0 && bank<100-1e-9){
                s.firstBelow100Hand=hand;
                s.firstBelow100Wager=rr.stake;
            }
            boolean nowBelow100=bank<100-1e-9;
            if(!wasBelow100 && nowBelow100)s.directEpisodesBelow100++;
            wasBelow100=nowBelow100;

            s.minBank=Math.min(s.minBank,bank);
            if(bank<80-1e-9)s.below80=true;
            if(bank<60-1e-9)s.below60=true;
            if(bank<40-1e-9)s.below40=true;
            if(bank<20-1e-9)s.below20=true;
            if(bank>=130-1e-9)s.reached130=true;
            if(bank>=150-1e-9)s.reached150=true;
            if(bank>=200-1e-9)s.reached200=true;

            peak=Math.max(peak,bank);maxPeak=Math.max(maxPeak,bank);maxDD=Math.max(maxDD,maxPeak-bank);
            hist[(hc-1)%hist.length]=rr.net>1e-9?1:(rr.net<-1e-9?-1:0);
            if(bank>=150-1e-9)activated150=true;

            boolean triggerStop=false;
            if(activated150&&peak>100+1e-9){
                double profit=peak-100,surr=Math.max(0,peak-bank);
                triggerStop=100*surr/profit>=25-1e-9;
            }
            if(triggerStop){
                boolean q=cum<=P139_EXPOSURE_GATE+1e-9&&bank>=P139_BANKROLL_GATE-1e-9;
                if(first<0){if(q)break;first=hand;}else if(q)break;
            }
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(everPlunge&&bank<=100&&!cooling){cooling=true;cautious=false;negativeEpisode=false;brakeArmed=false;}
        }

        s.hands=hc;s.finalBank=bank;s.totalExposure=cum;s.maxDrawdown=maxDD;
        if(bank<15.0-1e-9)s.tableExit=true;
        return s;
    }





















    // =======================================================================
    // PHASE 3.318 — INDEPENDENT PAIRED HIT REPLICATION
    // =======================================================================

    static final long[] SEEDS317={360101L,360201L};
    static final String[] COHORTS317={"PRIMARY","HOLDOUT"};
    static final int SESSIONS317=10000;

    static final class Round317{
        double net,stake; int endPointer,cardsConsumed,hits;
        int wins,losses,pushes,playerBusts,doubles,splits,playerNaturals,dealerNaturals,reached21Hands;
    }
    static final class Session317{
        String cohort,arm; int session,handsPlayed;
        double finalBank,peakBank,troughBank,maxDrawdown,cumulativeWager,peakGiveBack;
        int wins,losses,pushes,playerNaturals,dealerNaturals,playerBusts,doubles,splits,reached21Hands,totalHits;
        int firstBelow100Hand; double firstBelow100Bank,firstBelow100Amount;
        int handsBelow100,recoveryEpisodes,successfulRecoveries,failedRecoveries;
        long cardsConsumed;
        double minWager=Double.POSITIVE_INFINITY,maxWager=0,wagerSum;
        double totalAbsMovement,upMovement,downMovement;
        int tierTransitions,repeatedTierVisits,directionReversals;
        boolean reached150;
        int handReached150;

        boolean reached200,exhausted,tableExit;
        int targetHand,bankruptcyHand,tableExitHand;
    }

    static double wager317(int hand,double bank,int[]hist,int hc,
                           boolean[] coolingBox,boolean[] cautiousBox,
                           boolean[] negBox,boolean[] brakeBox,boolean[] everPlungeBox){
        boolean cooling=coolingBox[0], cautious=cautiousBox[0];
        boolean negativeEpisode=negBox[0], brakeArmed=brakeBox[0];
        if(cooling&&bank>=120){cooling=false;cautious=true;}
        if(cautious&&bank>=140)cautious=false;
        double requested;
        if(cooling){requested=10.0;negativeEpisode=false;brakeArmed=false;}
        else if(cautious){requested=cautious355(hist,hc);negativeEpisode=false;brakeArmed=false;}
        else if(hand>8&&bank>=140){
            int b=bal355(hist,hc);boolean negv=b<0;
            if(negv&&!negativeEpisode)brakeArmed=true;
            negativeEpisode=negv;
            double base=bank>=170.0?15.0:normal355(hand,bank);
            requested=brakeArmed?Math.min(base,15.0):base;
            if(brakeArmed)brakeArmed=false;
        }else{requested=normal355(hand,bank);negativeEpisode=false;brakeArmed=false;}
        if(!cooling&&!cautious&&hand>8&&bank>=130)everPlungeBox[0]=true;
        coolingBox[0]=cooling;cautiousBox[0]=cautious;negBox[0]=negativeEpisode;brakeBox[0]=brakeArmed;
        return casinoWager270(requested,bank);
    }

    static boolean frozenPairGate317(Hand h,int up,double bank,double wager){
        boolean pair=splitEligibleByStoredValue(h.c.get(0),h.c.get(1));
        boolean affordable=bank>=2*wager-1e-9;
        boolean pair20=pair&&h.total()==20;
        boolean v10=pair20&&up==10&&affordable, v8=pair20&&up==8&&affordable;
        boolean wants=pair;
        if(v10||v8)wants=false;
        if(wants&&!affordable)wants=false;
        return wants;
    }

    static Round317 hitRound317(int[]shoe,int pointer,double bank,double wager){
        int[]ptr={pointer}; Hand p=new Hand(),d=new Hand();
        p.c.add(draw(shoe,ptr));d.c.add(draw(shoe,ptr));
        p.c.add(draw(shoe,ptr));d.c.add(draw(shoe,ptr));
        Round317 r=new Round317();r.stake=wager;
        if(p.blackjack())r.playerNaturals++;
        if(d.blackjack())r.dealerNaturals++;

        if(!p.blackjack()&&!d.blackjack()){
            while(!p.bust()&&p.total()<21){p.c.add(draw(shoe,ptr));r.hits++;}
            if(!p.bust()&&p.total()==21)r.reached21Hands++;
        }else if(p.blackjack())r.reached21Hands++;

        if(!p.bust()&&!d.blackjack())while(d.total()<17)d.c.add(draw(shoe,ptr));

        double x;
        if(p.blackjack()&&!d.blackjack())x=1.5*wager;
        else if(d.blackjack()&&!p.blackjack())x=-wager;
        else if(p.blackjack()&&d.blackjack())x=0;
        else if(p.bust()){x=-wager;r.playerBusts++;}
        else if(d.bust()||p.total()>d.total())x=wager;
        else if(p.total()<d.total())x=-wager;
        else x=0;
        r.net=x;
        if(x>1e-9)r.wins++;else if(x<-1e-9)r.losses++;else r.pushes++;
        r.endPointer=ptr[0];r.cardsConsumed=ptr[0]-pointer;return r;
    }

    static Round317 referenceRound317(int[]shoe,int pointer,double bank,double wager,boolean coolingBefore){
        int[]ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));
        initial.c.add(draw(shoe,ptr));dealer.c.add(draw(shoe,ptr));

        Round317 r=new Round317();
        if(initial.blackjack())r.playerNaturals++;
        if(dealer.blackjack())r.dealerNaturals++;

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean affordable=bank>=2*wager-1e-9;
        int up=dealer.c.get(0);
        boolean pair20=pair&&initial.total()==20;
        boolean v10=pair20&&up==10&&affordable, v8=pair20&&up==8&&affordable;

        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                &&selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Switch=coolingBefore&&hard11Candidate&&affordable;

        boolean wantsSplit=pair;
        if(v10||v8)wantsSplit=false;
        if(wantsSplit&&!affordable)wantsSplit=false;

        ArrayList<Hand> hands=new ArrayList<>();
        ArrayList<Double> stakes=new ArrayList<>();
        ArrayList<Boolean> natural=new ArrayList<>();
        ArrayList<Boolean> splitChild=new ArrayList<>();

        if(wantsSplit){
            r.splits++;
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw(shoe,ptr));b.c.add(draw(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if((v10||v8)&&!wantsSplit)continue;

            if(hard11Switch&&!wantsSplit){
                h.c.add(draw(shoe,ptr));r.hits++;first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw(shoe,ptr));r.hits++;
                }
                continue;
            }

            if(!h.blackjack()&&!dealer.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i)):textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(bank<committed+wager-1e-9){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw(shoe,ptr));r.hits++;first=false;continue;
                        }
                        r.doubles++;stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw(shoe,ptr));r.hits++;break;
                    }
                    h.c.add(draw(shoe,ptr));r.hits++;first=false;
                }
            }
        }

        boolean live=false;
        for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&!ph.blackjack())x=-st;
            else if(natural.get(i)&&ph.blackjack()&&dealer.blackjack())x=0;
            else if(ph.bust()){x=-st;r.playerBusts++;}
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            if(ph.total()==21&&!ph.bust())r.reached21Hands++;
            if(x>1e-9)r.wins++;else if(x<-1e-9)r.losses++;else r.pushes++;
            net+=x;
        }
        r.net=net;r.stake=stake;r.endPointer=ptr[0];r.cardsConsumed=ptr[0]-pointer;return r;
    }

    static int tier321(double bank){
        if(bank<15)return 0; if(bank<100)return 1; if(bank<110)return 2;
        if(bank<120)return 3; if(bank<130)return 4; if(bank<140)return 5;
        if(bank<150)return 6; if(bank<160)return 7; if(bank<170)return 8;
        if(bank<180)return 9; if(bank<190)return 10; if(bank<200)return 11;
        return 12;
    }

    static Session317 runArm317(long seed,String cohort,int session,boolean hitArm){
        int[]shoe=sixDeckShoe(sessionSeed(seed,session));
        if(!auditShoe(shoe))throw new IllegalStateException("Inventory audit failed");

        int ptr=0,hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,trough=START_BANK,maxDD=0;
        boolean[]cooling={false},cautious={false},neg={false},brake={false},ever={false};
        boolean inRecovery=false;
        int lastTier=tier321(bank),lastDirection=0;
        boolean[] seenTier=new boolean[13]; seenTier[lastTier]=true;

        Session317 s=new Session317();s.cohort=cohort;s.arm=hitArm?"HIT_CONTROL":"FROZEN_REFERENCE";s.session=session+1;

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200||bank<=0)break;
            double wager=wager317(hand,bank,hist,hc,cooling,cautious,neg,brake,ever);
            if(wager<=0){
                if(bank>0&&bank<15-1e-9){s.tableExit=true;s.tableExitHand=hand;}
                break;
            }

            s.minWager=Math.min(s.minWager,wager);s.maxWager=Math.max(s.maxWager,wager);s.wagerSum+=wager;
            double before=bank;
            Round317 r=hitArm?hitRound317(shoe,ptr,bank,wager):referenceRound317(shoe,ptr,bank,wager,cooling[0]);
            ptr=r.endPointer;s.cumulativeWager+=r.stake;s.cardsConsumed+=r.cardsConsumed;
            s.wins+=r.wins;s.losses+=r.losses;s.pushes+=r.pushes;s.playerNaturals+=r.playerNaturals;
            s.dealerNaturals+=r.dealerNaturals;s.playerBusts+=r.playerBusts;s.doubles+=r.doubles;s.splits+=r.splits;
            s.reached21Hands+=r.reached21Hands;s.totalHits+=r.hits;

            bank+=r.net;if(bank<0)bank=0;s.handsPlayed++;

            double move=Math.abs(bank-before);
            s.totalAbsMovement+=move;
            if(bank>before)s.upMovement+=bank-before;
            else if(bank<before)s.downMovement+=before-bank;

            int direction=bank>before?1:(bank<before?-1:0);
            if(direction!=0){
                if(lastDirection!=0&&direction!=lastDirection)s.directionReversals++;
                lastDirection=direction;
            }

            int nowTier=tier321(bank);
            if(nowTier!=lastTier){
                s.tierTransitions++;
                if(seenTier[nowTier])s.repeatedTierVisits++;
                seenTier[nowTier]=true; lastTier=nowTier;
            }

            if(!s.reached150&&bank>=150){s.reached150=true;s.handReached150=hand;}
            if(bank<100){
                s.handsBelow100++;
                if(s.firstBelow100Hand==0){s.firstBelow100Hand=hand;s.firstBelow100Bank=bank;s.firstBelow100Amount=100-bank;}
            }
            peak=Math.max(peak,bank);trough=Math.min(trough,bank);maxDD=Math.max(maxDD,peak-bank);
            if(!inRecovery&&before>=100&&bank<100){inRecovery=true;s.recoveryEpisodes++;}
            else if(inRecovery&&bank>=100){inRecovery=false;s.successfulRecoveries++;}
            hist[hc%hist.length]=r.net>1e-9?1:(r.net<-1e-9?-1:0);hc++;
            if(bank>=200){s.reached200=true;s.targetHand=hand;break;}
            if(bank<=0){s.exhausted=true;s.bankruptcyHand=hand;break;}
            if(ever[0]&&bank<=100&&!cooling[0]){cooling[0]=true;cautious[0]=false;neg[0]=false;brake[0]=false;}
        }

        if(inRecovery)s.failedRecoveries++;
        s.finalBank=bank;s.peakBank=peak;s.troughBank=trough;s.maxDrawdown=maxDD;s.peakGiveBack=Math.max(0,peak-bank);
        if(s.minWager==Double.POSITIVE_INFINITY)s.minWager=0;
        return s;
    }

    static String csv317(ArrayList<Session317> rows){
        StringBuilder b=new StringBuilder(
          "cohort,arm,session,hands_played,final_bank,peak_bank,trough_bank,max_drawdown,cumulative_wager,"+
          "wins,losses,pushes,player_naturals,dealer_naturals,player_busts,doubles,splits,reached21_hands,total_hits,"+
          "first_below_100_hand,first_below_100_bank,first_below_100_amount,hands_below_100,recovery_episodes,"+
          "successful_recoveries,failed_recoveries,cards_consumed,min_wager,max_wager,mean_base_wager,"+
          "reached_200,target_hand,exhausted,bankruptcy_hand,table_exit,table_exit_hand,peak_giveback,total_abs_movement,up_movement,down_movement,tier_transitions,repeated_tier_visits,direction_reversals,reached_150,hand_reached_150\n");

        for(Session317 s:rows){
            b.append(s.cohort).append(",").append(s.arm).append(",").append(s.session).append(",")
             .append(s.handsPlayed).append(",").append(String.format(Locale.US,"%.2f",s.finalBank)).append(",")
             .append(String.format(Locale.US,"%.2f",s.peakBank)).append(",").append(String.format(Locale.US,"%.2f",s.troughBank)).append(",")
             .append(String.format(Locale.US,"%.2f",s.maxDrawdown)).append(",").append(String.format(Locale.US,"%.2f",s.cumulativeWager)).append(",")
             .append(s.wins).append(",").append(s.losses).append(",").append(s.pushes).append(",")
             .append(s.playerNaturals).append(",").append(s.dealerNaturals).append(",").append(s.playerBusts).append(",")
             .append(s.doubles).append(",").append(s.splits).append(",").append(s.reached21Hands).append(",").append(s.totalHits).append(",")
             .append(s.firstBelow100Hand).append(",").append(String.format(Locale.US,"%.2f",s.firstBelow100Bank)).append(",")
             .append(String.format(Locale.US,"%.2f",s.firstBelow100Amount)).append(",").append(s.handsBelow100).append(",")
             .append(s.recoveryEpisodes).append(",").append(s.successfulRecoveries).append(",").append(s.failedRecoveries).append(",")
             .append(s.cardsConsumed).append(",").append(String.format(Locale.US,"%.2f",s.minWager)).append(",")
             .append(String.format(Locale.US,"%.2f",s.maxWager)).append(",")
             .append(String.format(Locale.US,"%.3f",(s.handsPlayed==0?0:s.wagerSum/s.handsPlayed))).append(",")
             .append(s.reached200).append(",").append(s.targetHand).append(",").append(s.exhausted).append(",")
             .append(s.bankruptcyHand).append(",").append(s.tableExit).append(",").append(s.tableExitHand).append(",")
             .append(String.format(Locale.US,"%.2f",s.peakGiveBack)).append(",")
             .append(String.format(Locale.US,"%.2f",s.totalAbsMovement)).append(",")
             .append(String.format(Locale.US,"%.2f",s.upMovement)).append(",")
             .append(String.format(Locale.US,"%.2f",s.downMovement)).append(",")
             .append(s.tierTransitions).append(",").append(s.repeatedTierVisits).append(",")
             .append(s.directionReversals).append(",").append(s.reached150).append(",")
             .append(s.handReached150).append("\n");
        }
        return b.toString();
    }

    public static void main3330Archive(String[]args)throws Exception{
        System.out.println("CODE VERSION: Deterministic Blackjack Phase 3.330");
        System.out.println("CODE BUILD TAG: DBDE-3.330-REFINED-OUTCOME-REPRESENTATION-VALIDATION");
        System.out.println("HIT CONTROL: HIT below 21; stop at 21/bust; no DOUBLE/SPLIT.");
        System.out.println("WAGER RULE: £15 minimum, £5 increments, table exit below £15.");

        ArrayList<Session317> all=new ArrayList<>();
        for(int k=0;k<SEEDS317.length;k++){
            for(int s=0;s<SESSIONS317;s++){
                all.add(runArm317(SEEDS317[k],COHORTS317[k],s,false));
            }
        }

        write("Phase_3_330_Fresh_Replication_Raw.csv",csv317(all));
        System.out.println("Frozen-reference sessions: "+all.size());
        System.out.println("Independent full-arm replication complete.");
    }
    // =======================================================================
    // PHASE 3.335 — FRESH PAIRED EXIT / SWEET-SPOT FRONTIER EXECUTION
    // Frozen prospectively in Phase 3.334.
    // =======================================================================
    static final long[] P335_SEEDS={370101L,370201L};
    static final String[] P335_COHORTS={"PRIMARY","HOLDOUT"};
    static final int P335_PER_COHORT=10000;
    static final int P335_CUT=209;
    static final int[] P335_TARGETS={110,120,130,140,150,160,170,180,190,200};

    static final class Shoe335{
        long seed; int shoeIndex=0,ptr=0,resets=0; int[] shoe;
        Shoe335(long s){seed=s;shoe=newShoe();}
        int[] newShoe(){return sixDeckShoe(sessionSeed(seed,2000000+shoeIndex));}
        void reset(){shoeIndex++;shoe=newShoe();ptr=0;resets++;}
    }

    static final class S335{
        String cohort; int session,hands; double finalBank,exposure,maxDD,peak;
        boolean tableExit,reached200;
        int[] reachHand=new int[10];
        double[] reachBank=new double[10],reachExposure=new double[10],reachDD=new double[10];
        S335(){java.util.Arrays.fill(reachHand,-1);java.util.Arrays.fill(reachBank,Double.NaN);
               java.util.Arrays.fill(reachExposure,Double.NaN);java.util.Arrays.fill(reachDD,Double.NaN);}
    }

    static S335 run335Reference(Shoe335 st,String cohort,int session){
        S335 s=new S335(); s.cohort=cohort;s.session=session+1;
        int hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxDD=0;
        boolean[]cooling={false},cautious={false},neg={false},brake={false},ever={false};

        if(st.ptr>=P335_CUT)st.reset();

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200-1e-9||bank<=1e-9)break;
            if(bank<15-1e-9){s.tableExit=true;break;}
            if(st.ptr>=P335_CUT)st.reset(); // physical cut-card: between hands only

            double wager=wager317(hand,bank,hist,hc,cooling,cautious,neg,brake,ever);
            if(wager<=0){if(bank>0&&bank<15-1e-9)s.tableExit=true;break;}

            Round317 r=referenceRound317(st.shoe,st.ptr,bank,wager,cooling[0]);
            st.ptr=r.endPointer; cum+=r.stake; bank+=r.net;if(bank<0)bank=0; hc++;
            peak=Math.max(peak,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[(hc-1)%hist.length]=r.net>1e-9?1:(r.net<-1e-9?-1:0);

            for(int i=0;i<P335_TARGETS.length;i++){
                if(s.reachHand[i]<0 && bank>=P335_TARGETS[i]-1e-9){
                    s.reachHand[i]=hand;s.reachBank[i]=bank;s.reachExposure[i]=cum;s.reachDD[i]=maxDD;
                }
            }
            if(bank>=200-1e-9){s.reached200=true;break;}
            if(ever[0]&&bank<=100&&!cooling[0]){cooling[0]=true;cautious[0]=false;neg[0]=false;brake[0]=false;}
        }
        s.hands=hc;s.finalBank=bank;s.exposure=cum;s.maxDD=maxDD;s.peak=peak;
        return s;
    }

    public static void main3335Archive(String[]args)throws Exception{
        System.out.println("CODE VERSION: Deterministic Blackjack Phase 3.335");
        System.out.println("CODE BUILD TAG: DBDE-3.335-FRESH-PAIRED-EXIT-SWEET-SPOT-FRONTIER");
        System.out.println("FROZEN FRONTIER: £110..£200 in £10 steps");
        System.out.println("CASINO RULE: £15 minimum / £5 ordinary increments / table exit below £15");
        System.out.println("SHOE: persistent six-deck / 209-card cut point / reshuffle between hands");
        System.out.println("POPULATION: 10,000 Primary + 10,000 Holdout fresh session identities");

        StringBuilder ref=new StringBuilder("cohort,session,hands,final_bankroll,cumulative_wager,max_drawdown,peak_bankroll,table_exit,reached_200\n");
        StringBuilder arms=new StringBuilder(
          "cohort,session,arm,target,reached,target_hand,target_exit_bankroll,target_exposure,target_max_drawdown,"+
          "reference_final_bankroll,candidate_final_bankroll,paired_final_delta,giveback_avoided,reference_exposure,candidate_exposure,"+
          "exposure_saved,reference_hands,candidate_hands,reference_table_exit,candidate_table_exit,reference_reached_200,lost_later_200\n");

        for(int c=0;c<P335_SEEDS.length;c++){
            Shoe335 st=new Shoe335(P335_SEEDS[c]);
            for(int n=0;n<P335_PER_COHORT;n++){
                S335 s=run335Reference(st,P335_COHORTS[c],n);
                ref.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s%n",
                    s.cohort,s.session,s.hands,s.finalBank,s.exposure,s.maxDD,s.peak,s.tableExit,s.reached200));
                for(int i=0;i<P335_TARGETS.length;i++){
                    int t=P335_TARGETS[i];boolean reached=s.reachHand[i]>=0;
                    double cb=reached?s.reachBank[i]:s.finalBank;
                    double ce=reached?s.reachExposure[i]:s.exposure;
                    double cd=reached?s.reachDD[i]:s.maxDD;
                    int ch=reached?s.reachHand[i]:s.hands;
                    boolean cexit=reached?false:s.tableExit;
                    double delta=cb-s.finalBank;
                    double give=Math.max(0,delta);
                    boolean lost=(t<200)&&reached&&s.reached200;
                    arms.append(String.format(Locale.US,
                      "%s,%d,EXIT_%d,%d,%s,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%s,%s,%s,%s%n",
                      s.cohort,s.session,t,t,reached,reached?s.reachHand[i]:-1,
                      reached?s.reachBank[i]:Double.NaN,reached?s.reachExposure[i]:Double.NaN,
                      reached?s.reachDD[i]:Double.NaN,s.finalBank,cb,delta,give,s.exposure,ce,s.exposure-ce,
                      s.hands,ch,s.tableExit,cexit,s.reached200,lost));
                }
            }
        }
        write("Phase_3_335_Reference_Raw.csv",ref.toString());
        write("Phase_3_335_Exit_Frontier_Paired_Raw.csv",arms.toString());
        System.out.println("Execution complete.");
    }

    // =======================================================================
    // PHASE 3.339 — FRESH INDIVIDUAL SESSION-TERMINATION EXECUTION
    // Contract prospectively frozen in Phase 3.338.
    // Every tested termination rule is a pure prefix stop on the unchanged
    // reference trajectory. This gives exact paired pre-stop counterfactuals:
    // candidate and reference are identical until the candidate terminates.
    // =======================================================================
    static final long[] P339_SEEDS={420101L,420201L};
    static final String[] P339_COHORTS={"PRIMARY","HOLDOUT"};
    static final int P339_N=10000;

    static final String[] P339_ARMS={
        "REFERENCE_30",
        "HORIZON_10","HORIZON_20",
        "EXIT_110","EXIT_150","EXIT_190",
        "STOP_D40_6",
        "TRAIL_150_GIVEBACK_25",
        "EXPOSURE_200","EXPOSURE_300","EXPOSURE_400"
    };

    static final class Path339 {
        String cohort; int session;
        int hands; boolean tableExit,reached200;
        double finalBank,finalExposure,finalMaxDD,finalPeak;
        double[] bank=new double[HANDS+1];
        double[] exposure=new double[HANDS+1];
        double[] maxdd=new double[HANDS+1];
        double[] peak=new double[HANDS+1];
        double[] roundStake=new double[HANDS+1];
        boolean[] common200=new boolean[HANDS+1];
        boolean[] belowMinAfter=new boolean[HANDS+1];
        Path339(){
            bank[0]=START_BANK; exposure[0]=0; maxdd[0]=0; peak[0]=START_BANK;
        }
    }

    static Path339 run339Reference(Shoe335 st,String cohort,int session){
        Path339 s=new Path339(); s.cohort=cohort; s.session=session+1;
        int hc=0; int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,cum=0,maxDD=0;
        boolean[]cooling={false},cautious={false},neg={false},brake={false},ever={false};

        if(st.ptr>=P335_CUT)st.reset();

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200-1e-9){s.reached200=true;break;}
            if(bank<=1e-9)break;
            if(bank<15-1e-9){s.tableExit=true;break;}
            if(st.ptr>=P335_CUT)st.reset();

            double wager=wager317(hand,bank,hist,hc,cooling,cautious,neg,brake,ever);
            if(wager<=0){
                if(bank>0&&bank<15-1e-9)s.tableExit=true;
                break;
            }

            Round317 r=referenceRound317(st.shoe,st.ptr,bank,wager,cooling[0]);
            st.ptr=r.endPointer;
            cum+=r.stake;
            bank+=r.net;
            if(bank<0)bank=0;
            hc++;

            peak=Math.max(peak,bank);
            maxDD=Math.max(maxDD,peak-bank);
            hist[(hc-1)%hist.length]=r.net>1e-9?1:(r.net<-1e-9?-1:0);

            s.bank[hand]=bank;
            s.exposure[hand]=cum;
            s.maxdd[hand]=maxDD;
            s.peak[hand]=peak;
            s.roundStake[hand]=r.stake;
            s.common200[hand]=bank>=200-1e-9;
            s.belowMinAfter[hand]=(bank>1e-9 && bank<15-1e-9);

            if(bank>=200-1e-9){s.reached200=true;break;}
            if(ever[0]&&bank<=100&&!cooling[0]){
                cooling[0]=true;cautious[0]=false;neg[0]=false;brake[0]=false;
            }
        }

        s.hands=hc;
        s.finalBank=bank;
        s.finalExposure=cum;
        s.finalMaxDD=maxDD;
        s.finalPeak=peak;

        // Preserve the frozen engine's reference table-exit convention:
        // tableExit is set when another hand is attempted below £15.
        return s;
    }

    static final class Arm339 {
        String arm,family;
        int stopHand; boolean activated,tableExit,reached200;
        double finalBank,exposure,maxDD,peak;
        double triggerBank=Double.NaN,triggerPeak=Double.NaN,triggerExposure=Double.NaN;
        int triggerHand=-1;
    }

    static boolean commonTerminalAt(Path339 p,int h){
        if(h<=0)return false;
        if(p.common200[h])return true;
        // If bankroll is below minimum at this settled checkpoint, the common
        // terminal condition takes precedence over a discretionary stop.
        if(p.belowMinAfter[h])return true;
        return false;
    }

    static Arm339 eval339(Path339 p,String arm){
        Arm339 a=new Arm339(); a.arm=arm;
        if(arm.equals("REFERENCE_30")){
            a.family="REFERENCE";
            a.stopHand=p.hands;a.activated=false;
            a.finalBank=p.finalBank;a.exposure=p.finalExposure;a.maxDD=p.finalMaxDD;a.peak=p.finalPeak;
            a.tableExit=p.tableExit;a.reached200=p.reached200;
            return a;
        }

        int stop=-1;
        if(arm.startsWith("HORIZON_")){
            a.family="FIXED_HORIZON";
            int lim=Integer.parseInt(arm.substring("HORIZON_".length()));
            if(p.hands>lim || (p.hands==lim && !commonTerminalAt(p,lim))){
                // If reference has at least lim hands and no common condition
                // occurs on hand lim, the arm terminates after that settlement.
                if(p.hands>=lim && !commonTerminalAt(p,lim))stop=lim;
            }
        } else if(arm.startsWith("EXIT_")){
            a.family="TARGET_EXIT";
            int target=Integer.parseInt(arm.substring("EXIT_".length()));
            for(int h=1;h<=p.hands;h++){
                if(p.bank[h]>=target-1e-9){
                    // £200 common terminal takes precedence.
                    if(!commonTerminalAt(p,h))stop=h;
                    break;
                }
            }
        } else if(arm.equals("STOP_D40_6")){
            a.family="DRAWDOWN_STOP";
            int consec=0;
            for(int h=1;h<=p.hands;h++){
                if(p.peak[h]>100+1e-9 && p.bank[h]<=0.60*p.peak[h]+1e-9)consec++;
                else consec=0;
                if(consec>=6){
                    if(!commonTerminalAt(p,h))stop=h;
                    break;
                }
            }
        } else if(arm.equals("TRAIL_150_GIVEBACK_25")){
            a.family="PEAK_PROFIT_GIVEBACK";
            boolean armed=false;
            for(int h=1;h<=p.hands;h++){
                if(p.bank[h]>=150-1e-9)armed=true;
                if(armed){
                    double profit=p.peak[h]-100.0;
                    double surrendered=p.peak[h]-p.bank[h];
                    if(profit>1e-9 && surrendered/profit>=0.25-1e-12){
                        if(!commonTerminalAt(p,h))stop=h;
                        break;
                    }
                }
            }
        } else if(arm.startsWith("EXPOSURE_")){
            a.family="CUMULATIVE_WAGER_CEILING";
            double ceiling=Double.parseDouble(arm.substring("EXPOSURE_".length()));
            // Stop before NEXT hand if even the minimum legal £15 wager would
            // exceed the ceiling. Check after each settled hand; h=0 cannot
            // trigger for the frozen ceilings.
            for(int h=0;h<p.hands;h++){
                if(h>0 && commonTerminalAt(p,h))break;
                if(p.exposure[h]+15.0>ceiling+1e-9){
                    stop=h;
                    break;
                }
            }
        } else throw new IllegalArgumentException("Unknown arm "+arm);

        if(stop>=0){
            a.activated=true;a.stopHand=stop;
            a.finalBank=p.bank[stop];a.exposure=p.exposure[stop];a.maxDD=p.maxdd[stop];a.peak=p.peak[stop];
            a.tableExit=false;a.reached200=false;
            a.triggerHand=stop;a.triggerBank=a.finalBank;a.triggerPeak=a.peak;a.triggerExposure=a.exposure;
        }else{
            a.activated=false;a.stopHand=p.hands;
            a.finalBank=p.finalBank;a.exposure=p.finalExposure;a.maxDD=p.finalMaxDD;a.peak=p.finalPeak;
            a.tableExit=p.tableExit;a.reached200=p.reached200;
        }
        return a;
    }

    public static void main3340Archive(String[]args)throws Exception{
        System.out.println("CODE VERSION: Deterministic Blackjack Phase 3.340");
        System.out.println("CODE BUILD TAG: DBDE-3.340-INDEPENDENT-FULL-TERMINATION-REPLICATION");
        System.out.println("POPULATION: 10,000 Primary + 10,000 Holdout fresh sessions");
        System.out.println("ARMS: 11 including REFERENCE_30; NO COMBINATIONS");
        System.out.println("CASINO: £100 start / £15 minimum / £5 ordinary increments");
        System.out.println("SHOE: persistent six-deck / 209-card cut / between-hand reshuffle");

        StringBuilder ref=new StringBuilder(
          "cohort,session,hands,final_bankroll,cumulative_wager,max_drawdown,peak_bankroll,table_exit,reached_200\n");
        StringBuilder out=new StringBuilder(
          "cohort,session,arm,family,activated,trigger_hand,trigger_bankroll,trigger_peak,trigger_exposure,"+
          "candidate_hands,candidate_final_bankroll,candidate_exposure,candidate_max_drawdown,candidate_peak,"+
          "candidate_positive,candidate_table_exit,candidate_reached_200,reference_hands,reference_final_bankroll,"+
          "reference_exposure,reference_max_drawdown,reference_table_exit,reference_reached_200,paired_final_delta,"+
          "exposure_saved,giveback_avoided,opportunity_surrendered,reference_later_table_exit\n");

        for(int c=0;c<P339_SEEDS.length;c++){
            Shoe335 st=new Shoe335(P339_SEEDS[c]);
            for(int n=0;n<P339_N;n++){
                Path339 p=run339Reference(st,P339_COHORTS[c],n);
                ref.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s%n",
                    p.cohort,p.session,p.hands,p.finalBank,p.finalExposure,p.finalMaxDD,p.finalPeak,p.tableExit,p.reached200));

                for(String arm:P339_ARMS){
                    Arm339 a=eval339(p,arm);
                    boolean opp=a.activated && p.reached200 && !a.reached200;
                    boolean laterExit=a.activated && p.tableExit;
                    double delta=a.finalBank-p.finalBank;
                    double saved=p.finalExposure-a.exposure;
                    double give=Math.max(0,delta);
                    out.append(String.format(Locale.US,
                      "%s,%d,%s,%s,%s,%d,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%d,%.2f,%.2f,%.2f,%s,%s,%.2f,%.2f,%.2f,%s,%s%n",
                      p.cohort,p.session,a.arm,a.family,a.activated,a.triggerHand,a.triggerBank,a.triggerPeak,a.triggerExposure,
                      a.stopHand,a.finalBank,a.exposure,a.maxDD,a.peak,a.finalBank>100+1e-9,a.tableExit,a.reached200,
                      p.hands,p.finalBank,p.finalExposure,p.finalMaxDD,p.tableExit,p.reached200,delta,saved,give,opp,laterExit));
                }
            }
        }

        write("Phase_3_340_Reference_Raw.csv",ref.toString());
        write("Phase_3_340_Termination_Arms_Paired_Raw.csv",out.toString());
        System.out.println("Execution complete.");
    }

    // =======================================================================
    // PHASE 3.342 — FRESH MINIMAL COMBINATION EXECUTION
    // Frozen prospectively in Phase 3.341.
    // =======================================================================

    static final String[] P342_COMPONENTS={
        "REFERENCE_30","STOP_D40_6","TRAIL_150_GIVEBACK_25","EXPOSURE_200"
    };
    static final String[] P342_COMBOS={
        "COMBO_D40_TRAIL150",
        "COMBO_D40_EXPOSURE200",
        "COMBO_TRAIL150_EXPOSURE200"
    };

    static final class Combo342 {
        String arm,componentA,componentB,triggerClass;
        boolean activated,tableExit,reached200;
        int stopHand=-1;
        double finalBank,exposure,maxDD,peak;
        double triggerBank=Double.NaN,triggerPeak=Double.NaN,triggerExposure=Double.NaN;
        int triggerHand=-1;
    }

    static Combo342 evalCombo342(Path339 p,String combo){
        String aa,bb;
        if(combo.equals("COMBO_D40_TRAIL150")){
            aa="STOP_D40_6";bb="TRAIL_150_GIVEBACK_25";
        }else if(combo.equals("COMBO_D40_EXPOSURE200")){
            aa="STOP_D40_6";bb="EXPOSURE_200";
        }else if(combo.equals("COMBO_TRAIL150_EXPOSURE200")){
            aa="TRAIL_150_GIVEBACK_25";bb="EXPOSURE_200";
        }else throw new IllegalArgumentException(combo);

        Arm339 A=eval339(p,aa), B=eval339(p,bb);
        Combo342 c=new Combo342(); c.arm=combo;c.componentA=aa;c.componentB=bb;

        int ha=A.activated?A.stopHand:Integer.MAX_VALUE;
        int hb=B.activated?B.stopHand:Integer.MAX_VALUE;
        int h=Math.min(ha,hb);

        if(h==Integer.MAX_VALUE){
            c.activated=false;c.triggerClass="NONE";c.stopHand=p.hands;
            c.finalBank=p.finalBank;c.exposure=p.finalExposure;c.maxDD=p.finalMaxDD;c.peak=p.finalPeak;
            c.tableExit=p.tableExit;c.reached200=p.reached200;
            return c;
        }

        c.activated=true;c.stopHand=h;c.triggerHand=h;
        if(ha==hb)c.triggerClass="CO_TRIGGER";
        else if(ha<hb)c.triggerClass="UNIQUE_A";
        else c.triggerClass="UNIQUE_B";

        c.finalBank=p.bank[h];c.exposure=p.exposure[h];c.maxDD=p.maxdd[h];c.peak=p.peak[h];
        c.triggerBank=c.finalBank;c.triggerPeak=c.peak;c.triggerExposure=c.exposure;
        c.tableExit=false;c.reached200=false;
        return c;
    }

    static void append342(StringBuilder out,Path339 p,String arm,String family,boolean activated,
                          String componentA,String componentB,String triggerClass,
                          int triggerHand,double triggerBank,double triggerPeak,double triggerExposure,
                          int candidateHands,double finalBank,double exposure,double maxDD,double peak,
                          boolean tableExit,boolean reached200){
        boolean opp=activated && p.reached200 && !reached200;
        boolean laterExit=activated && p.tableExit;
        double delta=finalBank-p.finalBank;
        double saved=p.finalExposure-exposure;
        double give=Math.max(0,delta);

        out.append(String.format(Locale.US,
          "%s,%d,%s,%s,%s,%s,%s,%s,%d,%.2f,%.2f,%.2f,%d,%.2f,%.2f,%.2f,%.2f,%s,%s,%s,%d,%.2f,%.2f,%.2f,%s,%s,%.2f,%.2f,%.2f,%s,%s%n",
          p.cohort,p.session,arm,family,activated,componentA,componentB,triggerClass,
          triggerHand,triggerBank,triggerPeak,triggerExposure,
          candidateHands,finalBank,exposure,maxDD,peak,finalBank>100+1e-9,tableExit,reached200,
          p.hands,p.finalBank,p.finalExposure,p.finalMaxDD,p.tableExit,p.reached200,
          delta,saved,give,opp,laterExit));
    }

    public static void main3343Archive(String[]args)throws Exception{
        System.out.println("CODE VERSION: Deterministic Blackjack Phase 3.343");
        System.out.println("CODE BUILD TAG: DBDE-3.343-INDEPENDENT-MINIMAL-COMBINATION-REPLICATION");
        System.out.println("POPULATION: 10,000 Primary + 10,000 Holdout fresh sessions");
        System.out.println("SEEDS: 420101 / 420201");
        System.out.println("COMPONENTS: REFERENCE_30, STOP_D40_6, TRAIL_150_GIVEBACK_25, EXPOSURE_200");
        System.out.println("COMBINATIONS: 3 frozen two-rule pairs; NO THREE-WAY");
        System.out.println("TARGET EXIT COMBINATIONS: NONE");
        System.out.println("HORIZON_10 + EXPOSURE_200: EXCLUDED");

        StringBuilder ref=new StringBuilder(
          "cohort,session,hands,final_bankroll,cumulative_wager,max_drawdown,peak_bankroll,table_exit,reached_200\n");
        StringBuilder out=new StringBuilder(
          "cohort,session,arm,family,activated,component_a,component_b,trigger_class,trigger_hand,trigger_bankroll,trigger_peak,trigger_exposure,"+
          "candidate_hands,candidate_final_bankroll,candidate_exposure,candidate_max_drawdown,candidate_peak,candidate_positive,candidate_table_exit,candidate_reached_200,"+
          "reference_hands,reference_final_bankroll,reference_exposure,reference_max_drawdown,reference_table_exit,reference_reached_200,"+
          "paired_final_delta,exposure_saved,giveback_avoided,opportunity_surrendered,reference_later_table_exit\n");

        for(int ci=0;ci<P339_SEEDS.length;ci++){
            Shoe335 st=new Shoe335(P339_SEEDS[ci]);
            for(int n=0;n<P339_N;n++){
                Path339 p=run339Reference(st,P339_COHORTS[ci],n);

                ref.append(String.format(Locale.US,"%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%s,%s%n",
                    p.cohort,p.session,p.hands,p.finalBank,p.finalExposure,p.finalMaxDD,p.finalPeak,p.tableExit,p.reached200));

                for(String arm:P342_COMPONENTS){
                    Arm339 a=eval339(p,arm);
                    append342(out,p,arm,a.family,a.activated,"","","NONE",
                        a.triggerHand,a.triggerBank,a.triggerPeak,a.triggerExposure,
                        a.stopHand,a.finalBank,a.exposure,a.maxDD,a.peak,a.tableExit,a.reached200);
                }

                for(String combo:P342_COMBOS){
                    Combo342 c=evalCombo342(p,combo);
                    append342(out,p,c.arm,"COMBINATION",c.activated,c.componentA,c.componentB,c.triggerClass,
                        c.triggerHand,c.triggerBank,c.triggerPeak,c.triggerExposure,
                        c.stopHand,c.finalBank,c.exposure,c.maxDD,c.peak,c.tableExit,c.reached200);
                }
            }
        }

        write("Phase_3_343_Reference_Raw.csv",ref.toString());
        write("Phase_3_343_Combination_Paired_Raw.csv",out.toString());
        System.out.println("Independent full minimal-combination replication complete.");
    }


    // =======================================================================
    // PHASE 3.383 — BLACKJACKBENCH INDEPENDENT SEEDED-SHOE FROZEN REPLICATION
    // External shoe ordering: exact Python random.Random(seed).shuffle()
    // construction qualified prospectively in Phase 3.382.
    // PRIMARY seeds 0.. ; HOLDOUT seeds 10000.. .
    // Amit's mature 209-card between-hand cut remains frozen.
    // =======================================================================
    static final String BB383_FILE="/mnt/data/blackjackbench_20k_shoes.bin";
    static final int P383_N=10000;
    static final StringBuilder TRACE388=new StringBuilder("cohort,session,hand,shoe_seed,pointer_start,pointer_end,bank_before,wager,stake,net,bank_after,cooling_before,cards_consumed,card_sequence,hits,doubles,splits,wins,losses,pushes,player_busts,player_naturals,dealer_naturals\\n");

    static final class Shoe383{
        int seedIndex,ptr=0,resets=0; int[] shoe;
        Shoe383(int startSeed)throws Exception{seedIndex=startSeed;shoe=load();}
        int[] load()throws Exception{
            byte[] b=new byte[312];
            try(RandomAccessFile r=new RandomAccessFile(BB383_FILE,"r")){
                r.seek((long)seedIndex*312L); r.readFully(b);
            }
            int[] a=new int[312]; for(int i=0;i<312;i++)a[i]=b[i]&255;
            if(!auditShoe(a))throw new IllegalStateException("External shoe inventory failed seed "+seedIndex);
            return a;
        }
        void reset()throws Exception{seedIndex++;shoe=load();ptr=0;resets++;}
    }

    static final class S383{
        String cohort;int session,hands,shoeStart,shoeEnd;
        double finalBank,peak,trough,maxDD,exposure,totalAbsMovement,giveback;
        int recoveryEpisodes,successfulRecoveries;
        boolean tableExit,reached200;
    }

    static S383 run383(Shoe383 st,String cohort,int session)throws Exception{
        S383 s=new S383();s.cohort=cohort;s.session=session+1;s.shoeStart=st.seedIndex;
        int hc=0;int[]hist=new int[5];
        double bank=START_BANK,peak=START_BANK,trough=START_BANK,cum=0,maxDD=0,absMove=0;
        boolean[]cooling={false},cautious={false},neg={false},brake={false},ever={false};
        boolean below100=false;
        if(st.ptr>=P335_CUT)st.reset();

        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200-1e-9){s.reached200=true;break;}
            if(bank<=1e-9)break;
            if(bank<15-1e-9){s.tableExit=true;break;}
            if(st.ptr>=P335_CUT)st.reset();

            double wager=wager317(hand,bank,hist,hc,cooling,cautious,neg,brake,ever);
            if(wager<=0){if(bank>0&&bank<15-1e-9)s.tableExit=true;break;}

            double before=bank;
            boolean coolingBefore=cooling[0];
            int pointerBefore=st.ptr;
            int shoeSeedThisHand=st.seedIndex;
            Round317 r=referenceRound317(st.shoe,st.ptr,bank,wager,cooling[0]);
            st.ptr=r.endPointer;cum+=r.stake;bank+=r.net;if(bank<0)bank=0;hc++;
            StringBuilder cs=new StringBuilder();
            for(int ci=pointerBefore;ci<r.endPointer;ci++){if(ci>pointerBefore)cs.append("-");cs.append(st.shoe[ci]);}
            TRACE388.append(String.format(Locale.US,
                "%s,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%d,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
                cohort,session+1,hand,shoeSeedThisHand,pointerBefore,r.endPointer,before,wager,r.stake,r.net,bank,
                coolingBefore,r.cardsConsumed,cs.toString(),r.hits,r.doubles,r.splits,r.wins,r.losses,r.pushes,
                r.playerBusts,r.playerNaturals,r.dealerNaturals));
            absMove+=Math.abs(bank-before);
            peak=Math.max(peak,bank);trough=Math.min(trough,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[(hc-1)%hist.length]=r.net>1e-9?1:(r.net<-1e-9?-1:0);

            if(!below100 && bank<100-1e-9){below100=true;s.recoveryEpisodes++;}
            if(below100 && bank>=100-1e-9){below100=false;s.successfulRecoveries++;}

            if(bank>=200-1e-9){s.reached200=true;break;}
            if(ever[0]&&bank<=100&&!cooling[0]){cooling[0]=true;cautious[0]=false;neg[0]=false;brake[0]=false;}
        }
        s.hands=hc;s.finalBank=bank;s.peak=peak;s.trough=trough;s.maxDD=maxDD;s.exposure=cum;
        s.totalAbsMovement=absMove;s.giveback=Math.max(0,peak-bank);s.shoeEnd=st.seedIndex;
        return s;
    }


    // =======================================================================
    // PHASE 3.391 — DEALER-NATURAL TIMING COUNTERFACTUAL
    // Currency/denominations remain the frozen UK-facing GBP execution layer.
    // Only dealer-natural transaction timing differs between arms.
    // =======================================================================
    enum Timing391 { FROZEN_3388, STRICT_PRE_RESOLUTION, NO_CHECK_ALL_BETS_LOSE }

    static final String P391_PREFIX_FILE="Phase_3_394_Full_Shoes.csv";
    static final HashMap<Integer,int[]> P391_SHOES=new HashMap<>();

    static void load391Prefixes()throws Exception{
        try(BufferedReader br=new BufferedReader(new FileReader(P391_PREFIX_FILE))){
            String line=br.readLine();
            while((line=br.readLine())!=null){
                int comma=line.indexOf(',');
                int seed=Integer.parseInt(line.substring(0,comma));
                String[] z=line.substring(comma+1).split("-");
                int[] a=new int[z.length];
                for(int i=0;i<z.length;i++)a[i]=Integer.parseInt(z[i]);
                P391_SHOES.put(seed,a);
            }
        }
    }

    static final class Shoe391{
        int seedIndex,ptr=0; int[]shoe;
        Shoe391(int seed)throws Exception{seedIndex=seed;load();}
        void load()throws Exception{
            shoe=P391_SHOES.get(seedIndex);
            if(shoe==null)throw new IllegalStateException("No reconstructed prefix for seed "+seedIndex);
        }
        void reset()throws Exception{seedIndex++;ptr=0;load();}
    }

    static int draw391(int[]shoe,int[]ptr){
        if(ptr[0]>=shoe.length)throw new IllegalStateException("Reconstructed prefix exhausted at pointer "+ptr[0]+" / "+shoe.length);
        return shoe[ptr[0]++];
    }

    static Round317 round391(int[]shoe,int pointer,double bank,double wager,boolean coolingBefore,Timing391 mode){
        if(mode==Timing391.FROZEN_3388)return referenceRound317(shoe,pointer,bank,wager,coolingBefore);
        int[]ptr={pointer};
        Hand initial=new Hand(),dealer=new Hand();
        initial.c.add(draw391(shoe,ptr));dealer.c.add(draw391(shoe,ptr));
        initial.c.add(draw391(shoe,ptr));dealer.c.add(draw391(shoe,ptr));
        Round317 r=new Round317();
        if(initial.blackjack())r.playerNaturals++;
        if(dealer.blackjack())r.dealerNaturals++;

        // Strict pre-resolution: dealer natural ends the hand before split/hit/double.
        if(mode==Timing391.STRICT_PRE_RESOLUTION && dealer.blackjack()){
            r.stake=wager;
            if(initial.blackjack()){r.net=0;r.pushes++;}
            else {r.net=-wager;r.losses++;}
            r.endPointer=ptr[0];r.cardsConsumed=ptr[0]-pointer;
            return r;
        }

        boolean pair=splitEligibleByStoredValue(initial.c.get(0),initial.c.get(1));
        boolean affordable=bank>=2*wager-1e-9;
        int up=dealer.c.get(0);
        boolean pair20=pair&&initial.total()==20;
        boolean v10=pair20&&up==10&&affordable, v8=pair20&&up==8&&affordable;
        boolean hard11Candidate=(!pair)&&(!initial.soft())&&initial.total()==11&&up==10
                &&selectiveFirst167(initial,up,false)==Action.DOUBLE;
        boolean hard11Switch=coolingBefore&&hard11Candidate&&affordable;
        boolean wantsSplit=pair;
        if(v10||v8)wantsSplit=false;
        if(wantsSplit&&!affordable)wantsSplit=false;

        ArrayList<Hand>hands=new ArrayList<>();
        ArrayList<Double>stakes=new ArrayList<>();
        ArrayList<Boolean>natural=new ArrayList<>();
        ArrayList<Boolean>splitChild=new ArrayList<>();
        if(wantsSplit){
            r.splits++;
            Hand a=new Hand(),b=new Hand();
            a.c.add(initial.c.get(0));b.c.add(initial.c.get(1));
            a.c.add(draw391(shoe,ptr));b.c.add(draw391(shoe,ptr));
            hands.add(a);hands.add(b);stakes.add(wager);stakes.add(wager);
            natural.add(false);natural.add(false);splitChild.add(true);splitChild.add(true);
        }else{
            hands.add(initial);stakes.add(wager);natural.add(true);splitChild.add(false);
        }

        double committed=hands.size()*wager;
        for(int i=0;i<hands.size();i++){
            Hand h=hands.get(i);boolean first=true;
            if((v10||v8)&&!wantsSplit)continue;
            if(hard11Switch&&!wantsSplit){
                h.c.add(draw391(shoe,ptr));r.hits++;first=false;
                while(!h.bust()){
                    Action a=textbook(h,up,false);
                    if(a==Action.STAND)break;
                    h.c.add(draw391(shoe,ptr));r.hits++;
                }
                continue;
            }
            // In NO_CHECK, dealer natural is deliberately NOT a decision gate.
            if(!h.blackjack()){
                while(!h.bust()){
                    Action a=(first?selectiveFirst167(h,up,splitChild.get(i)):textbook(h,up,false));
                    if(a==Action.STAND)break;
                    if(a==Action.DOUBLE&&first){
                        if(bank<committed+wager-1e-9){
                            Action fb=textbook(h,up,true);
                            if(fb==Action.DOUBLE)fb=Action.HIT;
                            if(fb==Action.STAND)break;
                            h.c.add(draw391(shoe,ptr));r.hits++;first=false;continue;
                        }
                        r.doubles++;stakes.set(i,stakes.get(i)*2.0);committed+=wager;
                        h.c.add(draw391(shoe,ptr));r.hits++;break;
                    }
                    h.c.add(draw391(shoe,ptr));r.hits++;first=false;
                }
            }
        }

        boolean live=false;for(Hand h:hands)if(!h.bust())live=true;
        if(live&&!dealer.blackjack())while(dealer.total()<17)dealer.c.add(draw391(shoe,ptr));

        double net=0,stake=0;
        for(int i=0;i<hands.size();i++){
            Hand ph=hands.get(i);double st=stakes.get(i),x;stake+=st;
            if(natural.get(i)&&ph.blackjack()&&!dealer.blackjack())x=1.5*st;
            else if(natural.get(i)&&dealer.blackjack()&&ph.blackjack())x=0;
            else if(dealer.blackjack())x=-st; // no-check: all committed split/double stakes lose
            else if(ph.bust()){x=-st;r.playerBusts++;}
            else if(dealer.bust()||ph.total()>dealer.total())x=st;
            else if(ph.total()<dealer.total())x=-st;
            else x=0;
            if(ph.total()==21&&!ph.bust())r.reached21Hands++;
            if(x>1e-9)r.wins++;else if(x<-1e-9)r.losses++;else r.pushes++;
            net+=x;
        }
        r.net=net;r.stake=stake;r.endPointer=ptr[0];r.cardsConsumed=ptr[0]-pointer;return r;
    }

    static final class SessionTiming391{
        String cohort,arm;int session,hands,shoeStart,shoeEnd,firstDealerNaturalHand,firstDivergenceHand;
        double finalBank,peak,trough,maxDD,exposure;
        boolean tableExit,reached200;
        long cards,splits,doubles,dealerNaturals,wins,losses,pushes,playerNaturals,hits;
    }

    static SessionTiming391 run391(Shoe391 st,String cohort,int session,Timing391 mode)throws Exception{
        SessionTiming391 s=new SessionTiming391();s.cohort=cohort;s.arm=mode.toString();s.session=session+1;s.shoeStart=st.seedIndex;
        int hc=0;int[]hist=new int[5];double bank=START_BANK,peak=START_BANK,trough=START_BANK,maxDD=0,cum=0;
        boolean[]cooling={false},cautious={false},neg={false},brake={false},ever={false};
        if(st.ptr>=P335_CUT)st.reset();
        for(int hand=1;hand<=HANDS;hand++){
            if(bank>=200-1e-9){s.reached200=true;break;}
            if(bank<=1e-9)break;
            if(bank<15-1e-9){s.tableExit=true;break;}
            if(st.ptr>=P335_CUT)st.reset();
            double wager=wager317(hand,bank,hist,hc,cooling,cautious,neg,brake,ever);
            if(wager<=0){if(bank>0&&bank<15-1e-9)s.tableExit=true;break;}
            int beforePtr=st.ptr;double before=bank;
            Round317 r=round391(st.shoe,st.ptr,bank,wager,cooling[0],mode);
            st.ptr=r.endPointer;bank+=r.net;if(bank<0)bank=0;hc++;cum+=r.stake;
            s.cards+=r.cardsConsumed;s.splits+=r.splits;s.doubles+=r.doubles;s.dealerNaturals+=r.dealerNaturals;
            s.wins+=r.wins;s.losses+=r.losses;s.pushes+=r.pushes;s.playerNaturals+=r.playerNaturals;s.hits+=r.hits;
            if(r.dealerNaturals>0&&s.firstDealerNaturalHand==0)s.firstDealerNaturalHand=hand;
            peak=Math.max(peak,bank);trough=Math.min(trough,bank);maxDD=Math.max(maxDD,peak-bank);
            hist[(hc-1)%hist.length]=r.net>1e-9?1:(r.net<-1e-9?-1:0);
            if(bank>=200-1e-9){s.reached200=true;break;}
            if(ever[0]&&bank<=100&&!cooling[0]){cooling[0]=true;cautious[0]=false;neg[0]=false;brake[0]=false;}
        }
        s.hands=hc;s.finalBank=bank;s.peak=peak;s.trough=trough;s.maxDD=maxDD;s.exposure=cum;s.shoeEnd=st.seedIndex;
        return s;
    }

    static ArrayList<SessionTiming391> cohort391(int startSeed,String cohort,Timing391 mode)throws Exception{
        ArrayList<SessionTiming391>a=new ArrayList<>();
        for(int n=0;n<P383_N;n++){
            // Phase 3.394 common-start design: each complete session starts from
            // the same fresh deterministic shoe seed in every arm.
            Shoe391 st=new Shoe391(startSeed+n);
            a.add(run391(st,cohort,n,mode));
        }
        return a;
    }

    static String summary391(ArrayList<SessionTiming391>a){
        double fb=0,exp=0,dd=0;long target=0,exit=0,dn=0,cards=0,splits=0,doubles=0;
        for(SessionTiming391 s:a){fb+=s.finalBank;exp+=s.exposure;dd+=s.maxDD;if(s.reached200)target++;if(s.tableExit)exit++;dn+=s.dealerNaturals;cards+=s.cards;splits+=s.splits;doubles+=s.doubles;}
        return String.format(Locale.US,"n=%d mean_final=%.4f mean_exposure=%.4f mean_maxDD=%.4f reached200=%d (%.4f%%) table_exit=%d (%.4f%%) dealer_naturals=%d cards=%d splits=%d doubles=%d",
            a.size(),fb/a.size(),exp/a.size(),dd/a.size(),target,100.0*target/a.size(),exit,100.0*exit/a.size(),dn,cards,splits,doubles);
    }

    static void write391Csv(String file,ArrayList<SessionTiming391>...groups)throws Exception{
        StringBuilder b=new StringBuilder("cohort,arm,session,hands,final_bankroll,peak_bankroll,trough_bankroll,max_drawdown,cumulative_wager,table_exit,reached_200,wins,losses,pushes,hits,splits,doubles,player_naturals,dealer_naturals,cards_consumed,shoe_seed_start,shoe_seed_end\n");
        for(ArrayList<SessionTiming391>g:groups)for(SessionTiming391 s:g)b.append(String.format(Locale.US,
            "%s,%s,%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
            s.cohort,s.arm,s.session,s.hands,s.finalBank,s.peak,s.trough,s.maxDD,s.exposure,s.tableExit,s.reached200,
            s.wins,s.losses,s.pushes,s.hits,s.splits,s.doubles,s.playerNaturals,s.dealerNaturals,s.cards,s.shoeStart,s.shoeEnd));
        write(file,b.toString());
    }

    public static void main(String[]args)throws Exception{
        System.out.println("CODE VERSION: Deterministic Blackjack Phase 3.394");
        System.out.println("PURPOSE: common-start complete-session clean Peek vs clean No-Peek comparison.");
        load391Prefixes();

        ArrayList<SessionTiming391> pF=cohort391(0,"PRIMARY",Timing391.FROZEN_3388);
        ArrayList<SessionTiming391> hF=cohort391(10000,"HOLDOUT",Timing391.FROZEN_3388);
        ArrayList<SessionTiming391> pS=cohort391(0,"PRIMARY",Timing391.STRICT_PRE_RESOLUTION);
        ArrayList<SessionTiming391> hS=cohort391(10000,"HOLDOUT",Timing391.STRICT_PRE_RESOLUTION);
        ArrayList<SessionTiming391> pN=cohort391(0,"PRIMARY",Timing391.NO_CHECK_ALL_BETS_LOSE);
        ArrayList<SessionTiming391> hN=cohort391(10000,"HOLDOUT",Timing391.NO_CHECK_ALL_BETS_LOSE);

        write391Csv("Phase_3_394_Full_Session_Raw.csv",pF,hF,pS,hS,pN,hN);

        StringBuilder r=new StringBuilder("PHASE 3.394 — CLEAN PEEK vs NO-PEEK FULL-SESSION COMPARISON\n\n");
        r.append("Each session starts from the same fresh deterministic shoe seed in every arm. ");
        r.append("After play begins, card streams are allowed to diverge naturally. GBP and the frozen wager/controller rules are unchanged.\n\n");
        r.append("HISTORICAL_FROZEN PRIMARY: ").append(summary391(pF)).append("\n");
        r.append("HISTORICAL_FROZEN HOLDOUT: ").append(summary391(hF)).append("\n");
        r.append("CLEAN_PEEK PRIMARY: ").append(summary391(pS)).append("\n");
        r.append("CLEAN_PEEK HOLDOUT: ").append(summary391(hS)).append("\n");
        r.append("CLEAN_NO_PEEK PRIMARY: ").append(summary391(pN)).append("\n");
        r.append("CLEAN_NO_PEEK HOLDOUT: ").append(summary391(hN)).append("\n");
        write("Phase_3_394_Engine_Summary.txt",r.toString());
        System.out.println(r.toString());
    }

}
