function e(e){const t=Object.prototype.toString.call(e);return e instanceof Date||"object"==typeof e&&"[object Date]"===t?new e.constructor(+e):"number"==typeof e||"[object Number]"===t||"string"==typeof e||"[object String]"===t?new Date(e):new Date(NaN)}function t(e,t){return e instanceof Date?new e.constructor(t):new Date(t)}const n=6048e5;let a={};function r(){return a}function o(t,n){const a=r(),o=n?.weekStartsOn??n?.locale?.options?.weekStartsOn??a.weekStartsOn??a.locale?.options?.weekStartsOn??0,i=e(t),s=i.getDay(),c=(s<o?7:0)+s-o;return i.setDate(i.getDate()-c),i.setHours(0,0,0,0),i}function i(e){return o(e,{weekStartsOn:1})}function s(n){const a=e(n),r=a.getFullYear(),o=t(n,0);o.setFullYear(r+1,0,4),o.setHours(0,0,0,0);const s=i(o),c=t(n,0);c.setFullYear(r,0,4),c.setHours(0,0,0,0);const u=i(c);return a.getTime()>=s.getTime()?r+1:a.getTime()>=u.getTime()?r:r-1}function c(t){const n=e(t);return n.setHours(0,0,0,0),n}function u(t){const n=e(t),a=new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours(),n.getMinutes(),n.getSeconds(),n.getMilliseconds()));return a.setUTCFullYear(n.getFullYear()),+t-+a}function d(t){if(!(n=t,n instanceof Date||"object"==typeof n&&"[object Date]"===Object.prototype.toString.call(n)||"number"==typeof t))return!1;var n;const a=e(t);return!isNaN(Number(a))}const l={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}};function m(e){return(t={})=>{const n=t.width?String(t.width):e.defaultWidth;return e.formats[n]||e.formats[e.defaultWidth]}}const h={date:m({formats:{full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},defaultWidth:"full"}),time:m({formats:{full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},defaultWidth:"full"}),dateTime:m({formats:{full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},defaultWidth:"full"})},g={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"};function p(e){return(t,n)=>{let a;if("formatting"===(n?.context?String(n.context):"standalone")&&e.formattingValues){const t=e.defaultFormattingWidth||e.defaultWidth,r=n?.width?String(n.width):t;a=e.formattingValues[r]||e.formattingValues[t]}else{const t=e.defaultWidth,r=n?.width?String(n.width):e.defaultWidth;a=e.values[r]||e.values[t]}return a[e.argumentCallback?e.argumentCallback(t):t]}}function f(e){return(t,n={})=>{const a=n.width,r=a&&e.matchPatterns[a]||e.matchPatterns[e.defaultMatchWidth],o=t.match(r);if(!o)return null;const i=o[0],s=a&&e.parsePatterns[a]||e.parsePatterns[e.defaultParseWidth],c=Array.isArray(s)?function(e,t){for(let n=0;n<e.length;n++)if(t(e[n]))return n;return}(s,e=>e.test(i)):function(e,t){for(const n in e)if(Object.prototype.hasOwnProperty.call(e,n)&&t(e[n]))return n;return}(s,e=>e.test(i));let u;u=e.valueCallback?e.valueCallback(c):c,u=n.valueCallback?n.valueCallback(u):u;return{value:u,rest:t.slice(i.length)}}}var y;const w={code:"en-US",formatDistance:(e,t,n)=>{let a;const r=l[e];return a="string"==typeof r?r:1===t?r.one:r.other.replace("{{count}}",t.toString()),n?.addSuffix?n.comparison&&n.comparison>0?"in "+a:a+" ago":a},formatLong:h,formatRelative:(e,t,n,a)=>g[e],localize:{ordinalNumber:(e,t)=>{const n=Number(e),a=n%100;if(a>20||a<10)switch(a%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},era:p({values:{narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},defaultWidth:"wide"}),quarter:p({values:{narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},defaultWidth:"wide",argumentCallback:e=>e-1}),month:p({values:{narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},defaultWidth:"wide"}),day:p({values:{narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},defaultWidth:"wide"}),dayPeriod:p({values:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},defaultWidth:"wide",formattingValues:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},defaultFormattingWidth:"wide"})},match:{ordinalNumber:(y={matchPattern:/^(\d+)(th|st|nd|rd)?/i,parsePattern:/\d+/i,valueCallback:e=>parseInt(e,10)},(e,t={})=>{const n=e.match(y.matchPattern);if(!n)return null;const a=n[0],r=e.match(y.parsePattern);if(!r)return null;let o=y.valueCallback?y.valueCallback(r[0]):r[0];return o=t.valueCallback?t.valueCallback(o):o,{value:o,rest:e.slice(a.length)}}),era:f({matchPatterns:{narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},defaultMatchWidth:"wide",parsePatterns:{any:[/^b/i,/^(a|c)/i]},defaultParseWidth:"any"}),quarter:f({matchPatterns:{narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},defaultMatchWidth:"wide",parsePatterns:{any:[/1/i,/2/i,/3/i,/4/i]},defaultParseWidth:"any",valueCallback:e=>e+1}),month:f({matchPatterns:{narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},defaultParseWidth:"any"}),day:f({matchPatterns:{narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},defaultParseWidth:"any"}),dayPeriod:f({matchPatterns:{narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},defaultMatchWidth:"any",parsePatterns:{any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},defaultParseWidth:"any"})},options:{weekStartsOn:0,firstWeekContainsDate:1}};function b(n){const a=e(n),r=function(e,t){const n=c(e),a=c(t),r=+n-u(n),o=+a-u(a);return Math.round((r-o)/864e5)}(a,function(n){const a=e(n),r=t(n,0);return r.setFullYear(a.getFullYear(),0,1),r.setHours(0,0,0,0),r}(a));return r+1}function v(a){const r=e(a),o=+i(r)-+function(e){const n=s(e),a=t(e,0);return a.setFullYear(n,0,4),a.setHours(0,0,0,0),i(a)}(r);return Math.round(o/n)+1}function k(n,a){const i=e(n),s=i.getFullYear(),c=r(),u=a?.firstWeekContainsDate??a?.locale?.options?.firstWeekContainsDate??c.firstWeekContainsDate??c.locale?.options?.firstWeekContainsDate??1,d=t(n,0);d.setFullYear(s+1,0,u),d.setHours(0,0,0,0);const l=o(d,a),m=t(n,0);m.setFullYear(s,0,u),m.setHours(0,0,0,0);const h=o(m,a);return i.getTime()>=l.getTime()?s+1:i.getTime()>=h.getTime()?s:s-1}function P(a,i){const s=e(a),c=+o(s,i)-+function(e,n){const a=r(),i=n?.firstWeekContainsDate??n?.locale?.options?.firstWeekContainsDate??a.firstWeekContainsDate??a.locale?.options?.firstWeekContainsDate??1,s=k(e,n),c=t(e,0);return c.setFullYear(s,0,i),c.setHours(0,0,0,0),o(c,n)}(s,i);return Math.round(c/n)+1}function M(e,t){return(e<0?"-":"")+Math.abs(e).toString().padStart(t,"0")}const A={y(e,t){const n=e.getFullYear(),a=n>0?n:1-n;return M("yy"===t?a%100:a,t.length)},M(e,t){const n=e.getMonth();return"M"===t?String(n+1):M(n+1,2)},d:(e,t)=>M(e.getDate(),t.length),a(e,t){const n=e.getHours()/12>=1?"pm":"am";switch(t){case"a":case"aa":return n.toUpperCase();case"aaa":return n;case"aaaaa":return n[0];default:return"am"===n?"a.m.":"p.m."}},h:(e,t)=>M(e.getHours()%12||12,t.length),H:(e,t)=>M(e.getHours(),t.length),m:(e,t)=>M(e.getMinutes(),t.length),s:(e,t)=>M(e.getSeconds(),t.length),S(e,t){const n=t.length,a=e.getMilliseconds();return M(Math.trunc(a*Math.pow(10,n-3)),t.length)}},S="midnight",C="noon",x="morning",D="afternoon",T="evening",I="night",R={G:function(e,t,n){const a=e.getFullYear()>0?1:0;switch(t){case"G":case"GG":case"GGG":return n.era(a,{width:"abbreviated"});case"GGGGG":return n.era(a,{width:"narrow"});default:return n.era(a,{width:"wide"})}},y:function(e,t,n){if("yo"===t){const t=e.getFullYear(),a=t>0?t:1-t;return n.ordinalNumber(a,{unit:"year"})}return A.y(e,t)},Y:function(e,t,n,a){const r=k(e,a),o=r>0?r:1-r;if("YY"===t){return M(o%100,2)}return"Yo"===t?n.ordinalNumber(o,{unit:"year"}):M(o,t.length)},R:function(e,t){return M(s(e),t.length)},u:function(e,t){return M(e.getFullYear(),t.length)},Q:function(e,t,n){const a=Math.ceil((e.getMonth()+1)/3);switch(t){case"Q":return String(a);case"QQ":return M(a,2);case"Qo":return n.ordinalNumber(a,{unit:"quarter"});case"QQQ":return n.quarter(a,{width:"abbreviated",context:"formatting"});case"QQQQQ":return n.quarter(a,{width:"narrow",context:"formatting"});default:return n.quarter(a,{width:"wide",context:"formatting"})}},q:function(e,t,n){const a=Math.ceil((e.getMonth()+1)/3);switch(t){case"q":return String(a);case"qq":return M(a,2);case"qo":return n.ordinalNumber(a,{unit:"quarter"});case"qqq":return n.quarter(a,{width:"abbreviated",context:"standalone"});case"qqqqq":return n.quarter(a,{width:"narrow",context:"standalone"});default:return n.quarter(a,{width:"wide",context:"standalone"})}},M:function(e,t,n){const a=e.getMonth();switch(t){case"M":case"MM":return A.M(e,t);case"Mo":return n.ordinalNumber(a+1,{unit:"month"});case"MMM":return n.month(a,{width:"abbreviated",context:"formatting"});case"MMMMM":return n.month(a,{width:"narrow",context:"formatting"});default:return n.month(a,{width:"wide",context:"formatting"})}},L:function(e,t,n){const a=e.getMonth();switch(t){case"L":return String(a+1);case"LL":return M(a+1,2);case"Lo":return n.ordinalNumber(a+1,{unit:"month"});case"LLL":return n.month(a,{width:"abbreviated",context:"standalone"});case"LLLLL":return n.month(a,{width:"narrow",context:"standalone"});default:return n.month(a,{width:"wide",context:"standalone"})}},w:function(e,t,n,a){const r=P(e,a);return"wo"===t?n.ordinalNumber(r,{unit:"week"}):M(r,t.length)},I:function(e,t,n){const a=v(e);return"Io"===t?n.ordinalNumber(a,{unit:"week"}):M(a,t.length)},d:function(e,t,n){return"do"===t?n.ordinalNumber(e.getDate(),{unit:"date"}):A.d(e,t)},D:function(e,t,n){const a=b(e);return"Do"===t?n.ordinalNumber(a,{unit:"dayOfYear"}):M(a,t.length)},E:function(e,t,n){const a=e.getDay();switch(t){case"E":case"EE":case"EEE":return n.day(a,{width:"abbreviated",context:"formatting"});case"EEEEE":return n.day(a,{width:"narrow",context:"formatting"});case"EEEEEE":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},e:function(e,t,n,a){const r=e.getDay(),o=(r-a.weekStartsOn+8)%7||7;switch(t){case"e":return String(o);case"ee":return M(o,2);case"eo":return n.ordinalNumber(o,{unit:"day"});case"eee":return n.day(r,{width:"abbreviated",context:"formatting"});case"eeeee":return n.day(r,{width:"narrow",context:"formatting"});case"eeeeee":return n.day(r,{width:"short",context:"formatting"});default:return n.day(r,{width:"wide",context:"formatting"})}},c:function(e,t,n,a){const r=e.getDay(),o=(r-a.weekStartsOn+8)%7||7;switch(t){case"c":return String(o);case"cc":return M(o,t.length);case"co":return n.ordinalNumber(o,{unit:"day"});case"ccc":return n.day(r,{width:"abbreviated",context:"standalone"});case"ccccc":return n.day(r,{width:"narrow",context:"standalone"});case"cccccc":return n.day(r,{width:"short",context:"standalone"});default:return n.day(r,{width:"wide",context:"standalone"})}},i:function(e,t,n){const a=e.getDay(),r=0===a?7:a;switch(t){case"i":return String(r);case"ii":return M(r,t.length);case"io":return n.ordinalNumber(r,{unit:"day"});case"iii":return n.day(a,{width:"abbreviated",context:"formatting"});case"iiiii":return n.day(a,{width:"narrow",context:"formatting"});case"iiiiii":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},a:function(e,t,n){const a=e.getHours()/12>=1?"pm":"am";switch(t){case"a":case"aa":return n.dayPeriod(a,{width:"abbreviated",context:"formatting"});case"aaa":return n.dayPeriod(a,{width:"abbreviated",context:"formatting"}).toLowerCase();case"aaaaa":return n.dayPeriod(a,{width:"narrow",context:"formatting"});default:return n.dayPeriod(a,{width:"wide",context:"formatting"})}},b:function(e,t,n){const a=e.getHours();let r;switch(r=12===a?C:0===a?S:a/12>=1?"pm":"am",t){case"b":case"bb":return n.dayPeriod(r,{width:"abbreviated",context:"formatting"});case"bbb":return n.dayPeriod(r,{width:"abbreviated",context:"formatting"}).toLowerCase();case"bbbbb":return n.dayPeriod(r,{width:"narrow",context:"formatting"});default:return n.dayPeriod(r,{width:"wide",context:"formatting"})}},B:function(e,t,n){const a=e.getHours();let r;switch(r=a>=17?T:a>=12?D:a>=4?x:I,t){case"B":case"BB":case"BBB":return n.dayPeriod(r,{width:"abbreviated",context:"formatting"});case"BBBBB":return n.dayPeriod(r,{width:"narrow",context:"formatting"});default:return n.dayPeriod(r,{width:"wide",context:"formatting"})}},h:function(e,t,n){if("ho"===t){let t=e.getHours()%12;return 0===t&&(t=12),n.ordinalNumber(t,{unit:"hour"})}return A.h(e,t)},H:function(e,t,n){return"Ho"===t?n.ordinalNumber(e.getHours(),{unit:"hour"}):A.H(e,t)},K:function(e,t,n){const a=e.getHours()%12;return"Ko"===t?n.ordinalNumber(a,{unit:"hour"}):M(a,t.length)},k:function(e,t,n){let a=e.getHours();return 0===a&&(a=24),"ko"===t?n.ordinalNumber(a,{unit:"hour"}):M(a,t.length)},m:function(e,t,n){return"mo"===t?n.ordinalNumber(e.getMinutes(),{unit:"minute"}):A.m(e,t)},s:function(e,t,n){return"so"===t?n.ordinalNumber(e.getSeconds(),{unit:"second"}):A.s(e,t)},S:function(e,t){return A.S(e,t)},X:function(e,t,n){const a=e.getTimezoneOffset();if(0===a)return"Z";switch(t){case"X":return W(a);case"XXXX":case"XX":return E(a);default:return E(a,":")}},x:function(e,t,n){const a=e.getTimezoneOffset();switch(t){case"x":return W(a);case"xxxx":case"xx":return E(a);default:return E(a,":")}},O:function(e,t,n){const a=e.getTimezoneOffset();switch(t){case"O":case"OO":case"OOO":return"GMT"+q(a,":");default:return"GMT"+E(a,":")}},z:function(e,t,n){const a=e.getTimezoneOffset();switch(t){case"z":case"zz":case"zzz":return"GMT"+q(a,":");default:return"GMT"+E(a,":")}},t:function(e,t,n){return M(Math.trunc(e.getTime()/1e3),t.length)},T:function(e,t,n){return M(e.getTime(),t.length)}};function q(e,t=""){const n=e>0?"-":"+",a=Math.abs(e),r=Math.trunc(a/60),o=a%60;return 0===o?n+String(r):n+String(r)+t+M(o,2)}function W(e,t){if(e%60==0){return(e>0?"-":"+")+M(Math.abs(e)/60,2)}return E(e,t)}function E(e,t=""){const n=e>0?"-":"+",a=Math.abs(e);return n+M(Math.trunc(a/60),2)+t+M(a%60,2)}const L=(e,t)=>{switch(e){case"P":return t.date({width:"short"});case"PP":return t.date({width:"medium"});case"PPP":return t.date({width:"long"});default:return t.date({width:"full"})}},O=(e,t)=>{switch(e){case"p":return t.time({width:"short"});case"pp":return t.time({width:"medium"});case"ppp":return t.time({width:"long"});default:return t.time({width:"full"})}},H={p:O,P:(e,t)=>{const n=e.match(/(P+)(p+)?/)||[],a=n[1],r=n[2];if(!r)return L(e,t);let o;switch(a){case"P":o=t.dateTime({width:"short"});break;case"PP":o=t.dateTime({width:"medium"});break;case"PPP":o=t.dateTime({width:"long"});break;default:o=t.dateTime({width:"full"})}return o.replace("{{date}}",L(a,t)).replace("{{time}}",O(r,t))}},j=/^D+$/,F=/^Y+$/,z=["D","DD","YY","YYYY"];const N=/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g,Y=/P+p+|P+|p+|''|'(''|[^'])+('|$)|./g,B=/^'([^]*?)'?$/,V=/''/g,G=/[a-zA-Z]/;function U(t,n,a){const o=r(),i=o.locale??w,s=o.firstWeekContainsDate??o.locale?.options?.firstWeekContainsDate??1,c=o.weekStartsOn??o.locale?.options?.weekStartsOn??0,u=e(t);if(!d(u))throw new RangeError("Invalid time value");let l=n.match(Y).map(e=>{const t=e[0];if("p"===t||"P"===t){return(0,H[t])(e,i.formatLong)}return e}).join("").match(N).map(e=>{if("''"===e)return{isToken:!1,value:"'"};const t=e[0];if("'"===t)return{isToken:!1,value:Q(e)};if(R[t])return{isToken:!0,value:e};if(t.match(G))throw new RangeError("Format string contains an unescaped latin alphabet character `"+t+"`");return{isToken:!1,value:e}});i.localize.preprocessor&&(l=i.localize.preprocessor(u,l));const m={firstWeekContainsDate:s,weekStartsOn:c,locale:i};return l.map(e=>{if(!e.isToken)return e.value;const a=e.value;(function(e){return F.test(e)}(a)||function(e){return j.test(e)}(a))&&function(e,t,n){const a=function(e,t,n){const a="Y"===e[0]?"years":"days of the month";return`Use \`${e.toLowerCase()}\` instead of \`${e}\` (in \`${t}\`) for formatting ${a} to the input \`${n}\`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md`}(e,t,n);if(z.includes(e))throw new RangeError(a)}(a,n,String(t));return(0,R[a[0]])(u,a,i.localize,m)}).join("")}function Q(e){const t=e.match(B);return t?t[1].replace(V,"'"):e}const $=[{slug:"alpr-redaction-policy-guide",type:"guide",title:"ALPR & Public-Records Redaction: Policy, CJIS, and Audit in Practice",dek:"A field guide to shipping ALPR and video/audio redaction that stands up to PRA/FOIA and CJIS-style audits, without blocking operations.",tags:["CV","ALPR","Redaction","Policy","Audit","Security"],industries:["Public","Education"],products:["VISTA"],services:["CV FastTrack","Security & Compliance"],author:{name:"Sarah Chen",title:"Solutions Architect, Public Sector",avatar:"/avatars/sarah-chen.jpg"},readMinutes:12,heroImg:"/images/resources/alpr-redaction-hero.webp",heroAlt:"Evidence management system showing redacted video footage",publishedAt:"2025-01-15T00:00:00Z",ogImage:"/og/resources-alpr-redaction-policy-guide.webp",body:"\n# Why governance matters (and how it fails in practice)\n\nPublic-records laws and CJIS audits demand chain-of-custody, retention policies, and access controls. Yet most agencies still manage redaction through manual processes that can't scale and leave audit gaps. This guide shows you how to build a system that passes audit while supporting daily operations.\n\n## The gap between policy and practice\n\nPolicy documents specify retention periods, access levels, and redaction requirements. But without automated enforcement, these become wishful thinking. Officers and staff spend hours manually redacting footage, creating inconsistency and delays that undermine both compliance and operational efficiency.\n\n# Data model & chain-of-custody that auditors accept\n\nEvery piece of evidence needs:\n- Unique identifier with timestamps\n- Capture metadata (device, location, officer)\n- Access log (who viewed/edited when)\n- Redaction audit trail (what was redacted, by whom, why)\n- Retention classification and expiration date\n\nOur VISTA platform enforces this automatically. Every action is logged, every access is tracked, and every change is auditable.\n\n## Evidence lifecycle tracking\n\nFrom capture through retention to destruction, maintain unbroken chain-of-custody:\n1. Initial capture (CAD event linkage)\n2. Intake and classification\n3. Review and redaction workflow\n4. Publication or response to request\n5. Retention enforcement\n6. Secure destruction\n\n# Retention, access logging, and reviewer roles\n\nDefine roles with least-privilege access:\n- **Intake**: Upload and classify only\n- **Reviewer**: View and apply redactions\n- **Supervisor**: Approve release packages\n- **Auditor**: Read-only access to logs\n- **Admin**: System configuration\n\nSet retention rules by evidence type, automatically flagging items for review or destruction when retention periods expire.\n\n## Access logging requirements\n\nTrack every interaction:\n- Login/logout events\n- Evidence views (full timestamp, user ID)\n- Redaction actions (before/after states)\n- Export and download events\n- Configuration changes\n\nExport logs in standard formats (JSON, CSV) for external audit systems.\n\n# Bulk redaction at scale (faces/plates/objects/audio)\n\nManual redaction doesn't scale. VISTA processes:\n- Face detection and tracking across frames\n- License plate recognition and masking\n- Custom object detection (badges, documents)\n- Audio redaction (voices, sensitive content)\n\nBatch jobs handle hundreds of hours of footage overnight. Reviewers validate results, adjusting thresholds and manually correcting edge cases through an efficient review UI.\n\n## Accuracy gates and human review\n\nSet confidence thresholds per redaction type. Low-confidence detections route to human review. High-confidence detections apply automatically but remain auditable. This balance enables scale while maintaining quality.\n\n# Integration patterns (CAD/RMS, VMS, SSO)\n\nVISTA integrates with existing systems:\n- **CAD/RMS**: Automatic event linkage, case numbers\n- **VMS**: Direct ingest from body-worn and fixed cameras\n- **SSO**: SAML/OAuth for Active Directory/Okta\n- **Storage**: On-prem or hybrid with encrypted cloud backup\n\nAPIs enable custom workflows and third-party tool integration.\n\n## Deployment options\n\nRun fully on-premises for air-gapped environments or use hybrid cloud for scalability. All data stays within your infrastructure boundaries. Encryption in transit (TLS 1.3) and at rest (AES-256).\n\n# Acceptance criteria you can measure before go-live\n\nBefore production deployment, validate:\n- **Redaction accuracy**: ≥98% precision on test footage\n- **Throughput**: Process 100 hours of footage per day\n- **Latency**: PRA response packages ready within 48 hours\n- **Audit trail completeness**: 100% of actions logged\n- **Access control**: Role-based permissions enforced\n- **Retention**: Automated flagging and destruction workflows\n\nRun pilot with real cases, measure against these benchmarks, and iterate before full rollout.\n",faq:[{q:"How do you prove chain-of-custody?",a:"Every action is logged with timestamps, user IDs, and before/after states. Logs are append-only and digitally signed, providing tamper-evident audit trails that meet legal requirements."},{q:"Can we run fully on-prem?",a:"Yes. VISTA deploys on your infrastructure with no external dependencies. All processing, storage, and access control remain within your network boundaries."},{q:"What are typical redaction throughput numbers?",a:"On standard server hardware, process 100-500 hours of footage per day depending on resolution and redaction complexity. Scale horizontally by adding processing nodes."},{q:"How do we manage expungement/retention?",a:"Set retention policies by evidence type and classification. The system automatically flags items approaching expiration, routes for supervisor review, and securely destroys after approval."}]},{slug:"edge-computer-vision-production-blueprint",type:"guide",title:"Edge Computer Vision to Production: PoC → Pilot → Scale",dek:"A practical blueprint to move from a PoC to stable edge CV: datasets, accuracy gates, latency budgets, and operational review loops.",tags:["CV","Edge","Jetson","Latency","Accuracy","MLOps"],industries:["Manufacturing","Warehousing","Retail"],products:["SENTRA"],services:["CV FastTrack","MLOps & Model Ops"],author:{name:"Marcus Rodriguez",title:"Principal Engineer, Computer Vision",avatar:"/avatars/marcus-rodriguez.jpg"},readMinutes:14,heroImg:"/images/resources/edge-cv-hero.webp",heroAlt:"Edge computing devices processing real-time camera feeds in manufacturing facility",publishedAt:"2025-01-20T00:00:00Z",ogImage:"/og/resources-edge-computer-vision-production-blueprint.webp",body:"\n# Choosing sites and datasets that generalize\n\nPoCs often succeed on carefully selected test data but fail in production when conditions vary. To build models that generalize:\n\n## Site selection strategy\n\nChoose pilot sites that represent your operational diversity:\n- Varied lighting conditions (natural, artificial, mixed)\n- Different camera angles and mounting heights\n- Range of product/object variations\n- Typical background clutter and occlusions\n\nDon't pick your \"easiest\" site for pilot. Pick representative sites that will stress-test your models.\n\n## Dataset requirements\n\nCollect training data that covers:\n- All expected object classes and variations\n- Edge cases and failure modes\n- Seasonal and temporal variations (if relevant)\n- Multiple sites and camera positions\n\nAim for 1,000-5,000 labeled examples per class minimum. More is better, but quality trumps quantity. Ensure diverse, representative samples.\n\n# Accuracy & latency gates (and how to measure)\n\nSet quantitative acceptance criteria before deployment. Don't settle for \"it looks good.\" Measure precisely.\n\n## Accuracy gates\n\nDefine per-class thresholds:\n- **Precision**: ≥95% (minimize false positives)\n- **Recall**: ≥90% (minimize false negatives)\n- **F1 score**: ≥92% (balanced measure)\n\nMeasure on held-out test sets from production sites. Track confusion matrices to identify systematic errors.\n\n## Latency budgets\n\nDefine end-to-end latency requirements:\n- Camera capture → inference → alert: <500ms for real-time use cases\n- Batch processing: <1 hour for overnight jobs\n- Model load time: <30 seconds for edge device startup\n\nMeasure in production conditions, not just on development machines. Account for network latency, concurrent workloads, and thermal throttling on edge devices.\n\n| Pipeline Stage | Budget | Measurement |\n|---------------|--------|-------------|\n| Frame capture | 33ms (30fps) | Camera specs |\n| Preprocessing | 10ms | Profiler |\n| Inference | 100ms | Triton metrics |\n| Post-processing | 20ms | Profiler |\n| Alert dispatch | 50ms | Network monitor |\n| **Total** | **213ms** | End-to-end test |\n\n# Edge pipelines (DeepStream/Triton) with batching\n\nNVIDIA DeepStream and Triton Inference Server provide production-grade edge inference:\n\n## Pipeline architecture\n\n1. **Capture**: RTSP streams from IP cameras\n2. **Decode**: Hardware-accelerated video decode (NVDEC)\n3. **Batch**: Accumulate frames from multiple streams\n4. **Inference**: Run batched inference on GPU (Triton)\n5. **Track**: Multi-object tracking across frames\n6. **Alert**: Detect events and dispatch to upstream systems\n\nUse DeepStream's gst-launch pipelines for low-latency streaming or custom Python/C++ applications for complex logic.\n\n## Batching strategy\n\nBatch size trades off latency vs. throughput:\n- Batch size 1: Lowest latency (~50ms), lower GPU utilization\n- Batch size 8: Moderate latency (~120ms), high throughput\n- Batch size 32: High latency (~300ms), maximum throughput\n\nChoose based on your use case. Real-time alerting needs small batches; overnight analysis can use large batches.\n\n# Drift detection and retraining hooks\n\nModels degrade over time as conditions change. Detect drift and trigger retraining:\n\n## Monitoring signals\n\nTrack these metrics continuously:\n- **Confidence distribution**: Falling average confidence indicates drift\n- **Prediction entropy**: Rising entropy suggests uncertainty\n- **Human corrections**: Increased override rate signals model mismatch\n- **Performance metrics**: Declining accuracy on validation sets\n\nSet thresholds and alert when metrics cross into red zones.\n\n## Retraining workflow\n\n1. Detect drift signal\n2. Sample recent edge cases (low confidence, human corrections)\n3. Label and add to training set\n4. Retrain model with augmented dataset\n5. Validate on test set (must meet original accuracy gates)\n6. Deploy to edge devices via OTA update\n\nAutomate steps 1-2 and 6. Keep humans in the loop for steps 3-5 until you have high confidence in automated pipelines.\n\n# Reviewer tooling and evidence packaging\n\nEdge CV isn't fully autonomous. Humans review edge cases, validate alerts, and provide ground truth for retraining.\n\n## Review UI requirements\n\nBuild tooling that enables efficient review:\n- Queue of flagged items (low confidence, alerts, samples)\n- Side-by-side comparison (model prediction vs. ground truth)\n- Quick annotation actions (approve, reject, correct)\n- Keyboard shortcuts for power users\n- Progress tracking and quotas\n\nMeasure reviewer throughput (items/hour) and tune UI to maximize efficiency.\n\n## Evidence packaging\n\nWhen CV detects events, package evidence for downstream consumers:\n- **Video clip**: 5-10 seconds surrounding event\n- **Metadata**: Timestamp, camera ID, confidence scores\n- **Annotations**: Bounding boxes, class labels\n- **Context**: Related events, historical patterns\n\nExport in standard formats (JSON + MP4) for integration with MES, ERP, or analyst tools.\n\n# Scaling: health telemetry, upgrades, and costs\n\nDeploying to dozens or hundreds of edge devices requires operational discipline.\n\n## Health telemetry\n\nMonitor every device:\n- **System**: CPU, GPU, memory, disk, temperature\n- **Pipeline**: Frame rate, inference latency, queue depth\n- **Model**: Prediction counts, confidence distribution\n- **Network**: Bandwidth usage, packet loss, latency\n\nAggregate metrics in central dashboard. Alert on anomalies (thermal throttling, memory leaks, network issues).\n\n## OTA upgrade strategy\n\nDeploy model and software updates safely:\n1. **Canary**: Deploy to 1-2 devices, monitor for 24 hours\n2. **Pilot**: Expand to 10% of fleet, monitor for 48 hours\n3. **Rollout**: Deploy to remaining devices in waves\n4. **Rollback**: Maintain previous version as fallback\n\nUse device management platforms (Balena, AWS IoT, custom) to orchestrate deployments.\n\n## Cost model\n\nEdge CV costs include:\n- **Hardware**: $500-$5,000 per device (Jetson Orin, industrial PCs)\n- **Cameras**: $200-$1,000 per camera (IP cameras, lenses, mounts)\n- **Connectivity**: $50-$200/month per site (network, VPN)\n- **Maintenance**: 10-20% of hardware cost annually\n\nFactor in total cost of ownership over 3-5 year lifespan when comparing to cloud-based alternatives.\n",faq:[{q:"What frame rates and resolutions do you support?",a:"Typical deployments run 15-30fps at 1080p. Higher resolutions (4K) are possible but increase latency and hardware requirements. We optimize pipelines based on your specific accuracy and latency needs."},{q:"How do you validate accuracy against my sites?",a:"We collect representative datasets from your facilities, establish ground truth through manual annotation, and measure precision/recall against defined acceptance criteria before deploying to production."},{q:"What's a safe upgrade path on edge devices?",a:"Use canary deployments (1-2 devices first), monitor health metrics for 24-48 hours, then roll out in waves. Always maintain rollback capability to the previous stable version."}]},{slug:"agentic-ai-guardrails-evals-hitl",type:"guide",title:"Agentic AI Systems: Guardrails, Evals, and Human-in-the-Loop",dek:"How to design multi-agent automations that pass a security review: policy→prompts, eval suites, safety gates, and HITL patterns.",tags:["Agentic","GenAI","Guardrails","Evals","Security"],industries:["Enterprise"],services:["Agentic AI Systems","GenAI Product Accelerator","Security & Compliance"],author:{name:"Dr. Amara Okafor",title:"Lead, Agentic AI Practice",avatar:"/avatars/amara-okafor.jpg"},readMinutes:12,heroImg:"/images/resources/agentic-ai-hero.webp",heroAlt:"Multi-agent system architecture diagram showing guardrails and human review checkpoints",publishedAt:"2025-01-25T00:00:00Z",ogImage:"/og/resources-agentic-ai-guardrails-evals-hitl.webp",body:'\n# Risk model and policy mapping (PII, actions, approvals)\n\nBefore building agents, map your organization\'s policies to technical controls. Ask:\n\n## What can go wrong?\n\nIdentify failure modes:\n- **Data leakage**: PII, confidential info in prompts/responses\n- **Unauthorized actions**: Agents exceeding their authority\n- **Cost overruns**: Uncontrolled API usage\n- **Quality issues**: Hallucinations, incorrect outputs\n- **Security**: Prompt injection, jailbreaks\n\n## Policy → technical controls\n\nTranslate policies into enforceable rules:\n- "Don\'t share customer PII" → Input/output filters, redaction\n- "Require approval for orders >$10K" → Human-in-the-loop gate\n- "Limit AI spending to $500/day" → Rate limits, budget tracking\n- "Audit all decisions" → Comprehensive logging\n\nDocument this mapping. It becomes your acceptance criteria.\n\n# Prompt & tool contracts (least-privilege)\n\nDesign agents with narrow, explicit capabilities. Don\'t give a customer-service agent access to your entire API. Scope tools to minimum necessary permissions.\n\n## Prompt contracts\n\nDefine clear interfaces for each agent:\n- **Input schema**: What data the agent receives (typed, validated)\n- **Output schema**: What the agent returns (structured, not free-form)\n- **Constraints**: Boundaries the agent must respect\n\nExample:\n```\nAgent: Order Processor\nInput: { orderId: string, action: "cancel" | "refund" }\nOutput: { success: boolean, message: string, auditLog: string }\nConstraints: \n - Order must belong to authenticated user\n - Refunds ≤$10K auto-approve; >$10K route to human\n - All actions logged to audit table\n```\n\n## Tool least-privilege\n\nProvide agents only the tools they need:\n- Customer service agent: Read orders, create support tickets (no delete)\n- Analyst agent: Read-only database access (no write)\n- Automation agent: Execute approved workflows (no arbitrary code)\n\nEnforce through API keys with scoped permissions, not through prompts alone. Prompts can be jailbroken.\n\n# Evals you need (accuracy, jailbreak, toxicity, cost)\n\nContinuous evaluation prevents silent degradation. Build automated test suites:\n\n## Accuracy evals\n\nTest agent outputs against golden datasets:\n- Does the agent extract correct information?\n- Are calculations accurate?\n- Do responses match expected format?\n\nRun on every deployment. Regression should trigger rollback.\n\n## Safety evals\n\nTest for adversarial behavior:\n- **Jailbreak attempts**: Can users trick the agent into ignoring rules?\n- **Prompt injection**: Can users manipulate the agent\'s instructions?\n- **PII leakage**: Does the agent expose sensitive data?\n\nMaintain a "red team" dataset of known attacks. Add new attack vectors as discovered.\n\n## Quality evals\n\nMeasure subjective quality:\n- **Relevance**: Does the response address the query?\n- **Coherence**: Is the response logically consistent?\n- **Toxicity**: Does the agent generate harmful content?\n\nUse LLM-as-judge or human raters. Set acceptance thresholds (e.g., ≥4.0/5.0 average).\n\n## Cost evals\n\nTrack operational costs:\n- Tokens per interaction\n- API calls per workflow\n- Average cost per user session\n\nSet budget alerts. If costs spike, investigate prompt inefficiencies or abuse.\n\n## Minimal eval suite checklist\n\nBefore production:\n- [ ] 100+ accuracy test cases (happy path + edge cases)\n- [ ] 50+ safety test cases (jailbreaks, injections)\n- [ ] Cost per interaction measured and within budget\n- [ ] Quality spot-checked by human raters (n≥50)\n- [ ] All evals automated in CI/CD\n\n# Safety gates & rollback strategies\n\nEven with evals, things break. Build layered defenses:\n\n## Pre-flight checks\n\nBefore executing actions, validate:\n- Input schema compliance\n- User authorization\n- Rate limits not exceeded\n- Known-bad patterns not present\n\nReject invalid requests before they reach the agent.\n\n## Runtime guardrails\n\nWhile agents run, monitor:\n- Token usage (abort if exceeds threshold)\n- Confidence scores (route low-confidence to human)\n- Execution time (timeout if too slow)\n\nImplement circuit breakers. If error rate crosses threshold, disable agent and route to fallback.\n\n## Post-execution validation\n\nAfter agent completes, check:\n- Output schema compliance\n- Sensitive data redaction\n- Audit log completeness\n\nDon\'t return outputs that fail validation. Log failures and alert ops.\n\n## Rollback strategy\n\nWhen issues are detected:\n1. **Immediate**: Disable agent, route traffic to fallback (static responses, human queue)\n2. **Triage**: Review logs, identify root cause\n3. **Fix**: Update prompts, retrain models, patch code\n4. **Re-eval**: Run full eval suite\n5. **Gradual re-deploy**: Canary → pilot → full rollout\n\nMaintain version history. Fast rollback is essential.\n\n# Human-in-the-loop UI patterns (approve/annotate/retry)\n\nAgents augment humans, not replace them. Design HITL workflows that keep humans in control:\n\n## Approval workflows\n\nRoute high-stakes decisions to humans:\n- Present agent recommendation + confidence + reasoning\n- Show relevant context (order history, customer profile)\n- Provide approve/reject/modify actions\n- Track approval latency (SLA monitoring)\n\n## Annotation workflows\n\nHumans correct agent mistakes to improve future performance:\n- Show agent output vs. expected output\n- Provide easy correction interface (edit, select correct option)\n- Feed corrections back into retraining pipeline\n\nMeasure annotation quality (inter-rater agreement) to ensure reliable ground truth.\n\n## Retry workflows\n\nWhen agents fail, let humans retry with adjustments:\n- Show error message and context\n- Allow manual parameter tweaks (temperature, prompt modifications)\n- Re-run agent with new settings\n- Log retry attempts for later analysis\n\n## HITL reviewer flow (state machine)\n\n```\n[Agent Completes] \n ├─→ High confidence → Auto-approve → [Done]\n ├─→ Medium confidence → Human review → Approve/Reject → [Done]\n └─→ Low confidence → Human override → Manual completion → [Done]\n\n[Human Review]\n ├─→ Approve: Log acceptance, execute action\n ├─→ Reject: Log rejection reason, route to manual queue\n └─→ Modify: Annotate correction, re-run agent, log update\n```\n\n# Observability: success, fallback, cost\n\nInstrument everything. You can\'t improve what you don\'t measure.\n\n## Success metrics\n\nTrack:\n- **Completion rate**: % of agent runs that succeed\n- **Accuracy**: % of outputs matching expected results (from evals)\n- **Latency**: P50/P95/P99 response times\n- **User satisfaction**: Thumbs up/down, CSAT surveys\n\n## Fallback metrics\n\nWhen agents fail:\n- **Fallback rate**: % of requests routed to human/static fallback\n- **Fallback reasons**: Categorize failures (low confidence, timeout, error)\n- **Recovery time**: How long until agent restored after incident\n\n## Cost metrics\n\nMonitor spending:\n- **Token usage**: Tokens per request, daily/monthly totals\n- **API costs**: Dollars per interaction, by model/provider\n- **Infrastructure**: Compute, storage, bandwidth\n\nSet budgets and alerts. Cost spikes often indicate abuse or inefficiency.\n\n## Run logs\n\nStore comprehensive logs for every agent execution:\n- Timestamp, user ID, session ID\n- Input (prompt, parameters, context)\n- Output (response, confidence, tokens used)\n- Actions taken (API calls, database writes)\n- Success/failure status and error messages\n\nEnable searchability (Elasticsearch, CloudWatch Logs Insights). Logs are your debugging and audit trail.\n',faq:[{q:"How do we prevent unsafe actions?",a:"Layer defenses: scope agent permissions (least-privilege tools), validate inputs/outputs, enforce approval gates for high-stakes actions, and maintain audit logs. Test with adversarial evals."},{q:"Can we run on-prem/GovCloud?",a:"Yes. Deploy agents and LLMs within your infrastructure. Use self-hosted models (Llama, Mistral) or GovCloud-approved API providers. All data stays in your environment."},{q:"What belongs in an agent 'run log'?",a:"Log inputs (prompt, parameters), outputs (response, confidence), actions taken (API calls, data accessed), success/failure status, and timestamps. This enables debugging, audit, and retraining."}]}];export{U as f,$ as r};