{
  "version": 1,
  "id": "scn_plant_finance",
  "slug": "plant-finance",
  "name": "Plant finance",
  "icon": "eurosign.circle",
  "tint": "#D3A85A",
  "settings": {
    "description": "Rebuild a manufacturer's numbers from its ledger for its bank: sources and uses of every borrowed million, reported vs true result, margin per deal, the hedge book, and a rulebook of claims re-checked against the production system on every read. Read-only; not an audit opinion."
  },
  "assets": [
    {
      "id": "pf-bridge",
      "type": "daslab/webview",
      "name": "Bank bridge",
      "fields": {
        "html": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>\n  :root{\n    --bg:#0b0f14; --panel:#10161e; --line:rgba(255,255,255,.08);\n    --ink:#e6ecf3; --muted:#8e9aa8; --dim:#5b6774;\n    --acc:#d3a85a; --green:#43c98a; --red:#ef5a5e; --amber:#e3b04b; --blue:#5aa5e6;\n    --mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;\n    --sans:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  html,body{height:100%}\n  body{background:var(--bg);color:var(--ink);font-family:var(--sans);overflow:hidden;-webkit-font-smoothing:antialiased}\n  .stage{position:absolute;inset:0;overflow:hidden;background:var(--bg)}\n  .topbar{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line)}\n  .brand{font-weight:800;letter-spacing:.13em;font-size:11px;white-space:nowrap}\n  .brand b{color:var(--acc)}\n  .divider{width:1px;height:15px;background:var(--line);flex-shrink:0}\n  .role{font:600 10.5px/1 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .role span{color:var(--muted);font-weight:400}\n  .chip{margin-left:auto;font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--acc);background:rgba(211,168,90,.12);padding:4px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}\n  .body{position:absolute;top:39px;left:0;right:0;bottom:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:10px}\n  .body>*{flex-shrink:0}\n  .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}\n  .sc{display:inline-block;font:600 7.5px/1 var(--mono);letter-spacing:.06em;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:3px;text-transform:uppercase;vertical-align:middle;margin-left:5px}\n  .cols{display:grid;grid-template-columns:1fr 1fr;gap:10px}\n  .tbl{background:var(--panel);border:1px solid var(--line);border-radius:4px;overflow:hidden}\n  .tbl .hd{display:flex;justify-content:space-between;align-items:center;padding:7px 10px;border-bottom:1px solid var(--line);font:600 8.5px/1 var(--sans);letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}\n  .tbl .hd .num{color:var(--muted);letter-spacing:0}\n  .row{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:center;padding:6px 10px;border-bottom:1px solid var(--line);font-size:10.5px}\n  .row:last-child{border-bottom:0}\n  .row .lab{min-width:0;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .row .amt{font-size:11.5px;font-weight:600}\n  .row .amt.neg{color:var(--red)} .row .amt.zero{color:var(--dim)}\n  .row.total{background:rgba(255,255,255,.03);font-weight:600}\n  .row.total .amt{color:var(--acc)}\n  .row.pending .amt{color:var(--dim)}\n  .closes{display:flex;align-items:center;gap:8px;font:600 9px/1 var(--mono);color:var(--muted);padding:0 2px}\n  .closes b{color:var(--green);font-weight:600}\n  .closes.open b{color:var(--dim)}\n  .strip{background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:8px 10px 6px}\n  .strip .hd{display:flex;justify-content:space-between;align-items:center;font:600 8.5px/1 var(--sans);letter-spacing:.11em;text-transform:uppercase;color:var(--dim);margin-bottom:6px}\n  .legend{display:flex;gap:10px;font:500 8px/1 var(--mono);color:var(--muted);letter-spacing:0;text-transform:none}\n  .legend i{display:inline-block;width:7px;height:7px;border-radius:2px;vertical-align:-1px;margin-right:4px}\n  .bars{display:grid;grid-template-columns:repeat(8,1fr);gap:6px;align-items:end;height:64px}\n  .yr{display:flex;flex-direction:column;align-items:center;gap:2px;height:100%;justify-content:flex-end}\n  .yr .b{width:100%;display:flex;gap:2px;align-items:flex-end;height:52px}\n  .yr .b i{flex:1;display:block;border-radius:2px 2px 0 0;min-height:1px;transition:height .4s ease}\n  .yr .b i.d{background:var(--blue)} .yr .b i.r{background:var(--red);opacity:.85}\n  .yr small{font:500 7.5px/1 var(--mono);color:var(--dim)}\n  .flag{background:rgba(227,176,75,.08);border:1px solid rgba(227,176,75,.35);border-radius:4px;padding:8px 10px;display:flex;align-items:flex-start;gap:9px}\n  .flag[hidden]{display:none}\n  .flag .mk{font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--amber);border:1px solid rgba(227,176,75,.5);border-radius:3px;padding:3px 5px;flex-shrink:0;margin-top:1px}\n  .flag .m b{font:600 10.5px/1.3 var(--sans);color:var(--ink);display:block}\n  .flag .m small{font:500 9px/1.4 var(--mono);color:var(--muted)}\n  .prov{margin-top:auto;font:500 8px/1.4 var(--mono);color:var(--dim)}\n  @media (max-width:430px){ .cols{grid-template-columns:1fr} .bars{height:56px} .yr .b{height:44px} }\n</style></head>\n<body>\n  <div class=\"stage\">\n    <div class=\"topbar\">\n      <div class=\"brand\">DASLAB <b>LEDGER</b></div>\n      <div class=\"divider\"></div>\n      <div class=\"role\" id=\"role\">Bank bridge <span>· sources and uses · 2019 to last week · € m</span></div>\n      <div class=\"chip\" id=\"chip\">ACDOCA · MIRROR</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"cols\">\n        <div class=\"tbl\"><div class=\"hd\"><span>Sources</span><span class=\"num\" id=\"srcTotal\">0.0</span></div><div id=\"sources\"></div></div>\n        <div class=\"tbl\"><div class=\"hd\"><span>Uses</span><span class=\"num\" id=\"useTotal\">0.0</span></div><div id=\"uses\"></div></div>\n      </div>\n      <div class=\"closes\" id=\"closes\"></div>\n      <div class=\"strip\" id=\"strip\" hidden>\n        <div class=\"hd\"><span>By year</span><span class=\"legend\"><span><i style=\"background:var(--blue)\"></i>net bank draws</span><span><i style=\"background:var(--red)\"></i>net result</span></span></div>\n        <div class=\"bars\" id=\"bars\"></div>\n      </div>\n      <div class=\"flag\" id=\"flag\" hidden>\n        <div class=\"mk\">FLAG</div>\n        <div class=\"m\"><b id=\"flagT\"></b><small id=\"flagS\"></small></div>\n      </div>\n      <div class=\"prov\">Illustrated from recorded runs. Figures shaped, not copied. Read-only; not an audit opinion.</div>\n    </div>\n  </div>\n<script>\n(()=>{\n  const el=id=>document.getElementById(id);\n  const replay=window.__DASLAB_REPLAY__===true;\n  let d=window.__DASLAB_WIDGET_DATA__||{};\n  let tick=0;\n  const fmt=n=>(n<0?'−':'')+Math.abs(n).toFixed(1);\n  function rows(host,list){\n    host.innerHTML='';\n    (list||[]).forEach(r=>{\n      const div=document.createElement('div'); div.className='row'+(r.pending?' pending':'');\n      const cls=r.pending?'':(r.value<0?' neg':(r.value===0?' zero':''));\n      div.innerHTML='<div class=\"lab\">'+r.label+(r.src?'<span class=\"sc\">'+r.src+'</span>':'')+'</div><div class=\"amt num'+cls+'\">'+(r.pending?'…':fmt(r.value))+'</div>';\n      host.appendChild(div);\n    });\n  }\n  function sum(list){ return (list||[]).reduce((a,r)=>a+(r.pending?0:(r.value||0)),0); }\n  function renderBars(){\n    const b=el('bars'); b.innerHTML='';\n    const yrs=d.years||[]; if(!yrs.length){ el('strip').hidden=true; return; }\n    el('strip').hidden=false;\n    const max=Math.max(...yrs.map(y=>Math.max(Math.abs(y.draw||0),Math.abs(y.result||0))),1);\n    yrs.forEach(y=>{\n      const w=document.createElement('div'); w.className='yr';\n      const hd=Math.round(Math.abs(y.draw||0)/max*100), hr=Math.round(Math.abs(y.result||0)/max*100);\n      w.innerHTML='<div class=\"b\"><i class=\"d\" style=\"height:'+hd+'%\" title=\"draws '+fmt(y.draw||0)+'\"></i><i class=\"r\" style=\"height:'+hr+'%\" title=\"result '+fmt(y.result||0)+'\"></i></div><small>'+y.label+'</small>';\n      b.appendChild(w);\n    });\n  }\n  function render(){\n    if(d.role) el('role').innerHTML=d.role;\n    if(d.chip) el('chip').textContent=d.chip;\n    rows(el('sources'),d.sources); rows(el('uses'),d.uses);\n    const s=sum(d.sources), u=sum(d.uses);\n    el('srcTotal').textContent=fmt(s); el('useTotal').textContent=fmt(u);\n    const pending=(d.sources||[]).some(r=>r.pending)||(d.uses||[]).some(r=>r.pending);\n    const c=el('closes'); c.className='closes'+(pending?' open':'');\n    c.innerHTML=pending?'reading the universal journal'+'.'.repeat(1+(tick%3)):(Math.abs(s-u)<.05?'sources '+fmt(s)+' = uses '+fmt(u)+' <b>· the bridge closes</b>':'sources '+fmt(s)+' ≠ uses '+fmt(u)+' <b>· gap '+fmt(s-u)+'</b>');\n    renderBars();\n    const f=d.flag; el('flag').hidden=!f; if(f){ el('flagT').textContent=f.title||''; el('flagS').textContent=f.detail||''; }\n  }\n  addEventListener('message',e=>{\n    if(!replay||e.source!==parent||e.origin!==location.origin||e.data?.type!=='daslab:replay-clock') return;\n    if(e.data.data) d=e.data.data; render();\n  });\n  setInterval(()=>{ tick++; const pending=(d.sources||[]).some(r=>r.pending)||(d.uses||[]).some(r=>r.pending); if(pending) render(); }, 600);\n  render();\n})();\n</script>\n</body></html>\n",
        "data": {
          "role": "Bank bridge <span>· sources and uses · € m</span>",
          "chip": "ACDOCA · MIRROR",
          "sources": [],
          "uses": []
        }
      },
      "layout": {
        "sortOrder": 0,
        "size": "large"
      }
    },
    {
      "id": "pf-truth",
      "type": "daslab/webview",
      "name": "Reported vs true",
      "fields": {
        "html": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>\n  :root{\n    --bg:#0b0f14; --panel:#10161e; --line:rgba(255,255,255,.08);\n    --ink:#e6ecf3; --muted:#8e9aa8; --dim:#5b6774;\n    --acc:#d3a85a; --green:#43c98a; --red:#ef5a5e; --amber:#e3b04b; --blue:#5aa5e6;\n    --mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;\n    --sans:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  html,body{height:100%}\n  body{background:var(--bg);color:var(--ink);font-family:var(--sans);overflow:hidden;-webkit-font-smoothing:antialiased}\n  .stage{position:absolute;inset:0;overflow:hidden;background:var(--bg)}\n  .topbar{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line)}\n  .brand{font-weight:800;letter-spacing:.13em;font-size:11px;white-space:nowrap}\n  .brand b{color:var(--acc)}\n  .divider{width:1px;height:15px;background:var(--line);flex-shrink:0}\n  .role{font:600 10.5px/1 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .role span{color:var(--muted);font-weight:400}\n  .chip{margin-left:auto;font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--acc);background:rgba(211,168,90,.12);padding:4px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}\n  .body{position:absolute;top:39px;left:0;right:0;bottom:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:10px}\n  .body>*{flex-shrink:0}\n  .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}\n  .sc{display:inline-block;font:600 7.5px/1 var(--mono);letter-spacing:.06em;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:3px;text-transform:uppercase;vertical-align:middle;margin-left:5px}\n  .tbl{background:var(--panel);border:1px solid var(--line);border-radius:4px;overflow:hidden}\n  .tbl[hidden]{display:none}\n  .tbl .hd{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:7px 10px;border-bottom:1px solid var(--line);font:600 8.5px/1.3 var(--sans);letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}\n  .tbl .hd>span:first-child{flex-shrink:0}\n  .tbl .hd>span:last-child{text-align:right}\n  table{width:100%;border-collapse:collapse;font-size:10.5px}\n  th,td{padding:6px 10px;border-bottom:1px solid var(--line);text-align:right}\n  th{font:600 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--dim)}\n  th:first-child,td:first-child{text-align:left;color:var(--ink)}\n  tr:last-child td{border-bottom:0}\n  td.neg{color:var(--red)} td.pos{color:var(--green)} td.dim{color:var(--dim)}\n  tr.total td{background:rgba(255,255,255,.03);font-weight:600}\n  tr.true td{font-weight:600}\n  tr.true td:first-child{color:var(--acc)}\n  td.pending{color:var(--dim)}\n  .note{padding:7px 10px;border-top:1px solid var(--line);font:500 9px/1.45 var(--mono);color:var(--muted)}\n  .note b{color:var(--ink);font-weight:600}\n  .prov{margin-top:auto;font:500 8px/1.4 var(--mono);color:var(--dim)}\n  @media (max-width:430px){ th,td{padding:5px 7px;font-size:10px} }\n</style></head>\n<body>\n  <div class=\"stage\">\n    <div class=\"topbar\">\n      <div class=\"brand\">DASLAB <b>LEDGER</b></div>\n      <div class=\"divider\"></div>\n      <div class=\"role\" id=\"role\">Reported vs true <span>· three years · EBIT · € m</span></div>\n      <div class=\"chip\" id=\"chip\">ACDOCA · MIRROR</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"tbl\">\n        <div class=\"hd\"><span>Reconciliation</span><span id=\"recSrc\">ACDOCA · account set v3</span></div>\n        <table id=\"rec\"></table>\n      </div>\n      <div class=\"tbl\" id=\"marginTbl\" hidden>\n        <div class=\"hd\"><span>Ordinary product sales</span><span id=\"mSrc\">VBRP · CKMLCR</span></div>\n        <table id=\"margin\"></table>\n        <div class=\"note\" id=\"mNote\"></div>\n      </div>\n      <div class=\"prov\">Illustrated from recorded runs. Figures shaped, not copied. Read-only; not an audit opinion.</div>\n    </div>\n  </div>\n<script>\n(()=>{\n  const el=id=>document.getElementById(id);\n  const replay=window.__DASLAB_REPLAY__===true;\n  let d=window.__DASLAB_WIDGET_DATA__||{};\n  let tick=0;\n  const fmt=n=>(n>0?'+':n<0?'−':'')+Math.abs(n).toFixed(0);\n  const cls=n=>n>0?'pos':n<0?'neg':'dim';\n  function cell(v,t){ return v==null?'<td class=\"num pending\">'+'.'.repeat(1+(tick%3))+'</td>':'<td class=\"num '+cls(v)+'\">'+(t||fmt)(v)+'</td>'; }\n  function renderRec(){\n    const years=d.years||['Y1','Y2','Y3'];\n    const rowsDef=[\n      {key:'reported',label:'EBIT as reported',src:'FI · S1'},\n      {key:'removed',label:'Less: items removed',src:'ACDOCA',sub:true},\n      {key:'trueEbit',label:'True EBIT',src:'RECON',cls:'true'},\n    ];\n    let h='<tr><th>€ m</th>'+years.map(y=>'<th class=\"num\">'+y+'</th>').join('')+'<th class=\"num\">Total</th></tr>';\n    rowsDef.forEach(r=>{\n      const vals=d[r.key];\n      if(!vals&&!d.pending?.[r.key]) return;\n      const arr=vals||years.map(()=>null);\n      const total=vals?vals.reduce((a,b)=>a+b,0):null;\n      h+='<tr class=\"'+(r.cls||'')+'\"><td>'+r.label+'<span class=\"sc\">'+r.src+'</span></td>'+arr.map(v=>cell(v)).join('')+cell(total)+'</tr>';\n    });\n    el('rec').innerHTML=h;\n    if(d.removedNote){ /* keep table compact; note rendered as a row */ }\n  }\n  function renderMargin(){\n    const m=d.margin; el('marginTbl').hidden=!m; if(!m) return;\n    const years=d.years||['Y1','Y2','Y3'];\n    let h='<tr><th>Year</th><th class=\"num\">Tonnes</th><th class=\"num\">Sales € m</th><th class=\"num\">Margin</th></tr>';\n    m.rows.forEach((r,i)=>{\n      h+='<tr><td>'+years[i]+(i===1&&r.flag?'<span class=\"sc\">'+r.flag+'</span>':'')+'</td><td class=\"num\">'+r.tonnes.toLocaleString('en-US')+'</td><td class=\"num\">'+r.sales.toFixed(1)+'</td><td class=\"num '+cls(r.marginPct)+'\">'+(r.marginPct>0?'+':r.marginPct<0?'−':'')+Math.abs(r.marginPct).toFixed(1)+'%</td></tr>';\n    });\n    el('margin').innerHTML=h;\n    el('mNote').innerHTML=m.note||'';\n  }\n  function render(){\n    if(d.role) el('role').innerHTML=d.role;\n    if(d.chip) el('chip').textContent=d.chip;\n    if(d.recSrc) el('recSrc').textContent=d.recSrc;\n    renderRec(); renderMargin();\n  }\n  addEventListener('message',e=>{\n    if(!replay||e.source!==parent||e.origin!==location.origin||e.data?.type!=='daslab:replay-clock') return;\n    if(e.data.data) d=e.data.data; render();\n  });\n  setInterval(()=>{ tick++; if(d.pending&&Object.keys(d.pending).length) render(); }, 600);\n  render();\n})();\n</script>\n</body></html>\n",
        "data": {
          "role": "Reported vs true <span>· EBIT · € m</span>",
          "chip": "ACDOCA · MIRROR",
          "years": [
            "Y1",
            "Y2",
            "Y3"
          ],
          "pending": {
            "reported": 1
          }
        }
      },
      "layout": {
        "sortOrder": 1,
        "size": "large"
      }
    },
    {
      "id": "pf-deal",
      "type": "daslab/webview",
      "name": "Deal margin",
      "fields": {
        "html": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>\n  :root{\n    --bg:#0b0f14; --panel:#10161e; --line:rgba(255,255,255,.08);\n    --ink:#e6ecf3; --muted:#8e9aa8; --dim:#5b6774;\n    --acc:#d3a85a; --green:#43c98a; --red:#ef5a5e; --amber:#e3b04b; --blue:#5aa5e6;\n    --mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;\n    --sans:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  html,body{height:100%}\n  body{background:var(--bg);color:var(--ink);font-family:var(--sans);overflow:hidden;-webkit-font-smoothing:antialiased}\n  .stage{position:absolute;inset:0;overflow:hidden;background:var(--bg)}\n  .topbar{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line)}\n  .brand{font-weight:800;letter-spacing:.13em;font-size:11px;white-space:nowrap}\n  .brand b{color:var(--acc)}\n  .divider{width:1px;height:15px;background:var(--line);flex-shrink:0}\n  .role{font:600 10.5px/1 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .role span{color:var(--muted);font-weight:400}\n  .chip{margin-left:auto;font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--acc);background:rgba(211,168,90,.12);padding:4px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}\n  .body{position:absolute;top:39px;left:0;right:0;bottom:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:10px}\n  .body>*{flex-shrink:0}\n  .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}\n  .sc{display:inline-block;font:600 7.5px/1 var(--mono);letter-spacing:.06em;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:3px;text-transform:uppercase;vertical-align:middle}\n  .card{background:var(--panel);border:1px solid var(--line);border-radius:4px;overflow:hidden}\n  .card .hd{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:7px 10px;border-bottom:1px solid var(--line);font:600 8.5px/1 var(--sans);letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}\n  .card .hd .num{color:var(--muted);letter-spacing:0;text-transform:none}\n  .three{display:grid;grid-template-columns:repeat(3,1fr)}\n  .m{padding:9px 10px;border-right:1px solid var(--line);min-width:0}\n  .m:last-child{border-right:0}\n  .m .k{font:600 8px/1 var(--sans);letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}\n  .m .v{margin-top:6px;font:600 22px/1 var(--mono);color:var(--ink);letter-spacing:-.02em}\n  .m .v.pending{color:var(--dim)}\n  .m .v.actual{color:var(--acc)}\n  .m .v.plan{color:var(--muted)}\n  .m .s{margin-top:6px;font:500 8.5px/1.3 var(--sans);color:var(--muted);display:flex;flex-wrap:wrap;gap:4px;align-items:center}\n  .chain{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid var(--line);flex-wrap:wrap}\n  .node{border:1px solid var(--line);border-radius:4px;padding:5px 7px;min-width:0}\n  .node small{display:block;font:600 7.5px/1 var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--dim)}\n  .node b{display:block;margin-top:3px;font:600 10px/1 var(--mono);color:var(--ink)}\n  .node.pending b{color:var(--dim)}\n  .arrow{color:var(--dim);font:500 11px/1 var(--mono)}\n  .lines{display:flex;flex-direction:column}\n  .li{display:grid;grid-template-columns:24px 1fr auto;gap:8px;align-items:center;padding:6px 10px;border-bottom:1px solid var(--line);font-size:10.5px}\n  .li:last-child{border-bottom:0}\n  .li .op{font:600 12px/1 var(--mono);color:var(--dim);text-align:center}\n  .li .lab{min-width:0;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n  .li .lab .sc{margin-left:5px}\n  .li .amt{font-size:11.5px;font-weight:600}\n  .li.minus .amt{color:var(--muted)}\n  .li.scrap{background:rgba(227,176,75,.07)}\n  .li.scrap .amt{color:var(--amber)}\n  .li.total{background:rgba(255,255,255,.03)}\n  .li.total .amt{color:var(--acc)}\n  .li.total .op{color:var(--acc)}\n  .prov{margin-top:auto;font:500 8px/1.4 var(--mono);color:var(--dim)}\n  @media (max-width:430px){ .m .v{font-size:18px} .three{grid-template-columns:repeat(3,1fr)} }\n</style></head>\n<body>\n  <div class=\"stage\">\n    <div class=\"topbar\">\n      <div class=\"brand\">DASLAB <b>LEDGER</b></div>\n      <div class=\"divider\"></div>\n      <div class=\"role\" id=\"role\">Deal margin <span>· sales order 60012348 · MV cable 3x120 · € 184,600 net</span></div>\n      <div class=\"chip\" id=\"chip\">SD · CO · MM</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"card\">\n        <div class=\"hd\"><span>Margin on this order</span><span class=\"num\" id=\"net\"></span></div>\n        <div class=\"three\" id=\"metrics\"></div>\n      </div>\n      <div class=\"card\">\n        <div class=\"hd\"><span>Batch chain</span><span class=\"num\" id=\"chainSrc\">VBAK · LIPS · AUFK · MATDOC</span></div>\n        <div class=\"chain\" id=\"chain\"></div>\n        <div class=\"lines\" id=\"lines\"></div>\n      </div>\n      <div class=\"prov\">Illustrated from recorded runs. Figures shaped, not copied. Read-only; not an audit opinion.</div>\n    </div>\n  </div>\n<script>\n(()=>{\n  const el=id=>document.getElementById(id);\n  const replay=window.__DASLAB_REPLAY__===true;\n  let d=window.__DASLAB_WIDGET_DATA__||{};\n  let tick=0;\n  const eur=n=>'€ '+Math.round(n).toLocaleString('en-US');\n  const pct=n=>n.toFixed(1)+'%';\n  function metric(m,cls){\n    if(!m) return '';\n    const pend=m.pct==null;\n    return '<div class=\"m\"><div class=\"k\">'+m.label+'</div><div class=\"v num '+(pend?'pending':cls)+'\">'+(pend?'.'.repeat(1+(tick%3)):pct(m.pct))+'</div><div class=\"s\">'+(m.cost!=null?'<span class=\"num\">cost '+eur(m.cost)+'</span>':'')+(m.src?'<span class=\"sc\">'+m.src+'</span>':'')+(m.note?'<span>'+m.note+'</span>':'')+'</div></div>';\n  }\n  function render(){\n    if(d.role) el('role').innerHTML=d.role;\n    if(d.chip) el('chip').textContent=d.chip;\n    if(d.net!=null) el('net').textContent='net '+eur(d.net);\n    el('metrics').innerHTML=metric(d.quoted,'')+metric(d.plan,'plan')+metric(d.actual,'actual');\n    const ch=el('chain'); ch.innerHTML='';\n    (d.chain||[]).forEach((n,i)=>{\n      if(i>0){ const a=document.createElement('span'); a.className='arrow'; a.textContent='→'; ch.appendChild(a); }\n      const node=document.createElement('div'); node.className='node'+(n.id?'':' pending');\n      node.innerHTML='<small>'+n.kind+'</small><b class=\"num\">'+(n.id||'.'.repeat(1+(tick%3)))+'</b>';\n      ch.appendChild(node);\n    });\n    const ls=el('lines'); ls.innerHTML='';\n    (d.lines||[]).forEach(l=>{\n      const row=document.createElement('div'); row.className='li'+(l.kind==='minus'?' minus':'')+(l.scrap?' scrap':'')+(l.total?' total':'');\n      row.innerHTML='<div class=\"op\">'+(l.total?'=':l.kind==='minus'?'−':'+')+'</div><div class=\"lab\">'+l.label+(l.src?'<span class=\"sc\">'+l.src+'</span>':'')+'</div><div class=\"amt num\">'+eur(l.value)+'</div>';\n      ls.appendChild(row);\n    });\n  }\n  addEventListener('message',e=>{\n    if(!replay||e.source!==parent||e.origin!==location.origin||e.data?.type!=='daslab:replay-clock') return;\n    if(e.data.data) d=e.data.data; render();\n  });\n  setInterval(()=>{ tick++; const pending=[d.quoted,d.plan,d.actual].some(m=>m&&m.pct==null)||(d.chain||[]).some(n=>!n.id); if(pending) render(); }, 600);\n  render();\n})();\n</script>\n</body></html>\n",
        "data": {
          "role": "Deal margin <span>· pick a sales order</span>",
          "chip": "SD · CO · MM",
          "chain": [],
          "lines": []
        }
      },
      "layout": {
        "sortOrder": 2,
        "size": "large"
      }
    },
    {
      "id": "pf-hedge",
      "type": "daslab/webview",
      "name": "Hedge book",
      "fields": {
        "html": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>\n  :root{\n    --bg:#0b0f14; --panel:#10161e; --line:rgba(255,255,255,.08);\n    --ink:#e6ecf3; --muted:#8e9aa8; --dim:#5b6774;\n    --acc:#d3a85a; --green:#43c98a; --red:#ef5a5e; --amber:#e3b04b; --blue:#5aa5e6;\n    --mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;\n    --sans:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  html,body{height:100%}\n  body{background:var(--bg);color:var(--ink);font-family:var(--sans);overflow:hidden;-webkit-font-smoothing:antialiased}\n  .stage{position:absolute;inset:0;overflow:hidden;background:var(--bg)}\n  .topbar{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line)}\n  .brand{font-weight:800;letter-spacing:.13em;font-size:11px;white-space:nowrap}\n  .brand b{color:var(--acc)}\n  .divider{width:1px;height:15px;background:var(--line);flex-shrink:0}\n  .role{font:600 10.5px/1 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .role span{color:var(--muted);font-weight:400}\n  .chip{margin-left:auto;font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--acc);background:rgba(211,168,90,.12);padding:4px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}\n  .body{position:absolute;top:39px;left:0;right:0;bottom:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:10px}\n  .body>*{flex-shrink:0}\n  .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}\n  .sc{display:inline-block;font:600 7.5px/1 var(--mono);letter-spacing:.06em;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:3px;text-transform:uppercase;vertical-align:middle;margin-left:5px}\n  .card{background:var(--panel);border:1px solid var(--line);border-radius:4px;overflow:hidden}\n  .card .hd{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:7px 10px;border-bottom:1px solid var(--line);font:600 8.5px/1 var(--sans);letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}\n  .card .hd .legend{display:flex;gap:10px;font:500 8px/1 var(--mono);color:var(--muted);letter-spacing:0;text-transform:none}\n  .legend i{display:inline-block;width:7px;height:7px;border-radius:2px;vertical-align:-1px;margin-right:4px}\n  svg{display:block;width:100%;height:150px}\n  .kpis{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--line)}\n  .kpi{padding:8px 10px;border-right:1px solid var(--line)}\n  .kpi:last-child{border-right:0}\n  .kpi .k{font:600 8px/1 var(--sans);letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}\n  .kpi .v{margin-top:5px;font:600 16px/1 var(--mono);color:var(--ink)}\n  .kpi .v.warn{color:var(--amber)} .kpi .v.dim{color:var(--dim)} .kpi .v.up{color:var(--red)}\n  .kpi .s{margin-top:4px;font:500 8.5px/1.3 var(--sans);color:var(--muted)}\n  table{width:100%;border-collapse:collapse;font-size:10px}\n  th,td{padding:5px 10px;border-bottom:1px solid var(--line);text-align:right}\n  th{font:600 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--dim)}\n  th:first-child,td:first-child{text-align:left}\n  tr:last-child td{border-bottom:0}\n  td.pos{color:var(--green)}\n  tr.gap td{color:var(--amber);font-family:var(--mono);font-size:9px;text-align:left}\n  .prov{margin-top:auto;font:500 8px/1.4 var(--mono);color:var(--dim)}\n  @media (max-width:430px){ .kpi .v{font-size:14px} svg{height:130px} th,td{padding:5px 7px} th:nth-child(2),td:nth-child(2){display:none} tr.gap td{display:table-cell} }\n</style></head>\n<body>\n  <div class=\"stage\">\n    <div class=\"topbar\">\n      <div class=\"brand\">DASLAB <b>LEDGER</b></div>\n      <div class=\"divider\"></div>\n      <div class=\"role\" id=\"role\">Hedge book <span>· copper · 14 months · settlements against price</span></div>\n      <div class=\"chip\" id=\"chip\">FI · S1 · BANK REF</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"card\">\n        <div class=\"hd\"><span>Exposed vs hedged</span><span class=\"legend\"><span><i style=\"background:var(--red)\"></i>metal price, index</span><span><i style=\"background:var(--green)\"></i>settlement</span><span><i style=\"background:rgba(227,176,75,.35)\"></i>no settlements</span></span></div>\n        <svg id=\"chart\" viewBox=\"0 0 560 150\" preserveAspectRatio=\"none\"></svg>\n        <div class=\"kpis\" id=\"kpis\"></div>\n      </div>\n      <div class=\"card\" id=\"regCard\" hidden>\n        <div class=\"hd\"><span>Settlement register</span><span id=\"regSrc\">BSEG · bank reference</span></div>\n        <table id=\"reg\"></table>\n      </div>\n      <div class=\"prov\">Illustrated from recorded runs. Figures shaped, not copied. Read-only; not an audit opinion.</div>\n    </div>\n  </div>\n<script>\n(()=>{\n  const el=id=>document.getElementById(id);\n  const replay=window.__DASLAB_REPLAY__===true;\n  let d=window.__DASLAB_WIDGET_DATA__||{};\n  let tick=0;\n  const W=560,H=150,PL=30,PR=12,PT=14,PB=26;\n  function renderChart(){\n    const months=d.months||[]; const s=el('chart'); if(!months.length){ s.innerHTML=''; return; }\n    const n=months.length, x=i=>PL+(W-PL-PR)*(i/(n-1));\n    const vals=months.map(m=>m.price), lo=Math.min(...vals)*.96, hi=Math.max(...vals)*1.03;\n    const y=v=>PT+(H-PT-PB)*(1-(v-lo)/(hi-lo));\n    let g='';\n    const gap=d.gap;\n    if(gap){ const x0=x(gap.from)-((W-PL-PR)/(n-1))/2, x1=x(gap.to)+((W-PL-PR)/(n-1))/2; g+='<rect x=\"'+x0+'\" y=\"'+PT+'\" width=\"'+(x1-x0)+'\" height=\"'+(H-PT-PB)+'\" fill=\"rgba(227,176,75,.14)\" stroke=\"rgba(227,176,75,.5)\" stroke-dasharray=\"3 3\"/>';\n      if(gap.label) g+='<text x=\"'+((x0+x1)/2)+'\" y=\"'+(PT+12)+'\" text-anchor=\"middle\" fill=\"#e3b04b\" font-family=\"ui-monospace,Menlo,monospace\" font-size=\"9\" font-weight=\"600\">'+gap.label+'</text>';\n      if(gap.sub) g+='<text x=\"'+((x0+x1)/2)+'\" y=\"'+(PT+24)+'\" text-anchor=\"middle\" fill=\"#e3b04b\" font-family=\"ui-monospace,Menlo,monospace\" font-size=\"8.5\">'+gap.sub+'</text>'; }\n    [lo,(lo+hi)/2,hi].forEach(v=>{ g+='<line x1=\"'+PL+'\" x2=\"'+(W-PR)+'\" y1=\"'+y(v)+'\" y2=\"'+y(v)+'\" stroke=\"rgba(255,255,255,.06)\"/><text x=\"'+(PL-4)+'\" y=\"'+(y(v)+3)+'\" text-anchor=\"end\" fill=\"#5b6774\" font-family=\"ui-monospace,Menlo,monospace\" font-size=\"7.5\">'+Math.round(v)+'</text>'; });\n    const upto=d.priceUpto==null?n:d.priceUpto;\n    const pts=months.slice(0,upto).map((m,i)=>x(i).toFixed(1)+','+y(m.price).toFixed(1)).join(' ');\n    if(pts) g+='<polyline points=\"'+pts+'\" fill=\"none\" stroke=\"#ef5a5e\" stroke-width=\"1.6\" stroke-linejoin=\"round\"/>';\n    months.forEach((m,i)=>{ g+='<text x=\"'+x(i)+'\" y=\"'+(H-8)+'\" text-anchor=\"middle\" fill=\"#5b6774\" font-family=\"ui-monospace,Menlo,monospace\" font-size=\"7.5\">'+m.label+'</text>';\n      if(m.settled){ g+='<line x1=\"'+x(i)+'\" x2=\"'+x(i)+'\" y1=\"'+(H-PB+2)+'\" y2=\"'+(H-PB-8)+'\" stroke=\"#43c98a\" stroke-width=\"2\"/>'; } });\n    s.innerHTML=g;\n  }\n  function renderKpis(){\n    const k=el('kpis'); k.innerHTML='';\n    (d.kpis||[]).forEach(m=>{ const div=document.createElement('div'); div.className='kpi';\n      div.innerHTML='<div class=\"k\">'+m.label+'</div><div class=\"v num '+(m.state||'')+'\">'+(m.value==null?'.'.repeat(1+(tick%3)):m.value)+'</div><div class=\"s\">'+(m.sub||'')+(m.src?'<span class=\"sc\">'+m.src+'</span>':'')+'</div>'; k.appendChild(div); });\n  }\n  function renderReg(){\n    const r=d.register; el('regCard').hidden=!r; if(!r) return;\n    let h='<tr><th>Reference</th><th>Posted</th><th class=\"num\">Tonnes</th><th class=\"num\">Settlement €</th></tr>';\n    r.forEach(row=>{\n      if(row.gap){ h+='<tr class=\"gap\"><td colspan=\"4\">'+row.gap+'</td></tr>'; return; }\n      h+='<tr><td class=\"num\">'+row.ref+'</td><td class=\"num\">'+row.date+'</td><td class=\"num\">'+row.tonnes+'</td><td class=\"num pos\">+'+row.amount.toLocaleString('en-US')+'</td></tr>';\n    });\n    el('reg').innerHTML=h;\n  }\n  function render(){\n    if(d.role) el('role').innerHTML=d.role;\n    if(d.chip) el('chip').textContent=d.chip;\n    renderChart(); renderKpis(); renderReg();\n  }\n  addEventListener('message',e=>{\n    if(!replay||e.source!==parent||e.origin!==location.origin||e.data?.type!=='daslab:replay-clock') return;\n    if(e.data.data) d=e.data.data; render();\n  });\n  setInterval(()=>{ tick++; if((d.kpis||[]).some(m=>m.value==null)) render(); }, 600);\n  render();\n})();\n</script>\n</body></html>\n",
        "data": {
          "role": "Hedge book <span>· settlements against price</span>",
          "chip": "FI · S1 · BANK REF",
          "months": [],
          "kpis": []
        }
      },
      "layout": {
        "sortOrder": 3,
        "size": "large"
      }
    },
    {
      "id": "pf-rulebook",
      "type": "daslab/webview",
      "name": "Rulebook",
      "fields": {
        "html": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>\n  :root{\n    --bg:#0b0f14; --panel:#10161e; --line:rgba(255,255,255,.08);\n    --ink:#e6ecf3; --muted:#8e9aa8; --dim:#5b6774;\n    --acc:#d3a85a; --green:#43c98a; --red:#ef5a5e; --amber:#e3b04b; --blue:#5aa5e6;\n    --mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;\n    --sans:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  html,body{height:100%}\n  body{background:var(--bg);color:var(--ink);font-family:var(--sans);overflow:hidden;-webkit-font-smoothing:antialiased}\n  .stage{position:absolute;inset:0;overflow:hidden;background:var(--bg)}\n  .topbar{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line)}\n  .brand{font-weight:800;letter-spacing:.13em;font-size:11px;white-space:nowrap}\n  .brand b{color:var(--acc)}\n  .divider{width:1px;height:15px;background:var(--line);flex-shrink:0}\n  .role{font:600 10.5px/1 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n  .role span{color:var(--muted);font-weight:400}\n  .chip{margin-left:auto;font:700 8px/1 var(--mono);letter-spacing:.1em;color:var(--acc);background:rgba(211,168,90,.12);padding:4px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}\n  .body{position:absolute;top:39px;left:0;right:0;bottom:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:10px}\n  .body>*{flex-shrink:0}\n  .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}\n  .summary{display:flex;gap:6px;flex-wrap:wrap;align-items:center}\n  .st{font:600 8.5px/1 var(--mono);letter-spacing:.04em;padding:4px 6px;border-radius:4px;border:1px solid var(--line);color:var(--muted);white-space:nowrap}\n  .st.ok{color:var(--green);border-color:rgba(67,201,138,.4)} .st.single{color:var(--blue);border-color:rgba(90,165,230,.4)}\n  .st.tension{color:var(--amber);border-color:rgba(227,176,75,.5)} .st.open{color:var(--muted)}\n  .summary .checked{margin-left:auto;font:500 8.5px/1 var(--mono);color:var(--dim)}\n  .list{background:var(--panel);border:1px solid var(--line);border-radius:4px;overflow:hidden}\n  .rule{display:grid;grid-template-columns:30px 1fr auto;gap:8px;align-items:start;padding:8px 10px;border-bottom:1px solid var(--line)}\n  .rule:last-child{border-bottom:0}\n  .rule.active{background:rgba(227,176,75,.06)}\n  .rule.active.ok{background:rgba(67,201,138,.06)}\n  .rule .id{font:600 9.5px/1.3 var(--mono);color:var(--dim)}\n  .rule .claim{font:500 10.5px/1.35 var(--sans);color:var(--ink);min-width:0}\n  .rule .claim small{display:block;margin-top:3px;font:500 8.5px/1.4 var(--mono);color:var(--muted)}\n  .rule .claim small.note{color:var(--green)}\n  .rule .claim small.warn{color:var(--amber)}\n  .tags{display:inline-flex;gap:3px;margin-left:4px;vertical-align:middle}\n  .tag{font:600 7.5px/1 var(--mono);letter-spacing:.06em;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:3px}\n  .tag.COO{color:#c9a7e8;border-color:rgba(201,167,232,.4)} .tag.S4{color:var(--blue);border-color:rgba(90,165,230,.4)}\n  .tag.DOC{color:var(--acc);border-color:rgba(211,168,90,.4)} .tag.ASSUMED{color:var(--dim)}\n  .rule .st{align-self:start}\n  .prov{margin-top:auto;font:500 8px/1.4 var(--mono);color:var(--dim)}\n  @media (max-width:430px){ .rule{grid-template-columns:26px 1fr auto;padding:7px 8px} .rule .claim{font-size:10px} }\n</style></head>\n<body>\n  <div class=\"stage\">\n    <div class=\"topbar\">\n      <div class=\"brand\">DASLAB <b>LEDGER</b></div>\n      <div class=\"divider\"></div>\n      <div class=\"role\" id=\"role\">Rulebook <span>· one rule, one claim, one source · re-checked on every read</span></div>\n      <div class=\"chip\" id=\"chip\">RULES · LIVE</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"summary\" id=\"summary\"></div>\n      <div class=\"list\" id=\"list\"></div>\n      <div class=\"prov\">Illustrated from recorded runs. Figures shaped, not copied. Read-only; not an audit opinion.</div>\n    </div>\n  </div>\n<script>\n(()=>{\n  const el=id=>document.getElementById(id);\n  const replay=window.__DASLAB_REPLAY__===true;\n  let d=window.__DASLAB_WIDGET_DATA__||{};\n  let tick=0;\n  const STATUS={ok:{glyph:'✅',word:'confirmed',cls:'ok'},single:{glyph:'◐',word:'single-source',cls:'single'},tension:{glyph:'⚠',word:'tension',cls:'tension'},open:{glyph:'❓',word:'open',cls:'open'}};\n  const tags=list=>'<span class=\"tags\">'+(list||[]).map(t=>'<span class=\"tag '+t+'\">'+t+'</span>').join('')+'</span>';\n  function render(){\n    if(d.role) el('role').innerHTML=d.role;\n    if(d.chip) el('chip').textContent=d.chip;\n    const rules=d.rules||[];\n    const counts={ok:0,single:0,tension:0,open:0}; rules.forEach(r=>{ counts[r.status]=(counts[r.status]||0)+1; });\n    el('summary').innerHTML=Object.keys(STATUS).map(k=>'<span class=\"st '+STATUS[k].cls+'\">'+STATUS[k].glyph+' '+counts[k]+' '+STATUS[k].word+'</span>').join('')+'<span class=\"checked\">'+(d.checked?('last read '+d.checked):'reading'+'.'.repeat(1+(tick%3)))+'</span>';\n    const host=el('list'); host.innerHTML='';\n    rules.forEach(r=>{\n      const s=STATUS[r.status]||STATUS.open;\n      const row=document.createElement('div'); row.className='rule'+(r.active?' active '+s.cls:'');\n      row.innerHTML='<div class=\"id\">'+r.id+'</div><div class=\"claim\">'+r.claim+tags(r.tags)+(r.note?'<small class=\"'+(r.noteKind||'')+'\">'+r.note+'</small>':'')+'</div><span class=\"st '+s.cls+'\">'+s.glyph+' '+s.word+'</span>';\n      host.appendChild(row);\n    });\n  }\n  addEventListener('message',e=>{\n    if(!replay||e.source!==parent||e.origin!==location.origin||e.data?.type!=='daslab:replay-clock') return;\n    if(e.data.data) d=e.data.data; render();\n  });\n  setInterval(()=>{ tick++; if(!d.checked) render(); }, 600);\n  render();\n})();\n</script>\n</body></html>\n",
        "data": {
          "role": "Rulebook <span>· one rule, one claim, one source</span>",
          "chip": "RULES · LIVE",
          "rules": []
        }
      },
      "layout": {
        "sortOrder": 4,
        "size": "large"
      }
    }
  ],
  "meta": {
    "author": "Daslab",
    "license": "MIT"
  }
}
