[{"data":1,"prerenderedAt":657},["ShallowReactive",2],{"i-lucide:chevron-down":3,"i-lucide:search":8,"i-lucide:sun":10,"i-lucide:moon":12,"i-lucide:arrow-right":14,"i-lucide:menu":16,"i-lucide:mail":18,"i-simple-icons:x":20,"i-simple-icons:linkedin":22,"i-simple-icons:dribbble":25,"i-simple-icons:github":27,"work-\u002Fwork\u002Fhalyard-progressive-delivery":29,"work-order":575,"i-lucide:clock":607,"i-lucide:flask-conical":609,"i-lucide:target":611,"i-lucide:check":613,"i-lucide:minus":615,"i-lucide:chevron-right":617,"i-lucide:pen-tool":619,"i-lucide:lightbulb":621,"i-lucide:git-compare":623,"i-lucide:palette":625,"i-lucide:type":627,"i-lucide:variable":629,"i-lucide:blocks":631,"i-lucide:component":633,"i-lucide:circle-x":635,"i-lucide:circle-dashed":637,"i-lucide:triangle-alert":639,"i-lucide:circle-check":641,"i-lucide:plus":643,"i-lucide:users":645,"i-lucide:workflow":647,"i-lucide:zap":649,"i-lucide:git-branch":651,"i-lucide:shield-check":653,"i-lucide:activity":655},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m6 9l6 6l6-6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m21 21l-4.34-4.34\"\u002F>\u003Ccircle cx=\"11\" cy=\"11\" r=\"8\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":17},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":21},"\u003Cpath fill=\"currentColor\" d=\"M14.234 10.162L22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299l-.929-1.329L3.076 1.56h3.182l5.965 8.532l.929 1.329l7.754 11.09h-3.182z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":23,"hidden":24},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":26},"\u003Cpath fill=\"currentColor\" d=\"M12 24C5.385 24 0 18.615 0 12S5.385 0 12 0s12 5.385 12 12s-5.385 12-12 12m10.12-10.358c-.35-.11-3.17-.953-6.384-.438c1.34 3.684 1.887 6.684 1.992 7.308a10.28 10.28 0 0 0 4.395-6.87zm-6.115 7.808c-.153-.9-.75-4.032-2.19-7.77l-.066.02c-5.79 2.015-7.86 6.025-8.04 6.4a10.16 10.16 0 0 0 6.29 2.166c1.42 0 2.77-.29 4-.814zm-11.62-2.58c.232-.4 3.045-5.055 8.332-6.765q.202-.067.405-.12q-.392-.879-.832-1.74C7.17 11.775 2.206 11.71 1.756 11.7l-.004.312c0 2.633.998 5.037 2.634 6.855zm-2.42-8.955c.46.008 4.683.026 9.477-1.248a66 66 0 0 0-3.8-5.928a10.28 10.28 0 0 0-5.676 7.17zM9.6 2.052c.282.38 2.145 2.914 3.822 6c3.645-1.365 5.19-3.44 5.373-3.702A10.2 10.2 0 0 0 12 1.764c-.825 0-1.63.1-2.4.285zm10.335 3.483c-.218.29-1.935 2.493-5.724 4.04c.24.49.47.985.68 1.486c.08.18.15.36.22.53c3.41-.43 6.8.26 7.14.33c-.02-2.42-.88-4.64-2.31-6.38z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":28},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"id":30,"title":31,"accent":32,"accentLight":33,"body":34,"challenge":120,"client":141,"cover":142,"coverAlt":143,"decisions":144,"description":175,"excerpt":176,"extension":177,"featured":6,"features":178,"flows":203,"gallery":248,"ia":284,"industry":334,"kind":335,"meta":336,"navigation":24,"order":337,"outcomes":338,"path":362,"platform":363,"principles":367,"projectType":386,"research":387,"seo":463,"services":464,"stack":468,"stem":474,"system":475,"timeline":572,"year":573,"__hash__":574},"work\u002Fwork\u002F6.halyard-progressive-delivery.md","A progressive delivery console that can answer \"who is seeing this?\"","#818CF8","#4F46E5",{"type":35,"value":36,"toc":111},"minimark",[37,42,46,49,52,55,59,62,65,68,71,75,78,81,89,92,95,99,102,105,108],[38,39,41],"h2",{"id":40},"designing-for-the-reader-not-the-author","Designing for the reader, not the author",[43,44,45],"p",{},"Feature-flag tools are built by people configuring rollouts and used, at the\nmoments that matter, by people diagnosing them. Those are different jobs with\nopposite requirements, and the category consistently optimises for the first.",[43,47,48],{},"Configuration is calm. The person doing it understands the cohorts, has time to\nread, and benefits from a faithful, complete representation of every rule. That\nis what these consoles provide, and they provide it well.",[43,50,51],{},"Diagnosis is not calm. It happens at 3am, to someone who did not configure the\nrollout and has no idea why the cohorts are shaped as they are, while a graph\ngoes the wrong way. That person does not want a faithful representation of the\nrules. They want one sentence: here is who is affected.",[43,53,54],{},"Halyard is designed around the second reader, and the first reader is treated as\nthe easier case — they get the rules, one level down, where someone with time\nwill happily click.",[38,56,58],{"id":57},"computing-the-answer-changes-what-the-tool-is","Computing the answer changes what the tool is",[43,60,61],{},"Leading with a computed audience sounds like a presentation choice. It is\nactually the architectural decision the whole project turns on.",[43,63,64],{},"A console that displays rules is unfalsifiable. It shows you what is stored, and\nwhat is stored is by definition correct. There is nothing to check.",[43,66,67],{},"A console that computes an audience is making a claim, and a claim can be\nwrong. That is uncomfortable and it is the point: the computed answer can be\ncompared against what the SDK actually does on the same inputs, and any\ndivergence between the two becomes visible immediately rather than during an\noutage. The evaluation explainer shows both answers side by side for exactly\nthis reason.",[43,69,70],{},"It costs something real. Computing an audience over a large user base is\nexpensive and sometimes only approximate, so the figure carries its freshness\nand a visible marker when it is an estimate. An approximate number presented\nwith confidence would be worse than the rule list it replaced — trust in a\nconsole of this kind is binary, and one confidently wrong answer ends it\npermanently.",[38,72,74],{"id":73},"the-kill-switch-argument","The kill switch argument",[43,76,77],{},"The most contested decision here is removing the confirmation dialog, so the\nreasoning is worth setting out fully.",[43,79,80],{},"There are two conventional designs. A guarded kill switch puts a modal in front\nof the action; an unguarded one does not. The guarded version costs seconds in\nthe one flow where seconds are the entire value of the product, and it prevents\nnothing, because a dialog in a hot path is clicked through unread by everyone,\nevery time. The unguarded version gets hit by accident.",[43,82,83,84,88],{},"Both designs assume the failure is ",[85,86,87],"em",{},"pressing the button unintentionally",". That is\nnot the common failure. The common failure is pressing it intentionally without\nknowing what it covers — killing a flag that turns out to be attached to three\nother services, at 3am, while trying to help.",[43,90,91],{},"So the design addresses that instead. The blast radius is stated beside the\ncontrol, before the press: which services, which environments, how many users.\nThe action is reversible with one click for five minutes. Every kill writes an\naudit entry naming the person, which matters more for the follow-up than for the\nprevention.",[43,93,94],{},"This is a risk transfer, not a risk elimination, and it should be said plainly.\nAccidental kills will happen and will briefly affect production. A team whose\nrollback path is slow, or whose flags routinely have wide blast radii, should\nkeep the dialog — the trade only works if reversal is genuinely instant.",[38,96,98],{"id":97},"flag-debt-is-a-design-problem","Flag debt is a design problem",[43,100,101],{},"The hygiene work is the least glamorous part of this and possibly the most\nvaluable.",[43,103,104],{},"Every flag is created as temporary. A large share become permanent, and each\nsurvivor is a live conditional in production that nobody remembers the reason\nfor. The usual remedy is a platform engineer with a spreadsheet and persistence,\nwhich works exactly as well as one person's persistence.",[43,106,107],{},"Mandatory expiry makes the debt a state the tool displays rather than something\nsomeone tracks. But the expiry date alone would only produce a queue of\nnotifications, and notifications about other people's cleanup are the easiest\nthing in the world to ignore. What makes it work is generating the removal pull\nrequest once a flag's evaluation has been constant long enough to be safe —\nbecause the obstacle was never willingness. It was that removing a flag means\nfinding every call site, and nobody wants to do that on a Thursday.",[43,109,110],{},"The part that does not work is expiry churn. Rollouts legitimately run long,\nextensions become reflexive, and by the third snooze the date means nothing.\nRequiring a reason and showing extensions in the hygiene view slows the reflex a\nlittle. It does not fix it, and this design does not have a good answer.",{"title":112,"searchDepth":113,"depth":113,"links":114},"",3,[115,117,118,119],{"id":40,"depth":116,"text":41},2,{"id":57,"depth":116,"text":58},{"id":73,"depth":116,"text":74},{"id":97,"depth":116,"text":98},{"summary":121,"points":122},"Halyard is a scenario about a category of tool that is powerful, widely adopted, and consistently unhelpful at the exact moment it matters most. Feature-flag platforms are excellent at storing rules. During an incident nobody wants to read rules — they want an answer, and deriving the answer from four separate rule surfaces under pressure is where these tools fail.",[123,126,129,132,135,138],{"label":124,"detail":125},"The state is distributed across four surfaces","A flag's effect is the product of its default, its environment overrides, its cohort targeting and its individual overrides. Each is stored and displayed separately, and the reader has to combine them mentally to reach the only answer they came for.",{"label":127,"detail":128},"The critical question is asked under the worst conditions","\"Who is seeing this?\" is almost always asked at 3am, by someone who did not configure the rollout, while a graph is going the wrong way. Any interface requiring careful reading has failed at that moment.",{"label":130,"detail":131},"The kill switch is either slow or dangerous","Guarded by a confirmation dialog it costs seconds nobody has, and the dialog is clicked through unread anyway. Unguarded it gets hit by accident. Both designs are common and both are wrong.",{"label":133,"detail":134},"Temporary flags are permanent","A flag created for a two-week rollout is still evaluated three years later, and every one is a live branch in production code. Nothing in the tool makes that accumulation visible.",{"label":136,"detail":137},"Staging and production look identical","The same console, the same layout, one small dropdown between them. The resulting mistake is rare, severe, and entirely predictable from the design.",{"label":139,"detail":140},"The SDK and the console must agree","If the console says a user is in the rollout and the SDK disagrees, the console is worse than useless — it is confidently wrong, and it will be trusted during an incident.","Halyard","\u002Fcase-studies\u002Fhalyard\u002Fscreens\u002Fflag-surface.webp","Halyard flag surface leading with the computed audience",[145,151,157,163,169],{"title":146,"problem":147,"decision":148,"rationale":149,"tradeoff":150},"Compute the audience instead of displaying the rules","Flags store a default, environment overrides, cohort targeting and individual overrides. Every one of those is displayed faithfully, and the answer the reader wants is in none of them — it is the product of all four, computed in the reader's head under time pressure.","The flag surface leads with the computed audience — who is currently affected, by segment, with a count. Rules move one level down, where the person editing them will still find them.","It moves the computation from the reader to the machine, which is the whole job. It also makes the console checkable: a computed answer can be compared against the SDK's evaluation, whereas a list of rules can only be agreed with.","Computing an audience over a large user base is expensive and sometimes approximate, so the figure carries its own freshness and a clear marker when it is an estimate. An approximate answer presented confidently would be worse than the rule list it replaced.",{"title":152,"problem":153,"decision":154,"rationale":155,"tradeoff":156},"A kill switch with no confirmation dialog","The two conventional designs both fail. A confirmation dialog costs seconds during an incident and is clicked through unread, so it prevents nothing while slowing the one action that matters. No guard at all means accidental kills.","One action, no modal. Safety comes from three other places: the blast radius is stated beside the control before it is pressed, the action is reversible with one click for a sustained window, and every kill writes an audit entry naming the person.","Dialogs defend against the wrong failure. The real risk is not that someone presses the button without meaning to — it is that they press it not knowing what it covers. Stating the scope addresses that; instant reversibility handles the rest.","Accidental kills will happen and will briefly affect production. We judged a rare, immediately reversible accident better than seconds added to every genuine incident, but this is a real risk transfer rather than a risk elimination, and a team with a slow rollback path should not accept it.",{"title":158,"problem":159,"decision":160,"rationale":161,"tradeoff":162},"Mandatory expiry at flag creation","Every flag is created as temporary and a large share become permanent. Each survivor is a live conditional in production that nobody remembers the reason for, and no team voluntarily audits them.","Creation requires an expiry date. Past it the flag enters an expiring state, appears in the hygiene view with its owner, and — once its evaluation has been constant for long enough — generates a removal pull request.","It converts flag debt from an invisible accumulation into a state the tool displays, and the generated pull request removes the actual obstacle, which was never willingness but the tedium of finding every call site.","Expiry churn. Rollouts legitimately run long, and every extension is a small tax that becomes a reflex — after the third snooze the date is meaningless. Extensions therefore require a reason and are shown in the hygiene view, which helps a little and does not solve it.",{"title":164,"problem":165,"decision":166,"rationale":167,"tradeoff":168},"Production carries persistent chrome, not a dropdown","Staging and production share a console, a layout and a small environment selector. The resulting mistake is rare and severe, and it is entirely predictable from the design.","Production gets a persistent bordered frame, a distinct accent, the word PRODUCTION in the header, and the environment name inside every destructive control's label rather than only in the selector.","The signal needs to be present in peripheral vision at the moment of action, not available for checking beforehand. Putting the environment in the button label means the last thing read before clicking states which environment is about to change.","Persistent chrome costs screen space on every production view, which is most views, and the effect fades with familiarity as all such warnings do. Putting the environment in the control label is the part that keeps working after the frame becomes invisible.",{"title":170,"problem":171,"decision":172,"rationale":173,"tradeoff":174},"An evaluation explainer as a first-class surface","\"Is this specific user affected?\" cannot be answered from rule definitions without simulating the evaluation by hand, which is why incident tickets end up containing screenshots of SDK debug output.","Paste an identifier and see the exact rule path — every rule considered in order, which one short-circuited, and the resulting variant, alongside the SDK's answer on the same inputs.","It answers the question directly and, by showing both answers together, makes any console-versus-SDK divergence immediately visible rather than discovered during an outage.","It exposes internal evaluation order, which constrains future changes to it — people will build habits around what they see. It is also a surface that handles user identifiers, so it needs access control and audit that the rest of the console does not.","A concept study in developer tooling — a feature-flag and rollout platform designed around the one question nobody can answer during an incident, plus a kill switch that is fast without being accidental.",null,"md",[179,183,187,191,195,199],{"title":180,"detail":181,"icon":182},"Computed audience panel","One authoritative answer to who is currently affected, with a segment breakdown, its own freshness and an explicit marker when it is an estimate.","lucide:users",{"title":184,"detail":185,"icon":186},"Evaluation explainer","Any identifier evaluated against live rules, showing the ordered rule path and the SDK's answer on the same inputs.","lucide:workflow",{"title":188,"detail":189,"icon":190},"Reversible scoped kill","Blast radius stated before the action, no confirmation dialog, one-click reversal for five minutes, and an audit entry naming the actor.","lucide:zap",{"title":192,"detail":193,"icon":194},"Enforced flag lifecycle","Mandatory expiry at creation, six lifecycle states, and generated removal pull requests once evaluation has been constant.","lucide:git-branch",{"title":196,"detail":197,"icon":198},"Unmistakable environments","Persistent production chrome plus the environment name inside every destructive control label, so the signal survives familiarity.","lucide:shield-check",{"title":200,"detail":201,"icon":202},"Change-first landing view","Recent rollout changes across all flags, correlated with service error rates, because recency is what an incident asks about.","lucide:activity",[204,215,225,237],{"title":205,"note":206,"before":207,"after":214},"Answering \"who is seeing this?\"","The flow the entire product is judged on. The before column is not badly designed — each of those screens is fine on its own. The failure is that the answer exists in none of them.",[208,209,210,211,212,213],"Open the flag","Read the default","Open environment overrides","Open cohort targeting","Open individual overrides","Combine mentally",[208],{"title":216,"note":217,"before":218,"after":223},"Checking whether a specific user is affected","Impossible in the current state, which is why incident tickets contain screenshots of SDK debug logs.",[219,220,221,222],"Read the cohort definitions","Work out whether the user matches","Ask the owning team","Read SDK logs",[224],"Paste the identifier into Explain",{"title":226,"note":227,"before":228,"after":234},"Stopping a bad rollout","The blast radius being stated before the action is what allows the scoped kill to be chosen over the blunt one.",[229,230,231,232,233],"Find the flag","Guess the blast radius","Click disable","Dismiss a confirmation dialog","Hope nothing unrelated was attached",[235,236],"Read the stated blast radius","Kill, scoped",{"title":238,"note":239,"before":240,"after":245},"Retiring a finished flag","Currently driven entirely by one platform engineer with a spreadsheet and persistence.",[241,242,243,244],"Maintain a spreadsheet","Chase the owning team","Wait","Chase again",[246,247],"Flag enters the expiring state automatically","Accept the generated removal pull request",[249,256,263,267,273,278],{"title":250,"caption":251,"src":142,"width":252,"alt":253,"frame":254,"span":255},"Flag surface","The computed audience is the primary content; the rules that produce it are one level down. A console that lists rules is unfalsifiable — one that computes an answer is making a claim that can be checked.",1600,"Feature flag console showing a computed audience of 42,908 users","browser","full",{"title":257,"caption":258,"src":259,"width":260,"alt":261,"frame":262,"span":255},"The answer, not the rules","Who is affected, by segment, with the computation's own age and an explicit marker where the figure is sampled rather than exact.","\u002Fcase-studies\u002Fhalyard\u002Fcomponents\u002Fflag-surface--audience.webp",1372,"Computed audience panel with segment breakdown and freshness","plain",{"title":184,"caption":264,"src":265,"width":252,"alt":266,"frame":254},"An identifier in, the exact rule path out — including which rule short-circuited — beside the SDK's answer on identical inputs.","\u002Fcase-studies\u002Fhalyard\u002Fscreens\u002Fexplain.webp","Rule path trace for a single user identifier",{"title":268,"caption":269,"src":270,"width":271,"alt":272,"frame":262},"Console against SDK","Showing both answers together makes divergence visible here rather than during an outage. Trust in a console of this kind is binary.","\u002Fcase-studies\u002Fhalyard\u002Fcomponents\u002Fexplain--sdk.webp",543,"Console and SDK evaluation results shown side by side",{"title":274,"caption":275,"src":276,"width":252,"alt":277,"frame":254,"span":255},"Kill control","Blast radius stated before the press, no confirmation dialog, one-click reversal for five minutes. The reasoning is printed on the screen for whoever later proposes adding the dialog back.","\u002Fcase-studies\u002Fhalyard\u002Fscreens\u002Fkill.webp","Kill control showing blast radius and a five-minute undo window",{"title":279,"caption":280,"src":281,"width":282,"alt":283,"frame":262},"Production is unmistakable","Persistent frame, distinct accent, the word in the header — and the environment name inside the destructive control's own label, so the last text read before the click says what is about to change.","\u002Fcase-studies\u002Fhalyard\u002Fcomponents\u002Fkill--kill.webp",726,"Destructive control labelled with the production environment",[285,295,311,321],{"label":286,"detail":287,"children":288},"Changes","The landing surface. Ordered by recency, because that is the incident question.",[289,292],{"label":290,"detail":291},"Recent changes","Every rollout state change in the last 24 hours, across all flags",{"label":293,"detail":294},"Correlation","Change timeline overlaid on service error rates",{"label":296,"detail":297,"children":298},"Flag","One surface holding the computed audience, the lifecycle state and the controls.",[299,302,305,308],{"label":300,"detail":301},"Audience","The computed answer — who is currently affected, and how many",{"label":303,"detail":304},"Lifecycle","One of six states, with the expiry date and its owner",{"label":306,"detail":307},"Rules","Default, environment, cohort and individual overrides, one level down",{"label":309,"detail":310},"Kill","Scoped disable with the blast radius stated before the action",{"label":312,"detail":313,"children":314},"Explain","Evaluate any identifier against live rules and show the path taken.",[315,318],{"label":316,"detail":317},"Rule path","Every rule considered, in order, and which one short-circuited",{"label":319,"detail":320},"SDK parity","The console's answer checked against the SDK's on identical inputs",{"label":322,"detail":323,"children":324},"Hygiene","Flag debt as a visible state rather than a spreadsheet somebody maintains.",[325,328,331],{"label":326,"detail":327},"Expiring","Flags past or approaching their declared expiry, with owners",{"label":329,"detail":330},"Dead","Fully rolled out or fully off for a sustained period",{"label":332,"detail":333},"Removal pull requests","Generated for flags whose evaluation is now constant","Developer Tools","concept",{},6,[339,343,347,351,355,359],{"value":340,"label":341,"description":342},"1","Authoritative answer to \"who sees this\"","A computed audience, replacing four rule surfaces a reader had to combine mentally to reach an answer.",{"value":344,"label":345,"description":346},"5 → 1","Screens to diagnose a rollout","Flag state, environment, cohort membership, overrides and evaluation history consolidated onto one surface.",{"value":348,"label":349,"description":350},"0","Confirmation dialogs on the kill switch","One action, no modal. Safety comes from scope, reversibility and an audit entry, not from a dialog nobody reads at 3am.",{"value":352,"label":353,"description":354},"100%","Flags carrying an expiry","Creation requires one. A flag without an expiry is permanent branching disguised as a temporary experiment.",{"value":356,"label":357,"description":358},"6","Lifecycle states specified","Draft, rolling, held, complete, expiring and archived — making flag debt visible as a state rather than a spreadsheet.",{"value":340,"label":360,"description":361},"Action to explain any evaluation","Paste an identifier, get the exact rule path that produced that user's variant, including which rule short-circuited.","\u002Fwork\u002Fhalyard-progressive-delivery",[364,365,366],"Web console","CLI","SDK surface",[368,371,374,377,380,383],{"title":369,"detail":370},"Show the answer, not the rules that imply it","The console computes the current audience and presents it as the primary content. Rules remain available, one level down, for the person changing them rather than the person reading them.",{"title":372,"detail":373},"Design for the reader who did not write it","Every surface is built for someone encountering this flag for the first time, at speed, under stress. The author is the easier case and gets the second-priority treatment.",{"title":375,"detail":376},"Safety through reversibility, not friction","A confirmation dialog in a hot path is a speed bump that gets clicked through unread. Making the action instantly and obviously undoable is what actually prevents harm.",{"title":378,"detail":379},"Every flag has an expiry","Set at creation, no exceptions. A permanent flag is a branch in production code, and it should have to be named as one.",{"title":381,"detail":382},"Environments are never confusable","Production carries persistent chrome, a distinct colour and an explicit word. Colour alone is insufficient and is never used alone.",{"title":384,"detail":385},"The console must be provably right","Its computed answer is checked against the SDK's evaluation on the same inputs. A console that is confidently wrong once is never trusted again.","Developer platform design & information architecture",{"summary":388,"premises":389,"personas":408,"journey":435},"The premises focus on the incident path rather than the configuration path, because configuration is done calmly by someone who understands the system and diagnosis is done urgently by someone who does not. Tools in this category are almost always designed for the first case.",[390,393,396,399,402,405],{"label":391,"detail":392},"The reader is not the author","The person diagnosing a rollout at 3am did not set it up and has no context on why the cohorts are shaped as they are. Every surface must be readable cold.",{"label":394,"detail":395},"Rules are stored; answers are wanted","The gap between \"here are four rule sets\" and \"here is who is affected\" is small for a calm expert and enormous under pressure.",{"label":397,"detail":398},"Confirmation dialogs do not prevent mistakes","We assume any dialog in a hot path is clicked through unread. Safety has to come from reversibility and scope rather than from a speed bump.",{"label":400,"detail":401},"Flag debt accumulates silently","We assume no team voluntarily audits flags. If cleanup is not surfaced as state in the tool, it does not happen.",{"label":403,"detail":404},"Environment mistakes are a design failure","We assume that if staging and production are visually identical, someone will eventually act on the wrong one, and the design owns that outcome.",{"label":406,"detail":407},"Trust in the console is binary","One occasion where the console disagreed with observed behaviour, and engineers go back to reading the SDK logs permanently.",[409,422],{"name":410,"role":411,"context":412,"goals":413,"frustrations":417,"quote":421},"Sam Okafor","On-call backend engineer","Paged at 3am about an error rate on a service they do not own. They suspect a rollout, have never opened this flag before, and need to know within a minute whether to kill it.",[414,415,416],"Find out who is currently affected, immediately","Stop the bleeding without taking down anything unrelated","Leave a record so the owning team knows what was done",[418,419,420],"Four screens to combine before an answer exists","No way to check a specific reported user against the rules","A kill switch guarded by a dialog, or one that kills more than intended","I do not care how the targeting is configured. I need to know who is getting the bad code and how to make that stop.",{"name":423,"role":424,"context":425,"goals":426,"frustrations":430,"quote":434},"Priya Venkatesan","Platform engineer, developer experience","Owns the flag system across forty services. Spends a recurring part of every quarter chasing teams to remove flags that finished rolling out long ago and are now permanent conditionals.",[427,428,429],"See which flags are dead without auditing by hand","Give teams a reason to clean up that is not her asking","Keep the console and the SDK provably in agreement",[431,432,433],"No lifecycle state, so a finished flag looks like an active one","Cleanup is a spreadsheet she maintains personally","No way to prove the console's answer matches the SDK's","Every flag nobody removed is an `if` statement in production that somebody will trip over in two years.",[436,440,446,448,453,458],{"stage":437,"doing":438,"feeling":439},"Page fires","Wakes up, opens the alert, sees an error rate climbing on one service.","negative",{"stage":441,"doing":442,"feeling":443,"friction":444,"opportunity":445},"Suspect a rollout","Opens the flag console and searches for recent changes.","neutral","Recency is not a first-class view; changes are buried in per-flag history.","A changes-first landing view scoped to the last few hours.",{"stage":229,"doing":447,"feeling":443},"Locates a flag that changed forty minutes before the alert.",{"stage":449,"doing":450,"feeling":439,"friction":451,"opportunity":452},"Work out the audience","Reads the default, then environment overrides, then cohorts, then individual overrides.","Four surfaces to combine mentally, at 3am, on someone else's configuration.","Compute the audience and show it as the primary content.",{"stage":454,"doing":455,"feeling":439,"friction":456,"opportunity":457},"Check a reported user","Tries to confirm whether the one user in the ticket is actually affected.","No way to evaluate a specific identifier against the live rules.","An evaluation explainer that shows the exact rule path taken.",{"stage":459,"doing":460,"feeling":439,"friction":461,"opportunity":462},"Kill it","Hesitates over the scope of the kill switch, then disables the whole flag.","Unclear blast radius, so the safe move is the blunt one.","Scoped kill with the blast radius stated, instantly reversible.",{"title":31,"description":175},[465,466,467],"Product Design","Design Systems","Frontend Engineering",[469,470,471,472,473],"Figma","Vue 3","TypeScript","Go","OpenTelemetry","work\u002F6.halyard-progressive-delivery",{"summary":476,"radius":477,"density":478,"palette":479,"type":497,"tokens":522,"components":546,"specimens":567},"A dense console system tuned for reading under stress. Tight radii and compact density, monospace for anything an engineer will copy, a status ramp held apart from the categorical chart hues, and environment identity treated as a system-level concern rather than a page-level one.",4,"compact",[480,484,486,489,493],{"name":481,"value":482,"role":483},"Terminal","#0B0B10","Primary surface, dark theme",{"name":141,"value":32,"role":485},"Primary action and the subject series in charts, dark theme",{"name":487,"value":33,"role":488},"Halyard (light)","The same role restepped for the light theme",{"name":490,"value":491,"role":492},"Reference","#71717A","Secondary text, and the comparison series in every chart",{"name":494,"value":495,"role":496},"Production","#DC2626","Environment identity only. Never a series colour, never a status.",[498,504,508,513,517],{"name":499,"size":500,"weight":501,"tracking":502,"usage":503},"Count","1.75rem",600,"-0.02em","Audience sizes and affected-user counts, tabular",{"name":505,"size":506,"weight":501,"usage":507},"Heading","1.0625rem","Flag names and panel titles",{"name":509,"size":510,"weight":511,"usage":512},"Body","0.875rem",400,"Descriptions, rule text and console copy",{"name":514,"size":515,"weight":511,"usage":516},"Code","0.8125rem","Flag keys, identifiers and rule paths — anything that gets copied",{"name":518,"size":519,"weight":501,"tracking":520,"usage":521},"Chrome","0.6875rem","0.14em","PRODUCTION — environment identity in the persistent frame",[523,527,531,535,539,542],{"name":524,"value":525,"usage":526},"--env-chrome","persistent","Production identity is frame, colour and word. Never colour alone.",{"name":528,"value":529,"usage":530},"--destructive-label","includes environment","The last text read before a destructive click names the environment.",{"name":532,"value":533,"usage":534},"--undo-window","5min","One-click reversal on any kill. Replaces the confirmation dialog.",{"name":536,"value":537,"usage":538},"--audience-freshness","required","Every computed audience states its age and whether it is an estimate.",{"name":540,"value":537,"usage":541},"--expiry","Enforced at creation. There is no path to a flag without one.",{"name":543,"value":544,"usage":545},"--row-height","28px","Compact. A console is read in bulk, not admired.",[547,551,554,557,561,564],{"name":548,"variants":549,"detail":550},"AudiencePanel",5,"The computed answer, with segment breakdown, freshness and estimate marker.",{"name":552,"variants":477,"detail":553},"KillControl","Scoped disable stating its blast radius, with a five-minute one-click undo.",{"name":555,"variants":337,"detail":556},"LifecycleBadge","Draft, rolling, held, complete, expiring, archived — icon and word, never colour alone.",{"name":558,"variants":559,"detail":560},"RulePath",7,"Ordered evaluation trace showing which rule short-circuited and why.",{"name":562,"variants":113,"detail":563},"EnvironmentFrame","Persistent chrome carrying environment identity across every view.",{"name":565,"variants":337,"detail":566},"ChangeRow","A rollout state change with actor, time and correlated service impact.",[568,569,570,571],"status","table","chart","buttons","12-week scope","2026","RRzOGqFfee5MtsHHwKuvTI-U2zKZmoZxf5hSPSt_k1w",[576,582,588,594,600,606],{"path":577,"client":578,"title":579,"excerpt":176,"accent":580,"industry":581},"\u002Fwork\u002Fnorthwind-design-system","Northwind Cloud","One design system across four acquired products","#00D4FF","SaaS",{"path":583,"client":584,"title":585,"excerpt":176,"accent":586,"industry":587},"\u002Fwork\u002Fmeridian-clinical-ai","Meridian Health","Designing an AI that clinicians are allowed to disagree with","#22C55E","Healthcare",{"path":589,"client":590,"title":591,"excerpt":176,"accent":592,"industry":593},"\u002Fwork\u002Fledgerly-onboarding","Ledgerly","Rebuilding onboarding around the first useful moment","#7C3AED","Fintech",{"path":595,"client":596,"title":597,"excerpt":176,"accent":598,"industry":599},"\u002Fwork\u002Ffleetwise-dashboard","Fleetwise","A fleet dashboard people stop exporting to spreadsheets","#F59E0B","Logistics",{"path":601,"client":602,"title":603,"excerpt":176,"accent":604,"industry":605},"\u002Fwork\u002Fverdigris-marketplace","Verdigris","An e-commerce system where every product is one of one","#E07A5F","E-commerce",{"path":362,"client":141,"title":31,"excerpt":176,"accent":32,"industry":334},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":608},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 6v6l4 2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":610},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2M6.453 15h11.094M8.5 2h7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":612},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Ccircle cx=\"12\" cy=\"12\" r=\"6\"\u002F>\u003Ccircle cx=\"12\" cy=\"12\" r=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":614},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 6L9 17l-5-5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":616},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":618},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m9 18l6-6l-6-6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":620},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\"\u002F>\u003Cpath d=\"m18 13l-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18M2.3 2.3l7.286 7.286\"\u002F>\u003Ccircle cx=\"11\" cy=\"11\" r=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":622},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":624},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"18\" cy=\"18\" r=\"3\"\u002F>\u003Ccircle cx=\"6\" cy=\"6\" r=\"3\"\u002F>\u003Cpath d=\"M13 6h3a2 2 0 0 1 2 2v7m-7 3H8a2 2 0 0 1-2-2V9\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":626},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\"\u002F>\u003Ccircle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"\u002F>\u003Ccircle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"\u002F>\u003Ccircle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"\u002F>\u003Ccircle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":628},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2M9 20h6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":630},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 21s-4-3-4-9s4-9 4-9m8 0s4 3 4 9s-4 9-4 9M15 9l-6 6m0-6l6 6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":632},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M10 22V7a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5a1 1 0 0 0-1-1H2\"\u002F>\u003Crect width=\"8\" height=\"8\" x=\"14\" y=\"2\" rx=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":634},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.536 11.293a1 1 0 0 0 0 1.414l2.376 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0zm-13.239 0a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0zm6.619 6.619a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0zm0-13.238a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":636},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m15 9l-6 6m0-6l6 6\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":638},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10.1 2.182a10 10 0 0 1 3.8 0m0 19.636a10 10 0 0 1-3.8 0m7.509-18.097a10 10 0 0 1 2.69 2.7M2.182 13.9a10 10 0 0 1 0-3.8m18.097 7.509a10 10 0 0 1-2.7 2.69M21.818 10.1a10 10 0 0 1 0 3.8M3.721 6.391a10 10 0 0 1 2.7-2.69m-.03 16.578a10 10 0 0 1-2.69-2.7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":640},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m21.73 18l-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4m0 4h.01\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":642},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m9 12l2 2l4-4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":644},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7v14\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":646},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M16 3.128a4 4 0 0 1 0 7.744M22 21v-2a4 4 0 0 0-3-3.87\"\u002F>\u003Ccircle cx=\"9\" cy=\"7\" r=\"4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":648},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"8\" height=\"8\" x=\"3\" y=\"3\" rx=\"2\"\u002F>\u003Cpath d=\"M7 11v4a2 2 0 0 0 2 2h4\"\u002F>\u003Crect width=\"8\" height=\"8\" x=\"13\" y=\"13\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":650},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.914 4a1.5 1.5 0 0 0-2.474-1.561l-9 9A1.5 1.5 0 0 0 5.5 14h4.002a.5.5 0 0 1 .471.666L8.086 20a1.5 1.5 0 0 0 2.475 1.56l9-9A1.5 1.5 0 0 0 18.5 10h-3.997a.5.5 0 0 1-.472-.667z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":652},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 6a9 9 0 0 0-9 9V3\"\u002F>\u003Ccircle cx=\"18\" cy=\"6\" r=\"3\"\u002F>\u003Ccircle cx=\"6\" cy=\"18\" r=\"3\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":654},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\"\u002F>\u003Cpath d=\"m9 12l2 2l4-4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":656},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\"\u002F>",1787597897691]