From e9b8a7f6e300719539287e54d3583fc12349a60c Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:09:43 -0700 Subject: [PATCH 1/4] DOC: Replace landing page Roakey peeks with animated spritesheets Swap the two photoreal Roakey images on the landing page for three cartoon spritesheets whose frames are stepped by a scroll timeline, so each mascot plays a short sequence as its section scrolls into view. Each sprite is a fixed-size window onto a horizontal frame strip: object-fit none renders the strip at 1:1 and the box clips it to one frame, so animating object-position steps through frames. The base object-position is the last frame, which is what shows when scroll timelines are unsupported or reduced motion is requested; starting from the first frame would leave the scout invisible because its opening frame is an empty ledge. Placement is anchored to content rather than the page edge so the three sit at distinct levels: the scout perches on the CoPyRIT card, the spyglass rests on the install code block, and the flag arrives centred below the tab group. The flag scrubs over a fixed 200px rather than a percentage of cover, because it sits at the very bottom of the page where a viewport-relative range would strand the sequence mid-run on tall screens. Net asset size drops about 1.4 MB. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 13a6d940-c11c-4ba7-a4d4-bc6b9d75c757 --- doc/css/custom.css | 160 ++++++++++++++++++-------- doc/index.md | 22 ++-- doc/roakey_peek.png | Bin 989022 -> 0 bytes doc/roakey_tail.png | Bin 813273 -> 0 bytes doc/sprites/roakey-peek-and-scout.png | Bin 0 -> 136837 bytes doc/sprites/roakey-run-and-flag.png | Bin 0 -> 121851 bytes doc/sprites/roakey-spyglass-scan.png | Bin 0 -> 107478 bytes 7 files changed, 129 insertions(+), 53 deletions(-) delete mode 100644 doc/roakey_peek.png delete mode 100644 doc/roakey_tail.png create mode 100644 doc/sprites/roakey-peek-and-scout.png create mode 100644 doc/sprites/roakey-run-and-flag.png create mode 100644 doc/sprites/roakey-spyglass-scan.png diff --git a/doc/css/custom.css b/doc/css/custom.css index 50d005d44c..49db0021f5 100644 --- a/doc/css/custom.css +++ b/doc/css/custom.css @@ -82,83 +82,153 @@ pointer-events: none; } -/* --- Roakey scroll peeks --------------------------------------------------- - Decorative mascots anchored at predefined points in the landing page. They - sit absolutely (out of flow, so they never shift content) and slide in from - the edge as you scroll past, stopping flush against the side. */ -.roakey-peek { +/* --- Roakey sprite animations ---------------------------------------------- + Each sprite is a fixed-size window onto a horizontal frame strip. With + `object-fit: none` the strip renders at 1:1 and the box clips it to a single + frame, so animating `object-position` steps through the frames. A scroll + timeline drives that stepping, which means the animation is scrubbed by the + reader rather than played on a timer. + + The base `object-position` is the LAST frame: that is what shows when scroll + timelines are unsupported or reduced motion is requested. Starting from the + first frame would leave the scout invisible, since its opening frame is an + empty ledge. + + Sprites sit absolutely (out of flow, so they never shift content) and are + hidden below the width where the gutters beside the centered content column + have room for them. */ +.roakey-sprite { + display: none; position: absolute; - height: auto; + object-fit: none; margin: 0; pointer-events: none; user-select: none; z-index: 5; } -/* Off-screen peeks must not create horizontal scroll. */ +/* Safety net: sprites are positioned out of flow, so keep any stray horizontal + extent from adding a scrollbar. */ html, body { overflow-x: clip; } -/* Anchor the peeks to the full-width content column. The landing block that - wraps each directive is narrow and centered, so reaching the true screen - edge from it would require a viewport-based offset that overshoots past the - clip box (the vertical scrollbar makes the right side fall fully outside, - hiding the tail). Promoting `main` to the containing block lets us anchor - flush with a plain `left: 0` / `right: 0`, fully inside the clip box. */ -main:has(.roakey-peek) { +/* The flag is centred on the page, so it anchors to the full-width `main` + rather than to the narrow, centred landing block that wraps its directive. + + The scout and the spyglass instead anchor to the content they sit on, so + their own rules below promote a nearer ancestor. */ +main:has(.roakey-sprite) { position: relative; } -.myst-landing-block:has(.roakey-peek) { +.myst-landing-block:has(.roakey-sprite) { position: static; } -/* Head peeks in from the left edge */ -.roakey-peek-left { - left: 0; - width: 170px; - transform: translateX(-100%); +@media (min-width: 1536px) { + .roakey-sprite { + display: block; + } } -/* Tail peeks in from the right edge */ -.roakey-peek-tail { - right: 0; - width: 190px; - transform: translateX(100%); +/* Each sprite is anchored to the content it belongs to rather than to the page + edge, so the three sit at clearly different levels down the page. */ + +/* Perches on top of the CoPyRIT card: the capabilities grid is the anchor, and + the offsets centre the sprite over the third column. */ +.myst-grid:has(.roakey-sprite-scout) { + position: relative; +} +.roakey-sprite-scout { + right: 97px; + top: -123px; + width: 181px; + height: 156px; + object-position: -1086px 0; +} + +/* Climbs out of the install code block, flipped to look back along the line it + came from. The content column is centred in `main` and width-capped, so + offsetting from the centre lands the sprite at the right end of the code + block no matter how wide the viewport gets. + + `translateY` lifts it from its static position (immediately before the block) + so its feet come to rest on the block's top edge. Two offsets matter here: + the artwork stops 3px short of the frame's bottom, and the visible block edge + is the `.myst-code` wrapper that paints the background — not the inner `
`,
+ which sits 12px lower behind the wrapper's padding. */
+.roakey-sprite-spyglass {
+ left: calc(50% + 388px);
+ width: 151px;
+ height: 119px;
+ object-position: -604px 0;
+ transform: translateY(-116px) scaleX(-1);
+}
+
+/* Runs in from the left and comes to rest centred on the page. The centring is
+ done with `calc` rather than a negative margin because the theme's own image
+ rules override margins on these elements. */
+main:has(.roakey-sprite-flag) {
+ position: relative;
+}
+.roakey-sprite-flag {
+ left: calc(50% - 75.5px);
+ width: 151px;
+ height: 120px;
+ object-position: -755px 0;
}
-/* Slide in as the peek scrolls through the viewport (Chromium/Edge). */
+/* Advance frames as each sprite scrolls through the viewport (Chromium/Edge).
+ The range is `cover 0%` to `cover 50%`: the sequence starts as the sprite
+ comes into view and resolves by the time it reaches mid-viewport, then holds
+ its final frame. Scrubbing over `entry` instead would compress the whole
+ sequence into the sprite's own height — roughly 20px of scrolling per frame,
+ far too fast to read.
+
+ `steps(n)` where the keyframe travel is n frame-widths lands the final frame
+ at the end of the range. */
@supports (animation-timeline: view()) {
- /* Both peeks only reveal on wide viewports, where the gutters beside the
- centered content column have room for them. On narrower screens they would
- cover the content, so they stay hidden off-screen. */
@media (min-width: 1536px) {
- .roakey-peek-left {
- animation: roakey-peek-left linear both;
+ .roakey-sprite-spyglass {
+ animation: roakey-spyglass-frames steps(4) both;
animation-timeline: view();
- animation-range: entry 0% entry 100%;
+ animation-range: cover 0% cover 50%;
}
- .roakey-peek-tail {
- animation: roakey-peek-tail linear both;
+ .roakey-sprite-scout {
+ animation: roakey-scout-frames steps(6) both;
animation-timeline: view();
- animation-range: entry 0% entry 100%;
+ animation-range: cover 0% cover 50%;
}
+ /* The flag sits at the very bottom of the page, where only ~230px of
+ scrolling remains once it starts entering. A percentage of `cover` scales
+ with viewport height and would strand the sequence mid-run on tall
+ screens, so this one scrubs over a fixed length that always completes. */
+ .roakey-sprite-flag {
+ animation: roakey-flag-frames steps(5) both, roakey-flag-run linear both;
+ animation-timeline: view(), view();
+ animation-range: cover 0px cover 200px, cover 0px cover 200px;
+ }
+ }
+ @keyframes roakey-spyglass-frames {
+ from { object-position: 0 0; }
+ to { object-position: -604px 0; }
+ }
+ @keyframes roakey-scout-frames {
+ from { object-position: 0 0; }
+ to { object-position: -1086px 0; }
}
- @keyframes roakey-peek-left {
- 0% { transform: translateX(-100%); }
- 100% { transform: translateX(0); }
+ @keyframes roakey-flag-frames {
+ from { object-position: 0 0; }
+ to { object-position: -755px 0; }
}
- /* Stop before the wooden board enters the viewport, so only the tail shows
- (the board occupies the right ~10% of the image). */
- @keyframes roakey-peek-tail {
- 0% { transform: translateX(100%); }
- 100% { transform: translateX(13%); }
+ @keyframes roakey-flag-run {
+ from { transform: translateX(-100%); }
+ to { transform: translateX(0); }
}
}
@media (prefers-reduced-motion: reduce) {
- .roakey-peek-left,
- .roakey-peek-tail {
+ .roakey-sprite {
animation: none;
}
}
diff --git a/doc/index.md b/doc/index.md
index 3c568037b7..f7a353604e 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -42,9 +42,9 @@ Run standardized evaluation scenarios at large scale — covering content harms,
A graphical user interface for human-led red teaming. Interact with AI systems directly, track findings, and collaborate with your team — all from a modern web UI.
::::
-```{image} roakey_peek.png
-:alt: Roakey peeking in
-:class: roakey-peek roakey-peek-left
+```{image} sprites/roakey-peek-and-scout.png
+:alt: Roakey rising up to peek over a ledge
+:class: roakey-sprite roakey-sprite-scout
```
::::{card}
@@ -72,6 +72,12 @@ Evaluate AI responses with true/false, Likert scale, classification, and custom
## Getting Started
1. Install PyRIT and verify installation.\
For more details and alternative installation methods, see the [Install PyRIT](getting_started/install) page
+
+```{image} sprites/roakey-spyglass-scan.png
+:alt: Roakey raising a spyglass to scan the horizon
+:class: roakey-sprite roakey-sprite-spyglass
+```
+
```bash
# note: for local installation, python version 3.13 is recommended: https://www.python.org/downloads/latest/python3.13
pip install pyrit
@@ -111,11 +117,6 @@ initializers:
:::::
-```{image} roakey_tail.png
-:alt: Roakey's tail peeking in
-:class: roakey-peek roakey-peek-tail
-```
-
3. Use PyRIT in any mode that best fits your use case: Scanner, GUI, or Framework.
::::{tab-set}
@@ -170,3 +171,8 @@ await printer.write_async(result)
For more details, see the [Framework](code/framework) page.
::::
+
+```{image} sprites/roakey-run-and-flag.png
+:alt: Roakey running in and planting a pirate flag
+:class: roakey-sprite roakey-sprite-flag
+```
diff --git a/doc/roakey_peek.png b/doc/roakey_peek.png
deleted file mode 100644
index c3326e3573b758fe953c0ebc55f73ca880041508..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 989022
zcmW){d0dit_dfo7zcZglZOnx%HMc-qa$j;mO@9d}xaOYbP|z`3Tu?I+(@GLGH4(n|{P+v*7rgJ~T<>#T=Q@Y%i+-NRkDWgD
zuYdjPI2wfr{MWz!FYx}S0{MRfN1DdhbN;2QZh%Hy2)_4!QvaHLeKiZS^nQ1K;oATH
zOF`*O<6rqUGpk--ntI(WB$1&FvEHkYt*WnHOspq9zSN+oPX5;a%6~Zg?iO1!{Zqxu
zj?k#{Y33OxMh3X6DmYM;ee#HEG;W154K154EHs`!TSoB{g1=Ch^n+)d--vM?1JG^1
z#GK=BK^4(>n9Dv(&pPFyIv*d5w_Q@nTeWbAe$16T=fX?Amawl5qYkpY|`GbD2_>OzaFOG96M~#*1iLLQL)?JNooOjVfo{x@j$DAt8sa&A!r+tkfKB|2pOeNK%<{CQQrU`NeO;k`#W6K4y|s;aAkM6j?MAg0E4$rW
zeb16QuT4vKCrQG`VR~Pc(%VSDr(cH>
zIy47vj$UOz0xZ6k_~32T7?IC1BXJglxl!Ly->z8Y4yHE>lSsZUCwxB27SgWaUoe9$
z=GSd9I13E`vKX0FbH9`!ryLi)%sx6ceN%vm(8Y(1F8B!&i&gT(g?sVk=
zPYTh@myfepZG9Z?Q=T9+R3s+Qyl7TFcn1gDVy@uKZHORH(8(M(sK{~|}g?lK5dkzXseBfxp1$-6U7tq1`f5x;3UCK&Vukc
zkYbu6P3U9mpmrwR!K9Rka>s{R%vTyVvYoH13WaA#{uYG$@@yXihh^?6g`iy&U($W-
zmYT1w5G&e(PKUSC0rNv2U
zVopu3%awZve|g7FPUO9;y3*?yU#tz>WerB{Z3y>f@amd|
zTpm9JWr3mXsR8IfAOi*hOyG%Q_GMN~!OhBX#Z`%=5ILdNT&tllILwYKr0VY?X)t&IO9!%&`NtV(WTz~9WA-L4rxCDX5b5;w>?8;oY8l~E|=QMD-
z16HRFEKSRXfeZr%z759Pnv>=0PXxrG=iVl|dT(|Y4
zD>VnJYb<_2x&&Tx^hvINkFB>W*x4Auc=qpqbhrYnOkK$&6f=DLtQ@rPv(NZE#jn9x
zdHL}j+rhBO>3|%jCOnbslDnGdSDGL&Ec+=onh>_A@R*;FOZR^2!d>7_E!%YDy@oM?
zTtlaOTp}pgLg-loE{OJ9jxLDJuA&|=fpdX#^{$Q4)7nCK7e@D4Z&3V%?`oocgb>VB
zvp+@DfN!hRUtc_1HViA#WIw~dkJq-ab#VR_XJYRR%a6om@U(2Ta)zz&==Q0X&zQf|
zqlJS$5s0T^k3{=<0S-eOpO`L8x)$Hn$iB*O-^8D|TOsItQ8*4Re#{4Mh9}a%$}_Wh
zDOkoJpXYl{Xj8_$YJpiS$3%=8lre+jCwNrS)(GhfLwr*^VBq3n5K~~7YX=4^Yl3Qn
zOSDl}#+?H&ejU8wsSC!xJRX2%EDshImh>Di0?3bMT>3;KM^H7(UwsA@R`C@B`mY}c
zbNPx)bOXFRs}`?0K}M_jWiX)vaM>6;o&Xy&0E_30Jy4Fl#V#2xE$A^{lQF1+&ZZED
zzqm=}bM2GVa+vfiVzWTY3qQ*bv6r0;QqUsMy&mhYOrG3hBlh*3V_HCo2-{Y1JcAQ;*eA6GHR{BRBI>>&=@Y*B(u1C^jsX(2yz1?^J
zjznR5-m?GO##>XSkItZq$w-lxj)qMz&5EGTvG;oEyZY(R3&n-wMLhxx4!Eh(V@xe#
zYwrmmje%_mg1BGBY27Nx%W)soIw0fK=b@}-AWg%LG1X3a6k9RR66Lq&9KFPabOB8f
z7EHEkvs1|8m%Q+Wh}2dS6Uho_)#{xU
zv@Fu*6c`cR&MRWLK$YQ(8e+di6lzuc60a~HzuDCuYl^g>Gv@_1WJiHbjH6YV=5{DV
zc{@S_V`ehq$QW~2H54Hdha=rL-LF%|wCMClbYY@l*6DGp;#Vcz;)quiCU*fhb+Mv{
zd-D$%_6n8v)TTbh;>2m}Fs$^LH6oh!emM8p#ge4CY92hA4CV68hI&uXoVeE$?bjOk
zr49p#c4k~jf|>`ja&6s)Fo-XUhnm_S=M7H;d3N=_?JXW3#@mh^xa{WM^ILUvteJtW
zZ3A4g)Ak*Zmn+l$thH@`Hsf5^`-IP^4>T@qJQG+I%XUNxBVhWM?Cl9;2F`8uQo8caB*==ix|f_ON^bUQp{pZ
zlb>ad`o@o{66nxkE>E}|P(+fQ3
z=6}k^tzOZy5^^#GhT@Cm4C|7fslpznk5b&Gec80*S+(uC!XB_ajqTe`XS~S3;B-$b
zC2wEMvWIYaGkzH*J^T_L@47|3;Q1&o@^romM)&R?TDE0$_60hI+?#~j`1TH`i_5+F
z@lUFobcKW|hw5bI*f=m^j7{7hoB0L(Q*O+_4xR!-MS@wj`{JlCGft7oxk^iRPxQzv#FrV5^WN0bpgvD&45cvx
zOo@{Q=PHijh1VvIYQdFG7G-E#WYcC^Fg7Oxbn9rrqgtgon8jjfEyR6f`BNbS@1TY+
z$tvlgJN2Ff5+6Qn^R6E*P;RYot*z$GIuQJw&rwJB-Hw|7(G$|K>FHwSD}CP%N#Eqs
zzp?d*yHlomByqNS+m(B}%UM_Y?=3qjY1v!4-CO^3QB{XdOuv8E)h%Ur+0<$GFK@lH
zLw&vULw&dXslD@uW0s_?UzQHO8%dYk4sELe;gXd0aZ>ulpCq0wNZ&EahiN-P*N9F|
z!CkZbTz$o8`PIA(Z6(ie_%Uk-DqlwjAv{->ANQrfl#O3`Zu)?$9z6gz`687xGqhQS68@K>Z4S~hU3c^qt0^n#bcKl
z-WGIpIYPJ2%03xTJ);Zl!6vz6t1L$)j7RX;f|ZeXVh)Pt70494u&K`&g)>VS!SSO$
zb-{v842tPJ=G(tssO>~!5J!2V>_Flu+=3}M$1+v46RS{rLxI9bB`+T;_G>g&Yz$t!
zL2+M12ZFO0g>(i{!@f)tN46$Sx%=wnz>%isMQV(P}E|0D
z(H=>pocbNW#@5D9BjaIC;^k)Lv~OYqp-at|byK;CwYKwaZm_!>>$B9@{CXnH_1?jl
zI_qe_wz{Uq<$O(knPu7!j*)cTO=^@b>(HB-ULSG$abC8uB#E0$5g#l`^W2W6N!{w=
zA$1nswPu2l4^%i4Ye7u9er|$zuD7%j$AIxJS0E2YHNQ3D{kZm7ms}S`=5_9`NTzeIJton;5!m)xftG@c
zSvfRfd2bPB*oEs1M=ze{I2Vsc;&1>oc~%%&AsjXSA}@~?ym2O8H;~EYa$iZFV`he}
zl1=SJvl<>2Sza_~7TlnSp{ONH)CCyI0*yZ#&xLap37iGPM!1ei8D^Nwi~$7#3CxDg
zxyGDH3D3XPHp$f(J3$Ps@|ujuse-1b+gM<0)QG6kFX#>ug!`qR$N&XcO@iRt%I>8r&Bu3I~jFJUZ6rzm|bNU#6?YBOMp+`fOX
z@zYwr_@krt$nt^9am}rbhXoR;+kRI6{#*5aS)b^zhjrM>lFml`SnPKDPLhaZ41YK2
zy``fso<|#Htey2_w>ziT9F_e23BC7zV+xXw)6qD?TH5l9JQQw#>x>cNiW$9@q$Oc1
zRug{$b7kCj(RRs-(KB{+5siD-TXap@Pj?V%dnOL_CYcQg&t<_e8aY-=Rze(?ca5B3
zr3^nUwsP23fdG%G*h;xLlHBgXeU!zug5w)CF#WZ?*6~4V7@U#ks4s;F*WeA?pM2?S
z0JVkdlC8J~n)tH!Wa1>u6f=4##Cr)1Wmnsongn%|BxrITQrC;%z|wapu4K4di?r~z
zYlcu|0^Nbkg^IMWl(OwPoVT?g&ni35CdQ0TbaVhK13Wb##EByU=74flp3VP)Sd0)>
z(YY{uQ2b^N=AWql%G8>NDn-0ACga%8l;8~-nME+32ho%`dWhFF`Fa~-c6yu#6$EY$
zyx)<-+aCHr9{UwQWvP`hlsN>~qb*qLJR=h>Yzf28v#4
znB|-0_0MgQ)z$r7fa=&_D_@&fvwXY$P$??)ATvrL{G}%C`%f&1WKH^IN#-V9BYmH&
z^xqD1J8CR&lMWV;L?h{kt6^7;KETgU64SqytlYakqXe+de7?SH+U-d1NW5L+%t{sa
ziBjif2bQv@veg>d_R&UI)V=#Z#sKltvND8OF`ghUa;WU7OBR@DU;O$RCWF!2$%GQ<
zSyQz-H*#V0_xS74iFJT6(p#@l@d#E#w<-(BedL{KC5pi-tQi(DdW{^=@fOASZayM9
z5m#4yg3#?K#5tZz<~-%|xGuQ?qrCDSgt0Jjbh#BAkE3N-5g<@aVT?jH9$1U64MfWR
z-MO|r8s!)PFf1I#4MZ9F4~xPHVK(!@2*Bo&V~+EBPhmAG^4y80Ntwhb3$XHb5BZ|C
z!-3^k+!TKm%w-R71<%+wZ*8+OYISuQ3D5fRu9j9yD%#uW9v0}^s*Mg)&^1*
zzbV9HDK3K^IsiGcR~=_&aQYdA&PTdy*emj`VoG`x
zI*iW&o~vi&+82TGWK_*Wy^))2cJg~NX-{i%tyqur9j-?@obTUT@IPNuKS-QA$erGv
zPWpNf7e#!z9ajSs%>9xcONmr;)ZdnV6vvY8CTX8P{9W=f)@@fL{kp6tT_&w0Nk7)7
z|Bwi-X2}YyQserMtiBxfu5BNRj{onOfBoMl_e#DX>dZ{NqLc5hI20}3el{HzRFSGz
zb!F#e-zT5q$lK5IoTm*p5Ra~XMijj?t43EU|7`!l|MPt3JCf-5|A&7zx&3J?dQX%l
z7>_zSmhwrs`HSxP{h2EDD>t30T<+g{eQRZ?ENbhcI_txt9Ba!`y2{#dllqfB$^o`d
z`d%_=3D8B!)hV0#jGoCJfT;NyRCp
z$qbmYm2C9yLTdEcN0$S#65<_WgfDzoZ@gK)Q4J&BAV*flho3kNFSj~b&!NDyY%^vZ
zvChHe%sX?z`8dKO?%$59*@A504Z?fXXq1nIe5Wxat)%&)0-@_HVuo)bXZQpk5C9@#6Mdfs29z}O?&6D#
zv+J0p)XI~>xyBHu_gjLhIpHzSEAp5cf$dzEPF{#{X)}y*!e+AMa$}*ONdbPGg%kXMaN&?}3cdiP}yllT6T6ZHU&-WB4ycmMa!wv>ZaOD2=K
zvPqbPollQO)ETIs?Y1`}oQ81GI=C)+c(Ht@u`s@iGy6h;U>|F{{vQV2N#5XWtb&pDgj1z`
zg@O?WX&}fBl)FkOP4xrAA$V07gPIe_35N+xK&vM124Dza%H@if|hQ
z^Q4vmTJ3Qp&+Sq9Wg=D$91F**8e|}qd;;XeFl2d0c#yV^1qf`?jW6;yP={9=*MUsN
zS~Y2x0ce8^D(&l((5k{G<(Cy;`S7Q-4iL@DfSD7?wdyv(pCUq-6nPzbd@(h^gj*2_
zjSZMknpZ)N+IkjU#z>2WU(VH?DA0A?ksgY^NC62X4s+XfW^K>+Z{;QZame3JtWK%s
z@rtHbJayet|I{TO^14&MN$2w)vSdAa#Fh7~@2l^x>3e5hyH`(qW+_2
zmc9GEdy6SczgYHuFf=jR-oK3}5JnbyCR3It2v_c}8?Yp+ZT~;kB?}cr<#`72L~cQj)W@VPnEKN)5NQe`#jAw_8PDn
z51H|puFPcGsdIuj7aJo5*)+|8vtj5&gUNUbkW2h?nI^Q$w(Qyg3?qhV=g+l;d1nT@
z##WEI*<%<8CJ>CNBC6)_MGL%YEmZ6?@QOmWQ&(6=Wim@Ay;nn@58tGqGT5_{Ndt$eSEQv)jCuz5=1WCf{#_-wV#7g=n@Xohfy;)CUx*BYU<
zb&=5d)J4aO@pIZEV4~z(t*5f<)^HnXci}N{>le%WUptq?uT9$=Hy3yJ|AHrP^8eVI
z%F;cb{^{Y~(jC!bCc|7~TsFNL+0sa{RczhecQx@GeZ;^y-;*0%>elS`Kh&hHC;>t0Hq&ttRY_H>ee
zYy!X8O8I&dWfa@UZ5_C1Qu`7%J`^xe$Sr9;&OC;O2pa`0k--+i7%ia*=&8F?WoD!z
zr_y|E2<&84O0{B-hJ$Pf)`~DKrrn80Ms<8bb)jaJ2xLpLb~#m4j3PJ5M8i;s2O8WaZU$Lc5=s1vNa2l!(u
zd3pHunZk}j=-E&~5D|+)CHi{PjMdGN7$9$av6(P{hxvWtLlq
z5ly&06YgM4gT}Gz&uLUlVrIf=@=b)mEH+C5FILHPvF)~p8wx@V)B{XvLg>uVP-t222Dto{Qy#
zGiM^r$;`Lbcm6P`_iZTD1Z}9`uT2O|+~tT6MJ=uN>1bs=mz^ymz1EeT1=;=zYj4ck
z^6*`^G<&T^_F%;izWjV97koqvNvGDH;tBrK3Ak<=D
z*vAuhx6Y>6m{XDGRc=&4T{dT1=f{L;*fqlMd_Yb5^1Wg{y
z(N>ri1YLca#tx?iC-OLvdCYQf@WxH;EH9h*=m|e}d`PY)`vq|JiPK~{EJ4wl8_%|4
zjt+4-t%X*cAi_(Y{gcFCL3Si`GQO+*)@dyUSRIYZbSa&Yz(;O5=08+%f3s|yUCBdQ
z*u*k{9-}y%Q1n;}3#>gswiaSRcvBfFG0$Fh$);xIp)wtSY&8`<<4ngqLzf`cXX%FROMt+9Pdj^77hb@7|}$4oSi!8M~nO
z`&=1J$qgtK`;Hc!rJo9RJQ-nO#&zFSW5ps)azfPMy1a7h*%;(J_*#_
zWTlq<`*qz*sq7`mZcWcNA5dkxaeC?d&yyF^A5O#TN0e{h&nTXL?0IE>z`K8Eqb%(x
zIelJFs!kG2tz@|}W!Z;%OM79YgEEu)Y5mXb#CX3i0!YRXSGb`8h~~)nH?_w2IJ~OR
ztc%_;8gCnHQkp}H(HMX0r)aIn3=v=xS6|J(nDw&Bn3u8Rilz&5&hy@tS#M3&Ai5hL?t|6|j+;-w1-K)o1Kb`5e2l{x8nVHr!
zDi{id32w|>vX7Nx3vWz6(=mzR`81@O2nnEpNJY&&oS$%z9ISLUwp|f6e~ueoemPnm
zsZsny%$)(`Sq3!Rwx$%rC@!8}AADimO;*8RCkCvt1bWHkmiw^*h3RN$CB7OsnB^t&K2}5zC
z+<+3Hng1#z#=--g0Vye@%Krj)EscZ*HBzwA4T4aBamiR$eV8-RT;qlf7o`M@fDmNs?r8OOj!S
z))7~!pxU#*ubP#zGEt?q=hnZ*T&wQZIX%MrHA@T7U=?Li_klLh5m`MdmE%v6>`6cD
z0i#C?F4D!UJy(9!T2g=Vw3=sQWH4>ncsMe~Rb&iT$}DVlQPrx&RyRgMODj*3Da9OQ
zA`gjgFNzEv;37vZaNaDN_$zACsL)`6894Tqnsuy}XE_}*HDes}m}VSCFvS9d&
za;uG}YD=1}GMJ?uffK?yd}n|=jmjL2d;^YMg>>VpIkrrS5YjEgK8MtdAu}2xhwS6<
zr|jY6)KJ=++SMlhF=j(#Y2js9Bv(ZU2^edAQPiBnkBA46T>xr_aMpO`&2~`WN+O>O
zD58-?9rQ^rA`ay)Rt~`zF-S*Mq`XL8hz`vi3K-%6zF1msynze!NMI<;@+qN)51Nr@)JV*0kqHDEaa+T7R2or=9hS)Ric(sW7^OO(k_@7vy--&{N|0j7xhligC^M@d$r4%j5=WZ!skvafL=R9qAbtTQyMMBh~fq6M`Fj;8!fz(2aofQ^S3*F?CM)-^ymA*xw*#<~2l`mw1CG448Qa#);}
zu&$Cf#I59oc&h1Wt8O=H!WdrFGu+wAt6+R6KC~n+4@T$AqDzg&VI<7}8r5=ee;wt`)Q5^0tpsmS8*o;ftynZe;K=U*?<@&QS1<<1taeeam;s
zoBnd{?#C?-TTa>K-p-#!%C6tHYmT^OSB_}FJffCU;+NYmM+&O^3jQhm7KxvIl|@T?
z@8*;49kx2SxSroRa+CEJ1H)^7tXax7+7?KuO9V@owSzU*hxe@X1!dW$=O(}J^LUih
zJW9F|=5kLm8rPQ2$zmP+86_EF?R6&gZXBp@{+O5T>oJQ-yKT}^=VZ~on=DG&=2sxR
zytMyJPx4h6F#iwJNU}Y*@5?Ey<(<)_#gzHWZLH0Q$xE-!@BDQrngdGUbn(S{SdRWk
zm6mK)B&}`(W@w}wkt9Fr=!bgx?yzN_boldPn&{X1^Wsla`UQGbk$J_9Z?wzl9RbX-
zw~;&Aseq{<#NzDzaP`I0xMAT9wpExf@9j)v
zW_xzvQZ_QQOv-x8u@&dC2?@~=_#_DnG;b9>}
z-8OdR6(B)kJB|lcqsuwMm9BM1dpmEaatPntLfrrK+em>fQSza-U^7k7edQ>}lC*AD
z08|_MQ~LEI1!6t|kA
zBy#}!JyRB?eIx;`fUqm+>nBO#deTQgzGXT)OdfIyNFSv~{;6M0qqc_`ZHLQClH+@N
zDTlksM|v`4nGtE*fdm+lQL^`bBl@y#Kr?>sCaqm|JrG2*4tPnuJFmTguD`^&tzS|R
zB^9eDI!OSzu*>O7$rn0^`kMW8-R^(b`BZy8{mafhU5B=`ug&Rud!+Ya{gSJCeX?4u
zEC+y{8A{4}uK(05>s!(4S@%-06E+>Zq3h8n?A>*qdwfFSRqs|%Z`#yPXHQ2~@}0iM
zFqj&6M`&hwF&)E>G~f<#eQw>pn0OqpFSxI)WA)vIuQdGDTOjoWNizR(|I)i1VX@brv`11
z&@2q*Jc_ZQ!(j8-e3Q}`TsgCxni?u>EDSbLpPv~GuRdFItb=#gX8VnOSWyR9@b0=W
z{u}}cW^<7**|RPkbTD-|)kNLaUtnU3##spC>9DUcIAPGX4^Sa%t^DK4<Y+t-Et-9TVm_Tn?uvsjtIxPcL;3
zfYpvzo%IPAm>{o3?LU})Tnq>>KV?0@NC7;#KSWjCi(+bxBzNQ=^NuBc%sMDaO5eWR
zFI!vMo0QIW_wBz{KjPFJHU2}K4nR$8RFnEKS+-8v{Od?A{piPMSLuHAlH^CXWM4%3
zva=6(ygljP9|*a@FnIl8hm9@RN4SdSrP~KyRymf2b^VYsm7)RDpE3
zn|0KazVF~BZcR#`j*@)?q-$%^e*se(NJs}8VXRF+5`;0Cg!jB#j+^{@x1DYc{^f1i
z_le1Hc9njL)+0&UlNaxg>q)kgNTQ>?rFr&90V`!MbB(3$q*RA}PRoa16*?+0n(>cf
zy=({pXcUd}8yf$p*=zK~RYv{B&5XzpnxIbKoQbMKt07ggAXREa
zwmeuff2d^;D}SNoXCxQW5MBzp&>PBmaqXnS$4;7B(V&&eg%H)PG*#>Q{dIqmi9$A#
zT8OHq(DL9K|72vEnF
zI@CpKITA!2Zh41I$VEYJs6M!)fV}t?azWMnBVsVynu|419l4?E0m-Ixn%n>t4Mre%
zH%JtJ$s^=8SQ+Z{)6vY@7q{wQ*2;*h@X7)Lk^G#U#A`$E&f;Xs5z|d
zzC@7i+%3BIdE+YY+x}D#W4@l>mon)l9U*-hVac*tN0OwYw@Z?_qn_j=s%$;#-VX_r
z;gEEn*}Ycm@3zIu)9UiCxpV*U)#dJ_gZ*OvwB6M**WUDnzsAcF7yi3m)xGrgv6B-v
z?y#iss-pg_`-dfYigIb|j5gM{&7LILmzz#I@oUWOGD`_Z1B^NCgi%ye4Q|c61U;p2
z9DeSOnF99Ig|}Wsg(z%mf2>M}hGre5Q$s;P!6dH^ccJw-HJJP0SWfv+`#VTGr~`PM
zXfptJC%_*O5U`H?gV$Cq2Ef4%XvQNbPBpIm6e8sE2o@y|X^6-^k)Y#^J!P6LuW-Db
za^{9Pt|$ZH0fmAuTvthI;)wXynCjbLGk(@rtGajrq;EZ}(jFR-
zlks!AF?!JJ!KGgypTS5e4$o%g~^!722Dko_m`w
zw_`2mG%hPC=kI*_b33-+s*`wO!MVRD?R~MF|B<+ih2MD7wImS}-aqeKTV!WFzrx(;
zNm1rYgqO=KA_F`DAQRW-?3DG+?+m>seSTd^b?ue@Mp&CXtvOKz`)tILoe=dB-mZ6C
zPM7MDmKkk{`!%vM(mMOIXn$O`|6aPwk}g#(IIUFeE$;1xbyv>0tju-p9erG5-P{uY
z58#wq>AYLZN}8
zGCS=m`zmrFiU(WgyPtIS9JWj^|E8Gxd&bXOUfjSWc}
zP616hjl~rqiq!k9f2p(s`ft;y&7Ud`R`_P%He*6<5{+fwq#
zq&-m4*Z8!;gF+=$^G;gfnRj(LXUZ>rM1-^sM$|Pnoj8ku(&TSEy>^`kd2q&rLZLL=
zXli{_cj7dt(
zjf&B&YK{Nylm~g3H8tflJ*$w%&Y%?AP9}uBeNy$R(-{6g*13Zo(A{V
z_Xkea^adm-T2cSu@9%Qz?B@5QNI!x=?X-JAAoS0wSc8w3`Wj6_L8=JugNB^Wh+lFj
z8I)YG!Ue129MH#HO{&e>H2s8>>R5%!S@{O7C0}aaZC2#kiJ5g_Aa{tz!p6Y*mw6OTcR%vT%
zg6K-h(#+hec57{2T}LO!Z#&EI0zKE8-?`x|=@$n|QX>Bqi?uebcQjKYTd(Q4`!$UP
zG;e{wcNp~_ZdNZHZi$#ASuN1M9XsfV{UXvXynj>FAH=AyoLjuR_Wiu&-MeQU`ui{@
zr2PWvpRLZ_RWQPwvg^ShwNJ+(DeZH|Wcp{4L{FMBnOt+Y08C(c0wXmKMg9MbEdU$A
zBhoQtvADkA*Oaw{nxh}den~aoC*CH1{rY8gZUzz`uL!^G^oq$`e$(h{x%WMF@7r&A
z)0a0F`qltHe|hrm-MhJYJhxdsUu~+9hRMCA3WW?}y#fFh1+fcN2kW4!xhg+ddqa)`
ziIL)keWcjY6s{Pdrur6Adli8Q;XTL+=RpP`?tP$;>nH>ilM&jg7U;RF>a_Lqb6b_nYBUN9W0+4np_vDt>(VAC4$Q?6m
zt1*DarJ$y{oCqoa5{IGex+`&wr6`EP9SF*7?lovB%(T6sb5H|rV-^t+0U(WnoXURJ
zg6w-F|KNI)-w>j?75N~-wCP4*LV!ES{i0fNQ&T5&F*sP2djBcqQg*4+lnDfPHpJ-T
zapYh`z|#9uC!y`3A)O%VV4b-a1c&TY3rSGzpp^el>80Qhb9Y`-=mQ(j^li%A!tDA4
zRYzIZ
zZV|uauU3Y`*UkQKp8*P<4}1P!{6Sq3t8euSb9(W=KOV*UC%dFb-!QiU&@A3v89tu8
zxp?QEBT@V*nO9AWGH72V#QC26vZ|J`x5!BhH{^O
zULsJI{wep~?bTlVdq5j}aY_5Kx|yG)yt(`BKa=Oa&TEu=p<5KUyjn{i-F@x%?7B@O
z@}d!q0tlNoS~*P>AtB~o)X=vroq-{7fCN-X@HIDRXlg1|q~2>iW!HQuyYtMIYzp#X
zoO$OX6lMPqVdi!DE5f_=tye?oY3!pC+91U5P0L_5C4A7#92xKil3n+%=^sV+;8HWd
zUUvgKL%mx6r#+D5dA+gJ1cC*C0HKs-47PV|9Og82&E=eF2$!VQg>D>w`zYdUJB4K`
z|5H2Y!e#STncf{Uq<5Ns0JJD0BZBHs645OBCBn$7@9Y(7UX651ulN#F9`f`qGQzfU4MfmC*e^4>k?_h)_?KuS|>8)DG@*%}RyEpk(M=SfqA2NfYtRWAS{
z`DB9KD?5-oz}2R=AmGM`Mq~>hP@p9-lur2vXP^+{)*_TU1pJ_>^Ni-XricenKw=Mi
zAtb-5qE)Du5GXF7eL_y!c|)?#Jh({H(4;NnTDZ0OMN^Ye
zeV(*@Fs;6ra`c6cc?6Vzj!IA*i*Th`F$~^Um}dtOZ`^+@F85?^2*M_LeC;g+CNgD
zr=?{*u>99=t*t@BGq=yRcc#rXwjQs_=QHn2XKt^Re*}c?V*mGvnwWSEvbEoJ>TeN1
z6thbqAR`*8MRDYTJkqQQcOl3;yR;z;6bxv^a1a^+Em912M<}*~XecuDoe3qJdn2%e
zQi|w(^s{wyg~3$l#ka466|*}LA-%Lh73!0X&L(+)?113X0Bk}7;?VL6XnEB*
z=D<0c2KH1NbPyYeepUMO1upH9DdY;e_iT2>TQhR5N?T?GpaL$0pj8`7DJT>~AKK6f
zcGrMphl4JhyaPF<8i+;#nHL#y1AyS5MiBz5icmqTC|nO7@*+p0xjB?*-+&R??>Qzp
zDn>NNsR|^jA&iW@cK!NAA7k^UjpU3=*E^p+MTVH?47POI6rG`gv!gGB_%<2q(=M3V
zgV6Ff0)o#*#66X!UvO{v`KJrH8G|iVKITDZJ86{Y3r~J30;we&H<+?&3=at~&5J>i
z!|QK&kDm+hd1`mZ=8n4o6zXG+bjO~8TAMyN31
z8oN$!9MA3qqCxS4yMkY~T
zB(5c>Pt+vey!j-*(lu?a2XNfCR@ML!msAD2Gx7ahxI@469o=?*BEDwp!xWtKeT^ji
zvHN*3MfR&Q&`e7E@#?YP;{8J%k~EgIEY2K%9@+PiaXE@9erF*2rYHGnZ*y_0p7cX6
zvj65^Psht7-@93aBevc>ph5@IFMo5wo55gQ>7VKBYhQnt$9Tprt3IC|BN`%j9$KDH
zlZ@WJeXYXK-hPNo4O&$8*JCE{J*zL!`+m*o=Dphu(;2@tINEoD
zJTxF+NOtZhrLM_1r>W^tV~FWlFg6Bd4=q9f5+4*|9&w@NRa1oNQ=h9heDmL!$(y%^
ze@4JVv^qm?nLVf&iU_$}b%R3D@W8TFUfJDw9eVjri?LVpiHNZ$6`(;#Xhg}Q#3t
z!639*L~vCpqJ#=uh7sN2B(l!
z*NhU(bN+twq~zS|CbVz)lZF#^)bLg{1)ze>#!x8lX}_0rIfYzCUdF0|!9Sy+w^~{|
z8^Qz70YOFyZy9x0Z-j&dgmhFOv49L1Jkwv_>SuQ+(C(K9P#Q`jyY`(s2svI-@rKdV
zfP|~iPy-ZX1Lw`gx$u%fY*XoJ2t+}lwX6JGD7N)y1)xwKi~xusBBJ;PK;J4fO1N3X
zU)NBBEw^prs77{M;UDihOH|^bP>nKEd2+Du?p>96Dsmr{QOCd+0yaf5y8v=(wUmm5#26
zInI+N!;qiRxr!MVeGI=s>&kPiJfO8~jM2;5t0dCo!hHAn^m|KBsp?hEq{Z9kV2=Df
z$!ySJigRN6(Nmy@&AxK-S|-1aw-*D8#ydd
zIyrsKhRu0wF_pWK*pf;`gl|IIbU-XA$uftrN;8shcbm$cQ)0?7I_QKXhGGAw&vjqd
zeP6fJPVd+2^>{u`@AviviNDnEEq5qCD1W&sKVCZ)8L4=qR9OD_F}X1JVePS~e}UJ
zA6(`3Ph&cE2QRiyOo;n77W=MSbM>kg(H)7y;X7&6o}HehWj!83SnodvK<4bs2M#QZgFj9JcIO`kXd%#m8_v{nq
zVKW2Ds;jE{NWRyr)qt{M(5OVJq=zpk-H*OXY{hT+lM}k~v^m5I2>^~lhIN^cj>*#M
zYuV{pOiQQxOLQwKReeHk4grZ2GniCtCPAe~hE}5h@+M&n&@fzy^16%Ifs!5`8l&P@
zK4Xta=j%?<-2nv=MJe6n2+yk?BQJ~I6fV^ttyjLc1rX4F$9}T)-88p;&_3R_!#-(Q
z`t?o!=JPSb_3<(JeM8kXjUSf2_YTZ`PKyxonwFeh{UVP?F3hPKvcA7=Qr%@d6hCH<
z+Z{De;P2S@ZPk*=V5ANS^Yumww_n(FuDgk_mK#8BlDwl_q
zw!K4fy+JoD6$_vDJ1mTtB>sF>GAlPx&JHiy-q?0%w&g{^!uQ7I9FZURPTv0!oHQ><
zzwzL4lG0YMBlst9#$9D1oP2U%>i6rAz55v-5Opcyx$c+J^fF>pl;%qHNy|
zT5Xz8OiXOLWGVledE=6$=NhbQpEKaP4VB^RooJ-&cl~c>z}`UNE63m
zr;23;I
zQ3;xzdHC{bq<;`W>!Osum8e4`b(7sASib3h>3d1dVPWOz*tBjKCzR#fMIglVZWi$(
zCH?H9aF`1%8ySpPFb5tgEYQSR7@IwI4X~?RSLY&4vEq!I>{3ekC2p=6_5F
zg9P^T+U>r9+1-vxf%*RX3nt3njlbagNizkBBlo@=K3<+U19rS+RmZt6>xL7fU)7GM
zyQD=Q?TGvNv#