<mxfile host="app.diagrams.net"><diagram id="app-architecture" name="App architecture"><mxGraphModel dx="1100" dy="600" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="540" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="c2" value="" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=none;strokeColor=#9aa8a1;strokeWidth=2;dashed=1;dashPattern=8 6;" vertex="1" parent="1"><mxGeometry x="8" y="4" width="1084" height="532" as="geometry"/></mxCell><mxCell id="c3" value="Everything runs on the phone (no server, no account). Arrows: presentation watches view-model, view-model uses domain, domain maps to data." style="text;html=1;fontFamily=PT Sans;fontSize=15;fontColor=#5b6b64;align=left;verticalAlign=middle;whiteSpace=wrap;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="24" y="14" width="1050" height="30" as="geometry"/></mxCell><mxCell id="c4" value="Presentation" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=19;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#3b6ea5;strokeColor=#3b6ea5;fontColor=#ffffff;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="24" y="56" width="180" height="42" as="geometry"/></mxCell><mxCell id="c5" value="ViewModel" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=19;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#a07a12;strokeColor=#a07a12;fontColor=#ffffff;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="244" y="56" width="180" height="42" as="geometry"/></mxCell><mxCell id="c6" value="Domain" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=19;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#5d8a4b;strokeColor=#5d8a4b;fontColor=#ffffff;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="464" y="56" width="180" height="42" as="geometry"/></mxCell><mxCell id="c7" value="Data" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=19;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#7a5b96;strokeColor=#7a5b96;fontColor=#ffffff;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="684" y="56" width="180" height="42" as="geometry"/></mxCell><mxCell id="c8" value="Navigation" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=19;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#4b5b54;strokeColor=#4b5b54;fontColor=#ffffff;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="904" y="56" width="176" height="42" as="geometry"/></mxCell><mxCell id="c9" value="Circle list" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="24" y="118" width="200" height="70" as="geometry"/></mxCell><mxCell id="c10" value="Cycle detail&#10;(paid, amount, note)" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="24" y="208" width="200" height="70" as="geometry"/></mxCell><mxCell id="c11" value="Stats dashboard" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="24" y="298" width="200" height="70" as="geometry"/></mxCell><mxCell id="c12" value="CircleListNotifier" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="240" y="118" width="200" height="70" as="geometry"/></mxCell><mxCell id="c13" value="CycleNotifier" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="240" y="208" width="200" height="70" as="geometry"/></mxCell><mxCell id="c14" value="StatsProvider" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="240" y="298" width="200" height="70" as="geometry"/></mxCell><mxCell id="c15" value="Circle model&#10;dead / live hụi" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="456" y="118" width="200" height="70" as="geometry"/></mxCell><mxCell id="c16" value="Payment model" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="456" y="208" width="200" height="70" as="geometry"/></mxCell><mxCell id="c17" value="Progress rules&#10;paid, remaining, %" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="456" y="298" width="200" height="70" as="geometry"/></mxCell><mxCell id="c18" value="Drift DAOs" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="672" y="118" width="200" height="70" as="geometry"/></mxCell><mxCell id="c19" value="Drift tables" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="672" y="208" width="200" height="70" as="geometry"/></mxCell><mxCell id="c20" value="SQLite file&#10;on the device" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="672" y="298" width="200" height="70" as="geometry"/></mxCell><mxCell id="c21" value="GoRouter&#10;/circles&#10;/circles/:id&#10;/stats" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=17;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="890" y="118" width="190" height="108" as="geometry"/></mxCell><mxCell id="c22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c9" target="c12"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c23" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c10" target="c13"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c11" target="c14"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c12" target="c15"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c13" target="c16"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c14" target="c17"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c15" target="c18"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c16" target="c19"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;fontFamily=PT Sans;fontSize=15;strokeWidth=2.5;strokeColor=#4b5b54;endArrow=block;endFill=1;labelBackgroundColor=#ffffff;" edge="1" parent="1" source="c17" target="c20"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c31" value="New in 2.0 (SCAMPER)" style="text;html=1;fontFamily=PT Sans;fontSize=18;fontColor=#b45309;align=left;verticalAlign=middle;whiteSpace=wrap;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="24" y="394" width="500" height="28" as="geometry"/></mxCell><mxCell id="c32" value="R: Player / host view switch" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=16;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="24" y="428" width="200" height="84" as="geometry"/></mxCell><mxCell id="c33" value="C: Reminder scheduler&#10;+ payment QR" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=16;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="240" y="428" width="200" height="84" as="geometry"/></mxCell><mxCell id="c34" value="E: Auto payout for&#10;live hụi bids" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=16;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="456" y="428" width="200" height="84" as="geometry"/></mxCell><mxCell id="c35" value="P: Savings-goal&#10;table" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=16;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="672" y="428" width="200" height="84" as="geometry"/></mxCell><mxCell id="c36" value="M: Text size and cycle&#10;length settings" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=PT Sans;fontSize=16;fontColor=#1f2a26;align=center;verticalAlign=middle;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;" vertex="1" parent="1"><mxGeometry x="890" y="428" width="190" height="84" as="geometry"/></mxCell></root></mxGraphModel></diagram></mxfile>