[{"data":1,"prerenderedAt":592},["ShallowReactive",2],{"featured-work":3,"home-writing":240},[4,41,71,98,124,154,186,213],{"id":5,"title":6,"body":7,"description":13,"extension":27,"featured":28,"meta":29,"navigation":28,"order":30,"path":31,"role":32,"seo":33,"status":34,"statusTone":35,"stem":36,"tagline":37,"url":38,"year":39,"__hash__":40},"work\u002Fwork\u002F1.oky.md","OKY",{"type":8,"value":9,"toc":23},"minimark",[10,14,17,20],[11,12,13],"p",{},"Phishing defence usually lives inside the mail server, invisible to the person actually\nbeing attacked. OKY puts the verdict where the user already is — in the mail thread, the\nbrowser, the phone — and explains in plain language why something looks wrong. A silent\nfilter teaches nobody anything; a good explanation makes the next attempt easier to spot.",[11,15,16],{},"I built all of it alone: the product, the analysis engine, seven client surfaces across\nfive platforms, and the operations behind them.",[11,18,19],{},"It is live with real users and published on the Chrome Web Store. Early — a small cohort\nrather than scale — and beta is the honest word.",[11,21,22],{},"I do not write publicly about how it decides, what it inspects, or how it is deployed.\nFor a live security product that is just a map for its adversaries. Happy to go deep in\nconversation.",{"title":24,"searchDepth":25,"depth":25,"links":26},"",2,[],"md",true,{},1,"\u002Fwork\u002Foky","Founder & solo developer",{"title":6,"description":13},"Live · Beta","live","work\u002F1.oky","An AI-driven email and messaging security platform that stops phishing, credential theft and impersonation before they reach the inbox.","https:\u002F\u002Foky.ai","2026","gvScMAOoDGKrEYJ_TmnHgUoKAqgsFUmPo2aXINoD1JA",{"id":42,"title":43,"body":44,"description":48,"extension":27,"featured":28,"meta":60,"navigation":28,"order":25,"path":61,"role":62,"seo":63,"status":64,"statusTone":65,"stem":66,"tagline":67,"url":68,"year":69,"__hash__":70},"work\u002Fwork\u002F2.zentro-wallet.md","Zentro Wallet",{"type":8,"value":45,"toc":58},[46,49,52,55],[11,47,48],{},"The largest system I have been responsible for: a wallet holding both fiat and crypto\nbalances, moving money between users, and settling with merchants — around twenty\nservices with web and mobile clients on top.",[11,50,51],{},"I owned the architecture and led the team of seven who built it, while staying hands-on\nin the code and in review.",[11,53,54],{},"The hard part was never any single feature. It was that every feature touches the same\nbalance, and that balance has to stay correct under concurrency, partial failure and\nretry — while fiat and crypto settle on completely different terms, one reversible and\nscheduled, the other irreversible and at nobody's pace. Telling a user \"this is your\nmoney\" honestly across both is a modelling problem long before it is a UI one.",[11,56,57],{},"The product has since been discontinued. Employer work, so there is no repository, no\nscreenshots, and nothing here about its internals.",{"title":24,"searchDepth":25,"depth":25,"links":59},[],{},"\u002Fwork\u002Fzentro-wallet","Architect & team lead — Stratech Corp",{"title":43,"description":48},"Discontinued","archive","work\u002F2.zentro-wallet","A twenty-microservice fiat and crypto wallet platform — top-up, withdrawal, P2P transfer, scan-to-pay and a merchant marketplace, across web and mobile.",null,"2024 — 2026","AQneCUfZyfURG7W69yOGGeKzRBt9Zw440E-c4tk_yPc",{"id":72,"title":73,"body":74,"description":78,"extension":27,"featured":28,"meta":90,"navigation":28,"order":91,"path":92,"role":93,"seo":94,"status":64,"statusTone":65,"stem":95,"tagline":96,"url":68,"year":69,"__hash__":97},"work\u002Fwork\u002F3.juegalo-predictor.md","Juegalo — Predictor",{"type":8,"value":75,"toc":88},[76,79,82,85],[11,77,78],{},"Predictor was a sports-prediction game: players called outcomes ahead of real fixtures\nand were scored against what actually happened. I built it and the partner-programme\nsite alongside it.",[11,80,81],{},"The interesting constraint was live sport. Fixtures move, matches get abandoned, results\nget corrected hours later — and every one of those events has to resolve fairly for\npeople who already committed a prediction. Handling that without either freezing the\ngame or quietly changing someone's result was most of the work.",[11,83,84],{},"It settled at 500–1,500 daily active players before being discontinued.",[11,86,87],{},"Employer work, so there is no code to show and nothing here about its internals.",{"title":24,"searchDepth":25,"depth":25,"links":89},[],{},3,"\u002Fwork\u002Fjuegalo-predictor","Built & maintained — Stratech Corp",{"title":73,"description":78},"work\u002F3.juegalo-predictor","A sports-prediction game that ran at 500–1,500 daily active players, plus the partner-programme site behind it.","FNnRMdM6XdlZIX-JUMo-SynDIbpkCpAspp0DfCmqz24",{"id":99,"title":100,"body":101,"description":105,"extension":27,"featured":28,"meta":114,"navigation":28,"order":115,"path":116,"role":117,"seo":118,"status":119,"statusTone":35,"stem":120,"tagline":121,"url":122,"year":39,"__hash__":123},"work\u002Fwork\u002F4.neon-nights.md","Neon Nights",{"type":8,"value":102,"toc":112},[103,106,109],[11,104,105],{},"Real-money gaming has an unforgiving property: the game is the easy part, and the money\nboundary is where everything actually goes wrong. Networks drop mid-bet, aggregators\nretry, rollbacks arrive for rounds that already settled. If the accounting is not\nprovably correct, the operator eats the difference.",[11,107,108],{},"So I built the whole thing from nothing — game engine, server, and a deliberately\nhostile fake wallet whose entire job is to break it: dropping responses, duplicating\ncallbacks, settling out of order, reversing what the server believes is final. You\ncannot prove fault tolerance by hoping, and you do not get to make a real counterparty\nmisbehave on demand.",[11,110,111],{},"It is playable with play money. A demonstrator rather than a licensed operation — no\nreal money moves through it and it has not been certified.",{"title":24,"searchDepth":25,"depth":25,"links":113},[],{},4,"\u002Fwork\u002Fneon-nights","Solo build",{"title":100,"description":105},"Playable","work\u002F4.neon-nights","A certifiable slot game server built from scratch — provably fair, money-correct, and stress-tested against a deliberately hostile wallet simulator.","https:\u002F\u002Fneon.vardanov.me","Gqi-imhFuQBtxh9rCF-rj3jFS_JSVQbHnKq2c6uQACc",{"id":125,"title":126,"body":127,"description":131,"extension":27,"featured":28,"meta":145,"navigation":28,"order":146,"path":147,"role":32,"seo":148,"status":149,"statusTone":150,"stem":151,"tagline":152,"url":68,"year":39,"__hash__":153},"work\u002Fwork\u002F5.minishop.md","MiniShop",{"type":8,"value":128,"toc":143},[129,132,135],[11,130,131],{},"MiniShop resells digital goods sourced on demand from overseas marketplaces. The\nstorefront was never the interesting part — payment custody was.",[11,133,134],{},"Buyers fund a balance in crypto, and the server holds no private keys at all. That is a\nstructural guarantee rather than a policy promise: compromising the application does not\ncompromise anyone's funds. I started with a third-party payment processor and removed it\nin favour of settling directly on-chain — fewer intermediaries, no custody, and one less\ncompany able to freeze a balance.",[11,136,137,138,142],{},"The other hard problem was disputes. Buyers speak one language, upstream vendors speak\nanother, and these conversations rarely end with a clean signal — they trail off. An AI\nlayer reads the running thread and judges whether it actually resolved, but what it is\nallowed to ",[139,140,141],"em",{},"do"," with that judgement stays bounded, reversible and logged. An automated\nremediation path is an attack surface if anyone can work out how to trigger it.",{"title":24,"searchDepth":25,"depth":25,"links":144},[],{},5,"\u002Fwork\u002Fminishop",{"title":126,"description":131},"Near production","build","work\u002F5.minishop","A crypto-settled storefront for imported digital goods, with an AI layer that resolves cross-language vendor disputes.","YlXfZ7-yQmJWG1qEtgutoMqZp3G5bO0jkbHgzAjTfF4",{"id":155,"title":156,"body":157,"description":177,"extension":27,"featured":28,"meta":178,"navigation":28,"order":179,"path":180,"role":117,"seo":181,"status":182,"statusTone":150,"stem":183,"tagline":184,"url":68,"year":39,"__hash__":185},"work\u002Fwork\u002F6.vt-academy.md","vt-academy",{"type":8,"value":158,"toc":175},[159,166,169,172],[11,160,161,162,165],{},"Reading about a vulnerability and exploiting one are unrelated skills. vt-academy is\nbuilt on the assumption that the lab ",[139,163,164],{},"is"," the lesson and the writing is supporting\nmaterial.",[11,167,168],{},"Every exercise gives the learner a real, deliberately vulnerable target to attack,\nisolated and disposable. Coding exercises are graded on what they actually produce\nrather than pattern-matched against the source. And because security knowledge decays\nbadly — you learn a class of bug, then do not see it for eight months — the whole thing\nruns on a spaced-repetition schedule that stretches as recall proves reliable and\ncollapses when it does not.",[11,170,171],{},"Ten chapters, from web fundamentals through to AI security.",[11,173,174],{},"Honest status: the platform is well ahead of the content. The labs, grader and review\nscheduler work; the curriculum is still filling in behind them.",{"title":24,"searchDepth":25,"depth":25,"links":176},[],"Reading about a vulnerability and exploiting one are unrelated skills. vt-academy is\nbuilt on the assumption that the lab is the lesson and the writing is supporting\nmaterial.",{},6,"\u002Fwork\u002Fvt-academy",{"title":156,"description":177},"In development","work\u002F6.vt-academy","A hands-on security engineering curriculum built around disposable vulnerable labs rather than video lectures.","20uVUEk-9WAriMkSmQOSKoZ5KDb9mdJKOAIJvlLkQRs",{"id":187,"title":188,"body":189,"description":193,"extension":27,"featured":28,"meta":205,"navigation":28,"order":206,"path":207,"role":32,"seo":208,"status":209,"statusTone":150,"stem":210,"tagline":211,"url":68,"year":39,"__hash__":212},"work\u002Fwork\u002F7.amplix.md","Amplix",{"type":8,"value":190,"toc":203},[191,194,197,200],[11,192,193],{},"Amplix automates the genuinely repetitive part of social media management: producing\non-brand content for several brands across several markets, then getting it out on\nschedule.",[11,195,196],{},"The real problem is not scheduling one post — it is keeping distinct brand voices\ncoherent across different regions and channels without a human rewriting everything by\nhand.",[11,198,199],{},"The decision I would defend is putting content generation behind an editable workflow\nrather than hard-coding it. That side of the product changes constantly, and it should\nnot take a deploy to change how a post gets written.",[11,201,202],{},"My second product taken from empty repository to running system alone. An MVP — the\nbackbone, scheduling and publishing work; broader channel coverage does not yet.",{"title":24,"searchDepth":25,"depth":25,"links":204},[],{},7,"\u002Fwork\u002Famplix",{"title":188,"description":193},"MVP","work\u002F7.amplix","AI-powered social media automation — generating, scheduling and publishing on-brand content across multiple brands and markets.","JLXrzAIpBZ8VZ_7kt9OcZcKWouJqlOqN0-MbhzKjYyI",{"id":214,"title":215,"body":216,"description":220,"extension":27,"featured":28,"meta":232,"navigation":28,"order":233,"path":234,"role":117,"seo":235,"status":236,"statusTone":150,"stem":237,"tagline":238,"url":68,"year":39,"__hash__":239},"work\u002Fwork\u002F8.pm-mcp.md","pm-mcp",{"type":8,"value":217,"toc":230},[218,221,224,227],[11,219,220],{},"AI coding agents are amnesiac. Every session starts from zero, so the context that\nmatters — what was decided last week, what is half-finished, what is deliberately\npaused — either gets re-explained or gets lost.",[11,222,223],{},"pm-mcp gives them a project board they can read and write natively, with a live kanban\ndashboard for the human side and a hook that injects the current state into every\nsession automatically.",[11,225,226],{},"The consequential decision was storing the board as plain Markdown files rather than in\na database. A database would have been easier to query and completely wrong: the whole\nvalue is that the board is diffable, versionable alongside the code, and editable by\nhand when the tool is not running.",[11,228,229],{},"It also ships a triage workflow that checks the board against the actual repository,\nbecause boards rot. I use it on my own projects daily, including this website.",{"title":24,"searchDepth":25,"depth":25,"links":231},[],{},8,"\u002Fwork\u002Fpm-mcp",{"title":215,"description":220},"Working tool","work\u002F8.pm-mcp","A single binary that gives AI coding agents persistent project memory — board, dashboard and session hook in one.","cnIDjJaChK7neczTHICqJyNqem7OUIfDoTeiWUE0hFM",[241,348],{"id":242,"title":243,"body":244,"date":336,"description":337,"draft":338,"extension":27,"meta":339,"navigation":28,"path":340,"seo":341,"stem":342,"tags":343,"__hash__":347},"writing\u002Fwriting\u002Fthe-country-your-threat-feed-forgot.md","The country your threat feed forgot",{"type":8,"value":245,"toc":329},[246,249,252,257,260,263,269,272,276,286,289,292,296,299,306,309,313,316,319,322,326],[11,247,248],{},"Every URL reputation system I have worked with leans, directly or indirectly, on domain\npopularity. Tranco, Majestic, Cisco Umbrella — the reasoning is sound: a domain in the\nglobal top 100,000 with years of history is unlikely to be a phishing page spun up\nyesterday.",[11,250,251],{},"Then you point it at Armenia and it tells your users that their bank is suspicious.",[253,254,256],"h2",{"id":255},"why-popularity-fails-outside-the-anglophone-web","Why popularity fails outside the anglophone web",[11,258,259],{},"A national bank serving three million people generates a rounding error of global\ntraffic. So does the state tax portal, the electricity utility, the largest local news\nsite, and the government services gateway.",[11,261,262],{},"These domains have every property a reputation system claims to want — a decade of\nregistration history, valid certificates, stable infrastructure, institutional\nownership. They just do not have volume, because there are not enough people in the\ncountry to produce it.",[11,264,265,266,268],{},"Meanwhile the phishing page impersonating that bank is often hosted on a subdomain of a\nservice that ",[139,267,164],{}," globally popular, inheriting reputation it did not earn.",[11,270,271],{},"The signal is not merely weak in small markets. It is occasionally inverted.",[253,273,275],{"id":274},"the-real-cost-is-not-the-false-positive","The real cost is not the false positive",[11,277,278,279,282,283,285],{},"A security product that flags your bank is annoying. A security product that flags your\nbank ",[139,280,281],{},"and"," your tax portal ",[139,284,281],{}," your utility company teaches you that its warnings are\nnoise.",[11,287,288],{},"That is the actual damage. Every unnecessary warning spends a small amount of the\nuser's willingness to believe the next one, and you cannot get it back. By the time a\ngenuine credential-harvesting page appears, the user has been trained by your own\nproduct to click through.",[11,290,291],{},"Alert fatigue is not a UX problem. It is a security failure with a UX-shaped cause.",[253,293,295],{"id":294},"what-to-do-about-it","What to do about it",[11,297,298],{},"The fix is conceptually dull: stop treating global popularity as evidence of\nlegitimacy, and give the system a jurisdiction-aware notion of which institutions\nactually matter locally — sourced from authoritative local records rather than inferred\nfrom traffic.",[11,300,301,302,305],{},"The important part is what that changes. A low global ranking stops being ",[139,303,304],{},"evidence of\nbadness","; it goes back to being what it always was, an absence of information. The\nother signals in the pipeline then decide, on their own merits, instead of starting\nfrom a thumb on the scale.",[11,307,308],{},"I am deliberately not publishing the structure I use, how it is weighted, or how it\ninteracts with the rest of the detection pipeline. Anything specific enough to be\nuseful to another engineer here is also specific enough to be useful to someone\nbuilding a page designed to score well against it. If you are working on this problem\nseriously, get in touch and we can talk properly.",[253,310,312],{"id":311},"the-unglamorous-part","The unglamorous part",[11,314,315],{},"There is no clever algorithm in any of this. Someone has to assemble the data for each\njurisdiction, verify it against official sources, and maintain it as institutions merge\nand rebrand.",[11,317,318],{},"It does not generalise automatically, it does not scale to two hundred countries\nwithout two hundred units of work, and it demos terribly.",[11,320,321],{},"It is also the difference between a product that works where I live and one that does\nnot. Most security tooling is built by people in markets where the global signal\nhappens to be adequate, and the failure mode is invisible from there — you have to be\nin the small market to notice that the tool is quietly wrong about everything that\nmatters.",[253,323,325],{"id":324},"the-general-lesson","The general lesson",[11,327,328],{},"If your detection logic depends on a popularity, volume, or \"we have seen this before\"\nsignal, go and find the population for whom that signal is structurally unavailable.\nThey exist. They are not an edge case to be handled later — they are the group your\nproduct is actively worst for, and they will churn without ever filing a bug report\nexplaining why.",{"title":24,"searchDepth":25,"depth":25,"links":330},[331,332,333,334,335],{"id":255,"depth":25,"text":256},{"id":274,"depth":25,"text":275},{"id":294,"depth":25,"text":295},{"id":311,"depth":25,"text":312},{"id":324,"depth":25,"text":325},"2026-07-09","Domain reputation systems are trained on the anglophone web. Outside it, they flag the sites that matter most — and teach users to ignore you.",false,{},"\u002Fwriting\u002Fthe-country-your-threat-feed-forgot",{"title":243,"description":337},"writing\u002Fthe-country-your-threat-feed-forgot",[344,345,346],"security","phishing","product","zGecium6aHSjx6aT0oZEPje8imdJH7ZazVME0GDtpaI",{"id":349,"title":350,"body":351,"date":582,"description":583,"draft":338,"extension":27,"meta":584,"navigation":28,"path":585,"seo":586,"stem":587,"tags":588,"__hash__":591},"writing\u002Fwriting\u002Fintegers-all-the-way-down.md","Integers all the way down",{"type":8,"value":352,"toc":574},[353,356,364,368,378,381,384,388,391,394,408,412,415,418,453,461,464,468,471,484,491,495,502,505,553,556,560,563,570],[11,354,355],{},"There is a class of bug that never shows up in your tests, never reproduces locally, and\nsurfaces three months into production as a slow, unexplained drift between what your\nledger says and what your payment provider says.",[11,357,358,359,363],{},"It usually starts with a ",[360,361,362],"code",{},"float64",".",[253,365,367],{"id":366},"the-failure-mode","The failure mode",[11,369,370,371,374,375,377],{},"Floating point cannot represent ",[360,372,373],{},"0.1",". It represents something extremely close to ",[360,376,373],{},",\nand the error is deterministic but not intuitive. Add enough of those together —\nmultiply them by a payout multiplier, apply a percentage rake, split a pot three ways —\nand you accumulate a residue.",[11,379,380],{},"The residue is tiny. That is exactly the problem. It is too small to notice in a single\ntransaction and too large to ignore across a million of them, and by the time\nreconciliation flags it you have no idea which transactions were wrong.",[11,382,383],{},"Worse, in regulated gaming the drift is not just an accounting nuisance. A payout table\nthat does not sum to the certified return-to-player figure is a compliance failure,\nregardless of how small the discrepancy is.",[253,385,387],{"id":386},"the-rule","The rule",[11,389,390],{},"Money is an integer count of minor units. Always.",[11,392,393],{},"Not \"usually\". Not \"except for this one percentage calculation\". The moment a float\nappears anywhere in the path — computing a bonus, applying a multiplier, splitting a\npayout — you have reintroduced the whole problem, because the value will be converted\nback to an integer eventually and that conversion is where the error crystallises.",[11,395,396,397,400,401,403,404,407],{},"In Go this means ",[360,398,399],{},"int64"," cents, or ",[360,402,399],{}," of whatever the smallest indivisible unit is\nfor your currency. In the slot engine I built for\n",[405,406,100],"a",{"href":116},", the game core has a hard invariant: no floating-point\ntype appears in any function that touches balance, stake, or payout. It is enforceable\nby reading the code, which is the point.",[253,409,411],{"id":410},"but-percentages","But percentages",[11,413,414],{},"The objection is always the same: some calculations are genuinely fractional. A 3.5%\nrake. A 96.2% RTP. A payout multiplier of 2.5×.",[11,416,417],{},"Those are fine — you just do the division last and decide explicitly what happens to the\nremainder.",[419,420,424],"pre",{"className":421,"code":422,"language":423,"meta":24,"style":24},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F rake in basis points: 350 = 3.50%\nfunc applyRake(amount int64, rakeBps int64) (net, rake int64) {\n    rake = amount * rakeBps \u002F 10_000  \u002F\u002F truncates toward zero\n    return amount - rake, rake\n}\n","go",[360,425,426,433,438,443,448],{"__ignoreMap":24},[427,428,430],"span",{"class":429,"line":30},"line",[427,431,432],{},"\u002F\u002F rake in basis points: 350 = 3.50%\n",[427,434,435],{"class":429,"line":25},[427,436,437],{},"func applyRake(amount int64, rakeBps int64) (net, rake int64) {\n",[427,439,440],{"class":429,"line":91},[427,441,442],{},"    rake = amount * rakeBps \u002F 10_000  \u002F\u002F truncates toward zero\n",[427,444,445],{"class":429,"line":115},[427,446,447],{},"    return amount - rake, rake\n",[427,449,450],{"class":429,"line":146},[427,451,452],{},"}\n",[11,454,455,456,460],{},"Multiply first, divide once, and the truncation happens in one known place instead of\nbeing smeared across every intermediate step. Then answer the question the float was\nletting you avoid: ",[457,458,459],"strong",{},"who gets the remainder?"," The house? The player? A rounding\naccount?",[11,462,463],{},"That question has a correct answer in your jurisdiction and your certification\ndocuments. A float lets you ship without ever asking it.",[253,465,467],{"id":466},"representing-the-split","Representing the split",[11,469,470],{},"For anything where the remainder must be distributed rather than absorbed — splitting a\npot, allocating a jackpot contribution — the pattern is largest-remainder:",[472,473,474,478,481],"ol",{},[475,476,477],"li",{},"Compute each share by integer division",[475,479,480],{},"Sum the shares and compare against the total",[475,482,483],{},"Distribute the difference, one unit at a time, to the parties with the largest truncated remainders",[11,485,486,487,490],{},"It is more code than ",[360,488,489],{},"total * 0.333",". It is also the only version that guarantees the\nparts sum to the whole, which is the property you actually needed.",[253,492,494],{"id":493},"at-the-boundary","At the boundary",[11,496,497,498,501],{},"The last place floats sneak in is serialisation. JSON has one number type, and it is a\ndouble. ",[360,499,500],{},"1234.56"," in a JSON payload is already a float by the time your parser sees it,\nand if your API contract says \"amount is a decimal number\" you have pushed the problem\nonto every consumer.",[11,503,504],{},"Send minor units as an integer, with the currency alongside:",[419,506,510],{"className":507,"code":508,"language":509,"meta":24,"style":24},"language-json shiki shiki-themes github-light github-dark","{ \"amount\": 123456, \"currency\": \"AMD\", \"exponent\": 2 }\n","json",[360,511,512],{"__ignoreMap":24},[427,513,514,518,522,525,528,531,534,536,540,542,545,547,550],{"class":429,"line":30},[427,515,517],{"class":516},"sVt8B","{ ",[427,519,521],{"class":520},"sj4cs","\"amount\"",[427,523,524],{"class":516},": ",[427,526,527],{"class":520},"123456",[427,529,530],{"class":516},", ",[427,532,533],{"class":520},"\"currency\"",[427,535,524],{"class":516},[427,537,539],{"class":538},"sZZnC","\"AMD\"",[427,541,530],{"class":516},[427,543,544],{"class":520},"\"exponent\"",[427,546,524],{"class":516},[427,548,549],{"class":520},"2",[427,551,552],{"class":516}," }\n",[11,554,555],{},"Format for humans at the very edge — in the template, in the UI, after every\ncalculation is finished. Never before.",[253,557,559],{"id":558},"why-this-is-worth-being-dogmatic-about","Why this is worth being dogmatic about",[11,561,562],{},"Most engineering rules deserve exceptions. This one mostly does not, because the cost\nasymmetry is severe: the discipline costs you a small amount of ergonomics on every\ntransaction, and violating it costs you an unfalsifiable accounting discrepancy that you\nwill debug under pressure with real customer money involved.",[11,564,565,566,569],{},"I would rather write ",[360,567,568],{},"applyRake"," than explain drift to an auditor.",[571,572,573],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":24,"searchDepth":25,"depth":25,"links":575},[576,577,578,579,580,581],{"id":366,"depth":25,"text":367},{"id":386,"depth":25,"text":387},{"id":410,"depth":25,"text":411},{"id":466,"depth":25,"text":467},{"id":493,"depth":25,"text":494},{"id":558,"depth":25,"text":559},"2026-06-18","Why there is no floating-point number anywhere in the money path of anything I build, and what replaces it.",{},"\u002Fwriting\u002Fintegers-all-the-way-down",{"title":350,"description":583},"writing\u002Fintegers-all-the-way-down",[589,423,590],"money correctness","igaming","BC-jq2vA-vxB2s3t0_a6Buqr0Dj6zncDTsppnsk2rXk",1784960487494]